Bug 1573844 - Remove js::Class definition and alias JSClass to it r=tcampbell,mccr8
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 15 Aug 2019 08:32:22 +0000
changeset 488201 afb443764498dee705a5e1e06cd1c2de3f222035
parent 488200 c1683d4d191a40572b799947933b65aa94384209
child 488202 7ecc384e1afe190ae13ef6fce9aaaadb0971ebea
push id113904
push userncsoregi@mozilla.com
push dateThu, 15 Aug 2019 19:41:00 +0000
treeherdermozilla-inbound@b283a7ef186c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell, mccr8
bugs1573844
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1573844 - Remove js::Class definition and alias JSClass to it r=tcampbell,mccr8 JSClass contained void* members corresponding to the internal pointer members of js::Class. This stores the internal members in JSClass and removes js::Class. This leaves js::Class aliased to JSClass while we remove references to it. I also aliased Jsvalify and Valueify into global scope temporarily to make this compile. These get removed in the following patches. I had to remove a few functions which now don't compile with js::Class being the same type as JSClass. Differential Revision: https://phabricator.services.mozilla.com/D41983
dom/bindings/BindingUtils.h
dom/bindings/DOMJSClass.h
js/public/Class.h
js/public/TypeDecls.h
js/rust/src/rust.rs
js/rust/tests/rooting.rs
js/rust/tests/runtime.rs
js/src/builtin/JSON.h
js/src/builtin/TypedObject.h
js/src/builtin/intl/IntlObject.h
js/src/debugger/Environment.h
js/src/gc/Allocator.h
js/src/jsmath.h
js/src/vm/NativeObject.h
js/src/vm/TypeSet.h
js/xpconnect/idl/nsIXPCScriptable.idl
xpcom/base/CycleCollectedJSRuntime.h
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -78,39 +78,27 @@ bool ThrowInvalidThis(JSContext* aCx, co
 bool ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
                       bool aSecurityError, prototypes::ID aProtoId);
 
 // Returns true if the JSClass is used for DOM objects.
 inline bool IsDOMClass(const JSClass* clasp) {
   return clasp->flags & JSCLASS_IS_DOMJSCLASS;
 }
 
-inline bool IsDOMClass(const js::Class* clasp) {
-  return IsDOMClass(Jsvalify(clasp));
-}
-
 // Return true if the JSClass is used for non-proxy DOM objects.
-inline bool IsNonProxyDOMClass(const js::Class* clasp) {
+inline bool IsNonProxyDOMClass(const JSClass* clasp) {
   return IsDOMClass(clasp) && !clasp->isProxy();
 }
 
-inline bool IsNonProxyDOMClass(const JSClass* clasp) {
-  return IsNonProxyDOMClass(js::Valueify(clasp));
-}
-
 // Returns true if the JSClass is used for DOM interface and interface
 // prototype objects.
 inline bool IsDOMIfaceAndProtoClass(const JSClass* clasp) {
   return clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS;
 }
 
-inline bool IsDOMIfaceAndProtoClass(const js::Class* clasp) {
-  return IsDOMIfaceAndProtoClass(Jsvalify(clasp));
-}
-
 static_assert(DOM_OBJECT_SLOT == 0,
               "DOM_OBJECT_SLOT doesn't match the proxy private slot.  "
               "Expect bad things");
 template <class T>
 inline T* UnwrapDOMObject(JSObject* obj) {
   MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
              "Don't pass non-DOM objects to this function");
 
--- a/dom/bindings/DOMJSClass.h
+++ b/dom/bindings/DOMJSClass.h
@@ -447,20 +447,16 @@ struct DOMJSClass {
   // Null otherwise.
   WebIDLSerializer mSerializer;
 
   static const DOMJSClass* FromJSClass(const JSClass* base) {
     MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
     return reinterpret_cast<const DOMJSClass*>(base);
   }
 
-  static const DOMJSClass* FromJSClass(const js::Class* base) {
-    return FromJSClass(Jsvalify(base));
-  }
-
   const JSClass* ToJSClass() const { return Jsvalify(&mBase); }
 };
 
 // Special JSClass for DOM interface and interface prototype objects.
 struct DOMIfaceAndProtoJSClass {
   // It would be nice to just inherit from js::Class, but that precludes pure
   // compile-time initialization of the form
   // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace
@@ -486,19 +482,16 @@ struct DOMIfaceAndProtoJSClass {
   const char* mToString;
 
   ProtoGetter mGetParentProto;
 
   static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) {
     MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS);
     return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base);
   }
-  static const DOMIfaceAndProtoJSClass* FromJSClass(const js::Class* base) {
-    return FromJSClass(Jsvalify(base));
-  }
 
   const JSClass* ToJSClass() const { return Jsvalify(&mBase); }
 };
 
 class ProtoAndIfaceCache;
 
 inline bool DOMGlobalHasProtoAndIFaceCache(JSObject* global) {
   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -15,26 +15,25 @@
 
 #include "js/CallArgs.h"
 #include "js/Id.h"
 #include "js/TypeDecls.h"
 
 /*
  * A JSClass acts as a vtable for JS objects that allows JSAPI clients to
  * control various aspects of the behavior of an object like property lookup.
- * js::Class is an engine-private extension that allows more control over
+ * It contains some engine-private extensions that allows more control over
  * object behavior and, e.g., allows custom slow layout.
  */
 
 struct JSAtomState;
 struct JSFunctionSpec;
 
 namespace js {
 
-struct Class;
 class Shape;
 
 // This is equal to JSFunction::class_.  Use it in places where you don't want
 // to #include jsfun.h.
 extern JS_FRIEND_DATA const js::Class* const FunctionClassPtr;
 
 }  // namespace js
 
@@ -488,19 +487,19 @@ typedef bool (*JSHasInstanceOp)(JSContex
  * the traversal is a part of the marking phase through calling
  * JS_IsGCMarkingTracer and apply a special code like emptying caches or
  * marking its native structures.
  */
 typedef void (*JSTraceOp)(JSTracer* trc, JSObject* obj);
 
 typedef size_t (*JSObjectMovedOp)(JSObject* obj, JSObject* old);
 
-/* js::Class operation signatures. */
+namespace js {
 
-namespace js {
+/* Internal / friend API operation signatures. */
 
 typedef bool (*LookupPropertyOp)(JSContext* cx, JS::HandleObject obj,
                                  JS::HandleId id, JS::MutableHandleObject objp,
                                  JS::MutableHandle<JS::PropertyResult> propp);
 typedef bool (*DefinePropertyOp)(JSContext* cx, JS::HandleObject obj,
                                  JS::HandleId id,
                                  JS::Handle<JS::PropertyDescriptor> desc,
                                  JS::ObjectOpResult& result);
@@ -568,60 +567,16 @@ class JS_FRIEND_API ElementAdder {
   bool append(JSContext* cx, JS::HandleValue v);
   void appendHole();
 };
 
 typedef bool (*GetElementsOp)(JSContext* cx, JS::HandleObject obj,
                               uint32_t begin, uint32_t end,
                               ElementAdder* adder);
 
-// The special treatment of |finalize| and |trace| is necessary because if we
-// assign either of those hooks to a local variable and then call it -- as is
-// done with the other hooks -- the GC hazard analysis gets confused.
-#define JS_CLASS_MEMBERS                                                       \
-  const char* name;                                                            \
-  uint32_t flags;                                                              \
-  const JSClassOps* cOps;                                                      \
-                                                                               \
-  JSAddPropertyOp getAddProperty() const {                                     \
-    return cOps ? cOps->addProperty : nullptr;                                 \
-  }                                                                            \
-  JSDeletePropertyOp getDelProperty() const {                                  \
-    return cOps ? cOps->delProperty : nullptr;                                 \
-  }                                                                            \
-  JSEnumerateOp getEnumerate() const {                                         \
-    return cOps ? cOps->enumerate : nullptr;                                   \
-  }                                                                            \
-  JSNewEnumerateOp getNewEnumerate() const {                                   \
-    return cOps ? cOps->newEnumerate : nullptr;                                \
-  }                                                                            \
-  JSResolveOp getResolve() const { return cOps ? cOps->resolve : nullptr; }    \
-  JSMayResolveOp getMayResolve() const {                                       \
-    return cOps ? cOps->mayResolve : nullptr;                                  \
-  }                                                                            \
-  JSNative getCall() const { return cOps ? cOps->call : nullptr; }             \
-  JSHasInstanceOp getHasInstance() const {                                     \
-    return cOps ? cOps->hasInstance : nullptr;                                 \
-  }                                                                            \
-  JSNative getConstruct() const { return cOps ? cOps->construct : nullptr; }   \
-                                                                               \
-  bool hasFinalize() const { return cOps && cOps->finalize; }                  \
-  bool hasTrace() const { return cOps && cOps->trace; }                        \
-                                                                               \
-  bool isTrace(JSTraceOp trace) const { return cOps && cOps->trace == trace; } \
-                                                                               \
-  void doFinalize(JSFreeOp* fop, JSObject* obj) const {                        \
-    MOZ_ASSERT(cOps && cOps->finalize);                                        \
-    cOps->finalize(fop, obj);                                                  \
-  }                                                                            \
-  void doTrace(JSTracer* trc, JSObject* obj) const {                           \
-    MOZ_ASSERT(cOps && cOps->trace);                                           \
-    cOps->trace(trc, obj);                                                     \
-  }
-
 /** Callback for the creation of constructor and prototype objects. */
 typedef JSObject* (*ClassObjectCreationOp)(JSContext* cx, JSProtoKey key);
 
 /**
  * Callback for custom post-processing after class initialization via
  * ClassSpec.
  */
 typedef bool (*FinishClassInitOp)(JSContext* cx, JS::HandleObject ctor,
@@ -703,41 +658,16 @@ struct MOZ_STATIC_CLASS ObjectOps {
 };
 
 #define JS_NULL_OBJECT_OPS nullptr
 
 }  // namespace js
 
 // Classes, objects, and properties.
 
-typedef void (*JSClassInternal)();
-
-struct MOZ_STATIC_CLASS JSClassOps {
-  /* Function pointer members (may be null). */
-  JSAddPropertyOp addProperty;
-  JSDeletePropertyOp delProperty;
-  JSEnumerateOp enumerate;
-  JSNewEnumerateOp newEnumerate;
-  JSResolveOp resolve;
-  JSMayResolveOp mayResolve;
-  JSFinalizeOp finalize;
-  JSNative call;
-  JSHasInstanceOp hasInstance;
-  JSNative construct;
-  JSTraceOp trace;
-};
-
-#define JS_NULL_CLASS_OPS nullptr
-
-struct JSClass {
-  JS_CLASS_MEMBERS;
-
-  void* reserved[3];
-};
-
 // Objects have private slot.
 static const uint32_t JSCLASS_HAS_PRIVATE = 1 << 0;
 
 // Class's initialization code will call `SetNewObjectMetadata` itself.
 static const uint32_t JSCLASS_DELAY_METADATA_BUILDER = 1 << 1;
 
 // Class is an XPCWrappedNative. WeakMaps use this to override the wrapper
 // disposal mechanism.
@@ -837,28 +767,82 @@ static const uint32_t JSCLASS_CACHED_PRO
     JS_BITMASK(js::JSCLASS_CACHED_PROTO_WIDTH);
 
 #define JSCLASS_HAS_CACHED_PROTO(key) \
   (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT)
 #define JSCLASS_CACHED_PROTO_KEY(clasp)                          \
   ((JSProtoKey)(((clasp)->flags >> JSCLASS_CACHED_PROTO_SHIFT) & \
                 JSCLASS_CACHED_PROTO_MASK))
 
-// Initializer for unused members of statically initialized JSClass structs.
-#define JSCLASS_NO_INTERNAL_MEMBERS \
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-#define JSCLASS_NO_OPTIONAL_MEMBERS 0, 0, 0, 0, 0, JSCLASS_NO_INTERNAL_MEMBERS
+struct MOZ_STATIC_CLASS JSClassOps {
+  /* Function pointer members (may be null). */
+  JSAddPropertyOp addProperty;
+  JSDeletePropertyOp delProperty;
+  JSEnumerateOp enumerate;
+  JSNewEnumerateOp newEnumerate;
+  JSResolveOp resolve;
+  JSMayResolveOp mayResolve;
+  JSFinalizeOp finalize;
+  JSNative call;
+  JSHasInstanceOp hasInstance;
+  JSNative construct;
+  JSTraceOp trace;
+};
+
+#define JS_NULL_CLASS_OPS nullptr
+
+struct JSClass {
+  const char* name;
+  uint32_t flags;
+  const JSClassOps* cOps;
+
+  const js::ClassSpec* spec;
+  const js::ClassExtension* ext;
+  const js::ObjectOps* oOps;
+
+  // Public accessors:
 
-namespace js {
+  JSAddPropertyOp getAddProperty() const {
+    return cOps ? cOps->addProperty : nullptr;
+  }
+  JSDeletePropertyOp getDelProperty() const {
+    return cOps ? cOps->delProperty : nullptr;
+  }
+  JSEnumerateOp getEnumerate() const {
+    return cOps ? cOps->enumerate : nullptr;
+  }
+  JSNewEnumerateOp getNewEnumerate() const {
+    return cOps ? cOps->newEnumerate : nullptr;
+  }
+  JSResolveOp getResolve() const { return cOps ? cOps->resolve : nullptr; }
+  JSMayResolveOp getMayResolve() const {
+    return cOps ? cOps->mayResolve : nullptr;
+  }
+  JSNative getCall() const { return cOps ? cOps->call : nullptr; }
+  JSHasInstanceOp getHasInstance() const {
+    return cOps ? cOps->hasInstance : nullptr;
+  }
+  JSNative getConstruct() const { return cOps ? cOps->construct : nullptr; }
 
-struct MOZ_STATIC_CLASS Class {
-  JS_CLASS_MEMBERS;
-  const ClassSpec* spec;
-  const ClassExtension* ext;
-  const ObjectOps* oOps;
+  bool hasFinalize() const { return cOps && cOps->finalize; }
+  bool hasTrace() const { return cOps && cOps->trace; }
+
+  bool isTrace(JSTraceOp trace) const { return cOps && cOps->trace == trace; }
+
+  // The special treatment of |finalize| and |trace| is necessary because if we
+  // assign either of those hooks to a local variable and then call it -- as is
+  // done with the other hooks -- the GC hazard analysis gets confused.
+  void doFinalize(JSFreeOp* fop, JSObject* obj) const {
+    MOZ_ASSERT(cOps && cOps->finalize);
+    cOps->finalize(fop, obj);
+  }
+  void doTrace(JSTracer* trc, JSObject* obj) const {
+    MOZ_ASSERT(cOps && cOps->trace);
+    cOps->trace(trc, obj);
+  }
 
   /*
    * Objects of this class aren't native objects. They don't have Shapes that
    * describe their properties and layout. Classes using this flag must
    * provide their own property behavior, either by being proxy classes (do
    * this) or by overriding all the ObjectOps except getElements
    * (don't do this).
    */
@@ -884,88 +868,88 @@ struct MOZ_STATIC_CLASS Class {
   bool isDOMClass() const { return flags & JSCLASS_IS_DOMJSCLASS; }
 
   bool shouldDelayMetadataBuilder() const {
     return flags & JSCLASS_DELAY_METADATA_BUILDER;
   }
 
   bool isWrappedNative() const { return flags & JSCLASS_IS_WRAPPED_NATIVE; }
 
-  static size_t offsetOfFlags() { return offsetof(Class, flags); }
+  static size_t offsetOfFlags() { return offsetof(JSClass, flags); }
+
+  // Internal / friend API accessors:
 
   bool specDefined() const { return spec ? spec->defined() : false; }
   JSProtoKey specInheritanceProtoKey() const {
     return spec ? spec->inheritanceProtoKey() : JSProto_Null;
   }
   bool specShouldDefineConstructor() const {
     return spec ? spec->shouldDefineConstructor() : true;
   }
-  ClassObjectCreationOp specCreateConstructorHook() const {
+  js::ClassObjectCreationOp specCreateConstructorHook() const {
     return spec ? spec->createConstructor : nullptr;
   }
-  ClassObjectCreationOp specCreatePrototypeHook() const {
+  js::ClassObjectCreationOp specCreatePrototypeHook() const {
     return spec ? spec->createPrototype : nullptr;
   }
   const JSFunctionSpec* specConstructorFunctions() const {
     return spec ? spec->constructorFunctions : nullptr;
   }
   const JSPropertySpec* specConstructorProperties() const {
     return spec ? spec->constructorProperties : nullptr;
   }
   const JSFunctionSpec* specPrototypeFunctions() const {
     return spec ? spec->prototypeFunctions : nullptr;
   }
   const JSPropertySpec* specPrototypeProperties() const {
     return spec ? spec->prototypeProperties : nullptr;
   }
-  FinishClassInitOp specFinishInitHook() const {
+  js::FinishClassInitOp specFinishInitHook() const {
     return spec ? spec->finishInit : nullptr;
   }
 
   JSObjectMovedOp extObjectMovedOp() const {
     return ext ? ext->objectMovedOp : nullptr;
   }
 
-  LookupPropertyOp getOpsLookupProperty() const {
+  js::LookupPropertyOp getOpsLookupProperty() const {
     return oOps ? oOps->lookupProperty : nullptr;
   }
-  DefinePropertyOp getOpsDefineProperty() const {
+  js::DefinePropertyOp getOpsDefineProperty() const {
     return oOps ? oOps->defineProperty : nullptr;
   }
-  HasPropertyOp getOpsHasProperty() const {
+  js::HasPropertyOp getOpsHasProperty() const {
     return oOps ? oOps->hasProperty : nullptr;
   }
-  GetPropertyOp getOpsGetProperty() const {
+  js::GetPropertyOp getOpsGetProperty() const {
     return oOps ? oOps->getProperty : nullptr;
   }
-  SetPropertyOp getOpsSetProperty() const {
+  js::SetPropertyOp getOpsSetProperty() const {
     return oOps ? oOps->setProperty : nullptr;
   }
-  GetOwnPropertyOp getOpsGetOwnPropertyDescriptor() const {
+  js::GetOwnPropertyOp getOpsGetOwnPropertyDescriptor() const {
     return oOps ? oOps->getOwnPropertyDescriptor : nullptr;
   }
-  DeletePropertyOp getOpsDeleteProperty() const {
+  js::DeletePropertyOp getOpsDeleteProperty() const {
     return oOps ? oOps->deleteProperty : nullptr;
   }
-  GetElementsOp getOpsGetElements() const {
+  js::GetElementsOp getOpsGetElements() const {
     return oOps ? oOps->getElements : nullptr;
   }
   JSFunToStringOp getOpsFunToString() const {
     return oOps ? oOps->funToString : nullptr;
   }
 };
 
-static_assert(offsetof(JSClass, name) == offsetof(Class, name),
-              "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, flags) == offsetof(Class, flags),
-              "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, cOps) == offsetof(Class, cOps),
-              "Class and JSClass must be consistent");
-static_assert(sizeof(JSClass) == sizeof(Class),
-              "Class and JSClass must be consistent");
+// Initializer for unused members of statically initialized JSClass structs.
+#define JSCLASS_NO_INTERNAL_MEMBERS \
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define JSCLASS_NO_OPTIONAL_MEMBERS 0, 0, 0, 0, 0, JSCLASS_NO_INTERNAL_MEMBERS
+
+namespace js {
 
 static MOZ_ALWAYS_INLINE const JSClass* Jsvalify(const Class* c) {
   return (const JSClass*)c;
 }
 
 static MOZ_ALWAYS_INLINE const Class* Valueify(const JSClass* c) {
   return (const Class*)c;
 }
@@ -1001,9 +985,13 @@ enum class ESClass {
 bool Unbox(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp);
 
 #ifdef DEBUG
 JS_FRIEND_API bool HasObjectMovedOp(JSObject* obj);
 #endif
 
 } /* namespace js */
 
+// Alias these into global scope for now.
+using js::Jsvalify;
+using js::Valueify;
+
 #endif /* js_Class_h */
--- a/js/public/TypeDecls.h
+++ b/js/public/TypeDecls.h
@@ -21,25 +21,27 @@
 #include <stdint.h>
 
 #include "js-config.h"
 
 typedef uint8_t jsbytecode;
 
 class JSAtom;
 struct JSContext;
+struct JSClass;
 class JSFunction;
 class JSFreeOp;
 class JSObject;
 struct JSRuntime;
 class JSScript;
 class JSString;
 
 namespace js {
 class TempAllocPolicy;
+using Class = JSClass;
 };  // namespace js
 
 namespace JS {
 
 struct PropertyKey;
 
 typedef unsigned char Latin1Char;
 
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -1043,17 +1043,19 @@ static SIMPLE_GLOBAL_CLASS_OPS: JSClassO
     trace: Some(JS_GlobalObjectTraceHook),
 };
 
 /// This is a simple `JSClass` for global objects, primarily intended for tests.
 pub static SIMPLE_GLOBAL_CLASS: JSClass = JSClass {
     name: b"Global\0" as *const u8 as *const _,
     flags: (JSCLASS_IS_GLOBAL | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT)) as u32,
     cOps: &SIMPLE_GLOBAL_CLASS_OPS as *const JSClassOps,
-    reserved: [0 as *mut _; 3]
+    spec: 0 as *mut _,
+    ext: 0 as *mut _,
+    oOps: 0 as *mut _
 };
 
 #[inline]
 unsafe fn get_object_group(obj: *mut JSObject) -> *mut js::shadow::ObjectGroup {
     assert!(!obj.is_null());
     let obj = obj as *mut js::shadow::Object;
     (*obj).group
 }
--- a/js/rust/tests/rooting.rs
+++ b/js/rust/tests/rooting.rs
@@ -82,10 +82,12 @@ lazy_static! {
         }
     ];
 }
 
 static CLASS: JSClass = JSClass {
     name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
     flags: 0,
     cOps: 0 as *const _,
-    reserved: [0 as *mut _; 3]
+    spec: 0 as *mut _,
+    ext: 0 as *mut _,
+    oOps: 0 as *mut _
 };
--- a/js/rust/tests/runtime.rs
+++ b/js/rust/tests/runtime.rs
@@ -48,10 +48,12 @@ static CLASS_OPS: JSClassOps = JSClassOp
     construct: None,
     trace: None,
 };
 
 static CLASS: JSClass = JSClass {
     name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
     flags: 0 | JSCLASS_FOREGROUND_FINALIZE,
     cOps: &CLASS_OPS as *const JSClassOps,
-    reserved: [0 as *mut _; 3]
+    spec: 0 as *mut _,
+    ext: 0 as *mut _,
+    oOps: 0 as *mut _
 };
--- a/js/src/builtin/JSON.h
+++ b/js/src/builtin/JSON.h
@@ -10,17 +10,16 @@
 #include "mozilla/Range.h"
 
 #include "NamespaceImports.h"
 
 #include "js/RootingAPI.h"
 
 namespace js {
 
-struct Class;
 class GlobalObject;
 class StringBuffer;
 
 extern const Class JSONClass;
 
 extern JSObject* InitJSONClass(JSContext* cx, Handle<GlobalObject*> obj);
 
 enum class StringifyBehavior { Normal, RestrictedSafe };
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -1053,32 +1053,32 @@ inline bool TypedObject::opaque() const 
 
 JSObject* InitTypedObjectModuleObject(JSContext* cx,
                                       JS::Handle<GlobalObject*> global);
 
 }  // namespace js
 
 template <>
 inline bool JSObject::is<js::SimpleTypeDescr>() const {
-  return IsSimpleTypeDescrClass(getClass());
+  return js::IsSimpleTypeDescrClass(getClass());
 }
 
 template <>
 inline bool JSObject::is<js::ComplexTypeDescr>() const {
-  return IsComplexTypeDescrClass(getClass());
+  return js::IsComplexTypeDescrClass(getClass());
 }
 
 template <>
 inline bool JSObject::is<js::TypeDescr>() const {
-  return IsTypeDescrClass(getClass());
+  return js::IsTypeDescrClass(getClass());
 }
 
 template <>
 inline bool JSObject::is<js::TypedObject>() const {
-  return IsTypedObjectClass(getClass());
+  return js::IsTypedObjectClass(getClass());
 }
 
 template <>
 inline bool JSObject::is<js::OutlineTypedObject>() const {
   return getClass() == &js::OutlineTransparentTypedObject::class_ ||
          getClass() == &js::OutlineOpaqueTypedObject::class_;
 }
 
--- a/js/src/builtin/intl/IntlObject.h
+++ b/js/src/builtin/intl/IntlObject.h
@@ -9,17 +9,16 @@
 
 #include "mozilla/Attributes.h"
 
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 
 namespace js {
 
-struct Class;
 class GlobalObject;
 
 extern const Class IntlClass;
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
  * Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
  */
--- a/js/src/debugger/Environment.h
+++ b/js/src/debugger/Environment.h
@@ -21,17 +21,16 @@
 
 class JSObject;
 class JSTracer;
 struct JSContext;
 
 namespace js {
 
 class GlobalObject;
-struct Class;
 
 enum class DebuggerEnvironmentType { Declarative, With, Object };
 
 class DebuggerEnvironment : public NativeObject {
  public:
   enum { OWNER_SLOT };
 
   static const unsigned RESERVED_SLOTS = 1;
--- a/js/src/gc/Allocator.h
+++ b/js/src/gc/Allocator.h
@@ -10,18 +10,16 @@
 #include "gc/GCLock.h"
 #include "gc/Heap.h"
 #include "js/RootingAPI.h"
 
 class JSFatInlineString;
 
 namespace js {
 
-struct Class;
-
 // Allocate a new GC thing that's not a JSObject or a string.
 //
 // After a successful allocation the caller must fully initialize the thing
 // before calling any function that can potentially trigger GC. This will ensure
 // that GC tracing never sees junk values stored in the partially initialized
 // thing.
 template <typename T, AllowGC allowGC = CanGC>
 T* Allocate(JSContext* cx);
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -10,17 +10,16 @@
 #include "mozilla/MemoryReporting.h"
 
 #include <stdint.h>
 
 #include "NamespaceImports.h"
 
 namespace js {
 
-struct Class;
 class GlobalObject;
 
 typedef double (*UnaryFunType)(double);
 
 /*
  * JS math functions.
  */
 
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -406,17 +406,16 @@ static_assert(ObjectElements::VALUES_PER
 /*
  * Shared singletons for objects with no elements.
  * emptyObjectElementsShared is used only for TypedArrays, when the TA
  * maps shared memory.
  */
 extern HeapSlot* const emptyObjectElements;
 extern HeapSlot* const emptyObjectElementsShared;
 
-struct Class;
 class AutoCheckShapeConsistency;
 class GCMarker;
 class Shape;
 
 class NewObjectCache;
 
 // Operations which change an object's dense elements can either succeed, fail,
 // or be unable to complete. The latter is used when the object's elements must
--- a/js/src/vm/TypeSet.h
+++ b/js/src/vm/TypeSet.h
@@ -47,17 +47,16 @@ namespace jit {
 struct IonScript;
 class TempAllocator;
 
 }  // namespace jit
 
 class AutoClearTypeInferenceStateOnOOM;
 class AutoSweepBase;
 class AutoSweepObjectGroup;
-struct Class;
 class CompilerConstraintList;
 class HeapTypeSetKey;
 class LifoAlloc;
 class ObjectGroup;
 class SystemAllocPolicy;
 class TypeConstraint;
 class TypeNewScript;
 class TypeZone;
--- a/js/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/xpconnect/idl/nsIXPCScriptable.idl
@@ -9,19 +9,16 @@
 
 %{C++
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 #include "js/TypeDecls.h"
 
-namespace js {
-struct Class;
-}
 %}
 
 interface nsIXPConnectWrappedNative;
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native JSValPtr(JS::Value);
 [ptr] native JSFreeOpPtr(JSFreeOp);
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -24,20 +24,16 @@
 #include "nsHashKeys.h"
 #include "nsTHashtable.h"
 
 class nsCycleCollectionNoteRootCallback;
 class nsIException;
 class nsIRunnable;
 class nsWrapperCache;
 
-namespace js {
-struct Class;
-}  // namespace js
-
 namespace mozilla {
 
 class JSGCThingParticipant : public nsCycleCollectionParticipant {
  public:
   constexpr JSGCThingParticipant() : nsCycleCollectionParticipant(false) {}
 
   NS_IMETHOD_(void) Root(void*) override {
     MOZ_ASSERT(false, "Don't call Root on GC things");