Merge autoland to mozilla-central. a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 15 Aug 2019 22:32:31 +0300
changeset 488247 44aac6fc3352cc6e5d846863778a1d616990c9e7
parent 488154 aab73dbec4586b814066c09f96538f9e7ad235d0 (current diff)
parent 488246 17ef275f8a79eb2c79b618b62587873fe0acd781 (diff)
child 488251 b283a7ef186c216d765631f6cb1260a3fa2ee42c
push id36437
push userncsoregi@mozilla.com
push dateThu, 15 Aug 2019 19:33:18 +0000
treeherdermozilla-central@44aac6fc3352 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
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
Merge autoland to mozilla-central. a=merge
devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js
layout/reftests/mathml/dir-10-ref.html
layout/reftests/mathml/dir-10.html
layout/reftests/mathml/dir-11-ref.html
layout/reftests/mathml/dir-11.html
layout/reftests/mathml/dir-6-ref.html
layout/reftests/mathml/dir-6.html
layout/reftests/mathml/dir-7-ref.html
layout/reftests/mathml/dir-7.html
layout/reftests/mathml/dir-8-ref.html
layout/reftests/mathml/dir-8.html
layout/reftests/mathml/dir-9-ref.html
layout/reftests/mathml/dir-9.html
testing/firefox-ui/tests/functional/security/test_dv_certificate.py
testing/firefox-ui/tests/functional/security/test_ev_certificate.py
testing/firefox-ui/tests/functional/security/test_mixed_content_page.py
testing/firefox-ui/tests/functional/security/test_mixed_script_content_blocking.py
testing/firefox-ui/tests/functional/security/test_no_certificate.py
testing/firefox-ui/tests/functional/security/test_security_notification.py
testing/firefox-ui/tests/functional/security/test_ssl_disabled_error_page.py
testing/firefox-ui/tests/functional/security/test_submit_unencrypted_info_warning.py
testing/firefox-ui/tests/functional/security/test_unknown_issuer.py
testing/firefox-ui/tests/functional/security/test_untrusted_connection_error_page.py
third_party/rust/itertools-0.7.6/.cargo-checksum.json
third_party/rust/itertools-0.7.6/Cargo.toml
third_party/rust/itertools-0.7.6/LICENSE-APACHE
third_party/rust/itertools-0.7.6/LICENSE-MIT
third_party/rust/itertools-0.7.6/Makefile
third_party/rust/itertools-0.7.6/README.rst
third_party/rust/itertools-0.7.6/benches/bench1.rs
third_party/rust/itertools-0.7.6/benches/extra/mod.rs
third_party/rust/itertools-0.7.6/benches/extra/zipslices.rs
third_party/rust/itertools-0.7.6/benches/tuple_combinations.rs
third_party/rust/itertools-0.7.6/benches/tuples.rs
third_party/rust/itertools-0.7.6/custom.css
third_party/rust/itertools-0.7.6/examples/iris.data
third_party/rust/itertools-0.7.6/examples/iris.rs
third_party/rust/itertools-0.7.6/src/adaptors/mod.rs
third_party/rust/itertools-0.7.6/src/adaptors/multi_product.rs
third_party/rust/itertools-0.7.6/src/combinations.rs
third_party/rust/itertools-0.7.6/src/concat_impl.rs
third_party/rust/itertools-0.7.6/src/cons_tuples_impl.rs
third_party/rust/itertools-0.7.6/src/diff.rs
third_party/rust/itertools-0.7.6/src/either_or_both.rs
third_party/rust/itertools-0.7.6/src/format.rs
third_party/rust/itertools-0.7.6/src/free.rs
third_party/rust/itertools-0.7.6/src/groupbylazy.rs
third_party/rust/itertools-0.7.6/src/impl_macros.rs
third_party/rust/itertools-0.7.6/src/intersperse.rs
third_party/rust/itertools-0.7.6/src/kmerge_impl.rs
third_party/rust/itertools-0.7.6/src/lib.rs
third_party/rust/itertools-0.7.6/src/merge_join.rs
third_party/rust/itertools-0.7.6/src/minmax.rs
third_party/rust/itertools-0.7.6/src/multipeek_impl.rs
third_party/rust/itertools-0.7.6/src/pad_tail.rs
third_party/rust/itertools-0.7.6/src/peeking_take_while.rs
third_party/rust/itertools-0.7.6/src/process_results_impl.rs
third_party/rust/itertools-0.7.6/src/put_back_n_impl.rs
third_party/rust/itertools-0.7.6/src/rciter_impl.rs
third_party/rust/itertools-0.7.6/src/repeatn.rs
third_party/rust/itertools-0.7.6/src/size_hint.rs
third_party/rust/itertools-0.7.6/src/sources.rs
third_party/rust/itertools-0.7.6/src/tee.rs
third_party/rust/itertools-0.7.6/src/tuple_impl.rs
third_party/rust/itertools-0.7.6/src/unique_impl.rs
third_party/rust/itertools-0.7.6/src/with_position.rs
third_party/rust/itertools-0.7.6/src/zip_eq_impl.rs
third_party/rust/itertools-0.7.6/src/zip_longest.rs
third_party/rust/itertools-0.7.6/src/ziptuple.rs
third_party/rust/itertools-0.7.6/tests/merge_join.rs
third_party/rust/itertools-0.7.6/tests/peeking_take_while.rs
third_party/rust/itertools-0.7.6/tests/quick.rs
third_party/rust/itertools-0.7.6/tests/test_core.rs
third_party/rust/itertools-0.7.6/tests/test_std.rs
third_party/rust/itertools-0.7.6/tests/tuples.rs
third_party/rust/itertools-0.7.6/tests/zip.rs
toolkit/components/telemetry/histogram-whitelists.json
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1507,24 +1507,16 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itertools"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "itertools"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itoa"
@@ -2981,17 +2973,17 @@ dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
@@ -4040,17 +4032,16 @@ dependencies = [
 "checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1"
 "checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "663a975007e0b49903e2e8ac0db2c432c465855f2d65f17883ba1476e85f0b42"
 "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220"
 "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
 "checksum input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf"
 "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
-"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
 "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
 "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
 "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
 "checksum libdbus-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "18cb88963258d00f4962205dbb5933d82780d9962c8c8a064b651d2ad7189210"
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -75,18 +75,18 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eReadonlyUntilEditable
   },
   { // banner
     nsGkAtoms::banner,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // blockquote
     nsGkAtoms::blockquote,
@@ -161,28 +161,28 @@ static const nsRoleMapEntry sWAIRoleMaps
     eCombobox,
     states::COLLAPSED | states::HASPOPUP,
     eARIAAutoComplete,
     eARIAReadonly,
     eARIAOrientation
   },
   { // complementary
     nsGkAtoms::complementary,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // contentinfo
     nsGkAtoms::contentinfo,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // dialog
     nsGkAtoms::dialog,
@@ -783,18 +783,18 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
   { // main
     nsGkAtoms::main,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // marquee
     nsGkAtoms::marquee,
@@ -870,18 +870,18 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIACheckableBool,
     eARIAReadonly
   },
   { // navigation
     nsGkAtoms::navigation,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // none
     nsGkAtoms::none,
@@ -1020,18 +1020,18 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoLiveAttr,
     kGenericAccType,
     states::VERTICAL,
     eARIAOrientation,
     eARIAReadonly
   },
   { // search
     nsGkAtoms::search,
-    roles::NOTHING,
-    kUseNativeRole,
+    roles::LANDMARK,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // searchbox
     nsGkAtoms::searchbox,
--- a/accessible/base/TreeWalker.cpp
+++ b/accessible/base/TreeWalker.cpp
@@ -23,18 +23,17 @@ using namespace mozilla::a11y;
 TreeWalker::TreeWalker(Accessible* aContext)
     : mDoc(aContext->Document()),
       mContext(aContext),
       mAnchorNode(nullptr),
       mARIAOwnsIdx(0),
       mChildFilter(nsIContent::eSkipPlaceholderContent),
       mFlags(0),
       mPhase(eAtStart) {
-  mChildFilter |=
-      mContext->NoXBLKids() ? nsIContent::eAllButXBL : nsIContent::eAllChildren;
+  mChildFilter |= nsIContent::eAllChildren;
 
   mAnchorNode = mContext->IsDoc() ? mDoc->DocumentNode()->GetRootElement()
                                   : mContext->GetContent();
 
   MOZ_COUNT_CTOR(TreeWalker);
 }
 
 TreeWalker::TreeWalker(Accessible* aContext, nsIContent* aAnchorNode,
@@ -45,18 +44,17 @@ TreeWalker::TreeWalker(Accessible* aCont
       mARIAOwnsIdx(0),
       mChildFilter(nsIContent::eSkipPlaceholderContent),
       mFlags(aFlags),
       mPhase(eAtStart) {
   MOZ_ASSERT(mFlags & eWalkCache,
              "This constructor cannot be used for tree creation");
   MOZ_ASSERT(aAnchorNode, "No anchor node for the accessible tree walker");
 
-  mChildFilter |=
-      mContext->NoXBLKids() ? nsIContent::eAllButXBL : nsIContent::eAllChildren;
+  mChildFilter |= nsIContent::eAllChildren;
 
   MOZ_COUNT_CTOR(TreeWalker);
 }
 
 TreeWalker::TreeWalker(DocAccessible* aDocument, nsIContent* aAnchorNode)
     : mDoc(aDocument),
       mContext(nullptr),
       mAnchorNode(aAnchorNode),
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -922,22 +922,16 @@ class Accessible : public nsISupports {
   void SetRelocated(bool aRelocated) {
     if (aRelocated)
       mStateFlags |= eRelocated;
     else
       mStateFlags &= ~eRelocated;
   }
 
   /**
-   * Return true if the accessible doesn't allow accessible children from XBL
-   * anonymous subtree.
-   */
-  bool NoXBLKids() const { return mStateFlags & eNoXBLKids; }
-
-  /**
    * Return true if the accessible allows accessible children from subtree of
    * a DOM element of this accessible.
    */
   bool KidsFromDOM() const { return !(mStateFlags & eNoKidsFromDOM); }
 
   /**
    * Return true if this accessible has a parent whose name depends on this
    * accessible.
@@ -1032,21 +1026,20 @@ class Accessible : public nsISupports {
     eIsNotInDocument = 1 << 1,  // accessible is not in document
     eSharedNode = 1 << 2,  // accessible shares DOM node from another accessible
     eNotNodeMapEntry = 1 << 3,   // accessible shouldn't be in document node map
     eHasNumericValue = 1 << 4,   // accessible has a numeric value
     eGroupInfoDirty = 1 << 5,    // accessible needs to update group info
     eKidsMutating = 1 << 6,      // subtree is being mutated
     eIgnoreDOMUIEvent = 1 << 7,  // don't process DOM UI events for a11y events
     eRelocated = 1 << 8,         // accessible was moved in tree
-    eNoXBLKids = 1 << 9,         // accessible don't allows XBL children
-    eNoKidsFromDOM = 1 << 10,    // accessible doesn't allow children from DOM
-    eHasTextKids = 1 << 11,      // accessible have a text leaf in children
+    eNoKidsFromDOM = 1 << 9,    // accessible doesn't allow children from DOM
+    eHasTextKids = 1 << 10,      // accessible have a text leaf in children
 
-    eLastStateFlag = eNoKidsFromDOM
+    eLastStateFlag = eHasTextKids
   };
 
   /**
    * Flags used for contextual information about the accessible.
    */
   enum ContextFlags {
     eHasNameDependentParent =
         1 << 0,  // Parent's name depends on this accessible.
@@ -1140,17 +1133,17 @@ class Accessible : public nsISupports {
   // Data Members
   nsCOMPtr<nsIContent> mContent;
   RefPtr<DocAccessible> mDoc;
 
   Accessible* mParent;
   nsTArray<Accessible*> mChildren;
   int32_t mIndexInParent;
 
-  static const uint8_t kStateFlagsBits = 12;
+  static const uint8_t kStateFlagsBits = 11;
   static const uint8_t kContextFlagsBits = 2;
   static const uint8_t kTypeBits = 6;
   static const uint8_t kGenericTypesBits = 16;
 
   /**
    * Non-NO_ROLE_MAP_ENTRY_INDEX indicates author-supplied role;
    * possibly state & value as well
    */
--- a/accessible/html/HTMLListAccessible.cpp
+++ b/accessible/html/HTMLListAccessible.cpp
@@ -33,18 +33,17 @@ uint64_t HTMLListAccessible::NativeState
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLLIAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLLIAccessible::HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc)
     : HyperTextAccessibleWrap(aContent, aDoc), mBullet(nullptr) {
   mType = eHTMLLiType;
 
-  nsIContent* marker = nsLayoutUtils::GetMarkerPseudo(aContent);
-  if (marker && marker->GetPrimaryFrame()) {
+  if (nsLayoutUtils::GetMarkerFrame(aContent)) {
     mBullet = new HTMLListBulletAccessible(mContent, mDoc);
     Document()->BindToDocument(mBullet, nullptr);
     AppendChild(mBullet);
   }
 }
 
 void HTMLLIAccessible::Shutdown() {
   mBullet = nullptr;
@@ -114,18 +113,17 @@ HTMLListBulletAccessible::HTMLListBullet
   mGenericTypes |= eText;
   mStateFlags |= eSharedNode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLListBulletAccessible: Accessible
 
 nsIFrame* HTMLListBulletAccessible::GetFrame() const {
-  nsIContent* marker = nsLayoutUtils::GetMarkerPseudo(mContent);
-  return marker ? marker->GetPrimaryFrame() : nullptr;
+  return nsLayoutUtils::GetMarkerFrame(mContent);
 }
 
 ENameValueFlag HTMLListBulletAccessible::Name(nsString& aName) const {
   aName.Truncate();
 
   // Native anonymous content, ARIA can't be used. Get list bullet text.
   if (nsContainerFrame* frame = do_QueryFrame(mContent->GetPrimaryFrame())) {
     frame->GetSpokenMarkerText(aName);
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -82,17 +82,17 @@
       testRole("aria_treegrid", ROLE_TREE_TABLE);
       testRole("aria_treeitem", ROLE_OUTLINEITEM);
 
       // Note:
       // The phrase "weak foo" here means that there is no good foo-to-platform
       // role mapping. Similarly "strong foo" means there is a good foo-to-
       // platform role mapping.
 
-      testRole("articlemain", ROLE_ARTICLE);
+      testRole("articlemain", ROLE_LANDMARK);
       testRole("articleform", ROLE_FORM);
 
       // Test article exposed as article
       testRole("testArticle", ROLE_ARTICLE);
 
       // weak roles that are forms of "live regions"
       testRole("log_table", ROLE_TABLE);
       testRole("timer_div", ROLE_SECTION);
@@ -100,27 +100,28 @@
       // other roles that are forms of "live regions"
       testRole("marquee_h1", ROLE_ANIMATION);
 
       // strong landmark
       testRole("application", ROLE_APPLICATION);
       testRole("form", ROLE_FORM);
       testRole("application_table", ROLE_APPLICATION);
 
-      // weak landmarks
-      var weak_landmarks = ["banner", "complementary", "contentinfo",
+      // landmarks
+      let landmarks = ["banner", "complementary", "contentinfo",
           "main", "navigation", "search"];
-      for (l in weak_landmarks)
-        testRole(weak_landmarks[l], ROLE_SECTION);
+      for (l in landmarks) {
+        testRole(landmarks[l], ROLE_LANDMARK);
+      }
 
-      for (l in weak_landmarks) {
-        var id = weak_landmarks[l] + "_table";
-        testRole(id, ROLE_TABLE);
+      for (l in landmarks) {
+        let id = landmarks[l] + "_table";
+        testRole(id, ROLE_LANDMARK);
     
-        var accessibleTable = getAccessible(id, [nsIAccessibleTable], null,
+        let accessibleTable = getAccessible(id, [nsIAccessibleTable], null,
                                             DONOTFAIL_IF_NO_INTERFACE);
         ok(!!accessibleTable, "landmarked table should have nsIAccessibleTable");
     
         if (accessibleTable)
           is(accessibleTable.getCellAt(0, 0).firstChild.name, "hi", "no cell");
       }
 
       // ////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -211,21 +211,22 @@
       // strong landmark
       testStates("aria_application_link", 0, 0, STATE_LINKED);
       testStates("aria_application_anchor", 0, 0, STATE_SELECTABLE);
 
       // strange cases
       testStates("aria_link_link", STATE_LINKED);
       testStates("aria_link_anchor", STATE_SELECTABLE);
 
-      // some weak landmarks
-      testStates("aria_main_link", STATE_LINKED);
-      testStates("aria_navigation_link", STATE_LINKED);
-      testStates("aria_main_anchor", STATE_SELECTABLE);
-      testStates("aria_navigation_anchor", STATE_SELECTABLE);
+      // some landmarks that break accessibility for these native elements
+      // Note that these are illegal uses by web authors as per WAI-ARIA in HTML
+      testStates("aria_main_link", 0, 0, STATE_LINKED);
+      testStates("aria_navigation_link", 0, 0, STATE_LINKED);
+      testStates("aria_main_anchor", 0, 0, STATE_SELECTABLE);
+      testStates("aria_navigation_anchor", 0, 0, STATE_SELECTABLE);
 
       // aria-orientation
       testStates("aria_combobox", 0, 0, 0, EXT_STATE_HORIZONTAL | EXT_STATE_VERTICAL);
       testStates("aria_hcombobox", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_vcombobox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_listbox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
       testStates("aria_hlistbox", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL);
       testStates("aria_vlistbox", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
--- a/accessible/tests/mochitest/states/test_doc.html
+++ b/accessible/tests/mochitest/states/test_doc.html
@@ -18,17 +18,17 @@
     function doTest() {
       // Bug 566542: root accesible should expose active state when focused.
       testStates(getRootAccessible(), 0, EXT_STATE_ACTIVE);
 
       // Bug 509696, 607219.
       testStates(document, STATE_READONLY, 0); // role=""
 
       document.body.setAttribute("role", "banner"); // no platform mapping
-      testStates(document, STATE_READONLY);
+      testStates(document, 0, 0, STATE_READONLY);
       document.body.setAttribute("role", "foo"); // bogus role
       testStates(document, STATE_READONLY);
       document.body.removeAttribute("role");
       testStates(document, STATE_READONLY);
 
       // Bugs 454997 and 467387
       testStates(document, STATE_READONLY);
       testStates("document", STATE_READONLY);
--- a/accessible/tests/mochitest/value/test_general.html
+++ b/accessible/tests/mochitest/value/test_general.html
@@ -34,21 +34,21 @@
 
       var href = getRootDirectory(window.location.href) + "foo";
 
       // roles that can't live as HTMLLinkAccessibles
       testValue("aria_menuitem_link", "");
       testValue("aria_button_link", "");
       testValue("aria_checkbox_link", "");
       testValue("aria_application_link", "");
+      testValue("aria_main_link", "");
+      testValue("aria_navigation_link", "");
 
       // roles that can live as HTMLLinkAccessibles
       testValue("aria_link_link", href);
-      testValue("aria_main_link", href);
-      testValue("aria_navigation_link", href);
 
       // ////////////////////////////////////////////////////////////////////////
       // ARIA textboxes
 
       testValue("aria_textbox1", "helo");
 
       // ////////////////////////////////////////////////////////////////////////
       // ARIA comboboxes
--- a/accessible/xul/XULComboboxAccessible.cpp
+++ b/accessible/xul/XULComboboxAccessible.cpp
@@ -25,23 +25,16 @@ using namespace mozilla::a11y;
 XULComboboxAccessible::XULComboboxAccessible(nsIContent* aContent,
                                              DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {
   if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                          nsGkAtoms::autocomplete, eIgnoreCase))
     mGenericTypes |= eAutoComplete;
   else
     mGenericTypes |= eCombobox;
-
-  // The XUL <textbox type="autocomplete"> uses XULComboboxAccessible. We need
-  // to walk the anonymous children for these so that the entry field is a
-  // child. Otherwise no XBL children.
-  if (!mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL)) {
-    mStateFlags |= eNoXBLKids;
-  }
 }
 
 role XULComboboxAccessible::NativeRole() const {
   return IsAutoComplete() ? roles::AUTOCOMPLETE : roles::COMBOBOX;
 }
 
 uint64_t XULComboboxAccessible::NativeState() const {
   // As a nsComboboxAccessible we can have the following states:
--- a/accessible/xul/XULListboxAccessible.cpp
+++ b/accessible/xul/XULListboxAccessible.cpp
@@ -432,20 +432,16 @@ Accessible* XULListboxAccessible::Contai
 ////////////////////////////////////////////////////////////////////////////////
 
 XULListitemAccessible::XULListitemAccessible(nsIContent* aContent,
                                              DocAccessible* aDoc)
     : XULMenuitemAccessible(aContent, aDoc) {
   mIsCheckbox = mContent->AsElement()->AttrValueIs(
       kNameSpaceID_None, nsGkAtoms::type, nsGkAtoms::checkbox, eCaseMatters);
   mType = eXULListItemType;
-
-  // Walk XBL anonymous children for list items. Overrides the flag value from
-  // base XULMenuitemAccessible class.
-  mStateFlags &= ~eNoXBLKids;
 }
 
 XULListitemAccessible::~XULListitemAccessible() {}
 
 Accessible* XULListitemAccessible::GetListAccessible() const {
   if (IsDefunct()) return nullptr;
 
   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
--- a/accessible/xul/XULMenuAccessible.cpp
+++ b/accessible/xul/XULMenuAccessible.cpp
@@ -32,17 +32,16 @@ using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULMenuitemAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULMenuitemAccessible::XULMenuitemAccessible(nsIContent* aContent,
                                              DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {
-  mStateFlags |= eNoXBLKids;
 }
 
 uint64_t XULMenuitemAccessible::NativeState() const {
   uint64_t state = Accessible::NativeState();
 
   // Has Popup?
   if (mContent->NodeInfo()->Equals(nsGkAtoms::menu, kNameSpaceID_XUL)) {
     state |= states::HASPOPUP;
@@ -346,18 +345,16 @@ XULMenupopupAccessible::XULMenupopupAcce
       parent && parent->AsElement() ? parent->AsElement()->AsXULSelectControl()
                                     : nullptr;
   if (selectControl) {
     mSelectControl = parent->AsElement();
   } else {
     mSelectControl = nullptr;
     mGenericTypes &= ~eSelect;
   }
-
-  mStateFlags |= eNoXBLKids;
 }
 
 uint64_t XULMenupopupAccessible::NativeState() const {
   uint64_t state = Accessible::NativeState();
 
 #ifdef DEBUG
   // We are onscreen if our parent is active
   bool isActive =
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1608,18 +1608,20 @@ pref("browser.contentblocking.customBloc
 
 pref("browser.contentblocking.reportBreakage.url", "https://tracking-protection-issues.herokuapp.com/new");
 
 // Enable Protections report's Lockwise card by default.
 pref("browser.contentblocking.report.lockwise.enabled", true);
 
 // Enable Protections report's Monitor card by default.
 pref("browser.contentblocking.report.monitor.enabled", true);
+
 pref("browser.contentblocking.report.monitor.url", "https://monitor.firefox.com");
 pref("browser.contentblocking.report.lockwise.url", "https://lockwise.firefox.com/");
+pref("browser.contentblocking.report.manage_devices.url", "https://accounts.firefox.com/settings/clients");
 
 // Protection Report's SUMO urls
 pref("browser.contentblocking.report.monitor.how_it_works.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/monitor-faq");
 pref("browser.contentblocking.report.lockwise.how_it_works.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/password-manager-report");
 pref("browser.contentblocking.report.social.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/social-media-tracking-report");
 pref("browser.contentblocking.report.cookie.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/cross-site-tracking-report");
 pref("browser.contentblocking.report.tracker.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/tracking-content-report");
 pref("browser.contentblocking.report.fingerprinter.url", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/fingerprinters-report");
--- a/browser/base/content/test/performance/browser.ini
+++ b/browser/base/content/test/performance/browser.ini
@@ -2,17 +2,16 @@
 # to avoid overhead when running the browser normally, startupRecorder.js will
 # do almost nothing unless browser.startup.record is true.
 # gfx.canvas.willReadFrequently.enable is just an optimization, but needs to be
 # set during early startup to have an impact as a canvas will be used by
 # startupRecorder.js
 prefs =
   # Skip migration work in BG__migrateUI for browser_startup.js since it isn't
   # representative of common startup.
-  browser.messaging-system.fxatoolbarbadge.enabled=false # Bug 1570336
   browser.migration.version=9999999
   browser.startup.record=true
   gfx.canvas.willReadFrequently.enable=true
   # The form autofill framescript is only used in certain locales if this
   # pref is set to 'detect', which is the default value on non-Nightly.
   extensions.formautofill.available='on'
 support-files =
   head.js
--- a/browser/base/content/test/performance/browser_tabopen.js
+++ b/browser/base/content/test/performance/browser_tabopen.js
@@ -31,16 +31,19 @@ add_task(async function() {
 
   let tabStripRect = gBrowser.tabContainer.arrowScrollbox.getBoundingClientRect();
   let firstTabRect = gBrowser.selectedTab.getBoundingClientRect();
   let firstTabLabelRect = gBrowser.selectedTab.textLabel.getBoundingClientRect();
   let textBoxRect = gURLBar
     .querySelector("moz-input-box")
     .getBoundingClientRect();
   let historyDropmarkerRect = gURLBar.dropmarker.getBoundingClientRect();
+  let fxaAccountsButton = document
+    .getElementById("fxa-toolbar-menu-button")
+    .getBoundingClientRect();
 
   let inRange = (val, min, max) => min <= val && val <= max;
 
   // Add a reflow observer and open a new tab.
   await withPerfObserver(
     async function() {
       let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone");
       BrowserOpenTab();
@@ -123,16 +126,25 @@ add_task(async function() {
           {
             name: "bug 1547341 - addressbar history dropmarker is shown",
             condition: r =>
               r.x1 >= historyDropmarkerRect.x &&
               r.x2 <= historyDropmarkerRect.right &&
               r.y1 >= historyDropmarkerRect.y &&
               r.y2 <= historyDropmarkerRect.bottom,
           },
+          {
+            name:
+              "FxA accounts button is intentionally badged 10s after startup",
+            condition: r =>
+              r.x1 >= fxaAccountsButton.left &&
+              r.x2 <= fxaAccountsButton.right &&
+              r.y1 >= fxaAccountsButton.top &&
+              r.y2 <= fxaAccountsButton.bottom,
+          },
         ],
       },
     }
   );
 
   let switchDone = BrowserTestUtils.waitForEvent(window, "TabSwitchDone");
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
   await switchDone;
--- a/browser/base/content/test/performance/browser_windowopen.js
+++ b/browser/base/content/test/performance/browser_windowopen.js
@@ -50,16 +50,19 @@ add_task(async function() {
     AppConstants.BROWSER_CHROME_URL,
     "_blank",
     "chrome,all,dialog=no,remote,suppressanimation",
     "about:home"
   );
 
   let alreadyFocused = false;
   let inRange = (val, min, max) => min <= val && val <= max;
+  let fxaAccountsButton = document
+    .getElementById("fxa-toolbar-menu-button")
+    .getBoundingClientRect();
   let expectations = {
     expectedReflows: EXPECTED_REFLOWS,
     frames: {
       filter(rects, frame, previousFrame) {
         // The first screenshot we get in OSX / Windows shows an unfocused browser
         // window for some reason. See bug 1445161.
         if (!alreadyFocused && isLikelyFocusChange(rects)) {
           alreadyFocused = true;
@@ -97,16 +100,24 @@ add_task(async function() {
                 (AppConstants.platform == "linux" && AppConstants.ASAN)) &&
               r.x1 >= inputFieldRect.left &&
               r.x2 <= inputFieldRect.right &&
               r.y1 >= inputFieldRect.top &&
               r.y2 <= inputFieldRect.bottom
             );
           },
         },
+        {
+          name: "FxA accounts button is intentionally badged 10s after startup",
+          condition: r =>
+            r.x1 >= fxaAccountsButton.left &&
+            r.x2 <= fxaAccountsButton.right &&
+            r.y1 >= fxaAccountsButton.top &&
+            r.y2 <= fxaAccountsButton.bottom,
+        },
       ],
     },
   };
 
   await withPerfObserver(
     async function() {
       // Avoid showing the remotecontrol UI.
       await new Promise(resolve => {
--- a/browser/components/protections/content/lockwise-card.js
+++ b/browser/components/protections/content/lockwise-card.js
@@ -3,16 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env mozilla/frame-script */
 
 const LOCKWISE_URL = RPMGetStringPref(
   "browser.contentblocking.report.lockwise.url",
   ""
 );
+const MANAGE_DEVICES_URL = RPMGetStringPref(
+  "browser.contentblocking.report.manage_devices.url",
+  ""
+);
 const HOW_IT_WORKS_URL_PREF = RPMGetFormatURLPref(
   "browser.contentblocking.report.lockwise.how_it_works.url"
 );
 
 export default class LockwiseCard {
   constructor(document) {
     this.doc = document;
   }
@@ -144,11 +148,15 @@ export default class LockwiseCard {
       textEl.setAttribute("data-l10n-id", "lockwise-sync-status");
     } else {
       textEl.setAttribute("data-l10n-id", "lockwise-sync-not-syncing");
     }
     // Display the link for enabling sync if no synced devices are detected.
     if (syncedDevices === 0) {
       const syncLink = this.doc.getElementById("turn-on-sync");
       syncLink.classList.remove("hidden");
+    } else {
+      const manageDevicesLink = this.doc.getElementById("manage-devices");
+      manageDevicesLink.href = MANAGE_DEVICES_URL;
+      manageDevicesLink.classList.remove("hidden");
     }
   }
 }
--- a/browser/components/protections/content/protections.html
+++ b/browser/components/protections/content/protections.html
@@ -31,62 +31,62 @@
             <p class="content" data-l10n-id="etp-card-content"></p>
             <p id="protection-details" role="link" tabindex="0" data-l10n-title="go-to-privacy-settings"></p>
           </div>
         </div>
         <div class="card-body">
           <div class="body-wrapper">
             <p id="graph-week-summary"></p>
             <div id="graph-wrapper">
-              <div id="graph" role="table"></div>
+              <div id="graph" role="table" aria-labelledby="graphLegendDescription"></div>
               <div id="legend">
                 <label id="graphLegendDescription" data-l10n-id="graph-legend-description"></label>
-                <input id="tab-social" data-type="social" type="radio" name="tabs" aria-describedby="socialTitle" checked>
-                <label for="tab-social" data-type="social"></label>
+                <input id="tab-social" data-type="social" type="radio" name="tabs" aria-labelledby="socialLabel socialTitle" aria-describedby="socialContent" checked>
+                <label id="socialLabel" for="tab-social" data-type="social"></label>
 
-                <input id="tab-cookie" data-type="cookie" type="radio" name="tabs" aria-describedby="cookieTitle">
-                <label for="tab-cookie" data-type="cookie"></label>
+                <input id="tab-cookie" data-type="cookie" type="radio" name="tabs" aria-labelledby="cookieLabel cookieTitle" aria-describedby="cookieContent">
+                <label id="cookieLabel" for="tab-cookie" data-type="cookie"></label>
 
-                <input id="tab-tracker" data-type="tracker" type="radio" name="tabs" aria-describedby="trackerTitle">
-                <label for="tab-tracker" data-type="tracker"></label>
+                <input id="tab-tracker" data-type="tracker" type="radio" name="tabs" aria-labelledby="trackerLabel trackerTitle" aria-describedby="trackerContent">
+                <label id="trackerLabel" for="tab-tracker" data-type="tracker"></label>
 
-                <input id="tab-fingerprinter" data-type="fingerprinter" type="radio" name="tabs" aria-describedby="fingerprinterTitle">
-                <label for="tab-fingerprinter" data-type="fingerprinter"></label>
+                <input id="tab-fingerprinter" data-type="fingerprinter" type="radio" name="tabs" aria-labelledby="fingerprinterLabel fingerprinterTitle" aria-describedby="fingerprinterContent">
+                <label id="fingerprinterLabel" for="tab-fingerprinter" data-type="fingerprinter"></label>
 
-                <input id="tab-cryptominer" data-type="cryptominer" type="radio" name="tabs" aria-describedby="cryptominerTitle">
-                <label for="tab-cryptominer" data-type="cryptominer"></label>
+                <input id="tab-cryptominer" data-type="cryptominer" type="radio" name="tabs" aria-labelledby="cryptominerLabel cryptominerTitle" aria-describedby="cryptominerContent">
+                <label id="cryptominerLabel" for="tab-cryptominer" data-type="cryptominer"></label>
                 <div id=highlight></div>
                 <div id=highlight-hover></div>
                 <div id="social" class="tab-content">
                   <p id="socialTitle" class="content-title" data-l10n-id="social-tab-title"></p>
-                  <p data-l10n-id="social-tab-contant">
+                  <p id="socialContent" data-l10n-id="social-tab-contant">
                     <a target="_blank" id="social-link" data-l10n-name="learn-more-link"></a>
                   </p>
                 </div>
                 <div id="cookie" class="tab-content">
                   <p id="cookieTitle" class="content-title" data-l10n-id="cookie-tab-title"></p>
-                  <p data-l10n-id="cookie-tab-content">
+                  <p id="cookieContent" data-l10n-id="cookie-tab-content">
                     <a target="_blank" id="cookie-link" data-l10n-name="learn-more-link"></a>
                   </p>
                 </div>
                 <div id="tracker" class="tab-content">
                   <p id="trackerTitle" class="content-title" data-l10n-id="tracker-tab-title"></p>
-                  <p data-l10n-id="tracker-tab-content">
+                  <p id="trackerContent" data-l10n-id="tracker-tab-content">
                     <a target="_blank" id="tracker-link" data-l10n-name="learn-more-link"></a>
                   </p>
                 </div>
                 <div id="fingerprinter" class="tab-content">
                   <p id="fingerprinterTitle" class="content-title" data-l10n-id="fingerprinter-tab-title"></p>
-                  <p data-l10n-id="fingerprinter-tab-content">
+                  <p id="fingerprinterContent" data-l10n-id="fingerprinter-tab-content">
                     <a target="_blank" id="fingerprinter-link" data-l10n-name="learn-more-link"></a>
                   </p>
                 </div>
                 <div id="cryptominer" class="tab-content">
                   <p id="cryptominerTitle" class="content-title" data-l10n-id="cryptominer-tab-title"></p>
-                  <p data-l10n-id="cryptominer-tab-content">
+                  <p id="cryptominerContent" data-l10n-id="cryptominer-tab-content">
                     <a target="_blank" id="cryptominer-link" data-l10n-name="learn-more-link"></a>
                   </p>
                 </div>
               </div>
             </div>
             <div id="graph-total-summary"></div>
           </div>
         </div>
@@ -187,16 +187,17 @@
               <span class="number-of-synced-devices block">
                 <!-- Display number of synced devices here. -->
               </span>
               <span class="inline-text-icon synced-devices-text">
                 <span>
                   <!-- Display message for status of synced devices here. -->
                 </span>
                 <a id="turn-on-sync" tabindex="0" class="hidden" href="" data-l10n-id="turn-on-sync"></a>
+                <a id="manage-devices" target="_blank" class="hidden" href="" data-l10n-id="manage-devices"></a>
               </span>
             </div>
           </div>
         </div>
       </section>
     </div>
   </body>
 </html>
--- a/browser/components/protections/test/browser/browser_protections_lockwise.js
+++ b/browser/components/protections/test/browser/browser_protections_lockwise.js
@@ -99,16 +99,17 @@ add_task(async function() {
       ".number-of-logins.block"
     );
     const numberOfSyncedDevices = hasLoginsContent.querySelector(
       ".number-of-synced-devices.block"
     );
     const syncedDevicesStatusText = content.document.querySelector(
       ".synced-devices-text span"
     );
+    const syncLink = content.document.getElementById("turn-on-sync");
 
     ok(
       ContentTaskUtils.is_hidden(noLoginsContent),
       "Content for user with no logins is hidden."
     );
     ok(
       ContentTaskUtils.is_visible(hasLoginsContent),
       "Content for user with logins is shown."
@@ -121,16 +122,19 @@ add_task(async function() {
       0,
       "Zero synced devices are displayed."
     );
     is(
       syncedDevicesStatusText.getAttribute("data-l10n-id"),
       "lockwise-sync-not-syncing",
       "Not syncing to other devices."
     );
+
+    info("Check that the link to turn on sync is visible.");
+    ok(ContentTaskUtils.is_visible(syncLink), "Sync link is visible.");
   });
 
   info(
     "Add another login and check the number of stored logins is updated after reload."
   );
   Services.logins.addLogin(TEST_LOGIN2);
   await reloadTab(tab);
 
@@ -159,22 +163,28 @@ add_task(async function() {
         "#lockwise-body-content .has-logins"
       );
       return ContentTaskUtils.is_visible(hasLogins);
     }, "Lockwise card for user with logins is shown.");
 
     const numberOfSyncedDevices = content.document.querySelector(
       ".number-of-synced-devices.block"
     );
+    const manageDevicesLink = content.document.getElementById("manage-devices");
 
     is(
       numberOfSyncedDevices.textContent,
       5,
       "Five synced devices should be displayed"
     );
+    info("Check that the link to manage devices is visible.");
+    ok(
+      ContentTaskUtils.is_visible(manageDevicesLink),
+      "Manage devices link is visible."
+    );
   });
 
   info("Disable showing the Lockwise card.");
   Services.prefs.setBoolPref(
     "browser.contentblocking.report.lockwise.enabled",
     false
   );
   await reloadTab(tab);
--- a/browser/components/protections/test/browser/browser_protections_report_ui.js
+++ b/browser/components/protections/test/browser/browser_protections_report_ui.js
@@ -200,16 +200,21 @@ add_task(async function test_graph_displ
       "table",
       "Graph is an accessible table"
     );
     is(
       content.document.getElementById("graph").getAttribute("aria-colcount"),
       DATA_TYPES.length + 2,
       "Table has the right number of columns"
     );
+    is(
+      content.document.getElementById("graph").getAttribute("aria-labelledby"),
+      "graphLegendDescription",
+      "Table has an accessible label"
+    );
 
     // today has each type
     // yesterday will have no tracking cookies
     // 2 days ago will have no fingerprinters
     // 3 days ago will have no cryptominers
     // 4 days ago will have no trackers
     // 5 days ago will have no social (when we add social)
     // 6 days ago will be empty
@@ -386,53 +391,79 @@ add_task(async function test_graph_displ
     );
     ok(allBars[0].classList.contains("empty"), "6 days ago is an empty bar");
     is(
       allBars[0].getAttribute("aria-owns"),
       "day6 ",
       "Row has the columns in the right order"
     );
 
-    // Check that each tab has the correct aria-describedby value. This helps screen readers
-    // know what type of tracker the reported tab number is referencing.
+    // Check that each tab has the correct aria-labelledby and aria-describedby
+    // values. This helps screen readers know what type of tracker the reported
+    // tab number is referencing.
     const socialTab = content.document.getElementById("tab-social");
     is(
+      socialTab.getAttribute("aria-labelledby"),
+      "socialLabel socialTitle",
+      "aria-labelledby attribute is socialLabel socialTitle"
+    );
+    is(
       socialTab.getAttribute("aria-describedby"),
-      "socialTitle",
-      "aria-describedby attribute is socialTitle"
+      "socialContent",
+      "aria-describedby attribute is socialContent"
     );
 
     const cookieTab = content.document.getElementById("tab-cookie");
     is(
+      cookieTab.getAttribute("aria-labelledby"),
+      "cookieLabel cookieTitle",
+      "aria-labelledby attribute is cookieLabel cookieTitle"
+    );
+    is(
       cookieTab.getAttribute("aria-describedby"),
-      "cookieTitle",
-      "aria-describedby attribute is cookieTitle"
+      "cookieContent",
+      "aria-describedby attribute is cookieContent"
     );
 
     const trackerTab = content.document.getElementById("tab-tracker");
     is(
+      trackerTab.getAttribute("aria-labelledby"),
+      "trackerLabel trackerTitle",
+      "aria-labelledby attribute is trackerLabel trackerTitle"
+    );
+    is(
       trackerTab.getAttribute("aria-describedby"),
-      "trackerTitle",
-      "aria-describedby attribute is trackerTitle"
+      "trackerContent",
+      "aria-describedby attribute is trackerContent"
     );
 
     const fingerprinterTab = content.document.getElementById(
       "tab-fingerprinter"
     );
     is(
+      fingerprinterTab.getAttribute("aria-labelledby"),
+      "fingerprinterLabel fingerprinterTitle",
+      "aria-labelledby attribute is fingerprinterLabel fingerprinterTitle"
+    );
+    is(
       fingerprinterTab.getAttribute("aria-describedby"),
-      "fingerprinterTitle",
-      "aria-describedby attribute is fingerprinterTitle"
+      "fingerprinterContent",
+      "aria-describedby attribute is fingerprinterContent"
     );
 
     const cryptominerTab = content.document.getElementById("tab-cryptominer");
     is(
+      cryptominerTab.getAttribute("aria-labelledby"),
+      "cryptominerLabel cryptominerTitle",
+      "aria-labelledby attribute is cryptominerLabel cryptominerTitle"
+    );
+    is(
       cryptominerTab.getAttribute("aria-describedby"),
-      "cryptominerTitle",
-      "aria-describedby attribute is cryptominerTitle"
+      "cryptominerContent",
+      "aria-describedby attribute is cryptominerContent"
     );
   });
 
   // Use the TrackingDBService API to delete the data.
   await TrackingDBService.clearAll();
   // Make sure the data was deleted.
   let rows = await db.execute(SQL.selectAll);
   is(rows.length, 0, "length is 0");
--- a/browser/locales/en-US/browser/protections.ftl
+++ b/browser/locales/en-US/browser/protections.ftl
@@ -68,16 +68,18 @@ lockwise-passwords-stored =
   { $count ->
      [one] Password stored securely <a data-l10n-name="lockwise-how-it-works">How it works</a>
     *[other] Passwords stored securely <a data-l10n-name="lockwise-how-it-works">How it works</a>
   }
 
 turn-on-sync = Turn on { -sync-brand-short-name }…
   .title = Go to sync preferences
 
+manage-devices = Manage devices
+
 # Variables:
 #   $count (Number) - Number of devices connected with sync.
 lockwise-sync-status =
   { $count ->
      [one] Syncing to { $count } other device
     *[other] Syncing to { $count } other devices
   }
 lockwise-sync-not-syncing = Not syncing to other devices.
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -671,34 +671,23 @@ nsScriptSecurityManager::CheckLoadURIWit
     return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
   }
 
   //-- get the source scheme
   nsAutoCString sourceScheme;
   rv = sourceBaseURI->GetScheme(sourceScheme);
   if (NS_FAILED(rv)) return rv;
 
-  // When comparing schemes, if the relevant pref is set, view-source URIs
-  // are reachable from same-protocol (so e.g. file: can link to
-  // view-source:file). This is required for reftests.
-  static bool sViewSourceReachableFromInner = false;
-  static bool sCachedViewSourcePref = false;
-  if (!sCachedViewSourcePref) {
-    sCachedViewSourcePref = true;
-    mozilla::Preferences::AddBoolVarCache(
-        &sViewSourceReachableFromInner,
-        "security.view-source.reachable-from-inner-protocol");
-  }
-
   if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
     // A null principal can target its own URI.
     if (sourceURI == aTargetURI) {
       return NS_OK;
     }
-  } else if (sViewSourceReachableFromInner &&
+  } else if (StaticPrefs::
+                 security_view_source_reachable_from_inner_protocol() &&
              sourceScheme.EqualsIgnoreCase(targetScheme.get()) &&
              aTargetURI->SchemeIs("view-source")) {
     // exception for foo: linking to view-source:foo for reftests...
     return NS_OK;
   } else if (sourceScheme.EqualsIgnoreCase("file") &&
              targetScheme.EqualsIgnoreCase("moz-icon")) {
     // exception for file: linking to moz-icon://.ext?size=...
     // Note that because targetScheme is the base (innermost) URI scheme,
--- a/devtools/client/accessibility/constants.js
+++ b/devtools/client/accessibility/constants.js
@@ -116,36 +116,34 @@ exports.A11Y_CONTRAST_LEARN_MORE_LINK =
   "Color_contrast?utm_source=devtools&utm_medium=a11y-panel-checks-color-contrast";
 
 const A11Y_TEXT_LABEL_LINK_BASE =
   "https://developer.mozilla.org/docs/Web/Accessibility/Understanding_WCAG/Text_labels_and_names" +
   "?utm_source=devtools&utm_medium=a11y-panel-checks-text-label";
 
 const A11Y_TEXT_LABEL_LINK_IDS = {
   [AREA_NO_NAME_FROM_ALT]:
-    "Use_alt_attribute_to_label_<area>_elements_that_have_the_href_attribute",
+    "Use_alt_attribute_to_label_area_elements_that_have_the_href_attribute",
   [DIALOG_NO_NAME]: "Dialogs_should_be_labeled",
-  [DOCUMENT_NO_TITLE]: "Documents_must_have_a_<title>",
+  [DOCUMENT_NO_TITLE]: "Documents_must_have_a_title",
   [EMBED_NO_NAME]: "Embedded_content_must_be_labeled",
   [FIGURE_NO_NAME]: "Figures_with_optional_captions_should_be_labeled",
-  [FORM_FIELDSET_NO_NAME]: "<fieldset>_elements_must_be_labeled",
-  [FORM_FIELDSET_NO_NAME_FROM_LEGEND]:
-    "Use_<legend>_element_to_label_<fieldset>_elements",
+  [FORM_FIELDSET_NO_NAME]: "Fieldset_elements_must_be_labeled",
+  [FORM_FIELDSET_NO_NAME_FROM_LEGEND]: "Use_a_legend_to_label_a_fieldset",
   [FORM_NO_NAME]: "Form_elements_must_be_labeled",
   [FORM_NO_VISIBLE_NAME]: "Form_elements_should_have_a_visible_text_label",
   [FORM_OPTGROUP_NO_NAME_FROM_LABEL]:
-    "Use_label_attribute_to_label_<optgroup>_elements",
-  [FRAME_NO_NAME]: "<frame>_elements_must_be_labeled",
+    "Use_label_attribute_on_optgroup_elements",
+  [FRAME_NO_NAME]: "Frame_elements_must_be_labeled",
   [HEADING_NO_NAME]: "Headings_must_be_labeled",
   [HEADING_NO_CONTENT]: "Headings_should_have_visible_text_content",
-  [IFRAME_NO_NAME_FROM_TITLE]:
-    "Use_title_attribute_to_describe_<iframe>_content",
+  [IFRAME_NO_NAME_FROM_TITLE]: "Use_title_attribute_to_describe_iframe_content",
   [IMAGE_NO_NAME]: "Content_with_images_must_be_labeled",
   [INTERACTIVE_NO_NAME]: "Interactive_elements_must_be_labeled",
-  [MATHML_GLYPH_NO_NAME]: "Use_alt_attribute_to_label_<mglyph>_elements",
+  [MATHML_GLYPH_NO_NAME]: "Use_alt_attribute_to_label_mglyph_elements",
   [TOOLBAR_NO_NAME]:
     "Toolbars_must_be_labeled_when_there_is_more_than_one_toolbar",
 };
 
 const A11Y_TEXT_LABEL_LINKS = {};
 for (const key in A11Y_TEXT_LABEL_LINK_IDS) {
   A11Y_TEXT_LABEL_LINKS[key] = `${A11Y_TEXT_LABEL_LINK_BASE}#${
     A11Y_TEXT_LABEL_LINK_IDS[key]
--- a/devtools/client/debugger/src/components/Editor/Tab.js
+++ b/devtools/client/debugger/src/components/Editor/Tab.js
@@ -139,18 +139,18 @@ class Tab extends PureComponent<Props> {
           disabled: !selectedSource.url,
           click: () => showSource(cx, tab),
         },
       },
       {
         item: {
           ...tabMenuItems.toggleBlackBox,
           label: source.isBlackBoxed
-            ? L10N.getStr("sourceFooter.unblackbox")
-            : L10N.getStr("sourceFooter.blackbox"),
+            ? L10N.getStr("blackboxContextItem.unblackbox")
+            : L10N.getStr("blackboxContextItem.blackbox"),
           disabled: !shouldBlackbox(source),
           click: () => toggleBlackBox(cx, source),
         },
       },
       {
         item: {
           ...tabMenuItems.prettyPrint,
           click: () => togglePrettyPrint(cx, tab),
--- a/devtools/client/debugger/src/components/Editor/menus/editor.js
+++ b/devtools/client/debugger/src/components/Editor/menus/editor.js
@@ -118,19 +118,21 @@ const showSourceMenuItem = (
 
 const blackBoxMenuItem = (
   cx: Context,
   selectedSource: Source,
   editorActions: EditorItemActions
 ) => ({
   id: "node-menu-blackbox",
   label: selectedSource.isBlackBoxed
-    ? L10N.getStr("sourceFooter.unblackbox")
-    : L10N.getStr("sourceFooter.blackbox"),
-  accesskey: L10N.getStr("sourceFooter.blackbox.accesskey"),
+    ? L10N.getStr("blackboxContextItem.unblackbox")
+    : L10N.getStr("blackboxContextItem.blackbox"),
+  accesskey: selectedSource.isBlackBoxed
+    ? L10N.getStr("blackboxContextItem.unblackbox.accesskey")
+    : L10N.getStr("blackboxContextItem.blackbox.accesskey"),
   disabled: !shouldBlackbox(selectedSource),
   click: () => editorActions.toggleBlackBox(cx, selectedSource),
 });
 
 const watchExpressionItem = (
   cx: ThreadContext,
   selectedSource: Source,
   selectionText: string,
--- a/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js
+++ b/devtools/client/debugger/src/components/PrimaryPanes/SourcesTreeItem.js
@@ -123,19 +123,21 @@ class SourceTreeItem extends Component<P
           click: () => copyToTheClipboard(contents.url),
         };
 
         const { cx, source } = this.props;
         if (source) {
           const blackBoxMenuItem = {
             id: "node-menu-blackbox",
             label: source.isBlackBoxed
-              ? L10N.getStr("sourceFooter.unblackbox")
-              : L10N.getStr("sourceFooter.blackbox"),
-            accesskey: L10N.getStr("sourceFooter.blackbox.accesskey"),
+              ? L10N.getStr("blackboxContextItem.unblackbox")
+              : L10N.getStr("blackboxContextItem.blackbox"),
+            accesskey: source.isBlackBoxed
+              ? L10N.getStr("blackboxContextItem.unblackbox.accesskey")
+              : L10N.getStr("blackboxContextItem.blackbox.accesskey"),
             disabled: !shouldBlackbox(source),
             click: () => this.props.toggleBlackBox(cx, source),
           };
           const downloadFileItem = {
             id: "node-menu-download-file",
             label: L10N.getStr("downloadFile.label"),
             accesskey: L10N.getStr("downloadFile.accesskey"),
             disabled: false,
--- a/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js
+++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 import { showMenu } from "devtools-contextmenu";
 import { copyToTheClipboard } from "../../../utils/clipboard";
 import type { ContextMenuItem, Frame } from "../../../types";
 import { kebabCase } from "lodash";
 
-const blackboxString = "sourceFooter.blackbox";
-const unblackboxString = "sourceFooter.unblackbox";
+const blackboxString = "blackboxContextItem.blackbox";
+const unblackboxString = "blackboxContextItem.unblackbox";
 
 function formatMenuElement(
   labelString: string,
   click: Function,
   disabled: boolean = false
 ): ContextMenuItem {
   const label = L10N.getStr(labelString);
   const accesskey = L10N.getStr(`${labelString}.accesskey`);
--- a/devtools/client/debugger/src/utils/tabs.js
+++ b/devtools/client/debugger/src/utils/tabs.js
@@ -92,18 +92,18 @@ export function getTabMenuItems() {
     copySourceUri2: {
       id: "node-menu-copy-source-url",
       label: L10N.getStr("copySourceUri2"),
       accesskey: L10N.getStr("copySourceUri2.accesskey"),
       disabled: false,
     },
     toggleBlackBox: {
       id: "node-menu-blackbox",
-      label: L10N.getStr("sourceFooter.blackbox"),
-      accesskey: L10N.getStr("sourceFooter.blackbox.accesskey"),
+      label: L10N.getStr("blackboxContextItem.blackbox"),
+      accesskey: L10N.getStr("blackboxContextItem.blackbox.accesskey"),
       disabled: false,
     },
     prettyPrint: {
       id: "node-menu-pretty-print",
       label: L10N.getStr("sourceTabs.prettyPrint"),
       accesskey: L10N.getStr("sourceTabs.prettyPrint.accesskey"),
       disabled: false,
     },
--- a/devtools/client/inspector/grids/test/browser.ini
+++ b/devtools/client/inspector/grids/test/browser.ini
@@ -22,17 +22,18 @@ support-files =
 [browser_grids_grid-list-color-picker-on-RETURN.js]
 [browser_grids_grid-list-element-rep.js]
 [browser_grids_grid-list-no-grids.js]
 [browser_grids_grid-list-on-iframe-reloaded.js]
 skip-if = (verify && (os == 'win' || os == 'linux'))
 [browser_grids_grid-list-on-mutation-element-added.js]
 skip-if = true #Bug 1557326
 [browser_grids_grid-list-on-mutation-element-removed.js]
-[browser_grids_grid-list-subgrids.js]
+[browser_grids_grid-list-subgrids_01.js]
+[browser_grids_grid-list-subgrids_02.js]
 [browser_grids_grid-list-toggle-grids_01.js]
 [browser_grids_grid-list-toggle-grids_02.js]
 [browser_grids_grid-list-toggle-multiple-grids.js]
 [browser_grids_grid-outline-cannot-show-outline.js]
 [browser_grids_grid-outline-highlight-area.js]
 skip-if = (verify && (os == 'win')) || (os == "win" && os_version == "10.0" && !debug) #Bug 1501760
 [browser_grids_grid-outline-highlight-cell.js]
 skip-if = (verify && (os == 'win')) || (os == "win" && os_version == "10.0" && asan) #Bug 1501317
rename from devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids.js
rename to devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_01.js
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_02.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the state of grid highlighters after toggling the checkbox of subgrids.
+
+const TEST_URI = URL_ROOT + "doc_subgrid.html";
+
+add_task(async () => {
+  await addTab(TEST_URI);
+  const { gridInspector, inspector } = await openLayoutView();
+  const { document: doc } = gridInspector;
+  const { highlighters, store } = inspector;
+
+  await selectNode("#grid", inspector);
+  const parentEl = doc.getElementById("grid-list");
+  // Input for .container
+  const parentInput = parentEl.children[0].querySelector("input");
+  const subgridEl = parentEl.children[1];
+  // Input for <main>
+  const subgridInput = subgridEl.children[1].querySelector("input");
+  const grandSubgridEl = subgridEl.children[2];
+  // Input for .aside1
+  const grandSubgridInput = grandSubgridEl.children[0].querySelector("input");
+
+  info(
+    "Toggling ON the CSS grid highlighters for .container, <main> and .aside1"
+  );
+  await toggleHighlighter(parentInput, highlighters);
+  await toggleHighlighter(subgridInput, highlighters);
+  await toggleHighlighter(grandSubgridInput, highlighters);
+  await waitUntilState(
+    store,
+    state => state.grids.filter(g => g.highlighted).length === 3
+  );
+
+  info("Check the state of highlighters");
+  is(
+    highlighters.gridHighlighters.size,
+    3,
+    "All highlighters are use as normal highlighter"
+  );
+
+  info("Toggling OFF the CSS grid highlighter for <main>");
+  await toggleHighlighter(subgridInput, highlighters);
+  await waitUntilState(
+    store,
+    state => state.grids.filter(g => g.highlighted).length === 2
+  );
+
+  info("Check the state of highlighters after hiding subgrid for <main>");
+  is(
+    highlighters.gridHighlighters.size,
+    2,
+    "2 highlighters are use as normal highlighter"
+  );
+  is(
+    highlighters.parentGridHighlighters.size,
+    1,
+    "The highlighter for <main> is used as parent highlighter"
+  );
+});
+
+async function toggleHighlighter(input, highlighters) {
+  const eventName = input.checked
+    ? "grid-highlighter-hidden"
+    : "grid-highlighter-shown";
+  const onHighlighterEvent = highlighters.once(eventName);
+  input.click();
+  await onHighlighterEvent;
+}
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -667,19 +667,23 @@ class HighlightersOverlay {
       this.subgridToParentMap.delete(node);
       await this.hideParentGridHighlighter(parentGridNode);
     }
 
     // Check if the given node matches any of the subgrid's parent grid container.
     // Since the subgrid and its parent grid container were previously both highlighted
     // and the parent grid container (the given node) has just been hidden, show a
     // translucent highlight of the parent grid container.
-    for (const parentGridNode of this.subgridToParentMap.values()) {
-      if (parentGridNode === node) {
-        await this.showParentGridHighlighter(parentGridNode);
+    for (const highlightedNode of this.gridHighlighters.keys()) {
+      const parentGridNode = await this.walker.getParentGridNode(
+        highlightedNode
+      );
+      if (node === parentGridNode) {
+        this.subgridToParentMap.set(highlightedNode, node);
+        await this.showParentGridHighlighter(node);
         break;
       }
     }
 
     this._toggleRuleViewIcon(node, false, ".ruleview-grid");
 
     if (this.isGridHighlighterTimerActive && !this.gridHighlighters.size) {
       this.telemetry.toolClosed(
@@ -708,18 +712,20 @@ class HighlightersOverlay {
       if (parentGridNode === node) {
         // Don't hide the parent grid highlighter if another subgrid is highlighted
         // with the given parent node.
         return;
       }
     }
 
     const highlighter = this.parentGridHighlighters.get(node);
-    await highlighter.hide();
-    this.extraGridHighlighterPool.push(highlighter);
+    if (highlighter) {
+      await highlighter.hide();
+      this.extraGridHighlighterPool.push(highlighter);
+    }
     this.state.grids.delete(node);
     this.parentGridHighlighters.delete(node);
   }
 
   /**
    * Show the box model highlighter for the given node.
    *
    * @param  {NodeFront} node
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -498,22 +498,31 @@ sourceTabs.revealInTree.accesskey=r
 # LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item
 # for pretty printing the source.
 sourceTabs.prettyPrint=Pretty print source
 sourceTabs.prettyPrint.accesskey=p
 
 # LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated
 # with the blackbox button
 sourceFooter.blackbox=Blackbox source
-sourceFooter.blackbox.accesskey=B
 
 # LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated
 # with the blackbox button
 sourceFooter.unblackbox=Unblackbox source
 
+# LOCALIZATION NOTE (blackboxContextItem.blackbox): Text associated
+# with the blackbox context menu item
+blackboxContextItem.blackbox=Blackbox source
+blackboxContextItem.blackbox.accesskey=B
+
+# LOCALIZATION NOTE (blackboxContextItem.unblackbox): Text associated
+# with the unblackbox context menu item
+blackboxContextItem.unblackbox=Unblackbox source
+blackboxContextItem.unblackbox.accesskey=U
+
 # LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated
 # with a mapped source. %S is replaced by the source map origin.
 sourceFooter.mappedSource=(From %S)
 
 # LOCALIZATION NOTE (sourceFooter.mappedSourceTooltip): Tooltip text associated
 # with a mapped source. %S is replaced by the source map origin.
 sourceFooter.mappedSourceTooltip=(Source mapped from %S)
 
--- a/devtools/server/actors/breakpoint.js
+++ b/devtools/server/actors/breakpoint.js
@@ -186,18 +186,17 @@ BreakpointActor.prototype = {
   hit: function(frame) {
     // Don't pause if we are currently stepping (in or over) or the frame is
     // black-boxed.
     const location = this.threadActor.sources.getFrameLocation(frame);
     const { sourceActor, line, column } = location;
 
     if (
       this.threadActor.sources.isBlackBoxed(sourceActor.url, line, column) ||
-      this.threadActor.skipBreakpoints ||
-      frame.onStep
+      this.threadActor.skipBreakpoints
     ) {
       return undefined;
     }
 
     // If we're trying to pop this frame, and we see a breakpoint at
     // the spot at which popping started, ignore it.  See bug 970469.
     const locationAtFinish = frame.onPop && frame.onPop.location;
     if (
--- a/devtools/server/actors/common.js
+++ b/devtools/server/actors/common.js
@@ -140,16 +140,20 @@ SourceLocation.prototype = {
   get column() {
     return this._column;
   },
 
   get lastColumn() {
     return this._lastColumn;
   },
 
+  get sourceUrl() {
+    return this.sourceActor.url;
+  },
+
   equals: function(other) {
     return (
       this.sourceActor.url == other.sourceActor.url &&
       this.line === other.line &&
       (this.column === undefined ||
         other.column === undefined ||
         this.column === other.column)
     );
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -924,31 +924,36 @@ const ThreadActor = ActorClassWithSpec(t
   },
 
   _validFrameStepOffset: function(frame, startFrame, offset) {
     const meta = frame.script.getOffsetMetadata(offset);
 
     // Continue if:
     // 1. the location is not a valid breakpoint position
     // 2. the source is not blackboxed
-    // 3. has not moved
+    // 3. we have not moved since the last pause
     if (
       !meta.isBreakpoint ||
       this.sources.isFrameBlackBoxed(frame) ||
       !this.hasMoved(frame)
     ) {
       return false;
     }
 
     // Pause if:
     // 1. the frame has changed
     // 2. the location is a step position.
     return frame !== startFrame || meta.isStepStart;
   },
 
+  atBreakpointLocation(frame) {
+    const location = this.sources.getFrameLocation(frame);
+    return !!this.breakpointActorMap.get(location);
+  },
+
   createCompletionGrip: function(packet, completion) {
     if (!completion) {
       return packet;
     }
 
     const createGrip = value =>
       createValueGrip(value, this._pausePool, this.objectGrip);
     packet.why.frameFinished = {};
@@ -1755,26 +1760,27 @@ const ThreadActor = ActorClassWithSpec(t
    * A function that the engine calls when a debugger statement has been
    * executed in the specified frame.
    *
    * @param frame Debugger.Frame
    *        The stack frame that contained the debugger statement.
    */
   onDebuggerStatement: function(frame) {
     const location = this.sources.getFrameLocation(frame);
-    const url = location.sourceActor.url;
 
     // Don't pause if
-    // 1. the debugger is in the same position
+    // 1. we have not moved since the last pause
     // 2. breakpoints are disabled
     // 3. the source is blackboxed
+    // 4. there is a breakpoint at the same location
     if (
       !this.hasMoved(frame, "debuggerStatement") ||
       this.skipBreakpoints ||
-      this.sources.isBlackBoxed(url)
+      this.sources.isBlackBoxed(location.sourceUrl) ||
+      this.atBreakpointLocation(frame)
     ) {
       return undefined;
     }
 
     return this._pauseAndRespond(frame, { type: "debuggerStatement" });
   },
 
   onSkipBreakpoints: function({ skip }) {
--- a/devtools/server/actors/utils/breakpoint-actor-map.js
+++ b/devtools/server/actors/utils/breakpoint-actor-map.js
@@ -48,16 +48,21 @@ BreakpointActorMap.prototype = {
   getOrCreateBreakpointActor(location) {
     const key = this._locationKey(location);
     if (!this._actors[key]) {
       this._actors[key] = new BreakpointActor(this._threadActor, location);
     }
     return this._actors[key];
   },
 
+  get(location) {
+    const key = this._locationKey(location);
+    return this._actors[key];
+  },
+
   /**
    * Delete the BreakpointActor from the given location in this
    * BreakpointActorMap.
    *
    * @param BreakpointLocation location
    *        The location from which the BreakpointActor should be deleted.
    */
   deleteActor(location) {
--- a/devtools/server/tests/unit/test_breakpoint-13.js
+++ b/devtools/server/tests/unit/test_breakpoint-13.js
@@ -12,17 +12,20 @@
 add_task(
   threadFrontTest(async ({ threadFront, debuggee }) => {
     const packet = await executeOnNextTickAndWaitForPause(
       () => evaluateTestCode(debuggee),
       threadFront
     );
 
     const source = await getSourceById(threadFront, packet.frame.where.actor);
-    await threadFront.setBreakpoint({ sourceUrl: source.url, line: 3 }, {});
+    await threadFront.setBreakpoint(
+      { sourceUrl: source.url, line: 3, column: 6 },
+      {}
+    );
 
     info("Check that the stepping worked.");
     const packet1 = await stepIn(threadFront);
     Assert.equal(packet1.frame.where.line, 6);
     Assert.equal(packet1.why.type, "resumeLimit");
 
     info("Entered the foo function call frame.");
     const packet2 = await stepIn(threadFront);
--- a/devtools/server/tests/unit/test_breakpoint-24.js
+++ b/devtools/server/tests/unit/test_breakpoint-24.js
@@ -105,17 +105,17 @@ async function testBreakpoints({ threadF
       debugger;
     }
     function a() {}
     foo();
     //# sourceURL=http://example.com/testBreakpoints.js`
   );
 
   threadFront.setBreakpoint(
-    { sourceUrl: "http://example.com/testBreakpoints.js", line: 3 },
+    { sourceUrl: "http://example.com/testBreakpoints.js", line: 3, column: 6 },
     {}
   );
 
   await performActions(threadFront, [
     [
       "paused at first debugger statement",
       { line: 2, type: "debuggerStatement" },
       "stepOver",
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_breakpoint-26.js
@@ -0,0 +1,67 @@
+/* eslint-disable max-nested-callbacks */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Bug 925269 - Verify that debugger statements are skipped
+ * if there is a falsey conditional breakpoint at the same location.
+ */
+add_task(
+  threadFrontTest(async props => {
+    await testBreakpointsAndDebuggerStatements(props);
+  })
+);
+
+async function testBreakpointsAndDebuggerStatements({
+  threadFront,
+  targetFront,
+}) {
+  const consoleFront = await targetFront.getFront("console");
+  consoleFront.evaluateJSAsync(
+    `function foo(stop) {
+      debugger;
+      debugger;
+      debugger;
+    }
+    foo();
+    //# sourceURL=http://example.com/testBreakpointsAndDebuggerStatements.js`
+  );
+
+  threadFront.setBreakpoint(
+    {
+      sourceUrl: "http://example.com/testBreakpointsAndDebuggerStatements.js",
+      line: 3,
+      column: 6,
+    },
+    { condition: "false" }
+  );
+
+  await performActions(threadFront, [
+    [
+      "paused at first debugger statement",
+      { line: 2, type: "debuggerStatement" },
+      "resume",
+    ],
+    [
+      "pause at the third debugger statement",
+      { line: 4, type: "debuggerStatement" },
+      "resume",
+    ],
+  ]);
+}
+
+async function performActions(threadFront, actions) {
+  for (const action of actions) {
+    await performAction(threadFront, action);
+  }
+}
+
+async function performAction(threadFront, [description, result, action]) {
+  info(description);
+  const packet = await waitForEvent(threadFront, "paused");
+  Assert.equal(packet.frame.where.line, result.line);
+  Assert.equal(packet.why.type, result.type);
+  await threadFront[action]();
+}
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -131,16 +131,17 @@ skip-if = true
 reason = bug 1104838
 [test_breakpoint-20.js]
 [test_breakpoint-21.js]
 [test_breakpoint-22.js]
 skip-if = true # breakpoint sliding is not supported bug 1525685
 [test_breakpoint-23.js]
 [test_breakpoint-24.js]
 [test_breakpoint-25.js]
+[test_breakpoint-26.js]
 [test_conditional_breakpoint-01.js]
 [test_conditional_breakpoint-02.js]
 [test_conditional_breakpoint-03.js]
 [test_conditional_breakpoint-04.js]
 [test_logpoint-01.js]
 [test_logpoint-02.js]
 [test_logpoint-03.js]
 [test_listsources-01.js]
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -764,17 +764,17 @@ class RemoteLocationProxy
 };
 
 static const RemoteLocationProxy sSingleton;
 
 // Give RemoteLocationProxy 2 reserved slots, like the other wrappers,
 // so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 template <>
-const js::Class RemoteLocationProxy::Base::sClass =
+const JSClass RemoteLocationProxy::Base::sClass =
     PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
 
 void BrowsingContext::Location(JSContext* aCx,
                                JS::MutableHandle<JSObject*> aLocation,
                                ErrorResult& aError) {
   aError.MightThrowJSException();
   sSingleton.GetProxyObject(aCx, &mLocation, /* aTransplantTo = */ nullptr,
                             aLocation);
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -14394,17 +14394,18 @@ void Document::ReportUseCounters(UseCoun
   if (aKind == UseCounterReportKind::eIncludeExternalResources) {
     EnumerateExternalResources(ReportExternalResourceUseCounters, nullptr);
   }
 
   if (Telemetry::HistogramUseCounterCount > 0 &&
       (IsContentDocument() || IsResourceDoc())) {
     nsCOMPtr<nsIURI> uri;
     NodePrincipal()->GetURI(getter_AddRefs(uri));
-    if (!uri || uri->SchemeIs("about") || uri->SchemeIs("chrome")) {
+    if (!uri || uri->SchemeIs("about") || uri->SchemeIs("chrome") ||
+        uri->SchemeIs("resource")) {
       return;
     }
 
     if (sDebugUseCounters) {
       nsCString spec = uri->GetSpecOrDefault();
 
       // URIs can be rather long for data documents, so truncate them to
       // some reasonable length.
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Link.h"
 
-#include "mozilla/Components.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Element.h"
 #if defined(MOZ_PLACES)
 #  include "mozilla/places/History.h"
 #else
 #  include "mozilla/IHistory.h"
 #endif
@@ -90,250 +89,19 @@ void Link::CancelDNSPrefetch(nsWrapperCa
   } else if (mElement->HasFlag(aRequestedFlag)) {
     mElement->UnsetFlags(aRequestedFlag);
     // Possible that hostname could have changed since binding, but since this
     // covers common cases, most DNS prefetch requests will be canceled
     nsHTMLDNSPrefetch::CancelPrefetchLow(this, NS_ERROR_ABORT);
   }
 }
 
-void Link::GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
-                                         nsContentPolicyType& aPolicyType,
-                                         nsString& aMimeType,
-                                         nsAString& aMedia) {
-  nsAutoString as;
-  mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::as, as);
-  Link::ParseAsValue(as, aAsAttr);
-  aPolicyType = AsValueToContentPolicy(aAsAttr);
-
-  nsAutoString type;
-  mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
-  nsAutoString notUsed;
-  nsContentUtils::SplitMimeType(type, aMimeType, notUsed);
-
-  mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
-}
-
-void Link::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender() {
-  MOZ_ASSERT(mElement->IsInComposedDoc());
-  if (!ElementHasHref()) {
-    return;
-  }
-
-  nsAutoString rel;
-  if (!mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
-    return;
-  }
-
-  if (!nsContentUtils::PrefetchPreloadEnabled(
-          mElement->OwnerDoc()->GetDocShell())) {
-    return;
-  }
-
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
-
-  if ((linkTypes & nsStyleLinkElement::ePREFETCH) ||
-      (linkTypes & nsStyleLinkElement::eNEXT) ||
-      (linkTypes & nsStyleLinkElement::ePRELOAD)) {
-    nsCOMPtr<nsIPrefetchService> prefetchService(
-        components::Prefetch::Service());
-    if (prefetchService) {
-      nsCOMPtr<nsIURI> uri(GetURI());
-      if (uri) {
-        bool preload = !!(linkTypes & nsStyleLinkElement::ePRELOAD);
-        nsContentPolicyType policyType;
-
-        if (preload) {
-          nsAttrValue asAttr;
-          nsAutoString mimeType;
-          nsAutoString media;
-          GetContentPolicyMimeTypeMedia(asAttr, policyType, mimeType, media);
-
-          if (policyType == nsIContentPolicy::TYPE_INVALID) {
-            // Ignore preload with a wrong or empty as attribute.
-            return;
-          }
-
-          if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
-                                                  mElement->OwnerDoc())) {
-            policyType = nsIContentPolicy::TYPE_INVALID;
-          }
-        }
-
-        nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
-        referrerInfo->InitWithNode(mElement);
-        if (preload) {
-          prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
-        } else {
-          prefetchService->PrefetchURI(
-              uri, referrerInfo, mElement,
-              linkTypes & nsStyleLinkElement::ePREFETCH);
-        }
-        return;
-      }
-    }
-  }
-
-  if (linkTypes & nsStyleLinkElement::ePRECONNECT) {
-    nsCOMPtr<nsIURI> uri(GetURI());
-    if (uri && mElement->OwnerDoc()) {
-      mElement->OwnerDoc()->MaybePreconnect(
-          uri, Element::AttrValueToCORSMode(
-                   mElement->GetParsedAttr(nsGkAtoms::crossorigin)));
-      return;
-    }
-  }
-
-  if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
-    if (nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
-      nsHTMLDNSPrefetch::PrefetchLow(this);
-    }
-  }
-}
-
-void Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
-                         const nsAttrValue* aOldValue) {
-  MOZ_ASSERT(mElement->IsInComposedDoc());
-
-  if (!ElementHasHref()) {
-    return;
-  }
-
-  nsAutoString rel;
-  if (!mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
-    return;
-  }
-
-  if (!nsContentUtils::PrefetchPreloadEnabled(
-          mElement->OwnerDoc()->GetDocShell())) {
-    return;
-  }
-
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
-
-  if (!(linkTypes & nsStyleLinkElement::ePRELOAD)) {
-    return;
-  }
-
-  nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
-  if (!prefetchService) {
-    return;
-  }
-
-  nsCOMPtr<nsIURI> uri(GetURI());
-  if (!uri) {
-    return;
-  }
-
-  nsAttrValue asAttr;
-  nsContentPolicyType asPolicyType;
-  nsAutoString mimeType;
-  nsAutoString media;
-  GetContentPolicyMimeTypeMedia(asAttr, asPolicyType, mimeType, media);
-
-  if (asPolicyType == nsIContentPolicy::TYPE_INVALID) {
-    // Ignore preload with a wrong or empty as attribute, but be sure to cancel
-    // the old one.
-    prefetchService->CancelPrefetchPreloadURI(uri, mElement);
-    return;
-  }
-
-  nsContentPolicyType policyType = asPolicyType;
-  if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
-                                          mElement->OwnerDoc())) {
-    policyType = nsIContentPolicy::TYPE_INVALID;
-  }
-
-  if (aName == nsGkAtoms::crossorigin) {
-    CORSMode corsMode = Element::AttrValueToCORSMode(aValue);
-    CORSMode oldCorsMode = Element::AttrValueToCORSMode(aOldValue);
-    if (corsMode != oldCorsMode) {
-      prefetchService->CancelPrefetchPreloadURI(uri, mElement);
-
-      nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
-      referrerInfo->InitWithNode(mElement);
-      prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
-    }
-    return;
-  }
-
-  nsContentPolicyType oldPolicyType;
-
-  if (aName == nsGkAtoms::as) {
-    if (aOldValue) {
-      oldPolicyType = AsValueToContentPolicy(*aOldValue);
-      if (!HTMLLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media,
-                                              mElement->OwnerDoc())) {
-        oldPolicyType = nsIContentPolicy::TYPE_INVALID;
-      }
-    } else {
-      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
-    }
-  } else if (aName == nsGkAtoms::type) {
-    nsAutoString oldType;
-    nsAutoString notUsed;
-    if (aOldValue) {
-      aOldValue->ToString(oldType);
-    } else {
-      oldType = EmptyString();
-    }
-    nsAutoString oldMimeType;
-    nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed);
-    if (HTMLLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media,
-                                           mElement->OwnerDoc())) {
-      oldPolicyType = asPolicyType;
-    } else {
-      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
-    }
-  } else {
-    MOZ_ASSERT(aName == nsGkAtoms::media);
-    nsAutoString oldMedia;
-    if (aOldValue) {
-      aOldValue->ToString(oldMedia);
-    } else {
-      oldMedia = EmptyString();
-    }
-    if (HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia,
-                                           mElement->OwnerDoc())) {
-      oldPolicyType = asPolicyType;
-    } else {
-      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
-    }
-  }
-
-  if ((policyType != oldPolicyType) &&
-      (oldPolicyType != nsIContentPolicy::TYPE_INVALID)) {
-    prefetchService->CancelPrefetchPreloadURI(uri, mElement);
-  }
-
-  // Trigger a new preload if the policy type has changed.
-  // Also trigger load if the new policy type is invalid, this will only
-  // trigger an error event.
-  if ((policyType != oldPolicyType) ||
-      (policyType == nsIContentPolicy::TYPE_INVALID)) {
-    nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
-    referrerInfo->InitWithNode(mElement);
-    prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
-  }
-}
-
-void Link::CancelPrefetchOrPreload() {
-  nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
-  if (prefetchService) {
-    nsCOMPtr<nsIURI> uri(GetURI());
-    if (uri) {
-      prefetchService->CancelPrefetchPreloadURI(uri, mElement);
-    }
-  }
-}
-
 void Link::SetLinkState(nsLinkState aState) {
-  NS_ASSERTION(mRegistered, "Setting the link state of an unregistered Link!");
-  NS_ASSERTION(mLinkState != aState,
-               "Setting state to the currently set state!");
+  MOZ_ASSERT(mRegistered, "Setting the link state of an unregistered Link!");
+  MOZ_ASSERT(mLinkState != aState, "Setting state to the currently set state!");
 
   // Set our current state as appropriate.
   mLinkState = aState;
 
   // Per IHistory interface documentation, we are no longer registered.
   mRegistered = false;
 
   MOZ_ASSERT(LinkState() == NS_EVENT_STATE_VISITED ||
@@ -342,16 +110,18 @@ void Link::SetLinkState(nsLinkState aSta
 
   // Tell the element to update its visited state
   mElement->UpdateState(true);
 }
 
 EventStates Link::LinkState() const {
   // We are a constant method, but we are just lazily doing things and have to
   // track that state.  Cast away that constness!
+  //
+  // XXX(emilio): that's evil.
   Link* self = const_cast<Link*>(this);
 
   Element* element = self->mElement;
 
   // If we have not yet registered for notifications and need to,
   // due to our href changing, register now!
   if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc() &&
       !HasPendingLinkUpdate()) {
@@ -742,18 +512,22 @@ void Link::ResetLinkState(bool aNotify, 
     Document* doc = mElement->GetComposedDoc();
     if (doc && (mRegistered || mLinkState == eLinkState_Visited)) {
       // Tell the document to forget about this link if we've registered
       // with it before.
       doc->ForgetLink(this);
     }
   }
 
-  // If we have an href, we should register with the history.
-  mNeedsRegistration = aHasHref;
+  // If we have an href, and we're not a <link>, we should register with the
+  // history.
+  //
+  // FIXME(emilio): Do we really want to allow all MathML elements to be
+  // :visited? That seems not great.
+  mNeedsRegistration = aHasHref && !mElement->IsHTMLElement(nsGkAtoms::link);
 
   // If we've cached the URI, reset always invalidates it.
   UnregisterFromHistory();
   mCachedURI = nullptr;
 
   // Update our state back to the default.
   mLinkState = defaultState;
 
@@ -825,53 +599,10 @@ size_t Link::SizeOfExcludingThis(mozilla
   }
 
   // The following members don't need to be measured:
   // - mElement, because it is a pointer-to-self used to avoid QIs
 
   return n;
 }
 
-static const nsAttrValue::EnumTable kAsAttributeTable[] = {
-    {"", DESTINATION_INVALID},      {"audio", DESTINATION_AUDIO},
-    {"font", DESTINATION_FONT},     {"image", DESTINATION_IMAGE},
-    {"script", DESTINATION_SCRIPT}, {"style", DESTINATION_STYLE},
-    {"track", DESTINATION_TRACK},   {"video", DESTINATION_VIDEO},
-    {"fetch", DESTINATION_FETCH},   {nullptr, 0}};
-
-/* static */
-void Link::ParseAsValue(const nsAString& aValue, nsAttrValue& aResult) {
-  DebugOnly<bool> success =
-      aResult.ParseEnumValue(aValue, kAsAttributeTable, false,
-                             // default value is a empty string
-                             // if aValue is not a value we
-                             // understand
-                             &kAsAttributeTable[0]);
-  MOZ_ASSERT(success);
-}
-
-/* static */
-nsContentPolicyType Link::AsValueToContentPolicy(const nsAttrValue& aValue) {
-  switch (aValue.GetEnumValue()) {
-    case DESTINATION_INVALID:
-      return nsIContentPolicy::TYPE_INVALID;
-    case DESTINATION_AUDIO:
-      return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
-    case DESTINATION_TRACK:
-      return nsIContentPolicy::TYPE_INTERNAL_TRACK;
-    case DESTINATION_VIDEO:
-      return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
-    case DESTINATION_FONT:
-      return nsIContentPolicy::TYPE_FONT;
-    case DESTINATION_IMAGE:
-      return nsIContentPolicy::TYPE_IMAGE;
-    case DESTINATION_SCRIPT:
-      return nsIContentPolicy::TYPE_SCRIPT;
-    case DESTINATION_STYLE:
-      return nsIContentPolicy::TYPE_STYLESHEET;
-    case DESTINATION_FETCH:
-      return nsIContentPolicy::TYPE_OTHER;
-  }
-  return nsIContentPolicy::TYPE_INVALID;
-}
-
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/Link.h
+++ b/dom/base/Link.h
@@ -114,44 +114,35 @@ class Link : public nsISupports {
    *          Defaults to true; should be overridden for specialised cases
    */
   virtual bool HasDeferredDNSPrefetchRequest() { return true; }
 
   virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState) const;
 
   virtual bool ElementHasHref() const;
 
-  // This is called by HTMLAnchorElement.
+  // This is called by HTMLAnchorElement and HTMLLinkElement.
   void TryDNSPrefetch();
   void CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
                          nsWrapperCache::FlagsType aRequestedFlag);
 
-  // This is called by HTMLLinkElement.
-  void TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
-  void UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
-                     const nsAttrValue* aOldValue);
-  void CancelPrefetchOrPreload();
-
   bool HasPendingLinkUpdate() const { return mHasPendingLinkUpdate; }
   void SetHasPendingLinkUpdate() { mHasPendingLinkUpdate = true; }
   void ClearHasPendingLinkUpdate() { mHasPendingLinkUpdate = false; }
 
   // To ensure correct mHasPendingLinkUpdate handling, we have this method
   // similar to the one in Element. Overriders must call
   // ClearHasPendingLinkUpdate().
   // If you change this, change also the method in Element.
   virtual void NodeInfoChanged(Document* aOldDoc) = 0;
 
   bool IsInDNSPrefetch() { return mInDNSPrefetch; }
   void SetIsInDNSPrefetch() { mInDNSPrefetch = true; }
   void ClearIsInDNSPrefetch() { mInDNSPrefetch = false; }
 
-  static void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult);
-  static nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue);
-
  protected:
   virtual ~Link();
 
   /**
    * Return true if the link has associated URI.
    */
   bool HasURI() const {
     if (HasCachedURI()) {
@@ -168,20 +159,16 @@ class Link : public nsISupports {
   /**
    * Unregisters from History so this node no longer gets notifications about
    * changes to visitedness.
    */
   void UnregisterFromHistory();
 
   void SetHrefAttribute(nsIURI* aURI);
 
-  void GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
-                                     nsContentPolicyType& aPolicyType,
-                                     nsString& aMimeType, nsAString& aMedia);
-
   mutable nsCOMPtr<nsIURI> mCachedURI;
 
   Element* const mElement;
 
   uint16_t mLinkState;
 
   bool mNeedsRegistration : 1;
 
--- a/dom/base/RemoteOuterWindowProxy.cpp
+++ b/dom/base/RemoteOuterWindowProxy.cpp
@@ -53,17 +53,17 @@ class RemoteOuterWindowProxy
 };
 
 static const RemoteOuterWindowProxy sSingleton;
 
 // Give RemoteOuterWindowProxy 2 reserved slots, like the other wrappers,
 // so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 template <>
-const js::Class RemoteOuterWindowProxy::Base::sClass =
+const JSClass RemoteOuterWindowProxy::Base::sClass =
     PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
 
 bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
                                JS::Handle<JSObject*> aTransplantTo,
                                JS::MutableHandle<JSObject*> aRetVal) {
   MOZ_ASSERT(!aContext->GetDocShell(),
              "Why are we creating a RemoteOuterWindowProxy?");
 
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -795,18 +795,18 @@ void nsContentSink::PrefetchPreloadHref(
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI());
     if (uri) {
       bool preload = !!(aLinkTypes & nsStyleLinkElement::ePRELOAD);
       nsContentPolicyType policyType;
 
       if (preload) {
         nsAttrValue asAttr;
-        Link::ParseAsValue(aAs, asAttr);
-        policyType = Link::AsValueToContentPolicy(asAttr);
+        HTMLLinkElement::ParseAsValue(aAs, asAttr);
+        policyType = HTMLLinkElement::AsValueToContentPolicy(asAttr);
 
         if (policyType == nsIContentPolicy::TYPE_INVALID) {
           // Ignore preload with a wrong or empty as attribute.
           return;
         }
 
         nsAutoString mimeType;
         nsAutoString notUsed;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -148,17 +148,17 @@ extern already_AddRefed<nsIScriptTimeout
     mozilla::dom::Function& aFunction,
     const mozilla::dom::Sequence<JS::Value>& aArguments,
     mozilla::ErrorResult& aError);
 
 extern already_AddRefed<nsIScriptTimeoutHandler> NS_CreateJSTimeoutHandler(
     JSContext* aCx, nsGlobalWindowInner* aWindow, const nsAString& aExpression,
     mozilla::ErrorResult& aError);
 
-extern const js::Class OuterWindowProxyClass;
+extern const JSClass OuterWindowProxyClass;
 
 //*****************************************************************************
 // nsGlobalWindowInner: Global Object for Scripting
 //*****************************************************************************
 
 // nsGlobalWindowInner inherits PRCList for maintaining a list of all inner
 // windows still in memory for any given outer window. This list is needed to
 // ensure that mOuterWindow doesn't end up dangling. The nature of PRCList means
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -342,17 +342,17 @@ nsPIDOMWindowOuter* nsPIDOMWindowOuter::
 
 // Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
 // JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 //
 // We store the nsGlobalWindowOuter* in our first slot.
 //
 // We store our holder weakmap in the second slot.
-const js::Class OuterWindowProxyClass = PROXY_CLASS_DEF(
+const JSClass OuterWindowProxyClass = PROXY_CLASS_DEF(
     "Proxy", JSCLASS_HAS_RESERVED_SLOTS(2)); /* additional class flags */
 
 static const size_t OUTER_WINDOW_SLOT = 0;
 static const size_t HOLDER_WEAKMAP_SLOT = 1;
 
 class nsOuterWindowProxy : public MaybeCrossOriginObject<js::Wrapper> {
   typedef MaybeCrossOriginObject<js::Wrapper> Base;
 
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -135,17 +135,17 @@ extern already_AddRefed<nsIScriptTimeout
     mozilla::dom::Function& aFunction,
     const mozilla::dom::Sequence<JS::Value>& aArguments,
     mozilla::ErrorResult& aError);
 
 extern already_AddRefed<nsIScriptTimeoutHandler> NS_CreateJSTimeoutHandler(
     JSContext* aCx, nsGlobalWindowInner* aWindow, const nsAString& aExpression,
     mozilla::ErrorResult& aError);
 
-extern const js::Class OuterWindowProxyClass;
+extern const JSClass OuterWindowProxyClass;
 
 //*****************************************************************************
 // nsGlobalWindowOuter
 //*****************************************************************************
 
 // nsGlobalWindowOuter inherits PRCList for maintaining a list of all inner
 // windows still in memory for any given outer window. This list is needed to
 // ensure that mOuterWindow doesn't end up dangling. The nature of PRCList means
--- a/dom/base/test/test_viewport_metrics_on_landscape_content.html
+++ b/dom/base/test/test_viewport_metrics_on_landscape_content.html
@@ -7,15 +7,16 @@
 <pre id="test"></pre>
 <script>
 'use strict';
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPrefEnv({
   "set": [
     ["apz.allow_zooming", true],
     ["dom.meta-viewport.enabled", true],
+    ["layout.viewport_contains_no_contents_area", true],
   ]
 }, () => {
   // We need to open a new window to avoid running tests in an iframe since
   // we want to test metrics on the root document.
   window.open("file_viewport_metrics_on_landscape_content.html");
 });
 </script>
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -672,17 +672,17 @@ bool DefineUnforgeableAttributes(JSConte
 
 // We should use JSFunction objects for interface objects, but we need a custom
 // hasInstance hook because we have new interface objects on prototype chains of
 // old (XPConnect-based) bindings. We also need Xrays and arbitrary numbers of
 // reserved slots (e.g. for named constructors).  So we define a custom
 // funToString ObjectOps member for interface objects.
 JSString* InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
                                   bool /* isToSource */) {
-  const js::Class* clasp = js::GetObjectClass(aObject);
+  const JSClass* clasp = js::GetObjectClass(aObject);
   MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));
 
   const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
       DOMIfaceAndProtoJSClass::FromJSClass(clasp);
   return JS_NewStringCopyZ(aCx, ifaceAndProtoJSClass->mToString);
 }
 
 bool Constructor(JSContext* cx, unsigned argc, JS::Value* vp) {
@@ -721,27 +721,27 @@ static bool DefineConstructor(JSContext*
 
   // This is Enumerable: False per spec.
   return alreadyDefined ||
          JS_DefineProperty(cx, global, name, constructor, JSPROP_RESOLVING);
 }
 
 static JSObject* CreateInterfaceObject(
     JSContext* cx, JS::Handle<JSObject*> global,
-    JS::Handle<JSObject*> constructorProto, const js::Class* constructorClass,
+    JS::Handle<JSObject*> constructorProto, const JSClass* constructorClass,
     unsigned ctorNargs, const NamedConstructor* namedConstructors,
     JS::Handle<JSObject*> proto, const NativeProperties* properties,
     const NativeProperties* chromeOnlyProperties, const char* name,
     bool isChrome, bool defineOnGlobal,
     const char* const* legacyWindowAliases) {
   JS::Rooted<JSObject*> constructor(cx);
   MOZ_ASSERT(constructorProto);
   MOZ_ASSERT(constructorClass);
-  constructor = JS_NewObjectWithGivenProto(cx, Jsvalify(constructorClass),
-                                           constructorProto);
+  constructor =
+      JS_NewObjectWithGivenProto(cx, constructorClass, constructorProto);
   if (!constructor) {
     return nullptr;
   }
 
   if (!JS_DefineProperty(cx, constructor, "length", ctorNargs,
                          JSPROP_READONLY)) {
     return nullptr;
   }
@@ -850,23 +850,23 @@ static JSObject* CreateInterfaceObject(
     }
   }
 
   return constructor;
 }
 
 static JSObject* CreateInterfacePrototypeObject(
     JSContext* cx, JS::Handle<JSObject*> global,
-    JS::Handle<JSObject*> parentProto, const js::Class* protoClass,
+    JS::Handle<JSObject*> parentProto, const JSClass* protoClass,
     const NativeProperties* properties,
     const NativeProperties* chromeOnlyProperties,
     const char* const* unscopableNames, const char* toStringTag,
     bool isGlobal) {
   JS::Rooted<JSObject*> ourProto(
-      cx, JS_NewObjectWithUniqueType(cx, Jsvalify(protoClass), parentProto));
+      cx, JS_NewObjectWithUniqueType(cx, protoClass, parentProto));
   if (!ourProto ||
       // We don't try to define properties on the global's prototype; those
       // properties go on the global itself.
       (!isGlobal &&
        !DefineProperties(cx, ourProto, properties, chromeOnlyProperties))) {
     return nullptr;
   }
 
@@ -948,19 +948,19 @@ bool DefineProperties(JSContext* cx, JS:
     }
   }
 
   return true;
 }
 
 void CreateInterfaceObjects(
     JSContext* cx, JS::Handle<JSObject*> global,
-    JS::Handle<JSObject*> protoProto, const js::Class* protoClass,
+    JS::Handle<JSObject*> protoProto, const JSClass* protoClass,
     JS::Heap<JSObject*>* protoCache, const char* toStringTag,
-    JS::Handle<JSObject*> constructorProto, const js::Class* constructorClass,
+    JS::Handle<JSObject*> constructorProto, const JSClass* constructorClass,
     unsigned ctorNargs, const NamedConstructor* namedConstructors,
     JS::Heap<JSObject*>* constructorCache, const NativeProperties* properties,
     const NativeProperties* chromeOnlyProperties, const char* name,
     bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal,
     const char* const* legacyWindowAliases) {
   MOZ_ASSERT(protoClass || constructorClass, "Need at least one class!");
   MOZ_ASSERT(
       !((properties &&
@@ -1086,33 +1086,33 @@ bool TryPreserveWrapper(JS::Handle<JSObj
 
   // The addProperty hook for WebIDL classes does wrapper preservation, and
   // nothing else, so call it, if present.
   const DOMJSClass* domClass = GetDOMClass(obj);
   const JSClass* clasp = domClass->ToJSClass();
   JSAddPropertyOp addProperty = clasp->getAddProperty();
 
   // We expect all proxies to be nsISupports.
-  MOZ_RELEASE_ASSERT(!js::Valueify(clasp)->isProxy(),
+  MOZ_RELEASE_ASSERT(!clasp->isProxy(),
                      "Should not call addProperty for proxies.");
 
   // The class should have an addProperty hook iff it is a CC participant.
   MOZ_RELEASE_ASSERT(bool(domClass->mParticipant) == bool(addProperty));
 
   if (!addProperty) {
     return true;
   }
 
   JS::Rooted<jsid> dummyId(RootingCx());
   JS::Rooted<JS::Value> dummyValue(RootingCx());
   return addProperty(nullptr, obj, dummyId, dummyValue);
 }
 
 // Can only be called with a DOM JSClass.
-bool InstanceClassHasProtoAtDepth(const js::Class* clasp, uint32_t protoID,
+bool InstanceClassHasProtoAtDepth(const JSClass* clasp, uint32_t protoID,
                                   uint32_t depth) {
   const DOMJSClass* domClass = DOMJSClass::FromJSClass(clasp);
   return static_cast<uint32_t>(domClass->mInterfaceChain[depth]) == protoID;
 }
 
 // Only set allowNativeWrapper to false if you really know you need it; if in
 // doubt use true. Setting it to false disables security wrappers.
 bool XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
@@ -1321,17 +1321,17 @@ inline const NativePropertyHooks* GetNat
       obj, CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT);
   const JSNativeHolder* nativeHolder =
       static_cast<const JSNativeHolder*>(v.toPrivate());
   return nativeHolder->mPropertyHooks;
 }
 
 inline const NativePropertyHooks* GetNativePropertyHooks(
     JSContext* cx, JS::Handle<JSObject*> obj, DOMObjectType& type) {
-  const js::Class* clasp = js::GetObjectClass(obj);
+  const JSClass* clasp = js::GetObjectClass(obj);
 
   const DOMJSClass* domClass = GetDOMClass(clasp);
   if (domClass) {
     bool isGlobal = (clasp->flags & JSCLASS_DOM_GLOBAL) != 0;
     type = isGlobal ? eGlobalInstance : eInstance;
     return domClass->mNativeHooks;
   }
 
@@ -1737,17 +1737,17 @@ static void DEBUG_CheckXBLLookup(JSConte
     if (id.get() == GetJSIDByIndex(cx, XPCJSContext::IDX_PROTOTYPE)) {
       return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count ||
              ResolvePrototypeOrConstructor(
                  cx, wrapper, obj, nativePropertyHooks->mPrototypeID,
                  JSPROP_PERMANENT | JSPROP_READONLY, desc, cacheOnHolder);
     }
 
     if (id.get() == GetJSIDByIndex(cx, XPCJSContext::IDX_ISINSTANCE)) {
-      const js::Class* objClass = js::GetObjectClass(obj);
+      const JSClass* objClass = js::GetObjectClass(obj);
       if (IsDOMIfaceAndProtoClass(objClass) &&
           DOMIfaceAndProtoJSClass::FromJSClass(objClass)
               ->wantsInterfaceHasInstance) {
         cacheOnHolder = true;
         JSNativeWrapper interfaceIsInstanceWrapper = {InterfaceIsInstance,
                                                       nullptr};
         JSObject* funObj =
             XrayCreateFunction(cx, wrapper, interfaceIsInstanceWrapper, 1, id);
@@ -1761,17 +1761,17 @@ static void DEBUG_CheckXBLLookup(JSConte
         desc.setSetter(nullptr);
         desc.setGetter(nullptr);
         return true;
       }
     }
 
     if (id.get() == SYMBOL_TO_JSID(JS::GetWellKnownSymbol(
                         cx, JS::SymbolCode::hasInstance))) {
-      const js::Class* objClass = js::GetObjectClass(obj);
+      const JSClass* objClass = js::GetObjectClass(obj);
       if (IsDOMIfaceAndProtoClass(objClass) &&
           DOMIfaceAndProtoJSClass::FromJSClass(objClass)
               ->wantsInterfaceHasInstance) {
         cacheOnHolder = true;
         JSNativeWrapper interfaceHasInstanceWrapper = {InterfaceHasInstance,
                                                        nullptr};
         JSObject* funObj =
             XrayCreateFunction(cx, wrapper, interfaceHasInstanceWrapper, 1, id);
@@ -2420,17 +2420,17 @@ bool InterfaceHasInstance(JSContext* cx,
   // constructors, which are not cross-origin objects.
   JS::Rooted<JSObject*> thisObj(
       cx, js::CheckedUnwrapStatic(&args.thisv().toObject()));
   if (!thisObj) {
     // Just fall back on the normal thing, in case it still happens to work.
     return CallOrdinaryHasInstance(cx, args);
   }
 
-  const js::Class* thisClass = js::GetObjectClass(thisObj);
+  const JSClass* thisClass = js::GetObjectClass(thisObj);
 
   if (!IsDOMIfaceAndProtoClass(thisClass)) {
     return CallOrdinaryHasInstance(cx, args);
   }
 
   const DOMIfaceAndProtoJSClass* clasp =
       DOMIfaceAndProtoJSClass::FromJSClass(thisClass);
 
@@ -2496,17 +2496,17 @@ bool InterfaceIsInstance(JSContext* cx, 
   // whether this is a DOM constructor.
   JS::Rooted<JSObject*> thisObj(
       cx, js::CheckedUnwrapStatic(&args.thisv().toObject()));
   if (!thisObj) {
     args.rval().setBoolean(false);
     return true;
   }
 
-  const js::Class* thisClass = js::GetObjectClass(thisObj);
+  const JSClass* thisClass = js::GetObjectClass(thisObj);
   if (!IsDOMIfaceAndProtoClass(thisClass)) {
     args.rval().setBoolean(false);
     return true;
   }
 
   const DOMIfaceAndProtoJSClass* clasp =
       DOMIfaceAndProtoJSClass::FromJSClass(thisClass);
 
@@ -3424,17 +3424,17 @@ bool ForEachHandler(JSContext* aCx, unsi
   }
   JS::Rooted<JS::Value> rval(aCx, JS::UndefinedValue());
   // Now actually call the user specified callback
   return JS::Call(aCx, args.thisv(), callbackFn, newArgs, &rval);
 }
 
 static inline prototypes::ID GetProtoIdForNewtarget(
     JS::Handle<JSObject*> aNewTarget) {
-  const js::Class* newTargetClass = js::GetObjectClass(aNewTarget);
+  const JSClass* newTargetClass = js::GetObjectClass(aNewTarget);
   if (IsDOMIfaceAndProtoClass(newTargetClass)) {
     const DOMIfaceAndProtoJSClass* newTargetIfaceClass =
         DOMIfaceAndProtoJSClass::FromJSClass(newTargetClass);
     if (newTargetIfaceClass->mType == eInterface) {
       return newTargetIfaceClass->mPrototypeID;
     }
   } else if (JS_IsNativeFunction(aNewTarget, Constructor)) {
     return GetNativePropertyHooksFromConstructorFunction(aNewTarget)
--- 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");
 
@@ -129,17 +117,17 @@ inline T* UnwrapPossiblyNotInitializedDO
 
   JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
   if (val.isUndefined()) {
     return nullptr;
   }
   return static_cast<T*>(val.toPrivate());
 }
 
-inline const DOMJSClass* GetDOMClass(const js::Class* clasp) {
+inline const DOMJSClass* GetDOMClass(const JSClass* clasp) {
   return IsDOMClass(clasp) ? DOMJSClass::FromJSClass(clasp) : nullptr;
 }
 
 inline const DOMJSClass* GetDOMClass(JSObject* obj) {
   return GetDOMClass(js::GetObjectClass(obj));
 }
 
 inline nsISupports* UnwrapDOMObjectToISupports(JSObject* aObject) {
@@ -729,19 +717,19 @@ struct NamedConstructor {
  * At least one of protoClass, constructorClass or constructor should be
  * non-null. If constructorClass or constructor are non-null, the resulting
  * interface object will be defined on the given global with property name
  * |name|, which must also be non-null.
  */
 // clang-format on
 void CreateInterfaceObjects(
     JSContext* cx, JS::Handle<JSObject*> global,
-    JS::Handle<JSObject*> protoProto, const js::Class* protoClass,
+    JS::Handle<JSObject*> protoProto, const JSClass* protoClass,
     JS::Heap<JSObject*>* protoCache, const char* toStringTag,
-    JS::Handle<JSObject*> interfaceProto, const js::Class* constructorClass,
+    JS::Handle<JSObject*> interfaceProto, const JSClass* constructorClass,
     unsigned ctorNargs, const NamedConstructor* namedConstructors,
     JS::Heap<JSObject*>* constructorCache,
     const NativeProperties* regularProperties,
     const NativeProperties* chromeOnlyProperties, const char* name,
     bool defineOnGlobal, const char* const* unscopableNames, bool isGlobal,
     const char* const* legacyWindowAliases);
 
 /**
@@ -1383,17 +1371,18 @@ inline void ClearWrapper(T* p, nsWrapper
   // Skip clearing the wrapper when replaying. This method is called during
   // finalization of |obj|, and when replaying a strong reference is kept on
   // the contents of the cache: since |obj| is being finalized, the cache
   // cannot point to |obj|, and clearing here won't do anything.
   // Additionally, the reference held on the cache may have already been
   // released, if we are finalizing later than we did while recording, and the
   // cache may have already been deleted.
   if (!recordreplay::IsReplaying()) {
-    MOZ_ASSERT(cache->GetWrapperMaybeDead() == obj);
+    MOZ_ASSERT(cache->GetWrapperMaybeDead() == obj ||
+               (js::RuntimeIsBeingDestroyed() && !cache->GetWrapperMaybeDead()));
     cache->ClearWrapper(obj);
   }
 }
 
 template <class T>
 inline void ClearWrapper(T* p, void*, JSObject* obj) {
   // QueryInterface to nsWrapperCache can't GC, we hope.
   JS::AutoSuppressGCAnalysis nogc;
@@ -1428,17 +1417,17 @@ inline void UpdateWrapper(T* p, void*, J
 // because the object can only be obtained by JS once, or they cannot be
 // meaningfully owned from the native side.
 //
 // This operation will return false only for non-nsISupports cycle-collected
 // objects, because we cannot determine if they are wrappercached or not.
 bool TryPreserveWrapper(JS::Handle<JSObject*> obj);
 
 // Can only be called with a DOM JSClass.
-bool InstanceClassHasProtoAtDepth(const js::Class* clasp, uint32_t protoID,
+bool InstanceClassHasProtoAtDepth(const JSClass* clasp, uint32_t protoID,
                                   uint32_t depth);
 
 // Only set allowNativeWrapper to false if you really know you need it; if in
 // doubt use true. Setting it to false disables security wrappers.
 bool XPCOMObjectToJsval(JSContext* cx, JS::Handle<JSObject*> scope,
                         xpcObjectHelper& helper, const nsIID* iid,
                         bool allowNativeWrapper,
                         JS::MutableHandle<JS::Value> rval);
@@ -2279,17 +2268,17 @@ inline bool XrayGetNativeProto(JSContext
         protop.set(protoGetter(cx));
       } else {
         protop.set(JS::GetRealmObjectPrototype(cx));
       }
     } else if (JS_ObjectIsFunction(obj)) {
       MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
       protop.set(JS::GetRealmFunctionPrototype(cx));
     } else {
-      const js::Class* clasp = js::GetObjectClass(obj);
+      const JSClass* clasp = js::GetObjectClass(obj);
       MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));
       ProtoGetter protoGetter =
           DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mGetParentProto;
       protop.set(protoGetter(cx));
     }
   }
 
   return JS_WrapObject(cx, protop);
@@ -2343,28 +2332,28 @@ inline JSObject* GetCachedSlotStorageObj
 
 extern NativePropertyHooks sEmptyNativePropertyHooks;
 
 extern const JSClassOps sBoringInterfaceObjectClassClassOps;
 
 extern const js::ObjectOps sInterfaceObjectClassObjectOps;
 
 inline bool UseDOMXray(JSObject* obj) {
-  const js::Class* clasp = js::GetObjectClass(obj);
+  const JSClass* clasp = js::GetObjectClass(obj);
   return IsDOMClass(clasp) || JS_IsNativeFunction(obj, Constructor) ||
          IsDOMIfaceAndProtoClass(clasp);
 }
 
 inline bool IsDOMConstructor(JSObject* obj) {
   if (JS_IsNativeFunction(obj, dom::Constructor)) {
     // NamedConstructor, like Image
     return true;
   }
 
-  const js::Class* clasp = js::GetObjectClass(obj);
+  const JSClass* clasp = js::GetObjectClass(obj);
   // Check for a DOM interface object.
   return dom::IsDOMIfaceAndProtoClass(clasp) &&
          dom::DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mType ==
              dom::eInterface;
 }
 
 #ifdef DEBUG
 inline bool HasConstructor(JSObject* obj) {
@@ -2594,17 +2583,17 @@ class MOZ_STACK_CLASS BindingJSObjectCre
   explicit BindingJSObjectCreator(JSContext* aCx) : mReflector(aCx) {}
 
   ~BindingJSObjectCreator() {
     if (mReflector) {
       js::SetReservedSlot(mReflector, DOM_OBJECT_SLOT, JS::UndefinedValue());
     }
   }
 
-  void CreateProxyObject(JSContext* aCx, const js::Class* aClass,
+  void CreateProxyObject(JSContext* aCx, const JSClass* aClass,
                          const DOMProxyHandler* aHandler,
                          JS::Handle<JSObject*> aProto, bool aLazyProto,
                          T* aNative, JS::Handle<JS::Value> aExpandoValue,
                          JS::MutableHandle<JSObject*> aReflector) {
     js::ProxyOptions options;
     options.setClass(aClass);
     options.setLazyProto(aLazyProto);
 
--- a/dom/bindings/DOMJSClass.h
+++ b/dom/bindings/DOMJSClass.h
@@ -413,17 +413,17 @@ typedef JSObject* (*WebIDLDeserializer)(
                                         nsIGlobalObject* aGlobal,
                                         JSStructuredCloneReader* aReader);
 
 // Special JSClass for reflected DOM objects.
 struct DOMJSClass {
   // It would be nice to just inherit from JSClass, but that precludes pure
   // compile-time initialization of the form |DOMJSClass = {...};|, since C++
   // only allows brace initialization for aggregate/POD types.
-  const js::Class mBase;
+  const JSClass mBase;
 
   // A list of interfaces that this object implements, in order of decreasing
   // derivedness.
   const prototypes::ID mInterfaceChain[MAX_PROTOTYPE_CHAIN_LENGTH];
 
   // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in
   // the proxy private if we use a proxy object.
   // Sometimes it's an nsISupports and sometimes it's not; this class tells
@@ -447,30 +447,26 @@ 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); }
+  const JSClass* ToJSClass() const { return &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
+  // It would be nice to just inherit from JSClass, but that precludes pure
   // compile-time initialization of the form
   // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace
   // initialization for aggregate/POD types.
-  const js::Class mBase;
+  const JSClass mBase;
 
   // Either eInterface, eInterfacePrototype, eGlobalInterfacePrototype or
   // eNamedPropertiesObject.
   DOMObjectType mType;  // uint8_t
 
   // Boolean indicating whether this object wants a @@hasInstance property
   // pointing to InterfaceHasInstance defined on it.  Only ever true for the
   // eInterface case.
@@ -486,21 +482,18 @@ 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); }
+  const JSClass* ToJSClass() const { return &mBase; }
 };
 
 class ProtoAndIfaceCache;
 
 inline bool DOMGlobalHasProtoAndIFaceCache(JSObject* global) {
   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
   // This can be undefined if we GC while creating the global
   return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -148,17 +148,17 @@ class DOMProxyHandler : public BaseDOMPr
 
 // Class used by shadowing handlers (the ones that have [OverrideBuiltins].
 // This handles tracing the expando in ExpandoAndGeneration.
 class ShadowingDOMProxyHandler : public DOMProxyHandler {
   virtual void trace(JSTracer* trc, JSObject* proxy) const override;
 };
 
 inline bool IsDOMProxy(JSObject* obj) {
-  const js::Class* clasp = js::GetObjectClass(obj);
+  const JSClass* clasp = js::GetObjectClass(obj);
   return clasp->isProxy() &&
          js::GetProxyHandler(obj)->family() == &DOMProxyHandler::family;
 }
 
 inline const DOMProxyHandler* GetDOMProxyHandler(JSObject* obj) {
   MOZ_ASSERT(IsDOMProxy(obj));
   return static_cast<const DOMProxyHandler*>(js::GetProxyHandler(obj));
 }
--- a/dom/bindings/RemoteObjectProxy.cpp
+++ b/dom/bindings/RemoteObjectProxy.cpp
@@ -166,17 +166,17 @@ bool RemoteObjectProxyBase::getOwnEnumer
 const char* RemoteObjectProxyBase::className(
     JSContext* aCx, JS::Handle<JSObject*> aProxy) const {
   MOZ_ASSERT(js::IsProxy(aProxy));
 
   return "Object";
 }
 
 void RemoteObjectProxyBase::GetOrCreateProxyObject(
-    JSContext* aCx, void* aNative, const js::Class* aClasp,
+    JSContext* aCx, void* aNative, const JSClass* aClasp,
     JS::Handle<JSObject*> aTransplantTo, JS::MutableHandle<JSObject*> aProxy,
     bool& aNewObjectCreated) const {
   xpc::CompartmentPrivate* priv =
       xpc::CompartmentPrivate::Get(JS::CurrentGlobalOrNull(aCx));
   xpc::CompartmentPrivate::RemoteProxyMap& map = priv->GetRemoteProxyMap();
   auto result = map.lookupForAdd(aNative);
   if (result) {
     MOZ_ASSERT(!aTransplantTo,
--- a/dom/bindings/RemoteObjectProxy.h
+++ b/dom/bindings/RemoteObjectProxy.h
@@ -111,17 +111,17 @@ class RemoteObjectProxyBase : public js:
   /**
    * Gets an existing cached proxy object, or creates a new one and caches it.
    * aProxy will be null on failure. aNewObjectCreated is set to true if a new
    * object was created, callers probably need to addref the native in that
    * case. aNewObjectCreated can be true even if aProxy is null, if something
    * failed after creating the object.
    */
   void GetOrCreateProxyObject(JSContext* aCx, void* aNative,
-                              const js::Class* aClasp,
+                              const JSClass* aClasp,
                               JS::Handle<JSObject*> aTransplantTo,
                               JS::MutableHandle<JSObject*> aProxy,
                               bool& aNewObjectCreated) const;
 
   const prototypes::ID mPrototypeID;
 
   friend struct SetDOMProxyInformation;
   static const char sCrossOriginProxyFamily;
@@ -165,17 +165,17 @@ class RemoteObjectProxy : public RemoteO
 
  private:
   bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                     JS::MutableHandle<JSObject*> aHolder) const final {
     return MaybeCrossOriginObjectMixins::EnsureHolder(
         aCx, aProxy, /* slot = */ 0, P, F, aHolder);
   }
 
-  static const js::Class sClass;
+  static const JSClass sClass;
 };
 
 /**
  * Returns true if aObj is a cross-process proxy object that
  * represents an object implementing the WebIDL interface for
  * aProtoID.
  */
 inline bool IsRemoteObjectProxy(JSObject* aObj, prototypes::ID aProtoID) {
--- a/dom/bindings/SimpleGlobalObject.cpp
+++ b/dom/bindings/SimpleGlobalObject.cpp
@@ -71,24 +71,24 @@ static const JSClassOps SimpleGlobalClas
     nullptr,
     nullptr,
     JS_GlobalObjectTraceHook,
 };
 
 static const js::ClassExtension SimpleGlobalClassExtension = {
     SimpleGlobal_moved};
 
-const js::Class SimpleGlobalClass = {
-    "",
-    JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE |
-        JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_FOREGROUND_FINALIZE,
-    &SimpleGlobalClassOps,
-    JS_NULL_CLASS_SPEC,
-    &SimpleGlobalClassExtension,
-    JS_NULL_OBJECT_OPS};
+const JSClass SimpleGlobalClass = {"",
+                                   JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE |
+                                       JSCLASS_PRIVATE_IS_NSISUPPORTS |
+                                       JSCLASS_FOREGROUND_FINALIZE,
+                                   &SimpleGlobalClassOps,
+                                   JS_NULL_CLASS_SPEC,
+                                   &SimpleGlobalClassExtension,
+                                   JS_NULL_OBJECT_OPS};
 
 // static
 JSObject* SimpleGlobalObject::Create(GlobalType globalType,
                                      JS::Handle<JS::Value> proto) {
   // We can't root our return value with our AutoJSAPI because the rooting
   // analysis thinks ~AutoJSAPI can GC.  So we need to root in a scope outside
   // the lifetime of the AutoJSAPI.
   JS::Rooted<JSObject*> global(RootingCx());
@@ -106,20 +106,20 @@ JSObject* SimpleGlobalObject::Create(Glo
         // compartments.  This should help them be GCed quicker and take up
         // less memory before they're GCed.
         .setNewCompartmentInSystemZone();
 
     if (NS_IsMainThread()) {
       nsCOMPtr<nsIPrincipal> principal =
           NullPrincipal::CreateWithoutOriginAttributes();
       options.creationOptions().setTrace(xpc::TraceXPCGlobal);
-      global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
+      global = xpc::CreateGlobalObject(cx, &SimpleGlobalClass,
                                        nsJSPrincipals::get(principal), options);
     } else {
-      global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nullptr,
+      global = JS_NewGlobalObject(cx, &SimpleGlobalClass, nullptr,
                                   JS::DontFireOnNewGlobalHook, options);
     }
 
     if (!global) {
       jsapi.ClearException();
       return nullptr;
     }
 
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -3,30 +3,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLLinkElement.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Components.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLLinkElementBinding.h"
 #include "nsContentUtils.h"
+#include "nsDOMTokenList.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
-#include "nsDOMTokenList.h"
+#include "nsHTMLDNSPrefetch.h"
 #include "nsIContentInlines.h"
 #include "mozilla/dom/Document.h"
 #include "nsINode.h"
+#include "nsIPrefetchService.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIURL.h"
 #include "nsPIDOMWindow.h"
 #include "nsReadableUtils.h"
 #include "nsStyleConsts.h"
 #include "nsStyleLinkElement.h"
 #include "nsUnicharUtils.h"
 #include "nsWindowSizes.h"
@@ -119,19 +122,16 @@ bool HTMLLinkElement::HasDeferredDNSPref
 
 nsresult HTMLLinkElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (IsInComposedDoc()) {
-    if (!aContext.OwnerDoc().NodePrincipal()->IsSystemPrincipal()) {
-      aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
-    }
     TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
   }
 
   void (HTMLLinkElement::*update)() =
       &HTMLLinkElement::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(
       NewRunnableMethod("dom::HTMLLinkElement::BindToTree", this, update));
 
@@ -324,19 +324,19 @@ nsresult HTMLLinkElement::AfterSetAttr(i
          aName == nsGkAtoms::type || aName == nsGkAtoms::as ||
          aName == nsGkAtoms::crossorigin ||
          (aName == nsGkAtoms::disabled &&
           StaticPrefs::dom_link_disabled_attribute_enabled()))) {
       bool dropSheet = false;
       if (aName == nsGkAtoms::rel) {
         nsAutoString value;
         aValue->ToString(value);
-        uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(value);
+        uint32_t linkTypes = ParseLinkTypes(value);
         if (GetSheet()) {
-          dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET);
+          dropSheet = !(linkTypes & eSTYLESHEET);
         }
       }
 
       if ((aName == nsGkAtoms::rel || aName == nsGkAtoms::href) &&
           IsInComposedDoc()) {
         TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
       }
 
@@ -417,34 +417,34 @@ nsDOMTokenList* HTMLLinkElement::RelList
 
 already_AddRefed<nsIURI> HTMLLinkElement::GetHrefURI() const {
   return GetHrefURIForAnchors();
 }
 
 Maybe<nsStyleLinkElement::SheetInfo> HTMLLinkElement::GetStyleSheetInfo() {
   nsAutoString rel;
   GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
-  uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
-  if (!(linkTypes & nsStyleLinkElement::eSTYLESHEET)) {
+  uint32_t linkTypes = ParseLinkTypes(rel);
+  if (!(linkTypes & eSTYLESHEET)) {
     return Nothing();
   }
 
   if (!IsCSSMimeTypeAttribute(*this)) {
     return Nothing();
   }
 
   if (StaticPrefs::dom_link_disabled_attribute_enabled() && Disabled()) {
     return Nothing();
   }
 
   nsAutoString title;
   nsAutoString media;
   GetTitleAndMediaForElement(*this, title, media);
 
-  bool alternate = linkTypes & nsStyleLinkElement::eALTERNATE;
+  bool alternate = linkTypes & eALTERNATE;
   if (alternate && title.IsEmpty()) {
     // alternates must have title.
     return Nothing();
   }
 
   nsAutoString href;
   GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
   if (href.IsEmpty()) {
@@ -484,16 +484,279 @@ JSObject* HTMLLinkElement::WrapNode(JSCo
                                     JS::Handle<JSObject*> aGivenProto) {
   return HTMLLinkElement_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void HTMLLinkElement::GetAs(nsAString& aResult) {
   GetEnumAttr(nsGkAtoms::as, EmptyCString().get(), aResult);
 }
 
+static const nsAttrValue::EnumTable kAsAttributeTable[] = {
+    {"", DESTINATION_INVALID},      {"audio", DESTINATION_AUDIO},
+    {"font", DESTINATION_FONT},     {"image", DESTINATION_IMAGE},
+    {"script", DESTINATION_SCRIPT}, {"style", DESTINATION_STYLE},
+    {"track", DESTINATION_TRACK},   {"video", DESTINATION_VIDEO},
+    {"fetch", DESTINATION_FETCH},   {nullptr, 0}};
+
+/* static */
+void HTMLLinkElement::ParseAsValue(const nsAString& aValue,
+                                   nsAttrValue& aResult) {
+  DebugOnly<bool> success =
+      aResult.ParseEnumValue(aValue, kAsAttributeTable, false,
+                             // default value is a empty string
+                             // if aValue is not a value we
+                             // understand
+                             &kAsAttributeTable[0]);
+  MOZ_ASSERT(success);
+}
+
+/* static */
+nsContentPolicyType HTMLLinkElement::AsValueToContentPolicy(
+    const nsAttrValue& aValue) {
+  switch (aValue.GetEnumValue()) {
+    case DESTINATION_INVALID:
+      return nsIContentPolicy::TYPE_INVALID;
+    case DESTINATION_AUDIO:
+      return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
+    case DESTINATION_TRACK:
+      return nsIContentPolicy::TYPE_INTERNAL_TRACK;
+    case DESTINATION_VIDEO:
+      return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
+    case DESTINATION_FONT:
+      return nsIContentPolicy::TYPE_FONT;
+    case DESTINATION_IMAGE:
+      return nsIContentPolicy::TYPE_IMAGE;
+    case DESTINATION_SCRIPT:
+      return nsIContentPolicy::TYPE_SCRIPT;
+    case DESTINATION_STYLE:
+      return nsIContentPolicy::TYPE_STYLESHEET;
+    case DESTINATION_FETCH:
+      return nsIContentPolicy::TYPE_OTHER;
+  }
+  return nsIContentPolicy::TYPE_INVALID;
+}
+
+void HTMLLinkElement::GetContentPolicyMimeTypeMedia(
+    nsAttrValue& aAsAttr, nsContentPolicyType& aPolicyType, nsString& aMimeType,
+    nsAString& aMedia) {
+  nsAutoString as;
+  GetAttr(kNameSpaceID_None, nsGkAtoms::as, as);
+  ParseAsValue(as, aAsAttr);
+  aPolicyType = AsValueToContentPolicy(aAsAttr);
+
+  nsAutoString type;
+  GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
+  nsAutoString notUsed;
+  nsContentUtils::SplitMimeType(type, aMimeType, notUsed);
+
+  GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
+}
+
+void HTMLLinkElement::
+    TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender() {
+  MOZ_ASSERT(IsInComposedDoc());
+  if (!ElementHasHref()) {
+    return;
+  }
+
+  nsAutoString rel;
+  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
+    return;
+  }
+
+  if (!nsContentUtils::PrefetchPreloadEnabled(OwnerDoc()->GetDocShell())) {
+    return;
+  }
+
+  uint32_t linkTypes = ParseLinkTypes(rel);
+
+  if ((linkTypes & ePREFETCH) || (linkTypes & eNEXT) ||
+      (linkTypes & ePRELOAD)) {
+    nsCOMPtr<nsIPrefetchService> prefetchService(
+        components::Prefetch::Service());
+    if (prefetchService) {
+      nsCOMPtr<nsIURI> uri(GetURI());
+      if (uri) {
+        bool preload = !!(linkTypes & ePRELOAD);
+        nsContentPolicyType policyType;
+
+        if (preload) {
+          nsAttrValue asAttr;
+          nsAutoString mimeType;
+          nsAutoString media;
+          GetContentPolicyMimeTypeMedia(asAttr, policyType, mimeType, media);
+
+          if (policyType == nsIContentPolicy::TYPE_INVALID) {
+            // Ignore preload with a wrong or empty as attribute.
+            return;
+          }
+
+          if (!CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
+            policyType = nsIContentPolicy::TYPE_INVALID;
+          }
+        }
+
+        nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+        referrerInfo->InitWithNode(this);
+        if (preload) {
+          prefetchService->PreloadURI(uri, referrerInfo, this, policyType);
+        } else {
+          prefetchService->PrefetchURI(uri, referrerInfo, this,
+                                       linkTypes & ePREFETCH);
+        }
+        return;
+      }
+    }
+  }
+
+  if (linkTypes & ePRECONNECT) {
+    if (nsCOMPtr<nsIURI> uri = GetURI()) {
+      OwnerDoc()->MaybePreconnect(
+          uri, AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)));
+      return;
+    }
+  }
+
+  if (linkTypes & eDNS_PREFETCH) {
+    if (nsHTMLDNSPrefetch::IsAllowed(OwnerDoc())) {
+      nsHTMLDNSPrefetch::PrefetchLow(this);
+    }
+  }
+}
+
+void HTMLLinkElement::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
+                                    const nsAttrValue* aOldValue) {
+  MOZ_ASSERT(IsInComposedDoc());
+
+  if (!ElementHasHref()) {
+    return;
+  }
+
+  nsAutoString rel;
+  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
+    return;
+  }
+
+  if (!nsContentUtils::PrefetchPreloadEnabled(OwnerDoc()->GetDocShell())) {
+    return;
+  }
+
+  uint32_t linkTypes = ParseLinkTypes(rel);
+
+  if (!(linkTypes & ePRELOAD)) {
+    return;
+  }
+
+  nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
+  if (!prefetchService) {
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri(GetURI());
+  if (!uri) {
+    return;
+  }
+
+  nsAttrValue asAttr;
+  nsContentPolicyType asPolicyType;
+  nsAutoString mimeType;
+  nsAutoString media;
+  GetContentPolicyMimeTypeMedia(asAttr, asPolicyType, mimeType, media);
+
+  if (asPolicyType == nsIContentPolicy::TYPE_INVALID) {
+    // Ignore preload with a wrong or empty as attribute, but be sure to cancel
+    // the old one.
+    prefetchService->CancelPrefetchPreloadURI(uri, this);
+    return;
+  }
+
+  nsContentPolicyType policyType = asPolicyType;
+  if (!CheckPreloadAttrs(asAttr, mimeType, media, OwnerDoc())) {
+    policyType = nsIContentPolicy::TYPE_INVALID;
+  }
+
+  if (aName == nsGkAtoms::crossorigin) {
+    CORSMode corsMode = AttrValueToCORSMode(aValue);
+    CORSMode oldCorsMode = AttrValueToCORSMode(aOldValue);
+    if (corsMode != oldCorsMode) {
+      prefetchService->CancelPrefetchPreloadURI(uri, this);
+
+      nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+      referrerInfo->InitWithNode(this);
+      prefetchService->PreloadURI(uri, referrerInfo, this, policyType);
+    }
+    return;
+  }
+
+  nsContentPolicyType oldPolicyType;
+
+  if (aName == nsGkAtoms::as) {
+    if (aOldValue) {
+      oldPolicyType = AsValueToContentPolicy(*aOldValue);
+      if (!CheckPreloadAttrs(*aOldValue, mimeType, media, OwnerDoc())) {
+        oldPolicyType = nsIContentPolicy::TYPE_INVALID;
+      }
+    } else {
+      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
+    }
+  } else if (aName == nsGkAtoms::type) {
+    nsAutoString oldType;
+    nsAutoString notUsed;
+    if (aOldValue) {
+      aOldValue->ToString(oldType);
+    } else {
+      oldType = EmptyString();
+    }
+    nsAutoString oldMimeType;
+    nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed);
+    if (CheckPreloadAttrs(asAttr, oldMimeType, media, OwnerDoc())) {
+      oldPolicyType = asPolicyType;
+    } else {
+      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
+    }
+  } else {
+    MOZ_ASSERT(aName == nsGkAtoms::media);
+    nsAutoString oldMedia;
+    if (aOldValue) {
+      aOldValue->ToString(oldMedia);
+    } else {
+      oldMedia = EmptyString();
+    }
+    if (CheckPreloadAttrs(asAttr, mimeType, oldMedia, OwnerDoc())) {
+      oldPolicyType = asPolicyType;
+    } else {
+      oldPolicyType = nsIContentPolicy::TYPE_INVALID;
+    }
+  }
+
+  if ((policyType != oldPolicyType) &&
+      (oldPolicyType != nsIContentPolicy::TYPE_INVALID)) {
+    prefetchService->CancelPrefetchPreloadURI(uri, this);
+  }
+
+  // Trigger a new preload if the policy type has changed.
+  // Also trigger load if the new policy type is invalid, this will only
+  // trigger an error event.
+  if ((policyType != oldPolicyType) ||
+      (policyType == nsIContentPolicy::TYPE_INVALID)) {
+    nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
+    referrerInfo->InitWithNode(this);
+    prefetchService->PreloadURI(uri, referrerInfo, this, policyType);
+  }
+}
+
+void HTMLLinkElement::CancelPrefetchOrPreload() {
+  nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
+  if (prefetchService) {
+    if (nsCOMPtr<nsIURI> uri = GetURI()) {
+      prefetchService->CancelPrefetchPreloadURI(uri, this);
+    }
+  }
+}
+
 // We will use official mime-types from:
 // https://www.iana.org/assignments/media-types/media-types.xhtml#font
 // We do not support old deprecated mime-types for preload feature.
 // (We currectly do not support font/collection)
 static uint32_t StyleLinkElementFontMimeTypesNum = 5;
 static const char* StyleLinkElementFontMimeTypes[] = {
     "font/otf", "font/sfnt", "font/ttf", "font/woff", "font/woff2"};
 
@@ -508,17 +771,17 @@ bool IsFontMimeType(const nsAString& aTy
   }
   return false;
 }
 
 bool HTMLLinkElement::CheckPreloadAttrs(const nsAttrValue& aAs,
                                         const nsAString& aType,
                                         const nsAString& aMedia,
                                         Document* aDocument) {
-  nsContentPolicyType policyType = Link::AsValueToContentPolicy(aAs);
+  nsContentPolicyType policyType = AsValueToContentPolicy(aAs);
   if (policyType == nsIContentPolicy::TYPE_INVALID) {
     return false;
   }
 
   // Check if media attribute is valid.
   if (!aMedia.IsEmpty()) {
     RefPtr<MediaList> mediaList = MediaList::Create(aMedia);
     if (!mediaList->Matches(*aDocument)) {
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -12,16 +12,18 @@
 #include "nsGenericHTMLElement.h"
 #include "nsStyleLinkElement.h"
 
 namespace mozilla {
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 namespace dom {
 
+// NOTE(emilio): If we stop inheriting from Link, we need to remove the
+// IsHTMLElement(nsGkAtoms::link) checks in Link.cpp.
 class HTMLLinkElement final : public nsGenericHTMLElement,
                               public nsStyleLinkElement,
                               public Link {
  public:
   explicit HTMLLinkElement(
       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
   // nsISupports
@@ -113,16 +115,20 @@ class HTMLLinkElement final : public nsG
   }
   void SetHreflang(const nsAString& aHreflang, ErrorResult& aRv) {
     SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
   }
   void GetAs(nsAString& aResult);
   void SetAs(const nsAString& aAs, ErrorResult& aRv) {
     SetAttr(nsGkAtoms::as, aAs, aRv);
   }
+
+  static void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult);
+  static nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue);
+
   nsDOMTokenList* Sizes() { return GetTokenList(nsGkAtoms::sizes); }
   void GetType(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::type, aValue); }
   void SetType(const nsAString& aType, ErrorResult& aRv) {
     SetHTMLAttr(nsGkAtoms::type, aType, aRv);
   }
   void GetCharset(nsAString& aValue) override {
     GetHTMLAttr(nsGkAtoms::charset, aValue);
   }
@@ -160,16 +166,24 @@ class HTMLLinkElement final : public nsG
   }
 
   static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
                                 const nsAString& aMedia, Document* aDocument);
 
  protected:
   virtual ~HTMLLinkElement();
 
+  void GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
+                                     nsContentPolicyType& aPolicyType,
+                                     nsString& aMimeType, nsAString& aMedia);
+  void TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
+  void UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
+                     const nsAttrValue* aOldValue);
+  void CancelPrefetchOrPreload();
+
   // nsStyleLinkElement
   Maybe<SheetInfo> GetStyleSheetInfo() final;
 
   RefPtr<nsDOMTokenList> mRelList;
 
   // The "explicitly enabled" flag. This flag is set whenever the `disabled`
   // attribute is explicitly unset, and makes alternate stylesheets not be
   // disabled by default anymore.
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -228,17 +228,17 @@ static bool NPObjWrapper_toPrimitive(JSC
                                      JS::Value* vp);
 
 static bool CreateNPObjectMember(NPP npp, JSContext* cx,
                                  JS::Handle<JSObject*> obj, NPObject* npobj,
                                  JS::Handle<jsid> id,
                                  NPVariant* getPropertyResult,
                                  JS::MutableHandle<JS::Value> vp);
 
-const js::Class sNPObjWrapperProxyClass =
+const JSClass sNPObjWrapperProxyClass =
     PROXY_CLASS_DEF(NPRUNTIME_JSCLASS_NAME, JSCLASS_HAS_RESERVED_SLOTS(1));
 
 typedef struct NPObjectMemberPrivate {
   JS::Heap<JSObject*> npobjWrapper;
   JS::Heap<JS::Value> fieldValue;
   JS::Heap<jsid> methodName;
   NPP npp = nullptr;
 } NPObjectMemberPrivate;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3646,16 +3646,18 @@ already_AddRefed<nsIEventTarget> WorkerP
 }
 
 bool WorkerPrivate::RunCurrentSyncLoop() {
   AssertIsOnWorkerThread();
 
   JSContext* cx = GetJSContext();
   MOZ_ASSERT(cx);
 
+  AutoPushEventLoopGlobal eventLoopGlobal(this, cx);
+
   // This should not change between now and the time we finish running this sync
   // loop.
   uint32_t currentLoopIndex = mSyncLoopStack.Length() - 1;
 
   SyncLoopInfo* loopInfo = mSyncLoopStack[currentLoopIndex];
 
   MOZ_ASSERT(loopInfo);
   MOZ_ASSERT(!loopInfo->mHasRun);
@@ -3710,17 +3712,20 @@ bool WorkerPrivate::RunCurrentSyncLoop()
 
     if (normalRunnablesPending) {
       // Make sure the periodic timer is running before we continue.
       SetGCTimerMode(PeriodicTimer);
 
       MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(mThread, false));
 
       // Now *might* be a good time to GC. Let the JS engine make the decision.
-      if (JS::CurrentGlobalOrNull(cx)) {
+      if (GetCurrentEventLoopGlobal()) {
+        // If GetCurrentEventLoopGlobal() is non-null, our JSContext is in a
+        // Realm, so it's safe to try to GC.
+        MOZ_ASSERT(JS::CurrentGlobalOrNull(cx));
         JS_MaybeGC(cx);
       }
     }
   }
 
   // Make sure that the stack didn't change underneath us.
   MOZ_ASSERT(mSyncLoopStack[currentLoopIndex] == loopInfo);
 
@@ -3899,16 +3904,19 @@ void WorkerPrivate::PostMessageToParent(
   }
 }
 
 void WorkerPrivate::EnterDebuggerEventLoop() {
   MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
 
   JSContext* cx = GetJSContext();
   MOZ_ASSERT(cx);
+
+  AutoPushEventLoopGlobal eventLoopGlobal(this, cx);
+
   CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
 
   uint32_t currentEventLoopLevel = ++data->mDebuggerEventLoopLevel;
 
   while (currentEventLoopLevel <= data->mDebuggerEventLoopLevel) {
     bool debuggerRunnablesPending = false;
 
     {
@@ -3953,17 +3961,20 @@ void WorkerPrivate::EnterDebuggerEventLo
 
       MOZ_ASSERT(runnable);
       static_cast<nsIRunnable*>(runnable)->Run();
       runnable->Release();
 
       ccjscx->PerformDebuggerMicroTaskCheckpoint();
 
       // Now *might* be a good time to GC. Let the JS engine make the decision.
-      if (JS::CurrentGlobalOrNull(cx)) {
+      if (GetCurrentEventLoopGlobal()) {
+        // If GetCurrentEventLoopGlobal() is non-null, our JSContext is in a
+        // Realm, so it's safe to try to GC.
+        MOZ_ASSERT(JS::CurrentGlobalOrNull(cx));
         JS_MaybeGC(cx);
       }
     }
   }
 }
 
 void WorkerPrivate::LeaveDebuggerEventLoop() {
   MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
@@ -4961,10 +4972,25 @@ WorkerPrivate::EventTarget::IsOnCurrentT
   if (!mWorkerPrivate) {
     NS_WARNING("A worker's event target was used after the worker has !");
     return false;
   }
 
   return mWorkerPrivate->IsOnCurrentThread();
 }
 
+WorkerPrivate::AutoPushEventLoopGlobal::AutoPushEventLoopGlobal(
+    WorkerPrivate* aWorkerPrivate, JSContext* aCx)
+    : mWorkerPrivate(aWorkerPrivate) {
+  MOZ_ACCESS_THREAD_BOUND(mWorkerPrivate->mWorkerThreadAccessible, data);
+  mOldEventLoopGlobal = data->mCurrentEventLoopGlobal.forget();
+  if (JSObject* global = JS::CurrentGlobalOrNull(aCx)) {
+    data->mCurrentEventLoopGlobal = xpc::NativeGlobal(global);
+  }
+}
+
+WorkerPrivate::AutoPushEventLoopGlobal::~AutoPushEventLoopGlobal() {
+  MOZ_ACCESS_THREAD_BOUND(mWorkerPrivate->mWorkerThreadAccessible, data);
+  data->mCurrentEventLoopGlobal = mOldEventLoopGlobal.forget();
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -312,16 +312,24 @@ class WorkerPrivate : public RelativeTim
     return data->mScope;
   }
 
   WorkerDebuggerGlobalScope* DebuggerGlobalScope() const {
     MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
     return data->mDebuggerScope;
   }
 
+  // Get the global associated with the current nested event loop.  Will return
+  // null if we're not in a nested event loop or that nested event loop does not
+  // have an associated global.
+  nsIGlobalObject* GetCurrentEventLoopGlobal() const {
+    MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
+    return data->mCurrentEventLoopGlobal;
+  }
+
   nsICSPEventListener* CSPEventListener() const;
 
   void SetThread(WorkerThread* aThread);
 
   void SetWorkerPrivateInWorkerThread(WorkerThread* aThread);
 
   void ResetWorkerPrivateInWorkerThread();
 
@@ -1093,31 +1101,55 @@ class WorkerPrivate : public RelativeTim
     nsCOMPtr<nsITimerCallback> mTimerRunnable;
 
     nsCOMPtr<nsITimer> mGCTimer;
 
     RefPtr<MemoryReporter> mMemoryReporter;
 
     UniquePtr<ClientSource> mClientSource;
 
+    // While running a nested event loop, whether a sync loop or a debugger
+    // event loop we want to keep track of which global is running it, if any,
+    // so runnables that run off that event loop can get at that information. In
+    // practice this only matters for various worker debugger runnables running
+    // against sandboxes, because all other runnables know which globals they
+    // belong to already.  We could also address this by threading the relevant
+    // global through the chains of runnables involved, but we'd need to thread
+    // it through some runnables that run on the main thread, and that would
+    // require some care to make sure things get released on the correct thread,
+    // which we'd rather avoid.  This member is only accessed on the worker
+    // thread.
+    nsCOMPtr<nsIGlobalObject> mCurrentEventLoopGlobal;
+
     uint32_t mNumWorkerRefsPreventingShutdownStart;
     uint32_t mDebuggerEventLoopLevel;
 
     uint32_t mErrorHandlerRecursionCount;
     uint32_t mNextTimeoutId;
 
     bool mFrozen;
     bool mTimerRunning;
     bool mRunningExpiredTimeouts;
     bool mPeriodicGCTimerRunning;
     bool mIdleGCTimerRunning;
     bool mOnLine;
   };
   ThreadBound<WorkerThreadAccessible> mWorkerThreadAccessible;
 
+  class MOZ_RAII AutoPushEventLoopGlobal {
+   public:
+    AutoPushEventLoopGlobal(WorkerPrivate* aWorkerPrivate, JSContext* aCx);
+    ~AutoPushEventLoopGlobal();
+
+   private:
+    WorkerPrivate* mWorkerPrivate;
+    nsCOMPtr<nsIGlobalObject> mOldEventLoopGlobal;
+  };
+  friend class AutoPushEventLoopGlobal;
+
   uint32_t mPostSyncLoopOperations;
 
   // List of operations to do at the end of the last sync event loop.
   enum {
     ePendingEventQueueClearing = 0x01,
     eDispatchCancelingRunnable = 0x02,
   };
 
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -264,25 +264,18 @@ WorkerRunnable::Run() {
   }
 
   // Track down the appropriate global, if any, to use for the AutoEntryScript.
   nsCOMPtr<nsIGlobalObject> globalObject;
   bool isMainThread = !targetIsWorkerThread && !mWorkerPrivate->GetParent();
   MOZ_ASSERT(isMainThread == NS_IsMainThread());
   RefPtr<WorkerPrivate> kungFuDeathGrip;
   if (targetIsWorkerThread) {
-    JSContext* cx = GetCurrentWorkerThreadJSContext();
-    if (NS_WARN_IF(!cx)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    JSObject* global = JS::CurrentGlobalOrNull(cx);
-    if (global) {
-      globalObject = xpc::NativeGlobal(global);
-    } else {
+    globalObject = mWorkerPrivate->GetCurrentEventLoopGlobal();
+    if (!globalObject) {
       globalObject = DefaultGlobalObject();
     }
 
     // We may still not have a globalObject here: in the case of
     // CompileScriptRunnable, we don't actually create the global object until
     // we have the script data, which happens in a syncloop under
     // CompileScriptRunnable::WorkerRun, so we can't assert that it got created
     // in the PreRun call above.
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -30,16 +30,18 @@
 #include "nsIWeakReferenceUtils.h"
 #include "nsIWidget.h"
 #include "nsLayoutUtils.h"
 #include "nsQueryFrame.h"
 #include "TouchManager.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollbarMediator.h"
+#include "mozilla/StaticPrefs_dom.h"
+#include "mozilla/StaticPrefs_ui.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/widget/nsAutoRollup.h"
 
 #define APZES_LOG(...)
 // #define APZES_LOG(...) printf_stderr("APZES: " __VA_ARGS__)
 
 // Static helper functions
 namespace {
@@ -88,19 +90,16 @@ int32_t WidgetModifiersToDOMModifiers(mo
   return result;
 }
 
 }  // namespace
 
 namespace mozilla {
 namespace layers {
 
-static int32_t sActiveDurationMs = 10;
-static bool sActiveDurationMsSet = false;
-
 APZEventState::APZEventState(nsIWidget* aWidget,
                              ContentReceivedInputBlockCallback&& aCallback)
     : mWidget(nullptr)  // initialized in constructor body
       ,
       mActiveElementManager(new ActiveElementManager()),
       mContentReceivedInputBlockCallback(std::move(aCallback)),
       mPendingTouchPreventedResponse(false),
       mPendingTouchPreventedBlockId(0),
@@ -108,23 +107,16 @@ APZEventState::APZEventState(nsIWidget* 
       mFirstTouchCancelled(false),
       mTouchEndCancelled(false),
       mLastTouchIdentifier(0) {
   nsresult rv;
   mWidget = do_GetWeakReference(aWidget, &rv);
   MOZ_ASSERT(NS_SUCCEEDED(rv),
              "APZEventState constructed with a widget that"
              " does not support weak references. APZ will NOT work!");
-
-  if (!sActiveDurationMsSet) {
-    Preferences::AddIntVarCache(&sActiveDurationMs,
-                                "ui.touch_activation.duration_ms",
-                                sActiveDurationMs);
-    sActiveDurationMsSet = true;
-  }
 }
 
 APZEventState::~APZEventState() {}
 
 class DelayedFireSingleTapEvent final : public nsITimerCallback,
                                         public nsINamed {
  public:
   NS_DECL_ISUPPORTS
@@ -198,18 +190,19 @@ void APZEventState::ProcessSingleTap(con
   dom::BrowserChild* browserChild = widget->GetOwningBrowserChild();
 
   if (browserChild && XRE_IsContentProcess()) {
     timer->SetTarget(
         browserChild->TabGroup()->EventTargetFor(TaskCategory::Other));
   }
   RefPtr<DelayedFireSingleTapEvent> callback = new DelayedFireSingleTapEvent(
       mWidget, ldPoint, aModifiers, aClickCount, timer, touchRollup);
-  nsresult rv = timer->InitWithCallback(callback, sActiveDurationMs,
-                                        nsITimer::TYPE_ONE_SHOT);
+  nsresult rv = timer->InitWithCallback(
+      callback, StaticPrefs::ui_touch_activation_duration_ms(),
+      nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     // Make |callback| not hold the timer, so they will both be destructed when
     // we leave the scope of this function.
     callback->ClearTimer();
   }
 }
 
 bool APZEventState::FireContextmenuEvents(PresShell* aPresShell,
--- a/gfx/layers/apz/util/ActiveElementManager.cpp
+++ b/gfx/layers/apz/util/ActiveElementManager.cpp
@@ -2,40 +2,31 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ActiveElementManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/PresShell.h"
+#include "mozilla/StaticPrefs_ui.h"
 #include "base/message_loop.h"
 #include "base/task.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Document.h"
 
 #define AEM_LOG(...)
 // #define AEM_LOG(...) printf_stderr("AEM: " __VA_ARGS__)
 
 namespace mozilla {
 namespace layers {
 
-static int32_t sActivationDelayMs = 100;
-static bool sActivationDelayMsSet = false;
-
 ActiveElementManager::ActiveElementManager()
     : mCanBePan(false), mCanBePanSet(false), mSetActiveTask(nullptr) {
-  if (!sActivationDelayMsSet) {
-    Preferences::AddIntVarCache(&sActivationDelayMs,
-                                "ui.touch_activation.delay_ms",
-                                sActivationDelayMs);
-    sActivationDelayMsSet = true;
-  }
 }
 
 ActiveElementManager::~ActiveElementManager() {}
 
 void ActiveElementManager::SetTargetElement(dom::EventTarget* aTarget) {
   if (mTarget) {
     // Multiple fingers on screen (since HandleTouchEnd clears mTarget).
     AEM_LOG("Multiple fingers on-screen, clearing target element\n");
@@ -83,17 +74,18 @@ void ActiveElementManager::TriggerElemen
                    // bug properly should make this unnecessary.
     MOZ_ASSERT(mSetActiveTask == nullptr);
 
     RefPtr<CancelableRunnable> task =
         NewCancelableRunnableMethod<nsCOMPtr<dom::Element>>(
             "layers::ActiveElementManager::SetActiveTask", this,
             &ActiveElementManager::SetActiveTask, mTarget);
     mSetActiveTask = task;
-    MessageLoop::current()->PostDelayedTask(task.forget(), sActivationDelayMs);
+    MessageLoop::current()->PostDelayedTask(
+        task.forget(), StaticPrefs::ui_touch_activation_delay_ms());
     AEM_LOG("Scheduling mSetActiveTask %p\n", mSetActiveTask);
   }
 }
 
 void ActiveElementManager::ClearActivation() {
   AEM_LOG("Clearing element activation\n");
   CancelTask();
   ResetActive();
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -2404,17 +2404,17 @@ impl BatchBuilder {
                 );
 
                 let prim_cache_address = gpu_cache.get_address(&ctx.globals.default_image_handle);
                 let backdrop_picture = &ctx.prim_store.pictures[backdrop_pic_index.0];
                 let prim_header = PrimitiveHeader {
                     local_rect: backdrop_picture.snapped_local_rect,
                     local_clip_rect: prim_info.combined_local_clip_rect,
                     transform_id,
-                    snap_offsets,
+                    snap_offsets: SnapOffsets::empty(),
                     specific_prim_address: prim_cache_address,
                 };
 
                 let prim_header_index = prim_headers.push(
                     &prim_header,
                     z_id,
                     [
                         ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1959,16 +1959,20 @@ impl PictureCompositeMode {
                         FilterPrimitiveKind::Identity(ref primitive) =>
                             primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
                         FilterPrimitiveKind::Opacity(ref primitive) =>
                             primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
                         FilterPrimitiveKind::ColorMatrix(ref primitive) =>
                             primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
                         FilterPrimitiveKind::ComponentTransfer(ref primitive) =>
                             primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
+                        FilterPrimitiveKind::Offset(ref primitive) => {
+                            let input_rect = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
+                            input_rect.translate(primitive.offset * Scale::new(1.0))
+                        },
 
                         FilterPrimitiveKind::Flood(..) => picture_rect,
                     };
                     output_rects.push(output_rect);
                     result_rect = result_rect.union(&output_rect);
                 }
             }
             _ => {},
--- a/gfx/wr/webrender/src/prim_store/picture.rs
+++ b/gfx/wr/webrender/src/prim_store/picture.rs
@@ -26,16 +26,17 @@ pub enum FilterPrimitiveKey {
     Identity(ColorSpace, FilterPrimitiveInput),
     Flood(ColorSpace, ColorU),
     Blend(ColorSpace, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveInput),
     Blur(ColorSpace, Au, FilterPrimitiveInput),
     Opacity(ColorSpace, Au, FilterPrimitiveInput),
     ColorMatrix(ColorSpace, [Au; 20], FilterPrimitiveInput),
     DropShadow(ColorSpace, (VectorKey, Au, ColorU), FilterPrimitiveInput),
     ComponentTransfer(ColorSpace, FilterPrimitiveInput, Vec<SFilterData>),
+    Offset(ColorSpace, FilterPrimitiveInput, VectorKey),
 }
 
 /// Represents a hashable description of how a picture primitive
 /// will be composited into its parent.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
 pub enum PictureCompositeKey {
@@ -170,16 +171,18 @@ impl From<Option<PictureCompositeMode>> 
                                     Au::from_f32_px(drop_shadow.shadow.blur_radius),
                                     drop_shadow.shadow.color.into(),
                                 ),
                                 drop_shadow.input,
                             )
                         }
                         FilterPrimitiveKind::ComponentTransfer(component_transfer) =>
                             FilterPrimitiveKey::ComponentTransfer(primitive.color_space, component_transfer.input, filter_data.clone()),
+                        FilterPrimitiveKind::Offset(info) =>
+                            FilterPrimitiveKey::Offset(primitive.color_space, info.input, info.offset.into()),
                     }
                 }).collect())
             }
             Some(PictureCompositeMode::Blit(_)) |
             Some(PictureCompositeMode::TileCache { .. }) |
             None => {
                 PictureCompositeKey::Identity
             }
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -1471,16 +1471,36 @@ impl RenderTask {
                             vec![input_task_id],
                             content_size,
                             uv_rect_kind,
                             SvgFilterInfo::ComponentTransfer(filter_data.clone()),
                         );
                         render_tasks.add(task)
                     }
                 }
+                FilterPrimitiveKind::Offset(ref info) => {
+                    let input_task_id = get_task_input(
+                        &info.input,
+                        filter_primitives,
+                        render_tasks,
+                        cur_index,
+                        &outputs,
+                        original_task_id,
+                        primitive.color_space
+                    );
+
+                    let offset = info.offset * LayoutToWorldScale::new(1.0) * device_pixel_scale;
+                    let offset_task = RenderTask::new_svg_filter_primitive(
+                        vec![input_task_id],
+                        content_size,
+                        uv_rect_kind,
+                        SvgFilterInfo::Offset(offset),
+                    );
+                    render_tasks.add(offset_task)
+                }
             };
             outputs.push(render_task_id);
         }
 
         // The output of a filter is the output of the last primitive in the chain.
         let mut render_task_id = *outputs.last().unwrap();
 
         // Convert to sRGB if needed
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -832,31 +832,39 @@ pub struct ComponentTransferPrimitive {
 }
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
 pub struct IdentityPrimitive {
     pub input: FilterPrimitiveInput,
 }
 
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
+pub struct OffsetPrimitive {
+    pub input: FilterPrimitiveInput,
+    pub offset: LayoutVector2D,
+}
+
 /// See: https://github.com/eqrion/cbindgen/issues/9
 /// cbindgen:derive-eq=false
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
 pub enum FilterPrimitiveKind {
     Identity(IdentityPrimitive),
     Blend(BlendPrimitive),
     Flood(FloodPrimitive),
     Blur(BlurPrimitive),
     // TODO: Support animated opacity?
     Opacity(OpacityPrimitive),
     /// cbindgen:derive-eq=false
     ColorMatrix(ColorMatrixPrimitive),
     DropShadow(DropShadowPrimitive),
     ComponentTransfer(ComponentTransferPrimitive),
+    Offset(OffsetPrimitive),
 }
 
 impl Default for FilterPrimitiveKind {
     fn default() -> Self {
         FilterPrimitiveKind::Identity(IdentityPrimitive::default())
     }
 }
 
@@ -867,16 +875,17 @@ impl FilterPrimitiveKind {
             FilterPrimitiveKind::Blur(blur) => blur.sanitize(),
             FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
             FilterPrimitiveKind::DropShadow(drop_shadow) => drop_shadow.sanitize(),
 
             // No sanitization needed.
             FilterPrimitiveKind::Identity(..) |
             FilterPrimitiveKind::Blend(..) |
             FilterPrimitiveKind::ColorMatrix(..) |
+            FilterPrimitiveKind::Offset(..) |
             // Component transfer's filter data is sanitized separately.
             FilterPrimitiveKind::ComponentTransfer(..) => {}
         }
     }
 }
 
 /// SVG Filter Primitive.
 /// See: https://github.com/eqrion/cbindgen/issues/9
index 382171c2ae92000af8ba16378ea243b4ac6cc863..ef24c5c4f3635a2b5d0e0b1ecceceb7b6676fe95
GIT binary patch
literal 60137
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
--- a/gfx/wr/wrench/reftests/filters/reftest.list
+++ b/gfx/wr/wrench/reftests/filters/reftest.list
@@ -53,8 +53,9 @@ platform(linux,mac) == draw_calls(8) col
 platform(linux,mac) == svg-filter-drop-shadow.yaml svg-filter-drop-shadow.png
 == fuzzy(1,10000) svg-srgb-to-linear.yaml srgb-to-linear-ref.yaml
 platform(linux,mac) == fuzzy(4,28250) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml
 platform(linux,mac) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png
 platform(linux,mac) == svg-filter-drop-shadow-on-viewport-edge.yaml svg-filter-drop-shadow-on-viewport-edge.png
 platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-filter-drop-shadow-perspective.png
 == backdrop-filter-basic.yaml backdrop-filter-basic-ref.yaml
 platform(linux,mac) == backdrop-filter-perspective.yaml backdrop-filter-perspective.png
+platform(linux,max) == svg-filter-offset.yaml svg-filter-offset-ref.yaml
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/filters/svg-filter-offset-ref.yaml
@@ -0,0 +1,11 @@
+# Tests the SVG offset filter primitive
+# An offset filter should have the same effect as changing the origin of the rectangle.
+---
+root:
+  items:
+    - type: stacking-context
+      bounds: 0 0 0 0
+      items:
+      - type: rect
+        bounds: 20 20 100 100
+        color: red
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/filters/svg-filter-offset.yaml
@@ -0,0 +1,15 @@
+# Tests the SVG offset filter primitive
+# An offset filter should have the same effect as changing the origin of the rectangle.
+---
+root:
+  items:
+    - type: stacking-context
+      bounds: 0 0 0 0
+      filter-primitives:
+      - type: offset
+        offset: 10 10
+        in: original
+      items:
+      - type: rect
+        bounds: 10 10 100 100
+        color: red
--- a/gfx/wr/wrench/src/yaml_frame_writer.rs
+++ b/gfx/wr/wrench/src/yaml_frame_writer.rs
@@ -394,16 +394,21 @@ fn write_filter_primitives(
                 vector_node(&mut table, "offset", &drop_shadow_primitive.shadow.offset);
                 color_node(&mut table, "color", drop_shadow_primitive.shadow.color);
                 f32_node(&mut table, "radius", drop_shadow_primitive.shadow.blur_radius);
             }
             FilterPrimitiveKind::ComponentTransfer(component_transfer_primitive) => {
                 yaml_node(&mut table, "type", Yaml::String("component-transfer".into()));
                 filter_input_node(&mut table, "in", component_transfer_primitive.input);
             }
+            FilterPrimitiveKind::Offset(info) => {
+                yaml_node(&mut table, "type", Yaml::String("offset".into()));
+                filter_input_node(&mut table, "in", info.input);
+                vector_node(&mut table, "offset", &info.offset);
+            }
         }
         enum_node(&mut table, "color-space", filter_primitive.color_space);
         filter_primitives.push(Yaml::Hash(table));
     }
 
     yaml_node(parent, name, Yaml::Array(filter_primitives));
 }
 
--- a/gfx/wr/wrench/src/yaml_helper.rs
+++ b/gfx/wr/wrench/src/yaml_helper.rs
@@ -764,16 +764,22 @@ impl YamlHelper for Yaml {
                         }
                     })
                 }
                 "component-transfer" => {
                     FilterPrimitiveKind::ComponentTransfer(ComponentTransferPrimitive {
                         input: self["in"].as_filter_input().unwrap(),
                     })
                 }
+                "offset" => {
+                    FilterPrimitiveKind::Offset(OffsetPrimitive {
+                        input: self["in"].as_filter_input().unwrap(),
+                        offset: self["offset"].as_vector().unwrap(),
+                    })
+                }
                 _ => return None,
             };
 
             Some(FilterPrimitive {
                 kind,
                 color_space: self["color-space"].as_color_space().unwrap_or(ColorSpace::LinearRgb),
             })
         } else {
--- a/intl/hyphenation/glue/nsHyphenationManager.cpp
+++ b/intl/hyphenation/glue/nsHyphenationManager.cpp
@@ -32,24 +32,16 @@ static const char kMemoryPressureNotific
 class HyphenReporter final : public nsIMemoryReporter,
                              public CountingAllocatorBase<HyphenReporter> {
  private:
   ~HyphenReporter() = default;
 
  public:
   NS_DECL_ISUPPORTS
 
-  static void* Malloc(long aSize) { return CountingMalloc(aSize); }
-
-  static void Free(void* aPtr) { return CountingFree(aPtr); }
-
-  static void* Realloc(void* aPtr, long aNewSize) {
-    return CountingRealloc(aPtr, aNewSize);
-  }
-
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                             nsISupports* aData, bool aAnonymize) override {
     size_t total = MemoryAllocated();
     if (nsHyphenationManager::Instance()) {
       total += nsHyphenationManager::Instance()->SizeOfIncludingThis(
           moz_malloc_size_of);
     }
     MOZ_COLLECT_REPORT("explicit/hyphenation", KIND_HEAP, UNITS_BYTES, total,
@@ -61,30 +53,33 @@ class HyphenReporter final : public nsIM
 NS_IMPL_ISUPPORTS(HyphenReporter, nsIMemoryReporter)
 
 template <>
 CountingAllocatorBase<HyphenReporter>::AmountType
     CountingAllocatorBase<HyphenReporter>::sAmount(0);
 
 /**
  * Allocation wrappers to track the amount of memory allocated by libhyphen.
+ * Note that libhyphen assumes its malloc/realloc functions are infallible!
  */
 extern "C" {
 void* hnj_malloc(size_t aSize);
 void* hnj_realloc(void* aPtr, size_t aSize);
 void hnj_free(void* aPtr);
 };
 
-void* hnj_malloc(size_t aSize) { return HyphenReporter::Malloc(aSize); }
+void* hnj_malloc(size_t aSize) {
+  return HyphenReporter::InfallibleCountingMalloc(aSize);
+}
 
 void* hnj_realloc(void* aPtr, size_t aSize) {
-  return HyphenReporter::Realloc(aPtr, aSize);
+  return HyphenReporter::InfallibleCountingRealloc(aPtr, aSize);
 }
 
-void hnj_free(void* aPtr) { HyphenReporter::Free(aPtr); }
+void hnj_free(void* aPtr) { HyphenReporter::CountingFree(aPtr); }
 
 nsHyphenationManager* nsHyphenationManager::sInstance = nullptr;
 
 NS_IMPL_ISUPPORTS(nsHyphenationManager::MemoryPressureObserver, nsIObserver)
 
 NS_IMETHODIMP
 nsHyphenationManager::MemoryPressureObserver::Observe(nsISupports* aSubject,
                                                       const char* aTopic,
--- a/intl/unicharutil/util/ICUUtils.cpp
+++ b/intl/unicharutil/util/ICUUtils.cpp
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef MOZILLA_INTERNAL_API
 
 #  include "mozilla/Assertions.h"
 #  include "mozilla/UniquePtr.h"
 
 #  include "ICUUtils.h"
-#  include "mozilla/Preferences.h"
+#  include "mozilla/StaticPrefs_dom.h"
 #  include "mozilla/intl/LocaleService.h"
 #  include "nsIContent.h"
 #  include "mozilla/dom/Document.h"
 #  include "nsString.h"
 #  include "unicode/uloc.h"
 #  include "unicode/unum.h"
 
 using namespace mozilla;
@@ -25,38 +25,16 @@ class NumberFormatDeleter {
     MOZ_ASSERT(aPtr != nullptr,
                "UniquePtr deleter shouldn't be called for nullptr");
     unum_close(aPtr);
   }
 };
 
 using UniqueUNumberFormat = UniquePtr<UNumberFormat, NumberFormatDeleter>;
 
-/**
- * This pref just controls whether we format the number with grouping separator
- * characters when the internal value is set or updated. It does not stop the
- * user from typing in a number and using grouping separators.
- */
-static bool gLocaleNumberGroupingEnabled;
-static const char LOCALE_NUMBER_GROUPING_PREF_STR[] =
-    "dom.forms.number.grouping";
-
-static bool LocaleNumberGroupingIsEnabled() {
-  static bool sInitialized = false;
-
-  if (!sInitialized) {
-    /* check and register ourselves with the pref */
-    Preferences::AddBoolVarCache(&gLocaleNumberGroupingEnabled,
-                                 LOCALE_NUMBER_GROUPING_PREF_STR, false);
-    sInitialized = true;
-  }
-
-  return gLocaleNumberGroupingEnabled;
-}
-
 void ICUUtils::LanguageTagIterForContent::GetNext(nsACString& aBCP47LangTag) {
   if (mCurrentFallbackIndex < 0) {
     mCurrentFallbackIndex = 0;
     // Try the language specified by a 'lang'/'xml:lang' attribute on mContent
     // or any ancestor, if such an attribute is specified:
     nsAutoString lang;
     mContent->GetLang(lang);
     if (!lang.IsEmpty()) {
@@ -110,17 +88,17 @@ bool ICUUtils::LocalizeNumber(double aVa
         unum_open(UNUM_DECIMAL, nullptr, 0, langTag.get(), nullptr, &status));
     // Since unum_setAttribute have no UErrorCode parameter, we have to
     // check error status.
     if (U_FAILURE(status)) {
       aLangTags.GetNext(langTag);
       continue;
     }
     unum_setAttribute(format.get(), UNUM_GROUPING_USED,
-                      LocaleNumberGroupingIsEnabled());
+                      StaticPrefs::dom_forms_number_grouping());
     // ICU default is a maximum of 3 significant fractional digits. We don't
     // want that limit, so we set it to the maximum that a double can represent
     // (14-16 decimal fractional digits).
     unum_setAttribute(format.get(), UNUM_MAX_FRACTION_DIGITS, 16);
     int32_t length = unum_formatDouble(format.get(), aValue, buffer,
                                        kBufferSize, nullptr, &status);
     NS_ASSERTION(length < kBufferSize && status != U_BUFFER_OVERFLOW_ERROR &&
                      status != U_STRING_NOT_TERMINATED_WARNING,
@@ -146,17 +124,17 @@ double ICUUtils::ParseNumber(nsAString& 
   uint32_t length = aValue.Length();
 
   nsAutoCString langTag;
   aLangTags.GetNext(langTag);
   while (!langTag.IsEmpty()) {
     UErrorCode status = U_ZERO_ERROR;
     UniqueUNumberFormat format(
         unum_open(UNUM_DECIMAL, nullptr, 0, langTag.get(), nullptr, &status));
-    if (!LocaleNumberGroupingIsEnabled()) {
+    if (!StaticPrefs::dom_forms_number_grouping()) {
       unum_setAttribute(format.get(), UNUM_GROUPING_USED, UBool(0));
     }
     int32_t parsePos = 0;
     static_assert(sizeof(UChar) == 2 && sizeof(nsAString::char_type) == 2,
                   "Unexpected character size - the following cast is unsafe");
     double val = unum_parseDouble(format.get(),
                                   (const UChar*)PromiseFlatString(aValue).get(),
                                   length, &parsePos, &status);
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -15,31 +15,30 @@
 
 #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;
+extern JS_FRIEND_DATA const JSClass* const FunctionClassPtr;
 
 }  // namespace js
 
 namespace JS {
 
 /**
  * The answer to a successful query as to whether an object is an Array per
  * ES6's internal |IsArray| operation (as exposed by |Array.isArray|).
@@ -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,96 +868,83 @@ 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");
-
-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;
-}
+namespace js {
 
 /**
  * Enumeration describing possible values of the [[Class]] internal property
  * value of objects.
  */
 enum class ESClass {
   Object,
   Array,
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -370,17 +370,17 @@ class JS_FRIEND_API BaseProxyHandler {
   virtual bool isConstructor(JSObject* obj) const;
 
   virtual bool getElements(JSContext* cx, HandleObject proxy, uint32_t begin,
                            uint32_t end, ElementAdder* adder) const;
 
   virtual bool isScripted() const { return false; }
 };
 
-extern JS_FRIEND_DATA const js::Class ProxyClass;
+extern JS_FRIEND_DATA const JSClass ProxyClass;
 
 inline bool IsProxy(const JSObject* obj) {
   return GetObjectClass(obj)->isProxy();
 }
 
 namespace detail {
 
 // Proxy slot layout
@@ -569,26 +569,26 @@ class MOZ_STACK_CLASS ProxyOptions {
   }
 
   bool lazyProto() const { return lazyProto_; }
   ProxyOptions& setLazyProto(bool flag) {
     lazyProto_ = flag;
     return *this;
   }
 
-  const Class* clasp() const { return clasp_; }
-  ProxyOptions& setClass(const Class* claspArg) {
+  const JSClass* clasp() const { return clasp_; }
+  ProxyOptions& setClass(const JSClass* claspArg) {
     clasp_ = claspArg;
     return *this;
   }
 
  private:
   bool singleton_;
   bool lazyProto_;
-  const Class* clasp_;
+  const JSClass* clasp_;
 };
 
 JS_FRIEND_API JSObject* NewProxyObject(
     JSContext* cx, const BaseProxyHandler* handler, HandleValue priv,
     JSObject* proto, const ProxyOptions& options = ProxyOptions());
 
 JSObject* RenewProxyObject(JSContext* cx, JSObject* obj,
                            BaseProxyHandler* handler, const Value& priv);
@@ -723,17 +723,17 @@ constexpr unsigned CheckProxyFlags() {
                 "Proxies must not use JSCLASS_SKIP_NURSERY_FINALIZE; use "
                 "the canNurseryAllocate() proxy handler method instead.");
   return Flags;
 }
 
 #define PROXY_CLASS_DEF(name, flags)                                       \
   {                                                                        \
     name,                                                                  \
-        js::Class::NON_NATIVE | JSCLASS_IS_PROXY |                         \
+        JSClass::NON_NATIVE | JSCLASS_IS_PROXY |                           \
             JSCLASS_DELAY_METADATA_BUILDER | js::CheckProxyFlags<flags>(), \
         &js::ProxyClassOps, JS_NULL_CLASS_SPEC, &js::ProxyClassExtension,  \
         &js::ProxyObjectOps                                                \
   }
 
 // Converts a proxy into a DeadObjectProxy that will throw exceptions on all
 // access. This will run the proxy's finalizer to perform clean-up before the
 // conversion happens.
--- a/js/public/TypeDecls.h
+++ b/js/public/TypeDecls.h
@@ -21,16 +21,17 @@
 #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 {
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -149,17 +149,16 @@ const EXTRA_CLANG_FLAGS: &'static [&'sta
     "-DRUST_BINDGEN",
 ];
 
 /// Types which we want to generate bindings for (and every other type they
 /// transitively use).
 const WHITELIST_TYPES: &'static [&'static str] = &[
     "JS::AutoCheckCannotGC",
     "JS::CallArgs",
-    "js::Class",
     "JS::RealmOptions",
     "JS::ContextOptions",
     "js::DOMCallbacks",
     "js::DOMProxyShadowsResult",
     "js::ESClass",
     "JS::ForOfIterator",
     "JS::Handle",
     "JS::HandleFunction",
--- a/js/rust/src/glue.rs
+++ b/js/rust/src/glue.rs
@@ -233,17 +233,17 @@ extern "C" {
                       aHandler: *const ::libc::c_void,
                       aClass: *const JSClass,
                       aSingleton: bool)
                       -> *mut JSObject;
     pub fn NewWindowProxy(aCx: *mut JSContext,
                           aObj: JS::HandleObject,
                           aHandler: *const ::libc::c_void)
                           -> *mut JSObject;
-    pub fn GetWindowProxyClass() -> *const js::Class;
+    pub fn GetWindowProxyClass() -> *const JSClass;
     pub fn GetProxyPrivate(obj: *mut JSObject) -> JS::Value;
     pub fn SetProxyPrivate(obj: *mut JSObject, private: *const JS::Value);
     pub fn GetProxyReservedSlot(obj: *mut JSObject, slot: u32) -> JS::Value;
     pub fn SetProxyReservedSlot(obj: *mut JSObject, slot: u32, val: *const JS::Value);
     pub fn RUST_JSID_IS_INT(id: JS::HandleId) -> bool;
     pub fn RUST_JSID_TO_INT(id: JS::HandleId) -> i32;
     pub fn int_to_jsid(i: i32) -> jsid;
     pub fn RUST_JSID_IS_STRING(id: JS::HandleId) -> bool;
--- a/js/rust/src/jsglue.cpp
+++ b/js/rust/src/jsglue.cpp
@@ -451,38 +451,38 @@ JSObject* NewProxyObject(JSContext* aCx,
                             options);
 }
 
 JSObject* WrapperNew(JSContext* aCx, JS::HandleObject aObj,
                      const void* aHandler, const JSClass* aClass,
                      bool aSingleton) {
   js::WrapperOptions options;
   if (aClass) {
-    options.setClass(js::Valueify(aClass));
+    options.setClass(aClass);
   }
   options.setSingleton(aSingleton);
   return js::Wrapper::New(aCx, aObj, (const js::Wrapper*)aHandler, options);
 }
 
-const js::Class WindowProxyClass = PROXY_CLASS_DEF(
+const JSClass WindowProxyClass = PROXY_CLASS_DEF(
     "Proxy", JSCLASS_HAS_RESERVED_SLOTS(1)); /* additional class flags */
 
-const js::Class* GetWindowProxyClass() { return &WindowProxyClass; }
+const JSClass* GetWindowProxyClass() { return &WindowProxyClass; }
 
 JS::Value GetProxyReservedSlot(JSObject* obj, uint32_t slot) {
   return js::GetProxyReservedSlot(obj, slot);
 }
 
 void SetProxyReservedSlot(JSObject* obj, uint32_t slot, const JS::Value* val) {
   js::SetProxyReservedSlot(obj, slot, *val);
 }
 
 JSObject* NewWindowProxy(JSContext* aCx, JS::HandleObject aObj,
                          const void* aHandler) {
-  return WrapperNew(aCx, aObj, aHandler, Jsvalify(&WindowProxyClass), true);
+  return WrapperNew(aCx, aObj, aHandler, &WindowProxyClass, true);
 }
 
 JS::Value GetProxyPrivate(JSObject* obj) { return js::GetProxyPrivate(obj); }
 
 void SetProxyPrivate(JSObject* obj, const JS::Value* expando) {
   js::SetProxyPrivate(obj, *expando);
 }
 
--- 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/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -3988,17 +3988,17 @@ static const ClassSpec ArrayObjectClassS
                              &jit::JitInfo_Array>,
     CreateArrayPrototype,
     array_static_methods,
     array_static_props,
     array_methods,
     nullptr,
     array_proto_finish};
 
-const Class ArrayObject::class_ = {
+const JSClass ArrayObject::class_ = {
     "Array",
     JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_DELAY_METADATA_BUILDER,
     &ArrayObjectClassOps, &ArrayObjectClassSpec};
 
 /*
  * Array allocation functions.
  */
 
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -67,18 +67,18 @@
 #include "vm/Time.h"
 #include "vm/TypedArrayObject.h"
 #include "wasm/WasmInstance.h"
 
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 
-const Class AtomicsObject::class_ = {"Atomics",
-                                     JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics)};
+const JSClass AtomicsObject::class_ = {
+    "Atomics", JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics)};
 
 static bool ReportBadArrayType(JSContext* cx) {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             JSMSG_ATOMICS_BAD_ARRAY);
   return false;
 }
 
 static bool ReportOutOfRange(JSContext* cx) {
--- a/js/src/builtin/AtomicsObject.h
+++ b/js/src/builtin/AtomicsObject.h
@@ -18,17 +18,17 @@
 
 namespace js {
 
 class GlobalObject;
 class SharedArrayRawBuffer;
 
 class AtomicsObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
   static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
   static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc,
                                     Value* vp);
 };
 
 MOZ_MUST_USE bool atomics_compareExchange(JSContext* cx, unsigned argc,
                                           Value* vp);
 MOZ_MUST_USE bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/builtin/BigInt.cpp
+++ b/js/src/builtin/BigInt.cpp
@@ -205,23 +205,23 @@ const ClassSpec BigIntObject::classSpec_
     GenericCreateConstructor<BigIntConstructor, 1, gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<BigIntObject>,
     BigIntObject::staticMethods,
     nullptr,
     BigIntObject::methods,
     BigIntObject::properties};
 
 // The class is named "Object" as a workaround for bug 1277801.
-const Class BigIntObject::class_ = {
+const JSClass BigIntObject::class_ = {
     "Object",
     JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt) |
         JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
     JS_NULL_CLASS_OPS, &BigIntObject::classSpec_};
 
-const Class BigIntObject::protoClass_ = {
+const JSClass BigIntObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt), JS_NULL_CLASS_OPS,
     &BigIntObject::classSpec_};
 
 const JSPropertySpec BigIntObject::properties[] = {
     // BigInt proposal section 5.3.5
     JS_STRING_SYM_PS(toStringTag, "BigInt", JSPROP_READONLY), JS_PS_END};
 
 const JSFunctionSpec BigIntObject::methods[] = {
--- a/js/src/builtin/BigInt.h
+++ b/js/src/builtin/BigInt.h
@@ -17,18 +17,18 @@ namespace js {
 class GlobalObject;
 
 class BigIntObject : public NativeObject {
   static const unsigned PRIMITIVE_VALUE_SLOT = 0;
   static const unsigned RESERVED_SLOTS = 1;
 
  public:
   static const ClassSpec classSpec_;
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
   static JSObject* create(JSContext* cx, JS::Handle<JS::BigInt*> bi);
 
   // Methods defined on BigInt.prototype.
   static bool valueOf_impl(JSContext* cx, const CallArgs& args);
   static bool valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
   static bool toString_impl(JSContext* cx, const CallArgs& args);
   static bool toString(JSContext* cx, unsigned argc, JS::Value* vp);
--- a/js/src/builtin/Boolean.cpp
+++ b/js/src/builtin/Boolean.cpp
@@ -22,17 +22,17 @@
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/ProxyObject.h"
 
 #include "vm/BooleanObject-inl.h"
 
 using namespace js;
 
-const Class BooleanObject::class_ = {
+const JSClass BooleanObject::class_ = {
     "Boolean",
     JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean)};
 
 MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) {
   return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>());
 }
 
 MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext* cx, const CallArgs& args) {
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -997,24 +997,24 @@ const ClassSpec DataViewObject::classSpe
     GenericCreateConstructor<DataViewObject::construct, 1,
                              gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<DataViewObject>,
     nullptr,
     nullptr,
     DataViewObject::methods,
     DataViewObject::properties};
 
-const Class DataViewObject::class_ = {
+const JSClass DataViewObject::class_ = {
     "DataView",
     JSCLASS_HAS_PRIVATE |
         JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
     &DataViewObjectClassOps, &DataViewObject::classSpec_};
 
-const Class DataViewObject::protoClass_ = {
+const JSClass DataViewObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
     JS_NULL_CLASS_OPS, &DataViewObject::classSpec_};
 
 const JSFunctionSpec DataViewObject::methods[] = {
     JS_FN("getInt8", DataViewObject::fun_getInt8, 1, 0),
     JS_FN("getUint8", DataViewObject::fun_getUint8, 1, 0),
     JS_FN("getInt16", DataViewObject::fun_getInt16, 1, 0),
     JS_FN("getUint16", DataViewObject::fun_getUint16, 1, 0),
--- a/js/src/builtin/DataViewObject.h
+++ b/js/src/builtin/DataViewObject.h
@@ -57,18 +57,18 @@ class DataViewObject : public ArrayBuffe
   static bool constructWrapped(JSContext* cx, HandleObject bufobj,
                                const CallArgs& args);
 
   static DataViewObject* create(
       JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
       Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, HandleObject proto);
 
  public:
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
   static Value byteOffsetValue(const DataViewObject* view) {
     Value v = view->getFixedSlot(BYTEOFFSET_SLOT);
     MOZ_ASSERT(v.toInt32() >= 0);
     return v;
   }
 
   static Value byteLengthValue(const DataViewObject* view) {
--- a/js/src/builtin/JSON.cpp
+++ b/js/src/builtin/JSON.cpp
@@ -35,18 +35,18 @@ using namespace js;
 
 using mozilla::CheckedInt;
 using mozilla::IsFinite;
 using mozilla::Maybe;
 using mozilla::RangedPtr;
 
 using JS::AutoStableStringChars;
 
-const Class js::JSONClass = {js_JSON_str,
-                             JSCLASS_HAS_CACHED_PROTO(JSProto_JSON)};
+const JSClass js::JSONClass = {js_JSON_str,
+                               JSCLASS_HAS_CACHED_PROTO(JSProto_JSON)};
 
 /* ES5 15.12.3 Quote.
  * Requires that the destination has enough space allocated for src after
  * escaping (that is, `2 + 6 * (srcEnd - srcBegin)` characters).
  */
 template <typename SrcCharT, typename DstCharT>
 static MOZ_ALWAYS_INLINE RangedPtr<DstCharT> InfallibleQuote(
     RangedPtr<const SrcCharT> srcBegin, RangedPtr<const SrcCharT> srcEnd,
--- a/js/src/builtin/JSON.h
+++ b/js/src/builtin/JSON.h
@@ -10,21 +10,20 @@
 #include "mozilla/Range.h"
 
 #include "NamespaceImports.h"
 
 #include "js/RootingAPI.h"
 
 namespace js {
 
-struct Class;
 class GlobalObject;
 class StringBuffer;
 
-extern const Class JSONClass;
+extern const JSClass JSONClass;
 
 extern JSObject* InitJSONClass(JSContext* cx, Handle<GlobalObject*> obj);
 
 enum class StringifyBehavior { Normal, RestrictedSafe };
 
 /**
  * If maybeSafely is true, Stringify will attempt to assert the API requirements
  * of JS::ToJSONMaybeSafely as it traverses the graph, and will not try to
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -131,17 +131,17 @@ static const JSClassOps MapIteratorObjec
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     MapIteratorObject::finalize};
 
 static const ClassExtension MapIteratorObjectClassExtension = {
     MapIteratorObject::objectMoved};
 
-const Class MapIteratorObject::class_ = {
+const JSClass MapIteratorObject::class_ = {
     "Map Iterator",
     JSCLASS_HAS_RESERVED_SLOTS(MapIteratorObject::SlotCount) |
         JSCLASS_FOREGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE,
     &MapIteratorObjectClassOps, JS_NULL_CLASS_SPEC,
     &MapIteratorObjectClassExtension};
 
 const JSFunctionSpec MapIteratorObject::methods[] = {
     JS_SELF_HOSTED_FN("next", "MapIteratorNext", 0, 0), JS_FS_END};
@@ -387,24 +387,24 @@ const ClassSpec MapObject::classSpec_ = 
     GenericCreateConstructor<MapObject::construct, 0, gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<MapObject>,
     nullptr,
     MapObject::staticProperties,
     MapObject::methods,
     MapObject::properties,
 };
 
-const Class MapObject::class_ = {
+const JSClass MapObject::class_ = {
     "Map",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(MapObject::SlotCount) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_Map) | JSCLASS_FOREGROUND_FINALIZE |
         JSCLASS_SKIP_NURSERY_FINALIZE,
     &MapObject::classOps_, &MapObject::classSpec_};
 
-const Class MapObject::protoClass_ = {
+const JSClass MapObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_Map), JS_NULL_CLASS_OPS,
     &MapObject::classSpec_};
 
 const JSPropertySpec MapObject::properties[] = {
     JS_PSG("size", size, 0),
     JS_STRING_SYM_PS(toStringTag, "Map", JSPROP_READONLY), JS_PS_END};
 
 const JSFunctionSpec MapObject::methods[] = {
@@ -913,17 +913,17 @@ static const JSClassOps SetIteratorObjec
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     SetIteratorObject::finalize};
 
 static const ClassExtension SetIteratorObjectClassExtension = {
     SetIteratorObject::objectMoved};
 
-const Class SetIteratorObject::class_ = {
+const JSClass SetIteratorObject::class_ = {
     "Set Iterator",
     JSCLASS_HAS_RESERVED_SLOTS(SetIteratorObject::SlotCount) |
         JSCLASS_FOREGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE,
     &SetIteratorObjectClassOps, JS_NULL_CLASS_SPEC,
     &SetIteratorObjectClassExtension};
 
 const JSFunctionSpec SetIteratorObject::methods[] = {
     JS_SELF_HOSTED_FN("next", "SetIteratorNext", 0, 0), JS_FS_END};
@@ -1137,26 +1137,26 @@ const ClassSpec SetObject::classSpec_ = 
     GenericCreateConstructor<SetObject::construct, 0, gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<SetObject>,
     nullptr,
     SetObject::staticProperties,
     SetObject::methods,
     SetObject::properties,
 };
 
-const Class SetObject::class_ = {
+const JSClass SetObject::class_ = {
     "Set",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SetObject::SlotCount) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_Set) | JSCLASS_FOREGROUND_FINALIZE |
         JSCLASS_SKIP_NURSERY_FINALIZE,
     &SetObject::classOps_,
     &SetObject::classSpec_,
 };
 
-const Class SetObject::protoClass_ = {
+const JSClass SetObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_Set), JS_NULL_CLASS_OPS,
     &SetObject::classSpec_};
 
 const JSPropertySpec SetObject::properties[] = {
     JS_PSG("size", size, 0),
     JS_STRING_SYM_PS(toStringTag, "Set", JSPROP_READONLY), JS_PS_END};
 
 const JSFunctionSpec SetObject::methods[] = {
--- a/js/src/builtin/MapObject.h
+++ b/js/src/builtin/MapObject.h
@@ -100,18 +100,18 @@ class MapObject : public NativeObject {
   static_assert(Values == ITEM_KIND_VALUE,
                 "IteratorKind Values must match self-hosting define for item "
                 "kind value.");
   static_assert(
       Entries == ITEM_KIND_KEY_AND_VALUE,
       "IteratorKind Entries must match self-hosting define for item kind "
       "key-and-value.");
 
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
   enum { NurseryKeysSlot, HasNurseryMemorySlot, SlotCount };
 
   static MOZ_MUST_USE bool getKeysAndValuesInterleaved(
       HandleObject obj, JS::MutableHandle<GCVector<JS::Value>> entries);
   static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
   static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
   static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
@@ -176,17 +176,17 @@ class MapObject : public NativeObject {
   static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
   static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
   static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
   static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
 };
 
 class MapIteratorObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   enum { TargetSlot, RangeSlot, KindSlot, SlotCount };
 
   static_assert(
       TargetSlot == ITERATOR_SLOT_TARGET,
       "TargetSlot must match self-hosting define for iterated object slot.");
   static_assert(
       RangeSlot == ITERATOR_SLOT_RANGE,
@@ -220,18 +220,18 @@ class SetObject : public NativeObject {
   static_assert(Values == ITEM_KIND_VALUE,
                 "IteratorKind Values must match self-hosting define for item "
                 "kind value.");
   static_assert(
       Entries == ITEM_KIND_KEY_AND_VALUE,
       "IteratorKind Entries must match self-hosting define for item kind "
       "key-and-value.");
 
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
   enum { NurseryKeysSlot, HasNurseryMemorySlot, SlotCount };
 
   static MOZ_MUST_USE bool keys(JSContext* cx, HandleObject obj,
                                 JS::MutableHandle<GCVector<JS::Value>> keys);
   static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
   static MOZ_MUST_USE bool add(JSContext* cx, HandleObject obj,
                                HandleValue key);
@@ -289,17 +289,17 @@ class SetObject : public NativeObject {
   static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
   static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
   static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
   static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
 };
 
 class SetIteratorObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   enum { TargetSlot, RangeSlot, KindSlot, SlotCount };
 
   static_assert(
       TargetSlot == ITERATOR_SLOT_TARGET,
       "TargetSlot must match self-hosting define for iterated object slot.");
   static_assert(
       RangeSlot == ITERATOR_SLOT_RANGE,
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -76,17 +76,17 @@ static bool ModuleValueGetter(JSContext*
     MOZ_ASSERT(value.toNumber() >= 0);           \
     if (value.isInt32()) return value.toInt32(); \
     return JS::ToUint32(value.toDouble());       \
   }
 
 ///////////////////////////////////////////////////////////////////////////
 // ImportEntryObject
 
-/* static */ const Class ImportEntryObject::class_ = {
+/* static */ const JSClass ImportEntryObject::class_ = {
     "ImportEntry", JSCLASS_HAS_RESERVED_SLOTS(ImportEntryObject::SlotCount)};
 
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, localName, LocalNameSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, lineNumber, LineNumberSlot)
 DEFINE_GETTER_FUNCTIONS(ImportEntryObject, columnNumber, ColumnNumberSlot)
 
@@ -148,17 +148,17 @@ ImportEntryObject* ImportEntryObject::cr
   self->initReservedSlot(LineNumberSlot, NumberValue(lineNumber));
   self->initReservedSlot(ColumnNumberSlot, NumberValue(columnNumber));
   return self;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // ExportEntryObject
 
-/* static */ const Class ExportEntryObject::class_ = {
+/* static */ const JSClass ExportEntryObject::class_ = {
     "ExportEntry", JSCLASS_HAS_RESERVED_SLOTS(ExportEntryObject::SlotCount)};
 
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, exportName, ExportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, moduleRequest, ModuleRequestSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, importName, ImportNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, localName, LocalNameSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, lineNumber, LineNumberSlot)
 DEFINE_GETTER_FUNCTIONS(ExportEntryObject, columnNumber, ColumnNumberSlot)
@@ -233,17 +233,17 @@ ExportEntryObject* ExportEntryObject::cr
   self->initReservedSlot(LineNumberSlot, NumberValue(lineNumber));
   self->initReservedSlot(ColumnNumberSlot, NumberValue(columnNumber));
   return self;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // RequestedModuleObject
 
-/* static */ const Class RequestedModuleObject::class_ = {
+/* static */ const JSClass RequestedModuleObject::class_ = {
     "RequestedModule",
     JSCLASS_HAS_RESERVED_SLOTS(RequestedModuleObject::SlotCount)};
 
 DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, moduleSpecifier,
                         ModuleSpecifierSlot)
 DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, lineNumber, LineNumberSlot)
 DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, columnNumber, ColumnNumberSlot)
 
@@ -710,17 +710,17 @@ void FunctionDeclaration::trace(JSTracer
     nullptr, /* resolve     */
     nullptr, /* mayResolve  */
     ModuleObject::finalize,
     nullptr, /* call        */
     nullptr, /* hasInstance */
     nullptr, /* construct   */
     ModuleObject::trace};
 
-/* static */ const Class ModuleObject::class_ = {
+/* static */ const JSClass ModuleObject::class_ = {
     "Module",
     JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) |
         JSCLASS_BACKGROUND_FINALIZE,
     &ModuleObject::classOps_};
 
 #define DEFINE_ARRAY_SLOT_ACCESSOR(cls, name, slot)                 \
   ArrayObject& cls::name() const {                                  \
     return getReservedSlot(cls::slot).toObject().as<ArrayObject>(); \
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -36,17 +36,17 @@ class ImportEntryObject : public NativeO
     ModuleRequestSlot = 0,
     ImportNameSlot,
     LocalNameSlot,
     LineNumberSlot,
     ColumnNumberSlot,
     SlotCount
   };
 
-  static const Class class_;
+  static const JSClass class_;
   static bool isInstance(HandleValue value);
   static ImportEntryObject* create(JSContext* cx, HandleAtom moduleRequest,
                                    HandleAtom importName, HandleAtom localName,
                                    uint32_t lineNumber, uint32_t columnNumber);
   JSAtom* moduleRequest() const;
   JSAtom* importName() const;
   JSAtom* localName() const;
   uint32_t lineNumber() const;
@@ -63,17 +63,17 @@ class ExportEntryObject : public NativeO
     ModuleRequestSlot,
     ImportNameSlot,
     LocalNameSlot,
     LineNumberSlot,
     ColumnNumberSlot,
     SlotCount
   };
 
-  static const Class class_;
+  static const JSClass class_;
   static bool isInstance(HandleValue value);
   static ExportEntryObject* create(JSContext* cx, HandleAtom maybeExportName,
                                    HandleAtom maybeModuleRequest,
                                    HandleAtom maybeImportName,
                                    HandleAtom maybeLocalName,
                                    uint32_t lineNumber, uint32_t columnNumber);
   JSAtom* exportName() const;
   JSAtom* moduleRequest() const;
@@ -85,17 +85,17 @@ class ExportEntryObject : public NativeO
 
 typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
 typedef Handle<ExportEntryObject*> HandleExportEntryObject;
 
 class RequestedModuleObject : public NativeObject {
  public:
   enum { ModuleSpecifierSlot = 0, LineNumberSlot, ColumnNumberSlot, SlotCount };
 
-  static const Class class_;
+  static const JSClass class_;
   static bool isInstance(HandleValue value);
   static RequestedModuleObject* create(JSContext* cx,
                                        HandleAtom moduleSpecifier,
                                        uint32_t lineNumber,
                                        uint32_t columnNumber);
   JSAtom* moduleSpecifier() const;
   uint32_t lineNumber() const;
   uint32_t columnNumber() const;
@@ -251,17 +251,17 @@ class ModuleObject : public NativeObject
                 "StatusSlot must match self-hosting define");
   static_assert(EvaluationErrorSlot == MODULE_OBJECT_EVALUATION_ERROR_SLOT,
                 "EvaluationErrorSlot must match self-hosting define");
   static_assert(DFSIndexSlot == MODULE_OBJECT_DFS_INDEX_SLOT,
                 "DFSIndexSlot must match self-hosting define");
   static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
                 "DFSAncestorIndexSlot must match self-hosting define");
 
-  static const Class class_;
+  static const JSClass class_;
 
   static bool isInstance(HandleValue value);
 
   static ModuleObject* create(JSContext* cx);
   void init(HandleScript script);
   void setInitialEnvironment(
       Handle<ModuleEnvironmentObject*> initialEnvironment);
   void initImportExportData(HandleArrayObject requestedModules,
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -514,17 +514,17 @@ static bool GetBuiltinTagSlow(JSContext*
         }
       }
       builtinTag.set(nullptr);
       return true;
   }
 }
 
 static MOZ_ALWAYS_INLINE JSString* GetBuiltinTagFast(JSObject* obj,
-                                                     const Class* clasp,
+                                                     const JSClass* clasp,
                                                      JSContext* cx) {
   MOZ_ASSERT(clasp == obj->getClass());
   MOZ_ASSERT(!clasp->isProxy());
 
   // Optimize the non-proxy case to bypass GetBuiltinClass.
   if (clasp == &PlainObject::class_) {
     // This is not handled by GetBuiltinTagSlow, but this case is by far
     // the most common so we optimize it here.
@@ -593,17 +593,17 @@ bool js::obj_toString(JSContext* cx, uns
 
   // Step 3.
   RootedObject obj(cx, ToObject(cx, args.thisv()));
   if (!obj) {
     return false;
   }
 
   RootedString builtinTag(cx);
-  const Class* clasp = obj->getClass();
+  const JSClass* clasp = obj->getClass();
   if (MOZ_UNLIKELY(clasp->isProxy())) {
     if (!GetBuiltinTagSlow(cx, obj, &builtinTag)) {
       return false;
     }
   } else {
     builtinTag = GetBuiltinTagFast(obj, clasp, cx);
 #ifdef DEBUG
     // Assert this fast path is correct and matches BuiltinTagSlow. The
@@ -663,17 +663,17 @@ bool js::obj_toString(JSContext* cx, uns
     return false;
   }
 
   args.rval().setString(str);
   return true;
 }
 
 JSString* js::ObjectClassToString(JSContext* cx, HandleObject obj) {
-  const Class* clasp = obj->getClass();
+  const JSClass* clasp = obj->getClass();
 
   if (JSString* tag = GetBuiltinTagFast(obj, clasp, cx)) {
     return tag;
   }
 
   const char* className = clasp->name;
   StringBuffer sb(cx);
   if (!sb.append("[object ") || !sb.append(className, strlen(className)) ||
@@ -2061,13 +2061,13 @@ static bool FinishObjectClassInit(JSCont
 }
 
 static const ClassSpec PlainObjectClassSpec = {
     CreateObjectConstructor, CreateObjectPrototype,
     object_static_methods,   nullptr,
     object_methods,          object_properties,
     FinishObjectClassInit};
 
-const Class PlainObject::class_ = {js_Object_str,
-                                   JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
-                                   JS_NULL_CLASS_OPS, &PlainObjectClassSpec};
+const JSClass PlainObject::class_ = {js_Object_str,
+                                     JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+                                     JS_NULL_CLASS_OPS, &PlainObjectClassSpec};
 
-const Class* const js::ObjectClassPtr = &PlainObject::class_;
+const JSClass* const js::ObjectClassPtr = &PlainObject::class_;
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -206,17 +206,17 @@ class MutableWrappedPtrOperations<Promis
     return MutableHandleObject::fromMarkedLocation(&capability().reject);
   }
 };
 
 }  // namespace js
 
 class PromiseAllDataHolder : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
   JSObject* promiseObj() {
     return &getFixedSlot(PromiseAllDataHolderSlot_Promise).toObject();
   }
   JSObject* resolveObj() {
     return &getFixedSlot(PromiseAllDataHolderSlot_ResolveFunction).toObject();
   }
   Value valuesArray() {
     return getFixedSlot(PromiseAllDataHolderSlot_ValuesArray);
@@ -237,17 +237,17 @@ class PromiseAllDataHolder : public Nati
         getFixedSlot(PromiseAllDataHolderSlot_RemainingElements).toInt32();
     remainingCount--;
     setFixedSlot(PromiseAllDataHolderSlot_RemainingElements,
                  Int32Value(remainingCount));
     return remainingCount;
   }
 };
 
-const Class PromiseAllDataHolder::class_ = {
+const JSClass PromiseAllDataHolder::class_ = {
     "PromiseAllDataHolder",
     JSCLASS_HAS_RESERVED_SLOTS(PromiseAllDataHolderSlots)};
 
 static PromiseAllDataHolder* NewPromiseAllDataHolder(JSContext* cx,
                                                      HandleObject resultPromise,
                                                      HandleValue valuesArray,
                                                      HandleObject resolve) {
   PromiseAllDataHolder* dataHolder =
@@ -296,17 +296,17 @@ class PromiseDebugInfo : public NativeOb
     Slot_ResolutionSite,
     Slot_AllocationTime,
     Slot_ResolutionTime,
     Slot_Id,
     SlotCount
   };
 
  public:
-  static const Class class_;
+  static const JSClass class_;
   static PromiseDebugInfo* create(
       JSContext* cx, Handle<PromiseObject*> promise,
       const mozilla::Maybe<mozilla::TimeStamp>& maybeNow) {
     Rooted<PromiseDebugInfo*> debugInfo(
         cx, NewBuiltinClassInstance<PromiseDebugInfo>(cx));
     if (!debugInfo) {
       return nullptr;
     }
@@ -419,18 +419,18 @@ class PromiseDebugInfo : public NativeOb
     }
 
     debugInfo->setFixedSlot(Slot_ResolutionSite, ObjectOrNullValue(stack));
     debugInfo->setFixedSlot(Slot_ResolutionTime,
                             DoubleValue(MillisecondsSinceStartup(maybeNow)));
   }
 };
 
-const Class PromiseDebugInfo::class_ = {"PromiseDebugInfo",
-                                        JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
+const JSClass PromiseDebugInfo::class_ = {
+    "PromiseDebugInfo", JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
 
 double PromiseObject::allocationTime() {
   auto debugInfo = PromiseDebugInfo::FromPromise(this);
   if (debugInfo) {
     return debugInfo->allocationTime();
   }
   return 0;
 }
@@ -588,17 +588,17 @@ class PromiseReactionRecord : public Nat
   uint32_t handlerArgSlot() {
     MOZ_ASSERT(targetState() != JS::PromiseState::Pending);
     return targetState() == JS::PromiseState::Fulfilled
                ? ReactionRecordSlot_OnFulfilledArg
                : ReactionRecordSlot_OnRejectedArg;
   }
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   JSObject* promise() {
     return getFixedSlot(ReactionRecordSlot_Promise).toObjectOrNull();
   }
   int32_t flags() { return getFixedSlot(ReactionRecordSlot_Flags).toInt32(); }
   JS::PromiseState targetState() {
     int32_t flags = this->flags();
     if (!(flags & REACTION_FLAG_RESOLVED)) {
@@ -684,17 +684,17 @@ class PromiseReactionRecord : public Nat
   JSObject* getAndClearIncumbentGlobalObject() {
     JSObject* obj =
         getFixedSlot(ReactionRecordSlot_IncumbentGlobalObject).toObjectOrNull();
     setFixedSlot(ReactionRecordSlot_IncumbentGlobalObject, UndefinedValue());
     return obj;
   }
 };
 
-const Class PromiseReactionRecord::class_ = {
+const JSClass PromiseReactionRecord::class_ = {
     "PromiseReactionRecord", JSCLASS_HAS_RESERVED_SLOTS(ReactionRecordSlots)};
 
 static void AddPromiseFlags(PromiseObject& promise, int32_t flag) {
   int32_t flags = promise.flags();
   promise.setFixedSlot(PromiseSlot_Flags, Int32Value(flags | flag));
 }
 
 static void RemovePromiseFlags(PromiseObject& promise, int32_t flag) {
@@ -5780,18 +5780,18 @@ static const JSPropertySpec promise_stat
 static const ClassSpec PromiseObjectClassSpec = {
     GenericCreateConstructor<PromiseConstructor, 1, gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<PromiseObject>,
     promise_static_methods,
     promise_static_properties,
     promise_methods,
     promise_properties};
 
-const Class PromiseObject::class_ = {
+const JSClass PromiseObject::class_ = {
     "Promise",
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_Promise) |
         JSCLASS_HAS_XRAYED_CONSTRUCTOR,
     JS_NULL_CLASS_OPS, &PromiseObjectClassSpec};
 
-const Class PromiseObject::protoClass_ = {
+const JSClass PromiseObject::protoClass_ = {
     "PromiseProto", JSCLASS_HAS_CACHED_PROTO(JSProto_Promise),
     JS_NULL_CLASS_OPS, &PromiseObjectClassSpec};
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -81,18 +81,18 @@ enum PromiseSlots {
 // PROMISE_FLAG_REQUIRES_USER_INTERACTION_HANDLING is set.
 #define PROMISE_FLAG_HAD_USER_INTERACTION_UPON_CREATION 0x40
 
 class AutoSetNewObjectMetadata;
 
 class PromiseObject : public NativeObject {
  public:
   static const unsigned RESERVED_SLOTS = PromiseSlots;
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
   static PromiseObject* create(JSContext* cx, HandleObject executor,
                                HandleObject proto = nullptr,
                                bool needsWrapping = false);
 
   static PromiseObject* createSkippingExecutor(JSContext* cx);
 
   static JSObject* unforgeableResolve(JSContext* cx, HandleValue value);
   static JSObject* unforgeableReject(JSContext* cx, HandleValue value);
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -1804,17 +1804,17 @@ bool js::intrinsic_GetElemBaseForLambda(
   }
 
   /* 'b' must behave like a normal object. */
   if (!b.isObject()) {
     return true;
   }
 
   JSObject& bobj = b.toObject();
-  const Class* clasp = bobj.getClass();
+  const JSClass* clasp = bobj.getClass();
   if (!clasp->isNative() || clasp->getOpsLookupProperty() ||
       clasp->getOpsGetProperty()) {
     return true;
   }
 
   args.rval().setObject(bobj);
   return true;
 }
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -172,17 +172,17 @@ class ByteStreamChunk : public NativeObj
     enum Slots {
         Slot_Buffer = 0,
         Slot_ByteOffset,
         Slot_ByteLength,
         SlotCount
     };
 
   public:
-    static const Class class_;
+    static const JSClass class_;
 
     ArrayBufferObject* buffer() {
         return &getFixedSlot(Slot_Buffer).toObject().as<ArrayBufferObject>();
     }
     uint32_t byteOffset() { return getFixedSlot(Slot_ByteOffset).toInt32(); }
     void SetByteOffset(uint32_t offset) {
         setFixedSlot(Slot_ByteOffset, Int32Value(offset));
     }
@@ -201,17 +201,17 @@ class ByteStreamChunk : public NativeObj
 
         chunk->setFixedSlot(Slot_Buffer, ObjectValue(*buffer));
         chunk->setFixedSlot(Slot_ByteOffset, Int32Value(byteOffset));
         chunk->setFixedSlot(Slot_ByteLength, Int32Value(byteLength));
         return chunk;
     }
 };
 
-const Class ByteStreamChunk::class_ = {
+const JSClass ByteStreamChunk::class_ = {
     "ByteStreamChunk",
     JSCLASS_HAS_RESERVED_SLOTS(SlotCount)
 };
 
 #endif  // user-defined byte streams
 
 class PullIntoDescriptor : public NativeObject {
  private:
@@ -222,17 +222,17 @@ class PullIntoDescriptor : public Native
     Slot_BytesFilled,
     Slot_ElementSize,
     Slot_Ctor,
     Slot_ReaderType,
     SlotCount
   };
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   ArrayBufferObject* buffer() {
     return &getFixedSlot(Slot_buffer).toObject().as<ArrayBufferObject>();
   }
   void setBuffer(ArrayBufferObject* buffer) {
     setFixedSlot(Slot_buffer, ObjectValue(*buffer));
   }
   JSObject* ctor() { return getFixedSlot(Slot_Ctor).toObjectOrNull(); }
@@ -276,25 +276,25 @@ class PullIntoDescriptor : public Native
     descriptor->setFixedSlot(Slot_BytesFilled, Int32Value(bytesFilled));
     descriptor->setFixedSlot(Slot_ElementSize, Int32Value(elementSize));
     descriptor->setFixedSlot(Slot_ReaderType,
                              Int32Value(static_cast<int32_t>(readerType)));
     return descriptor;
   }
 };
 
-const Class PullIntoDescriptor::class_ = {
+const JSClass PullIntoDescriptor::class_ = {
     "PullIntoDescriptor", JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
 
 class QueueEntry : public NativeObject {
  private:
   enum Slots { Slot_Value = 0, Slot_Size, SlotCount };
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   Value value() { return getFixedSlot(Slot_Value); }
   double size() { return getFixedSlot(Slot_Size).toNumber(); }
 
   static QueueEntry* create(JSContext* cx, HandleValue value, double size) {
     Rooted<QueueEntry*> entry(cx, NewBuiltinClassInstance<QueueEntry>(cx));
     if (!entry) {
       return nullptr;
@@ -302,18 +302,18 @@ class QueueEntry : public NativeObject {
 
     entry->setFixedSlot(Slot_Value, value);
     entry->setFixedSlot(Slot_Size, NumberValue(size));
 
     return entry;
   }
 };
 
-const Class QueueEntry::class_ = {"QueueEntry",
-                                  JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
+const JSClass QueueEntry::class_ = {"QueueEntry",
+                                    JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
 
 /**
  * TeeState objects implement the local variables in Streams spec 3.3.9
  * ReadableStreamTee, which are accessed by several algorithms.
  */
 class TeeState : public NativeObject {
  public:
   /**
@@ -354,17 +354,17 @@ class TeeState : public NativeObject {
     Flag_Canceled1 = 1 << 1,
     Flag_Canceled2 = 1 << 2,
     Flag_CloneForBranch2 = 1 << 3,
   };
   uint32_t flags() const { return getFixedSlot(Slot_Flags).toInt32(); }
   void setFlags(uint32_t flags) { setFixedSlot(Slot_Flags, Int32Value(flags)); }
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   bool cloneForBranch2() const { return flags() & Flag_CloneForBranch2; }
 
   bool closedOrErrored() const { return flags() & Flag_ClosedOrErrored; }
   void setClosedOrErrored() {
     MOZ_ASSERT(!(flags() & Flag_ClosedOrErrored));
     setFlags(flags() | Flag_ClosedOrErrored);
   }
@@ -443,40 +443,40 @@ class TeeState : public NativeObject {
       return nullptr;
     }
     state->setFixedSlot(Slot_Stream, ObjectValue(*wrappedStream));
 
     return state;
   }
 };
 
-const Class TeeState::class_ = {"TeeState",
-                                JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
-
-#define CLASS_SPEC(cls, nCtorArgs, nSlots, specFlags, classFlags, classOps) \
-  const ClassSpec cls::classSpec_ = {                                       \
-      GenericCreateConstructor<cls::constructor, nCtorArgs,                 \
-                               gc::AllocKind::FUNCTION>,                    \
-      GenericCreatePrototype<cls>,                                          \
-      nullptr,                                                              \
-      nullptr,                                                              \
-      cls##_methods,                                                        \
-      cls##_properties,                                                     \
-      nullptr,                                                              \
-      specFlags};                                                           \
-                                                                            \
-  const Class cls::class_ = {#cls,                                          \
-                             JSCLASS_HAS_RESERVED_SLOTS(nSlots) |           \
-                                 JSCLASS_HAS_CACHED_PROTO(JSProto_##cls) |  \
-                                 classFlags,                                \
-                             classOps, &cls::classSpec_};                   \
-                                                                            \
-  const Class cls::protoClass_ = {"object",                                 \
-                                  JSCLASS_HAS_CACHED_PROTO(JSProto_##cls),  \
-                                  JS_NULL_CLASS_OPS, &cls::classSpec_};
+const JSClass TeeState::class_ = {"TeeState",
+                                  JSCLASS_HAS_RESERVED_SLOTS(SlotCount)};
+
+#define CLASS_SPEC(cls, nCtorArgs, nSlots, specFlags, classFlags, classOps)  \
+  const ClassSpec cls::classSpec_ = {                                        \
+      GenericCreateConstructor<cls::constructor, nCtorArgs,                  \
+                               gc::AllocKind::FUNCTION>,                     \
+      GenericCreatePrototype<cls>,                                           \
+      nullptr,                                                               \
+      nullptr,                                                               \
+      cls##_methods,                                                         \
+      cls##_properties,                                                      \
+      nullptr,                                                               \
+      specFlags};                                                            \
+                                                                             \
+  const JSClass cls::class_ = {#cls,                                         \
+                               JSCLASS_HAS_RESERVED_SLOTS(nSlots) |          \
+                                   JSCLASS_HAS_CACHED_PROTO(JSProto_##cls) | \
+                                   classFlags,                               \
+                               classOps, &cls::classSpec_};                  \
+                                                                             \
+  const JSClass cls::protoClass_ = {"object",                                \
+                                    JSCLASS_HAS_CACHED_PROTO(JSProto_##cls), \
+                                    JS_NULL_CLASS_OPS, &cls::classSpec_};
 
 /*** 3.2. Class ReadableStream **********************************************/
 
 static MOZ_MUST_USE bool SetUpExternalReadableByteStreamController(
     JSContext* cx, Handle<ReadableStream*> stream,
     JS::ReadableStreamUnderlyingSource* source);
 
 ReadableStream* ReadableStream::createExternalSourceStream(
@@ -2030,17 +2030,17 @@ static const JSFunctionSpec ReadableStre
     JS_FN("cancel", ReadableStreamDefaultReader_cancel, 1, 0),
     JS_FN("read", ReadableStreamDefaultReader_read, 0, 0),
     JS_FN("releaseLock", ReadableStreamDefaultReader_releaseLock, 0, 0),
     JS_FS_END};
 
 static const JSPropertySpec ReadableStreamDefaultReader_properties[] = {
     JS_PSG("closed", ReadableStreamDefaultReader_closed, 0), JS_PS_END};
 
-const Class ReadableStreamReader::class_ = {"ReadableStreamReader"};
+const JSClass ReadableStreamReader::class_ = {"ReadableStreamReader"};
 
 CLASS_SPEC(ReadableStreamDefaultReader, 1, SlotCount,
            ClassSpec::DontDefineConstructor, 0, JS_NULL_CLASS_OPS);
 
 /*** 3.7. Class ReadableStreamBYOBReader ************************************/
 
 // Not implemented.
 
--- a/js/src/builtin/Stream.h
+++ b/js/src/builtin/Stream.h
@@ -110,19 +110,19 @@ class ReadableStream : public NativeObje
       HandleObject proto = nullptr);
   static ReadableStream* createExternalSourceStream(
       JSContext* cx, JS::ReadableStreamUnderlyingSource* source,
       void* nsISupportsObject_alreadyAddreffed = nullptr,
       HandleObject proto = nullptr);
 
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 /**
  * Tells whether or not read() result objects inherit from Object.prototype.
  * Generally, they should do so only if the reader was created by author code.
  * See <https://streams.spec.whatwg.org/#readable-stream-create-read-result>.
  */
 enum class ForAuthorCodeBool { No, Yes };
@@ -194,26 +194,26 @@ class ReadableStreamReader : public Nati
 
   JSObject* closedPromise() const {
     return &getFixedSlot(Slot_ClosedPromise).toObject();
   }
   void setClosedPromise(JSObject* wrappedPromise) {
     setFixedSlot(Slot_ClosedPromise, ObjectValue(*wrappedPromise));
   }
 
-  static const Class class_;
+  static const JSClass class_;
 };
 
 class ReadableStreamDefaultReader : public ReadableStreamReader {
  public:
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 /**
  * Common base class of both readable and writable stream controllers.
  */
 class StreamController : public NativeObject {
  public:
   /**
@@ -381,19 +381,19 @@ class ReadableStreamDefaultController : 
  public:
   Value strategySize() const { return getFixedSlot(Slot_StrategySize); }
   void setStrategySize(const Value& size) {
     setFixedSlot(Slot_StrategySize, size);
   }
 
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 class ReadableByteStreamController : public ReadableStreamController {
  public:
   /**
    * Memory layout for ReadableByteStreamControllers, starting after the
    * slots shared among all types of controllers.
    *
@@ -421,37 +421,37 @@ class ReadableByteStreamController : pub
     return getFixedSlot(Slot_AutoAllocateSize);
   }
   void setAutoAllocateChunkSize(const Value& size) {
     setFixedSlot(Slot_AutoAllocateSize, size);
   }
 
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 class ByteLengthQueuingStrategy : public NativeObject {
  public:
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 class CountQueuingStrategy : public NativeObject {
  public:
   static bool constructor(JSContext* cx, unsigned argc, Value* vp);
   static const ClassSpec classSpec_;
-  static const Class class_;
+  static const JSClass class_;
   static const ClassSpec protoClassSpec_;
-  static const Class protoClass_;
+  static const JSClass protoClass_;
 };
 
 }  // namespace js
 
 template <>
 inline bool JSObject::is<js::StreamController>() const {
   return is<js::ReadableStreamDefaultController>() ||
          is<js::ReadableByteStreamController>();
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -440,17 +440,17 @@ static bool str_resolve(JSContext* cx, H
 }
 
 static const JSClassOps StringObjectClassOps = {
     nullptr,                /* addProperty */
     nullptr,                /* delProperty */
     str_enumerate, nullptr, /* newEnumerate */
     str_resolve,   str_mayResolve};
 
-const Class StringObject::class_ = {
+const JSClass StringObject::class_ = {
     js_String_str,
     JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_String),
     &StringObjectClassOps};
 
 /*
  * Perform the initial |RequireObjectCoercible(thisv)| and |ToString(thisv)|
  * from nearly all String.prototype.* functions.
--- a/js/src/builtin/Symbol.cpp
+++ b/js/src/builtin/Symbol.cpp
@@ -12,17 +12,17 @@
 #include "vm/SymbolType.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using JS::Symbol;
 using namespace js;
 
-const Class SymbolObject::class_ = {
+const JSClass SymbolObject::class_ = {
     "Symbol", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
                   JSCLASS_HAS_CACHED_PROTO(JSProto_Symbol)};
 
 SymbolObject* SymbolObject::create(JSContext* cx, JS::HandleSymbol symbol) {
   SymbolObject* obj = NewBuiltinClassInstance<SymbolObject>(cx);
   if (!obj) {
     return nullptr;
   }
--- a/js/src/builtin/Symbol.h
+++ b/js/src/builtin/Symbol.h
@@ -16,17 +16,17 @@ class GlobalObject;
 
 class SymbolObject : public NativeObject {
   /* Stores this Symbol object's [[PrimitiveValue]]. */
   static const unsigned PRIMITIVE_VALUE_SLOT = 0;
 
  public:
   static const unsigned RESERVED_SLOTS = 1;
 
-  static const Class class_;
+  static const JSClass class_;
 
   static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global,
                              bool defineMembers);
 
   /*
    * Creates a new Symbol object boxing the given primitive Symbol.  The
    * object's [[Prototype]] is determined from context.
    */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2932,20 +2932,20 @@ static bool SetIonCheckGraphCoherency(JS
 class CloneBufferObject : public NativeObject {
   static const JSPropertySpec props_[3];
 
   static const size_t DATA_SLOT = 0;
   static const size_t SYNTHETIC_SLOT = 1;
   static const size_t NUM_SLOTS = 2;
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static CloneBufferObject* Create(JSContext* cx) {
-    RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_)));
+    RootedObject obj(cx, JS_NewObject(cx, &class_));
     if (!obj) {
       return nullptr;
     }
     obj->as<CloneBufferObject>().setReservedSlot(DATA_SLOT,
                                                  PrivateValue(nullptr));
     obj->as<CloneBufferObject>().setReservedSlot(SYNTHETIC_SLOT,
                                                  BooleanValue(false));
 
@@ -3156,17 +3156,17 @@ static const JSClassOps CloneBufferObjec
     nullptr, /* addProperty */
     nullptr, /* delProperty */
     nullptr, /* enumerate */
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     CloneBufferObject::Finalize};
 
-const Class CloneBufferObject::class_ = {
+const JSClass CloneBufferObject::class_ = {
     "CloneBuffer",
     JSCLASS_HAS_RESERVED_SLOTS(CloneBufferObject::NUM_SLOTS) |
         JSCLASS_FOREGROUND_FINALIZE,
     &CloneBufferObjectClassOps};
 
 const JSPropertySpec CloneBufferObject::props_[] = {
     JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0),
     JS_PSGS("arraybuffer", getCloneBufferAsArrayBuffer, setCloneBuffer, 0),
@@ -4338,17 +4338,17 @@ static bool AllocationMarker(JSContext* 
 
     RootedValue nurseryVal(cx);
     if (!JS_GetProperty(cx, options, "nursery", &nurseryVal)) {
       return false;
     }
     allocateInsideNursery = ToBoolean(nurseryVal);
   }
 
-  static const Class cls = {"AllocationMarker"};
+  static const JSClass cls = {"AllocationMarker"};
 
   auto newKind = allocateInsideNursery ? GenericObject : TenuredObject;
   RootedObject obj(cx, NewObjectWithGivenProto(cx, &cls, nullptr, newKind));
   if (!obj) {
     return false;
   }
 
   args.rval().setObject(*obj);
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -34,17 +34,17 @@
 using mozilla::AssertedCast;
 using mozilla::CheckedInt32;
 using mozilla::IsPowerOfTwo;
 using mozilla::PodCopy;
 using mozilla::PointerRangeSize;
 
 using namespace js;
 
-const Class js::TypedObjectModuleObject::class_ = {
+const JSClass js::TypedObjectModuleObject::class_ = {
     "TypedObject", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
                        JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject)};
 
 static const JSFunctionSpec TypedObjectMethods[] = {
     JS_SELF_HOSTED_FN("objectType", "TypeOfTypedObject", 1, 0), JS_FS_END};
 
 static void ReportCannotConvertTo(JSContext* cx, HandleValue fromValue,
                                   const char* toType) {
@@ -188,17 +188,17 @@ static JSObject* GetPrototype(JSContext*
 /***************************************************************************
  * Typed Prototypes
  *
  * Every type descriptor has an associated prototype. Instances of
  * that type descriptor use this as their prototype. Per the spec,
  * typed object prototypes cannot be mutated.
  */
 
-const Class js::TypedProto::class_ = {
+const JSClass js::TypedProto::class_ = {
     "TypedProto", JSCLASS_HAS_RESERVED_SLOTS(JS_TYPROTO_SLOTS)};
 
 /***************************************************************************
  * Scalar type objects
  *
  * Scalar type objects like `uint8`, `uint16`, are all instances of
  * the ScalarTypeDescr class. Like all type objects, they have a reserved
  * slot pointing to a TypeRepresentation object, which is used to
@@ -209,17 +209,17 @@ static const JSClassOps ScalarTypeDescrC
                                                    nullptr, /* delProperty */
                                                    nullptr, /* enumerate */
                                                    nullptr, /* newEnumerate */
                                                    nullptr, /* resolve */
                                                    nullptr, /* mayResolve */
                                                    TypeDescr::finalize,
                                                    ScalarTypeDescr::call};
 
-const Class js::ScalarTypeDescr::class_ = {
+const JSClass js::ScalarTypeDescr::class_ = {
     "Scalar",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     &ScalarTypeDescrClassOps};
 
 const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
     JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0), JS_FS_END};
@@ -363,17 +363,17 @@ static const JSClassOps ReferenceTypeDes
     nullptr, /* delProperty */
     nullptr, /* enumerate */
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     TypeDescr::finalize,
     ReferenceTypeDescr::call};
 
-const Class js::ReferenceTypeDescr::class_ = {
+const JSClass js::ReferenceTypeDescr::class_ = {
     "Reference",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     &ReferenceTypeDescrClassOps};
 
 const JSFunctionSpec js::ReferenceTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     {JSFunctionSpec::Name("array"), {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     {JSFunctionSpec::Name("equivalent"),
@@ -505,17 +505,17 @@ static const JSClassOps ArrayTypeDescrCl
                                                   nullptr, /* newEnumerate */
                                                   nullptr, /* resolve */
                                                   nullptr, /* mayResolve */
                                                   TypeDescr::finalize,
                                                   nullptr, /* call */
                                                   nullptr, /* hasInstance */
                                                   TypedObject::construct};
 
-const Class ArrayTypeDescr::class_ = {
+const JSClass ArrayTypeDescr::class_ = {
     "ArrayType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     &ArrayTypeDescrClassOps};
 
 const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = {JS_PS_END};
 
 const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
     {JSFunctionSpec::Name("array"), {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
@@ -754,17 +754,17 @@ static const JSClassOps StructTypeDescrC
                                                    nullptr, /* newEnumerate */
                                                    nullptr, /* resolve */
                                                    nullptr, /* mayResolve */
                                                    TypeDescr::finalize,
                                                    StructTypeDescr::call,
                                                    nullptr, /* hasInstance */
                                                    TypedObject::construct};
 
-const Class StructTypeDescr::class_ = {
+const JSClass StructTypeDescr::class_ = {
     "StructType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     &StructTypeDescrClassOps};
 
 const JSPropertySpec StructMetaTypeDescr::typeObjectProperties[] = {JS_PS_END};
 
 const JSFunctionSpec StructMetaTypeDescr::typeObjectMethods[] = {
     {JSFunctionSpec::Name("array"), {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
@@ -1600,17 +1600,17 @@ void OutlineTypedObject::setOwnerAndData
       // catch the actual write, register the owner preemptively now.
       storeBuffer()->putWholeCell(owner);
     }
   }
 }
 
 /*static*/
 OutlineTypedObject* OutlineTypedObject::createUnattachedWithClass(
-    JSContext* cx, const Class* clasp, HandleTypeDescr descr,
+    JSContext* cx, const JSClass* clasp, HandleTypeDescr descr,
     gc::InitialHeap heap) {
   MOZ_ASSERT(clasp == &OutlineTransparentTypedObject::class_ ||
              clasp == &OutlineOpaqueTypedObject::class_);
 
   AutoSetNewObjectMetadata metadata(cx);
 
   RootedObjectGroup group(
       cx, ObjectGroup::defaultNewGroup(
@@ -1673,19 +1673,19 @@ void OutlineTypedObject::attach(JSContex
 
 /*static*/
 OutlineTypedObject* OutlineTypedObject::createDerived(
     JSContext* cx, HandleTypeDescr type, HandleTypedObject typedObj,
     uint32_t offset) {
   MOZ_ASSERT(offset <= typedObj->size());
   MOZ_ASSERT(offset + type->size() <= typedObj->size());
 
-  const js::Class* clasp = typedObj->opaque()
-                               ? &OutlineOpaqueTypedObject::class_
-                               : &OutlineTransparentTypedObject::class_;
+  const JSClass* clasp = typedObj->opaque()
+                             ? &OutlineOpaqueTypedObject::class_
+                             : &OutlineTransparentTypedObject::class_;
   Rooted<OutlineTypedObject*> obj(cx);
   obj = createUnattachedWithClass(cx, clasp, type);
   if (!obj) {
     return nullptr;
   }
 
   obj->attach(cx, *typedObj, offset);
   return obj;
@@ -2185,18 +2185,19 @@ void OutlineTypedObject::notifyBufferDet
  */
 
 /* static */
 InlineTypedObject* InlineTypedObject::create(JSContext* cx,
                                              HandleTypeDescr descr,
                                              gc::InitialHeap heap) {
   gc::AllocKind allocKind = allocKindForTypeDescriptor(descr);
 
-  const Class* clasp = descr->opaque() ? &InlineOpaqueTypedObject::class_
-                                       : &InlineTransparentTypedObject::class_;
+  const JSClass* clasp = descr->opaque()
+                             ? &InlineOpaqueTypedObject::class_
+                             : &InlineTransparentTypedObject::class_;
 
   RootedObjectGroup group(
       cx, ObjectGroup::defaultNewGroup(
               cx, clasp, TaggedProto(&descr->typedProto()), descr));
   if (!group) {
     return nullptr;
   }
 
@@ -2274,36 +2275,36 @@ const ObjectOps TypedObject::objectOps_ 
     TypedObject::obj_getProperty,
     TypedObject::obj_setProperty,
     TypedObject::obj_getOwnPropertyDescriptor,
     TypedObject::obj_deleteProperty,
     nullptr, /* getElements */
     nullptr, /* thisValue */
 };
 
-#define DEFINE_TYPEDOBJ_CLASS(Name, Trace, Moved)                          \
-  static const JSClassOps Name##ClassOps = {                               \
-      nullptr, /* addProperty */                                           \
-      nullptr, /* delProperty */                                           \
-      nullptr, /* enumerate   */                                           \
-      TypedObject::obj_newEnumerate,                                       \
-      nullptr, /* resolve     */                                           \
-      nullptr, /* mayResolve  */                                           \
-      nullptr, /* finalize    */                                           \
-      nullptr, /* call        */                                           \
-      nullptr, /* hasInstance */                                           \
-      nullptr, /* construct   */                                           \
-      Trace,                                                               \
-  };                                                                       \
-  static const ClassExtension Name##ClassExt = {                           \
-      Moved /* objectMovedOp */                                            \
-  };                                                                       \
-  const Class Name::class_ = {                                             \
-      #Name,           Class::NON_NATIVE | JSCLASS_DELAY_METADATA_BUILDER, \
-      &Name##ClassOps, JS_NULL_CLASS_SPEC,                                 \
+#define DEFINE_TYPEDOBJ_CLASS(Name, Trace, Moved)                            \
+  static const JSClassOps Name##ClassOps = {                                 \
+      nullptr, /* addProperty */                                             \
+      nullptr, /* delProperty */                                             \
+      nullptr, /* enumerate   */                                             \
+      TypedObject::obj_newEnumerate,                                         \
+      nullptr, /* resolve     */                                             \
+      nullptr, /* mayResolve  */                                             \
+      nullptr, /* finalize    */                                             \
+      nullptr, /* call        */                                             \
+      nullptr, /* hasInstance */                                             \
+      nullptr, /* construct   */                                             \
+      Trace,                                                                 \
+  };                                                                         \
+  static const ClassExtension Name##ClassExt = {                             \
+      Moved /* objectMovedOp */                                              \
+  };                                                                         \
+  const JSClass Name::class_ = {                                             \
+      #Name,           JSClass::NON_NATIVE | JSCLASS_DELAY_METADATA_BUILDER, \
+      &Name##ClassOps, JS_NULL_CLASS_SPEC,                                   \
       &Name##ClassExt, &TypedObject::objectOps_}
 
 DEFINE_TYPEDOBJ_CLASS(OutlineTransparentTypedObject,
                       OutlineTypedObject::obj_trace, nullptr);
 DEFINE_TYPEDOBJ_CLASS(OutlineOpaqueTypedObject, OutlineTypedObject::obj_trace,
                       nullptr);
 DEFINE_TYPEDOBJ_CLASS(InlineTransparentTypedObject,
                       InlineTypedObject::obj_trace,
@@ -2366,17 +2367,17 @@ bool TypedObject::construct(JSContext* c
   return false;
 }
 
 /* static */ JS::Result<TypedObject*, JS::OOM&> TypedObject::create(
     JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
     js::HandleShape shape, js::HandleObjectGroup group) {
   debugCheckNewObject(group, shape, kind, heap);
 
-  const js::Class* clasp = group->clasp();
+  const JSClass* clasp = group->clasp();
   MOZ_ASSERT(::IsTypedObjectClass(clasp));
 
   JSObject* obj =
       js::AllocateObject(cx, kind, /* nDynamicSlots = */ 0, heap, clasp);
   if (!obj) {
     return cx->alreadyReportedOOM();
   }
 
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -34,17 +34,17 @@
  * info on the API itself, see the Harmony wiki page at
  * http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects or the
  * ES6 spec (not finalized at the time of this writing).
  *
  * - Initialization:
  *
  * Currently, all "globals" related to typed objects are packaged
  * within a single "module" object `TypedObject`. This module has its
- * own js::Class and when that class is initialized, we also create
+ * own JSClass and when that class is initialized, we also create
  * and define all other values (in `js::InitTypedObjectModuleClass()`).
  *
  * - Type objects, meta type objects, and type representations:
  *
  * There are a number of pre-defined type objects, one for each
  * scalar type (`uint8` etc). Each of these has its own class_,
  * defined in `DefineNumericClass()`.
  *
@@ -134,17 +134,17 @@ class ComplexTypeDescr;
 class StructTypeDescr;
 class TypedProto;
 
 /*
  * The prototype for a typed object.
  */
 class TypedProto : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 };
 
 class TypeDescr : public NativeObject {
  public:
   TypedProto& typedProto() const {
     return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
   }
 
@@ -205,30 +205,30 @@ class TypeDescr : public NativeObject {
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
 typedef Handle<TypeDescr*> HandleTypeDescr;
 
 class SimpleTypeDescr : public TypeDescr {};
 
 // Type for scalar type constructors like `uint8`. All such type
-// constructors share a common js::Class and JSFunctionSpec. Scalar
+// constructors share a common JSClass and JSFunctionSpec. Scalar
 // types are non-opaque (their storage is visible unless combined with
 // an opaque reference type.)
 class ScalarTypeDescr : public SimpleTypeDescr {
  public:
   typedef Scalar::Type Type;
 
   static const type::Kind Kind = type::Scalar;
   static const bool Opaque = false;
   static uint32_t size(Type t);
   static uint32_t alignment(Type t);
   static const char* typeName(Type type);
 
-  static const Class class_;
+  static const JSClass class_;
   static const JSFunctionSpec typeObjectMethods[];
 
   Type type() const {
     // Make sure the values baked into TypedObjectConstants.h line up with
     // the Scalar::Type enum. We don't define Scalar::Type directly in
     // terms of these constants to avoid making TypedObjectConstants.h a
     // public header file.
     static_assert(
@@ -301,28 +301,28 @@ class ScalarTypeDescr : public SimpleTyp
 enum class ReferenceType {
   TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
   TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
   TYPE_WASM_ANYREF = JS_REFERENCETYPEREPR_WASM_ANYREF,
   TYPE_STRING = JS_REFERENCETYPEREPR_STRING
 };
 
 // Type for reference type constructors like `Any`, `String`, and
-// `Object`. All such type constructors share a common js::Class and
+// `Object`. All such type constructors share a common JSClass and
 // JSFunctionSpec. All these types are opaque.
 class ReferenceTypeDescr : public SimpleTypeDescr {
  public:
   // Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
   typedef ReferenceType Type;
   static const char* typeName(Type type);
 
   static const int32_t TYPE_MAX = int32_t(ReferenceType::TYPE_STRING) + 1;
   static const type::Kind Kind = type::Reference;
   static const bool Opaque = true;
-  static const Class class_;
+  static const JSClass class_;
   static uint32_t size(Type t);
   static uint32_t alignment(Type t);
   static const JSFunctionSpec typeObjectMethods[];
 
   ReferenceType type() const {
     return (ReferenceType)getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
   }
 
@@ -350,17 +350,17 @@ class ComplexTypeDescr : public TypeDesc
   }
 
   bool allowConstruct() const {
     return getReservedSlot(JS_DESCR_SLOT_FLAGS).toInt32() &
            JS_DESCR_FLAG_ALLOW_CONSTRUCT;
   }
 };
 
-bool IsTypedObjectClass(const Class* clasp);  // Defined below
+bool IsTypedObjectClass(const JSClass* clasp);  // Defined below
 bool IsTypedObjectArray(JSObject& obj);
 
 MOZ_MUST_USE bool CreateUserSizeAndAlignmentProperties(JSContext* cx,
                                                        HandleTypeDescr obj);
 
 class ArrayTypeDescr;
 
 /*
@@ -397,17 +397,17 @@ class ArrayMetaTypeDescr : public Native
   static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 };
 
 /*
  * Type descriptor created by `new ArrayType(type, n)`
  */
 class ArrayTypeDescr : public ComplexTypeDescr {
  public:
-  static const Class class_;
+  static const JSClass class_;
   static const type::Kind Kind = type::Array;
 
   TypeDescr& elementType() const {
     return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE)
         .toObject()
         .as<TypeDescr>();
   }
 
@@ -479,17 +479,17 @@ class StructMetaTypeDescr : public Nativ
     // alignment and returns that size.  If `alignment` is not NULL then
     // return the structure alignment through that pointer.
     mozilla::CheckedInt32 close(int32_t* alignment = nullptr);
   };
 };
 
 class StructTypeDescr : public ComplexTypeDescr {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   // Returns the number of fields defined in this struct.
   size_t fieldCount() const;
 
   // Set `*out` to the index of the field named `id` and returns true,
   // or return false if no such field exists.
   MOZ_MUST_USE bool fieldIndex(jsid id, size_t* out) const;
 
@@ -529,17 +529,17 @@ class TypedObjectModuleObject : public N
     Int64Desc,
     Float32Desc,
     Float64Desc,
     ObjectDesc,
     WasmAnyRefDesc,
     SlotCount
   };
 
-  static const Class class_;
+  static const JSClass class_;
 };
 
 /* Base type for transparent and opaque typed objects. */
 class TypedObject : public JSObject {
   static const bool IsTypedObjectClass = true;
 
   static MOZ_MUST_USE bool obj_getArrayElement(JSContext* cx,
                                                Handle<TypedObject*> typedObj,
@@ -673,17 +673,17 @@ class OutlineTypedObject : public TypedO
 
   void resetOffset(size_t offset) {
     MOZ_ASSERT(offset <= (size_t)size());
     setData(typedMemBase() + offset);
   }
 
   // Helper for createUnattached()
   static OutlineTypedObject* createUnattachedWithClass(
-      JSContext* cx, const Class* clasp, HandleTypeDescr type,
+      JSContext* cx, const JSClass* clasp, HandleTypeDescr type,
       gc::InitialHeap heap = gc::DefaultHeap);
 
   // Creates an unattached typed object or handle (depending on the
   // type parameter T). Note that it is only legal for unattached
   // handles to escape to the end user; for non-handles, the caller
   // should always invoke one of the `attach()` methods below.
   //
   // Arguments:
@@ -709,24 +709,24 @@ class OutlineTypedObject : public TypedO
   void notifyBufferDetached(void* newData);
 
   static void obj_trace(JSTracer* trace, JSObject* object);
 };
 
 // Class for a transparent typed object whose owner is an array buffer.
 class OutlineTransparentTypedObject : public OutlineTypedObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 };
 
 // Class for an opaque typed object whose owner may be either an array buffer
 // or an opaque inlined typed object.
 class OutlineOpaqueTypedObject : public OutlineTypedObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 };
 
 // Class for a typed object whose data is allocated inline.
 class InlineTypedObject : public TypedObject {
   friend class TypedObject;
 
   // Start of the inline data, which immediately follows the shape and type.
   uint8_t data_[1];
@@ -765,27 +765,27 @@ class InlineTypedObject : public TypedOb
       JSContext* cx, Handle<InlineTypedObject*> templateObject,
       gc::InitialHeap heap);
 };
 
 // Class for a transparent typed object with inline data, which may have a
 // lazily allocated array buffer.
 class InlineTransparentTypedObject : public InlineTypedObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   uint8_t* inlineTypedMem() const {
     return InlineTypedObject::inlineTypedMem();
   }
 };
 
 // Class for an opaque typed object with inline data and no array buffer.
 class InlineOpaqueTypedObject : public InlineTypedObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 };
 
 /*
  * Usage: NewOpaqueTypedObject(typeObj)
  *
  * Constructs a new, unattached instance of `Handle`.
  */
 MOZ_MUST_USE bool NewOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
@@ -1002,83 +1002,83 @@ MOZ_MUST_USE bool UnboxBoxedWasmAnyRef(J
 // into problems with the Unagi compiler.
 JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
 JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
 JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_STORE_SCALAR_CLASS_DEFN)
 JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_LOAD_SCALAR_CLASS_DEFN)
 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_DEFN)
 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
 
-inline bool IsTypedObjectClass(const Class* class_) {
+inline bool IsTypedObjectClass(const JSClass* class_) {
   return class_ == &OutlineTransparentTypedObject::class_ ||
          class_ == &InlineTransparentTypedObject::class_ ||
          class_ == &OutlineOpaqueTypedObject::class_ ||
          class_ == &InlineOpaqueTypedObject::class_;
 }
 
-inline bool IsOpaqueTypedObjectClass(const Class* class_) {
+inline bool IsOpaqueTypedObjectClass(const JSClass* class_) {
   return class_ == &OutlineOpaqueTypedObject::class_ ||
          class_ == &InlineOpaqueTypedObject::class_;
 }
 
-inline bool IsOutlineTypedObjectClass(const Class* class_) {
+inline bool IsOutlineTypedObjectClass(const JSClass* class_) {
   return class_ == &OutlineOpaqueTypedObject::class_ ||
          class_ == &OutlineTransparentTypedObject::class_;
 }
 
-inline bool IsInlineTypedObjectClass(const Class* class_) {
+inline bool IsInlineTypedObjectClass(const JSClass* class_) {
   return class_ == &InlineOpaqueTypedObject::class_ ||
          class_ == &InlineTransparentTypedObject::class_;
 }
 
-inline const Class* GetOutlineTypedObjectClass(bool opaque) {
+inline const JSClass* GetOutlineTypedObjectClass(bool opaque) {
   return opaque ? &OutlineOpaqueTypedObject::class_
                 : &OutlineTransparentTypedObject::class_;
 }
 
-inline bool IsSimpleTypeDescrClass(const Class* clasp) {
+inline bool IsSimpleTypeDescrClass(const JSClass* clasp) {
   return clasp == &ScalarTypeDescr::class_ ||
          clasp == &ReferenceTypeDescr::class_;
 }
 
-inline bool IsComplexTypeDescrClass(const Class* clasp) {
+inline bool IsComplexTypeDescrClass(const JSClass* clasp) {
   return clasp == &StructTypeDescr::class_ || clasp == &ArrayTypeDescr::class_;
 }
 
-inline bool IsTypeDescrClass(const Class* clasp) {
+inline bool IsTypeDescrClass(const JSClass* clasp) {
   return IsSimpleTypeDescrClass(clasp) || IsComplexTypeDescrClass(clasp);
 }
 
 inline bool TypedObject::opaque() const {
   return IsOpaqueTypedObjectClass(getClass());
 }
 
 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/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -272,23 +272,23 @@ const ClassSpec WeakMapObject::classSpec
                              gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<WeakMapObject>,
     nullptr,
     nullptr,
     WeakMapObject::methods,
     WeakMapObject::properties,
 };
 
-const Class WeakMapObject::class_ = {
+const JSClass WeakMapObject::class_ = {
     "WeakMap",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap) |
         JSCLASS_BACKGROUND_FINALIZE,
     &WeakCollectionObject::classOps_, &WeakMapObject::classSpec_};
 
-const Class WeakMapObject::protoClass_ = {
+const JSClass WeakMapObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap), JS_NULL_CLASS_OPS,
     &WeakMapObject::classSpec_};
 
 const JSPropertySpec WeakMapObject::properties[] = {
     JS_STRING_SYM_PS(toStringTag, "WeakMap", JSPROP_READONLY), JS_PS_END};
 
 const JSFunctionSpec WeakMapObject::methods[] = {
     JS_FN("has", has, 1, 0), JS_FN("get", get, 1, 0),
--- a/js/src/builtin/WeakMapObject.h
+++ b/js/src/builtin/WeakMapObject.h
@@ -31,18 +31,18 @@ class WeakCollectionObject : public Nati
       MutableHandleObject ret);
 
  protected:
   static const JSClassOps classOps_;
 };
 
 class WeakMapObject : public WeakCollectionObject {
  public:
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
  private:
   static const ClassSpec classSpec_;
 
   static const JSPropertySpec properties[];
   static const JSFunctionSpec methods[];
 
   static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -134,23 +134,23 @@ const ClassSpec WeakSetObject::classSpec
                              gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<WeakSetObject>,
     nullptr,
     nullptr,
     WeakSetObject::methods,
     WeakSetObject::properties,
 };
 
-const Class WeakSetObject::class_ = {
+const JSClass WeakSetObject::class_ = {
     "WeakSet",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet) |
         JSCLASS_BACKGROUND_FINALIZE,
     &WeakCollectionObject::classOps_, &WeakSetObject::classSpec_};
 
-const Class WeakSetObject::protoClass_ = {
+const JSClass WeakSetObject::protoClass_ = {
     js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet), JS_NULL_CLASS_OPS,
     &WeakSetObject::classSpec_};
 
 const JSPropertySpec WeakSetObject::properties[] = {
     JS_STRING_SYM_PS(toStringTag, "WeakSet", JSPROP_READONLY), JS_PS_END};
 
 const JSFunctionSpec WeakSetObject::methods[] = {
     JS_FN("add", add, 1, 0), JS_FN("delete", delete_, 1, 0),
--- a/js/src/builtin/WeakSetObject.h
+++ b/js/src/builtin/WeakSetObject.h
@@ -10,18 +10,18 @@
 #include "builtin/WeakMapObject.h"
 
 namespace js {
 
 class GlobalObject;
 
 class WeakSetObject : public WeakCollectionObject {
  public:
-  static const Class class_;
-  static const Class protoClass_;
+  static const JSClass class_;
+  static const JSClass protoClass_;
 
  private:
   static const ClassSpec classSpec_;
 
   static const JSPropertySpec properties[];
   static const JSFunctionSpec methods[];
 
   static WeakSetObject* create(JSContext* cx, HandleObject proto = nullptr);
--- a/js/src/builtin/intl/Collator.cpp
+++ b/js/src/builtin/intl/Collator.cpp
@@ -42,17 +42,17 @@ using js::intl::StringsAreEqual;
 const JSClassOps CollatorObject::classOps_ = {nullptr, /* addProperty */
                                               nullptr, /* delProperty */
                                               nullptr, /* enumerate */
                                               nullptr, /* newEnumerate */
                                               nullptr, /* resolve */
                                               nullptr, /* mayResolve */
                                               CollatorObject::finalize};
 
-const Class CollatorObject::class_ = {
+const JSClass CollatorObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(CollatorObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
     &CollatorObject::classOps_};
 
 static bool collator_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().Collator);
--- a/js/src/builtin/intl/Collator.h
+++ b/js/src/builtin/intl/Collator.h
@@ -20,17 +20,17 @@ struct UCollator;
 namespace js {
 
 class GlobalObject;
 
 /******************** Collator ********************/
 
 class CollatorObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t UCOLLATOR_SLOT = 1;
   static constexpr uint32_t SLOT_COUNT = 2;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
                 "INTERNALS_SLOT must match self-hosting define for internals "
                 "object slot");
--- a/js/src/builtin/intl/DateTimeFormat.cpp
+++ b/js/src/builtin/intl/DateTimeFormat.cpp
@@ -50,17 +50,17 @@ const JSClassOps DateTimeFormatObject::c
     nullptr, /* addProperty */
     nullptr, /* delProperty */
     nullptr, /* enumerate */
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     DateTimeFormatObject::finalize};
 
-const Class DateTimeFormatObject::class_ = {
+const JSClass DateTimeFormatObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(DateTimeFormatObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
     &DateTimeFormatObject::classOps_};
 
 static bool dateTimeFormat_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().DateTimeFormat);
--- a/js/src/builtin/intl/DateTimeFormat.h
+++ b/js/src/builtin/intl/DateTimeFormat.h
@@ -18,17 +18,17 @@
 using UDateFormat = void*;
 
 namespace js {
 
 class GlobalObject;
 
 class DateTimeFormatObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t UDATE_FORMAT_SLOT = 1;
   static constexpr uint32_t SLOT_COUNT = 2;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
                 "INTERNALS_SLOT must match self-hosting define for internals "
                 "object slot");
--- a/js/src/builtin/intl/IntlObject.cpp
+++ b/js/src/builtin/intl/IntlObject.cpp
@@ -496,18 +496,18 @@ bool js::intl_GetLocaleInfo(JSContext* c
   if (!DefineDataProperty(cx, info, cx->names().direction, dir)) {
     return false;
   }
 
   args.rval().setObject(*info);
   return true;
 }
 
-const Class js::IntlClass = {js_Object_str,
-                             JSCLASS_HAS_CACHED_PROTO(JSProto_Intl)};
+const JSClass js::IntlClass = {js_Object_str,
+                               JSCLASS_HAS_CACHED_PROTO(JSProto_Intl)};
 
 static bool intl_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().Intl);
   return true;
 }
 
 static const JSFunctionSpec intl_static_methods[] = {
--- a/js/src/builtin/intl/IntlObject.h
+++ b/js/src/builtin/intl/IntlObject.h
@@ -9,20 +9,19 @@
 
 #include "mozilla/Attributes.h"
 
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 
 namespace js {
 
-struct Class;
 class GlobalObject;
 
-extern const Class IntlClass;
+extern const JSClass IntlClass;
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
  * Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
  */
 extern JSObject* InitIntlClass(JSContext* cx, JS::Handle<GlobalObject*> global);
 
 /**
--- a/js/src/builtin/intl/Locale.cpp
+++ b/js/src/builtin/intl/Locale.cpp
@@ -25,17 +25,17 @@
 #include "vm/JSContext.h"
 #include "vm/StringType.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
-const Class LocaleObject::class_ = {
+const JSClass LocaleObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(LocaleObject::SLOT_COUNT),
 };
 
 static bool locale_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().Locale);
   return true;
--- a/js/src/builtin/intl/Locale.h
+++ b/js/src/builtin/intl/Locale.h
@@ -14,17 +14,17 @@
 #include "vm/NativeObject.h"
 
 namespace js {
 
 class GlobalObject;
 
 class LocaleObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t SLOT_COUNT = 1;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
                 "INTERNALS_SLOT must match self-hosting define for internals "
                 "object slot");
 };
--- a/js/src/builtin/intl/NumberFormat.cpp
+++ b/js/src/builtin/intl/NumberFormat.cpp
@@ -61,17 +61,17 @@ using JS::AutoStableStringChars;
 const JSClassOps NumberFormatObject::classOps_ = {nullptr, /* addProperty */
                                                   nullptr, /* delProperty */
                                                   nullptr, /* enumerate */
                                                   nullptr, /* newEnumerate */
                                                   nullptr, /* resolve */
                                                   nullptr, /* mayResolve */
                                                   NumberFormatObject::finalize};
 
-const Class NumberFormatObject::class_ = {
+const JSClass NumberFormatObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(NumberFormatObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
     &NumberFormatObject::classOps_};
 
 static bool numberFormat_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().NumberFormat);
--- a/js/src/builtin/intl/NumberFormat.h
+++ b/js/src/builtin/intl/NumberFormat.h
@@ -22,17 +22,17 @@ struct UFormattedValue;
 struct UNumberFormatter;
 
 namespace js {
 
 class ArrayObject;
 
 class NumberFormatObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t UNUMBER_FORMATTER_SLOT = 1;
   static constexpr uint32_t UFORMATTED_NUMBER_SLOT = 2;
   static constexpr uint32_t SLOT_COUNT = 3;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
                 "INTERNALS_SLOT must match self-hosting define for internals "
--- a/js/src/builtin/intl/PluralRules.cpp
+++ b/js/src/builtin/intl/PluralRules.cpp
@@ -37,17 +37,17 @@ using js::intl::IcuLocale;
 const JSClassOps PluralRulesObject::classOps_ = {nullptr, /* addProperty */
                                                  nullptr, /* delProperty */
                                                  nullptr, /* enumerate */
                                                  nullptr, /* newEnumerate */
                                                  nullptr, /* resolve */
                                                  nullptr, /* mayResolve */
                                                  PluralRulesObject::finalize};
 
-const Class PluralRulesObject::class_ = {
+const JSClass PluralRulesObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(PluralRulesObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
     &PluralRulesObject::classOps_};
 
 static bool pluralRules_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().PluralRules);
--- a/js/src/builtin/intl/PluralRules.h
+++ b/js/src/builtin/intl/PluralRules.h
@@ -17,17 +17,17 @@
 struct UFormattedNumber;
 struct UNumberFormatter;
 struct UPluralRules;
 
 namespace js {
 
 class PluralRulesObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t UPLURAL_RULES_SLOT = 1;
   static constexpr uint32_t UNUMBER_FORMATTER_SLOT = 2;
   static constexpr uint32_t UFORMATTED_NUMBER_SLOT = 3;
   static constexpr uint32_t SLOT_COUNT = 4;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
--- a/js/src/builtin/intl/RelativeTimeFormat.cpp
+++ b/js/src/builtin/intl/RelativeTimeFormat.cpp
@@ -36,17 +36,17 @@ const JSClassOps RelativeTimeFormatObjec
     nullptr, /* addProperty */
     nullptr, /* delProperty */
     nullptr, /* enumerate */
     nullptr, /* newEnumerate */
     nullptr, /* resolve */
     nullptr, /* mayResolve */
     RelativeTimeFormatObject::finalize};
 
-const Class RelativeTimeFormatObject::class_ = {
+const JSClass RelativeTimeFormatObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(RelativeTimeFormatObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
     &RelativeTimeFormatObject::classOps_};
 
 static bool relativeTimeFormat_toSource(JSContext* cx, unsigned argc,
                                         Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/builtin/intl/RelativeTimeFormat.h
+++ b/js/src/builtin/intl/RelativeTimeFormat.h
@@ -16,17 +16,17 @@
 #include "vm/NativeObject.h"
 
 struct URelativeDateTimeFormatter;
 
 namespace js {
 
 class RelativeTimeFormatObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t URELATIVE_TIME_FORMAT_SLOT = 1;
   static constexpr uint32_t SLOT_COUNT = 2;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
                 "INTERNALS_SLOT must match self-hosting define for internals "
                 "object slot");
--- a/js/src/debugger/Debugger.cpp
+++ b/js/src/debugger/Debugger.cpp
@@ -534,17 +534,17 @@ static const JSClassOps GlobalDebuggerVe
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     GlobalDebuggerVectorHolder_finalize};
 
-static const Class GlobalDebuggerVectorHolder_class = {
+static const JSClass GlobalDebuggerVectorHolder_class = {
     "GlobalDebuggerVectorHolder",
     JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE,
     &GlobalDebuggerVectorHolder_classOps};
 
 /* static */
 JSObject* DebugAPI::newGlobalDebuggersHolder(JSContext* cx) {
   NativeObject* obj = NewNativeObjectWithGivenProto(
       cx, &GlobalDebuggerVectorHolder_class, nullptr);
@@ -3861,17 +3861,17 @@ const JSClassOps Debugger::classOps_ = {
                                         nullptr, /* resolve     */
                                         nullptr, /* mayResolve  */
                                         nullptr, /* finalize    */
                                         nullptr, /* call        */
                                         nullptr, /* hasInstance */
                                         nullptr, /* construct   */
                                         Debugger::traceObject};
 
-const Class Debugger::class_ = {
+const JSClass Debugger::class_ = {
     "Debugger",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUG_COUNT),
     &Debugger::classOps_};
 
 static Debugger* Debugger_fromThisValue(JSContext* cx, const CallArgs& args,
                                         const char* fnname) {
   JSObject* thisobj = RequireObject(cx, args.thisv());
   if (!thisobj) {
--- a/js/src/debugger/Debugger.h
+++ b/js/src/debugger/Debugger.h
@@ -832,17 +832,17 @@ class Debugger : private mozilla::Linked
   friend struct js::GCManagedDeletePolicy<Debugger>;
 
   void traceForMovingGC(JSTracer* trc);
   void traceCrossCompartmentEdges(JSTracer* tracer);
 
   static const JSClassOps classOps_;
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
  private:
   static MOZ_MUST_USE bool getHookImpl(JSContext* cx, CallArgs& args,
                                        Debugger& dbg, Hook which);
   static MOZ_MUST_USE bool setHookImpl(JSContext* cx, CallArgs& args,
                                        Debugger& dbg, Hook which);
 
   static bool getEnabled(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/debugger/DebuggerMemory.cpp
+++ b/js/src/debugger/DebuggerMemory.cpp
@@ -60,17 +60,17 @@ Debugger* DebuggerMemory::getDebugger() 
 
 /* static */
 bool DebuggerMemory::construct(JSContext* cx, unsigned argc, Value* vp) {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                             "Debugger.Source");
   return false;
 }
 
-/* static */ const Class DebuggerMemory::class_ = {
+/* static */ const JSClass DebuggerMemory::class_ = {
     "Memory", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_COUNT)};
 
 /* static */
 DebuggerMemory* DebuggerMemory::checkThis(JSContext* cx, CallArgs& args,
                                           const char* fnName) {
   const Value& thisValue = args.thisv();
 
   if (!thisValue.isObject()) {
--- a/js/src/debugger/DebuggerMemory.h
+++ b/js/src/debugger/DebuggerMemory.h
@@ -25,17 +25,17 @@ class DebuggerMemory : public NativeObje
   Debugger* getDebugger();
 
  public:
   static DebuggerMemory* create(JSContext* cx, Debugger* dbg);
 
   enum { JSSLOT_DEBUGGER, JSSLOT_COUNT };
 
   static bool construct(JSContext* cx, unsigned argc, Value* vp);
-  static const Class class_;
+  static const JSClass class_;
   static const JSPropertySpec properties[];
   static const JSFunctionSpec methods[];
 
   // Accessor properties of Debugger.Memory.prototype.
 
   static bool setTrackingAllocationSites(JSContext* cx, unsigned argc,
                                          Value* vp);
   static bool getTrackingAllocationSites(JSContext* cx, unsigned argc,
--- a/js/src/debugger/Environment.cpp
+++ b/js/src/debugger/Environment.cpp
@@ -60,17 +60,17 @@ const JSClassOps DebuggerEnvironment::cl
     nullptr,                              /* mayResolve  */
     nullptr,                              /* finalize    */
     nullptr,                              /* call        */
     nullptr,                              /* hasInstance */
     nullptr,                              /* construct   */
     CallTraceMethod<DebuggerEnvironment>, /* trace */
 };
 
-const Class DebuggerEnvironment::class_ = {
+const JSClass DebuggerEnvironment::class_ = {
     "Environment",
     JSCLASS_HAS_PRIVATE |
         JSCLASS_HAS_RESERVED_SLOTS(DebuggerEnvironment::RESERVED_SLOTS),
     &classOps_};
 
 void DebuggerEnvironment::trace(JSTracer* trc) {
   // There is a barrier on private pointers, so the Unbarriered marking
   // is okay.
--- a/js/src/debugger/Environment.h
+++ b/js/src/debugger/Environment.h
@@ -21,27 +21,26 @@
 
 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;
 
-  static const Class class_;
+  static const JSClass class_;
 
   static NativeObject* initClass(JSContext* cx, Handle<GlobalObject*> global,
                                  HandleObject dbgCtor);
   static DebuggerEnvironment* create(JSContext* cx, HandleObject proto,
                                      HandleObject referent,
                                      HandleNativeObject debugger);
 
   void trace(JSTracer* trc);
--- a/js/src/debugger/Frame.cpp
+++ b/js/src/debugger/Frame.cpp
@@ -181,27 +181,27 @@ const JSClassOps DebuggerFrame::classOps
     nullptr,                        /* mayResolve  */
     finalize,                       /* finalize */
     nullptr,                        /* call        */
     nullptr,                        /* hasInstance */
     nullptr,                        /* construct   */
     CallTraceMethod<DebuggerFrame>, /* trace */
 };
 
-const Class DebuggerFrame::class_ = {
+const JSClass DebuggerFrame::class_ = {
     "Frame",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
         // We require foreground finalization so we can destruct GeneratorInfo's
         // HeapPtrs.
         JSCLASS_FOREGROUND_FINALIZE,
     &DebuggerFrame::classOps_};
 
 enum { JSSLOT_DEBUGARGUMENTS_FRAME, JSSLOT_DEBUGARGUMENTS_COUNT };
 
-const Class DebuggerArguments::class_ = {
+const JSClass DebuggerArguments::class_ = {
     "Arguments", JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGARGUMENTS_COUNT)};
 
 bool DebuggerFrame::resume(const FrameIter& iter) {
   FrameIter::Data* data = iter.copyData();
   if (!data) {
     return false;
   }
   setFrameIterData(data);
--- a/js/src/debugger/Frame.h
+++ b/js/src/debugger/Frame.h
@@ -95,34 +95,34 @@ class ScriptedOnPopHandler final : publi
 };
 
 enum class DebuggerFrameType { Eval, Global, Call, Module, WasmCall };
 
 enum class DebuggerFrameImplementation { Interpreter, Baseline, Ion, Wasm };
 
 class DebuggerArguments : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static DebuggerArguments* create(JSContext* cx, HandleObject proto,
                                    HandleDebuggerFrame frame);
 
  private:
   enum { FRAME_SLOT };
 
   static const unsigned RESERVED_SLOTS = 1;
 };
 
 class DebuggerFrame : public NativeObject {
   friend class DebuggerArguments;
   friend class ScriptedOnStepHandler;
   friend class ScriptedOnPopHandler;
 
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   enum {
     OWNER_SLOT = 0,
     ARGUMENTS_SLOT,
     ONSTEP_HANDLER_SLOT,
     ONPOP_HANDLER_SLOT,
 
     // If this is a frame for a generator call, and the generator object has
--- a/js/src/debugger/Object.cpp
+++ b/js/src/debugger/Object.cpp
@@ -80,17 +80,17 @@ const JSClassOps DebuggerObject::classOp
     nullptr,                         /* mayResolve  */
     nullptr,                         /* finalize    */
     nullptr,                         /* call        */
     nullptr,                         /* hasInstance */
     nullptr,                         /* construct   */
     CallTraceMethod<DebuggerObject>, /* trace */
 };
 
-const Class DebuggerObject::class_ = {
+const JSClass DebuggerObject::class_ = {
     "Object", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
     &classOps_};
 
 void DebuggerObject::trace(JSTracer* trc) {
   // There is a barrier on private pointers, so the Unbarriered marking
   // is okay.
   if (JSObject* referent = (JSObject*)getPrivate()) {
     TraceManuallyBarrieredCrossCompartmentEdge(
--- a/js/src/debugger/Object.h
+++ b/js/src/debugger/Object.h
@@ -31,17 +31,17 @@ class Debugger;
 class EvalOptions;
 class GlobalObject;
 class PromiseObject;
 
 enum { JSSLOT_DEBUGOBJECT_OWNER, JSSLOT_DEBUGOBJECT_COUNT };
 
 class DebuggerObject : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   static NativeObject* initClass(JSContext* cx, Handle<GlobalObject*> global,
                                  HandleObject debugCtor);
   static DebuggerObject* create(JSContext* cx, HandleObject proto,
                                 HandleObject referent,
                                 HandleNativeObject debugger);
 
   void trace(JSTracer* trc);
--- a/js/src/debugger/Script.cpp
+++ b/js/src/debugger/Script.cpp
@@ -66,17 +66,17 @@ const JSClassOps DebuggerScript::classOp
     nullptr,                         /* mayResolve  */
     nullptr,                         /* finalize    */
     nullptr,                         /* call        */
     nullptr,                         /* hasInstance */
     nullptr,                         /* construct   */
     CallTraceMethod<DebuggerScript>, /* trace */
 };
 
-const Class DebuggerScript::class_ = {
+const JSClass DebuggerScript::class_ = {
     "Script", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
     &classOps_};
 
 void DebuggerScript::trace(JSTracer* trc) {
   JSObject* upcast = this;
   // This comes from a private pointer, so no barrier needed.
   gc::Cell* cell = getReferentCell();
   if (cell) {
--- a/js/src/debugger/Script.h
+++ b/js/src/debugger/Script.h
@@ -22,17 +22,17 @@ class BaseScript;
 class GlobalObject;
 
 namespace gc {
 struct Cell;
 }
 
 class DebuggerScript : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   enum {
     OWNER_SLOT,
 
     // Holds any instrumentation ID that has been assigned to the script.
     INSTRUMENTATION_ID_SLOT,
 
     RESERVED_SLOTS,
--- a/js/src/debugger/Source.cpp
+++ b/js/src/debugger/Source.cpp
@@ -58,17 +58,17 @@ const JSClassOps DebuggerSource::classOp
     nullptr,                         /* mayResolve  */
     nullptr,                         /* finalize    */
     nullptr,                         /* call        */
     nullptr,                         /* hasInstance */
     nullptr,                         /* construct   */
     CallTraceMethod<DebuggerSource>, /* trace */
 };
 
-const Class DebuggerSource::class_ = {
+const JSClass DebuggerSource::class_ = {
     "Source", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
     &classOps_};
 
 /* static */
 NativeObject* DebuggerSource::initClass(JSContext* cx,
                                         Handle<GlobalObject*> global,
                                         HandleObject debugCtor) {
   return InitClass(cx, debugCtor, nullptr, &class_, construct, 0, properties_,
--- a/js/src/debugger/Source.h
+++ b/js/src/debugger/Source.h
@@ -17,17 +17,17 @@
 namespace js {
 class GlobalObject;
 }
 
 namespace js {
 
 class DebuggerSource : public NativeObject {
  public:
-  static const Class class_;
+  static const JSClass class_;
 
   enum {
     OWNER_SLOT,
     TEXT_SLOT,
     RESERVED_SLOTS,
   };
 
   static NativeObject* initClass(JSContext* cx, Handle<GlobalObject*> global,
--- a/js/src/gc/Allocator.cpp
+++ b/js/src/gc/Allocator.cpp
@@ -27,17 +27,17 @@ using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
 using namespace js;
 using namespace gc;
 
 template <AllowGC allowGC /* = CanGC */>
 JSObject* js::AllocateObject(JSContext* cx, AllocKind kind,
                              size_t nDynamicSlots, InitialHeap heap,
-                             const Class* clasp) {
+                             const JSClass* clasp) {
   MOZ_ASSERT(IsObjectAllocKind(kind));
   size_t thingSize = Arena::thingSize(kind);
 
   MOZ_ASSERT(thingSize == Arena::thingSize(kind));
   MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0));
   static_assert(
       sizeof(JSObject_Slots0) >= MinCellSize,
       "All allocations must be at least the allocator-imposed minimum size.");
@@ -78,29 +78,29 @@ JSObject* js::AllocateObject(JSContext* 
   }
 
   return GCRuntime::tryNewTenuredObject<allowGC>(cx, kind, thingSize,
                                                  nDynamicSlots);
 }
 template JSObject* js::AllocateObject<NoGC>(JSContext* cx, gc::AllocKind kind,
                                             size_t nDynamicSlots,
                                             gc::InitialHeap heap,
-                                            const Class* clasp);
+                                            const JSClass* clasp);
 template JSObject* js::AllocateObject<CanGC>(JSContext* cx, gc::AllocKind kind,
                                              size_t nDynamicSlots,
                                              gc::InitialHeap heap,
-                                             const Class* clasp);
+                                             const JSClass* clasp);
 
 // Attempt to allocate a new JSObject out of the nursery. If there is not
 // enough room in the nursery or there is an OOM, this method will return
 // nullptr.
 template <AllowGC allowGC>
 JSObject* GCRuntime::tryNewNurseryObject(JSContext* cx, size_t thingSize,
                                          size_t nDynamicSlots,
-                                         const Class* clasp) {
+                                         const JSClass* clasp) {
   MOZ_RELEASE_ASSERT(!cx->isHelperThreadContext());
 
   MOZ_ASSERT(cx->isNurseryAllocAllowed());
   MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
 
   JSObject* obj =
       cx->nursery().allocateObject(cx, thingSize, nDynamicSlots, clasp);
--- 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);
@@ -29,17 +27,17 @@ T* Allocate(JSContext* cx);
 // Allocate a JSObject.
 //
 // A longer signature that includes additional information in support of various
 // optimizations. If dynamic slots are requested they will be allocated and the
 // pointer stored directly in |NativeObject::slots_|.
 template <AllowGC allowGC = CanGC>
 JSObject* AllocateObject(JSContext* cx, gc::AllocKind kind,
                          size_t nDynamicSlots, gc::InitialHeap heap,
-                         const Class* clasp);
+                         const JSClass* clasp);
 
 // Internal function used for nursery-allocatable strings.
 template <typename StringAllocT, AllowGC allowGC = CanGC>
 StringAllocT* AllocateStringImpl(JSContext* cx, gc::InitialHeap heap);
 
 // Allocate a string.
 //
 // Use for nursery-allocatable strings. Returns a value cast to the correct
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -484,17 +484,17 @@ class GCRuntime {
   void releaseHeldRelocatedArenas();
   void releaseHeldRelocatedArenasWithoutUnlocking(const AutoLockGC& lock);
 
   // Allocator
   template <AllowGC allowGC>
   MOZ_MUST_USE bool checkAllocatorState(JSContext* cx, AllocKind kind);
   template <AllowGC allowGC>
   JSObject* tryNewNurseryObject(JSContext* cx, size_t thingSize,
-                                size_t nDynamicSlots, const Class* clasp);
+                                size_t nDynamicSlots, const JSClass* clasp);
   template <AllowGC allowGC>
   static JSObject* tryNewTenuredObject(JSContext* cx, AllocKind kind,
                                        size_t thingSize, size_t nDynamicSlots);
   template <typename T, AllowGC allowGC>
   static T* tryNewTenuredThing(JSContext* cx, AllocKind kind, size_t thingSize);
   template <AllowGC allowGC>
   JSString* tryNewNurseryString(JSContext* cx, size_t thingSize,
                                 AllocKind kind);
--- a/js/src/gc/GCTrace.cpp
+++ b/js/src/gc/GCTrace.cpp
@@ -127,17 +127,17 @@ void GCTrace::traceNurseryAlloc(Cell* th
 
 void GCTrace::traceTenuredAlloc(Cell* thing, AllocKind kind) {
   if (thing) {
     TraceEvent(gcTraceFile, TraceEventTenuredAlloc, uint64_t(thing),
                uint8_t(kind));
   }
 }
 
-void js::gc::GCTrace::maybeTraceClass(const Class* clasp) {
+void js::gc::GCTrace::maybeTraceClass(const JSClass* clasp) {
   if (tracedClasses.has(clasp)) {
     return;
   }
 
   TraceEvent(gcTraceFile, TraceEventClassInfo, uint64_t(clasp));
   TraceString(gcTraceFile, clasp->name);
   TraceInt(gcTraceFile, clasp->flags);
   TraceInt(gcTraceFile, clasp->hasFinalize());
--- a/js/src/gc/GCTrace.h
+++ b/js/src/gc/GCTrace.h
@@ -38,23 +38,23 @@ class GCTrace {
   void traceMajorGCStart();
   void traceTenuredFinalize(Cell* thing);
   void traceMajorGCEnd();
   void traceTypeNewScript(js::ObjectGroup* group);
 
  private:
   FILE* gcTraceFile = nullptr;
 
-  HashSet<const Class*, DefaultHasher<const Class*>, SystemAllocPolicy>
+  HashSet<const JSClass*, DefaultHasher<const JSClass*>, SystemAllocPolicy>
       tracedClasses;
   HashSet<const ObjectGroup*, DefaultHasher<const ObjectGroup*>,
           SystemAllocPolicy>
       tracedGroups;
 
-  void maybeTraceClass(const Class* clasp);
+  void maybeTraceClass(const JSClass* clasp);
   void maybeTraceGroup(ObjectGroup* group);
 
 #else
 
   MOZ_MUST_USE bool initTrace(GCRuntime& gc) { return true; }
   void finishTrace() {}
   bool traceEnabled() { return false; }
   void traceNurseryAlloc(Cell* thing, size_t size) {}
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1432,17 +1432,17 @@ static void VisitTraceList(const Functor
 
 // Call the trace hook set on the object, if present. If further tracing of
 // NativeObject fields is required, this will return the native object.
 enum class CheckGeneration { DoChecks, NoChecks };
 template <typename Functor>
 static inline NativeObject* CallTraceHook(Functor&& f, JSTracer* trc,
                                           JSObject* obj,
                                           CheckGeneration check) {
-  const Class* clasp = obj->getClass();
+  const JSClass* clasp = obj->getClass();
   MOZ_ASSERT(clasp);
   MOZ_ASSERT(obj->isNative() == clasp->isNative());
 
   if (!clasp->hasTrace()) {
     return &obj->as<NativeObject>();
   }
 
   if (clasp->isTrace(InlineTypedObject::obj_trace)) {
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -404,17 +404,17 @@ void js::Nursery::leaveZealMode() {
     setStartPosition();
     poisonAndInitCurrentChunk();
   }
 }
 #endif  // JS_GC_ZEAL
 
 JSObject* js::Nursery::allocateObject(JSContext* cx, size_t size,
                                       size_t nDynamicSlots,
-                                      const js::Class* clasp) {
+                                      const JSClass* clasp) {
   // Ensure there's enough space to replace the contents with a
   // RelocationOverlay.
   MOZ_ASSERT(size >= sizeof(RelocationOverlay));
 
   // Sanity check the finalizer.
   MOZ_ASSERT_IF(clasp->hasFinalize(),
                 CanNurseryAllocateFinalizedClass(clasp) || clasp->isProxy());
 
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -151,17 +151,17 @@ class TenuringTracer : public JSTracer {
   void traceSlots(JS::Value* vp, JS::Value* end);
 };
 
 // Classes with JSCLASS_SKIP_NURSERY_FINALIZE or Wrapper classes with
 // CROSS_COMPARTMENT flags will not have their finalizer called if they are
 // nursery allocated and not promoted to the tenured heap. The finalizers for
 // these classes must do nothing except free data which was allocated via
 // Nursery::allocateBuffer.
-inline bool CanNurseryAllocateFinalizedClass(const js::Class* const clasp) {
+inline bool CanNurseryAllocateFinalizedClass(const JSClass* const clasp) {
   MOZ_ASSERT(clasp->hasFinalize());
   return clasp->flags & JSCLASS_SKIP_NURSERY_FINALIZE;
 }
 
 class Nursery {
  public:
   static const size_t Alignment = gc::ChunkSize;
   static const size_t ChunkShift = gc::ChunkShift;
@@ -225,17 +225,17 @@ class Nursery {
   }
 
   template <typename T>
   inline bool isInside(const SharedMem<T>& p) const;
 
   // Allocate and return a pointer to a new GC object with its |slots|
   // pointer pre-filled. Returns nullptr if the Nursery is full.
   JSObject* allocateObject(JSContext* cx, size_t size, size_t numDynamic,
-                           const js::Class* clasp);
+                           const JSClass* clasp);
 
   // Allocate and return a pointer to a new string. Returns nullptr if the
   // Nursery is full.
   gc::Cell* allocateString(JS::Zone* zone, size_t size, gc::AllocKind kind);
 
   // String zones are stored just before the string in nursery memory.
   static JS::Zone* getStringZone(const JSString* str) {
 #ifdef DEBUG
--- a/js/src/gc/ObjectKind-inl.h
+++ b/js/src/gc/ObjectKind-inl.h
@@ -13,17 +13,17 @@
 #define gc_ObjectKind_inl_h
 
 #include "vm/NativeObject.h"
 
 namespace js {
 namespace gc {
 
 static inline bool CanBeFinalizedInBackground(AllocKind kind,
-                                              const Class* clasp) {
+                                              const JSClass* clasp) {
   MOZ_ASSERT(IsObjectAllocKind(kind));
   /* If the class has no finalizer or a finalizer that is safe to call on
    * a different thread, we change the alloc kind. For example,
    * AllocKind::OBJECT0 calls the finalizer on the main thread,
    * AllocKind::OBJECT0_BACKGROUND calls the finalizer on the gcHelperThread.
    * IsBackgroundFinalized is called to prevent recursively incrementing
    * the alloc kind; kind may already be a background finalize kind.
    */
@@ -46,17 +46,17 @@ extern const AllocKind slotsToThingKind[
 /* Get the best kind to use when making an object with the given slot count. */
 static inline AllocKind GetGCObjectKind(size_t numSlots) {
   if (numSlots >= SLOTS_TO_THING_KIND_LIMIT) {
     return AllocKind::OBJECT16;
   }
   return slotsToThingKind[numSlots];
 }
 
-static inline AllocKind GetGCObjectKind(const Class* clasp) {
+static inline AllocKind GetGCObjectKind(const JSClass* clasp) {
   if (clasp == FunctionClassPtr) {
     return AllocKind::FUNCTION;
   }
 
   MOZ_ASSERT(!clasp->isProxy(), "Proxies should use GetProxyGCObjectKind");
 
   uint32_t nslots = JSCLASS_RESERVED_SLOTS(clasp);
   if (clasp->flags & JSCLASS_HAS_PRIVATE) {
@@ -127,17 +127,17 @@ static inline size_t GetGCKindSlots(Allo
     case AllocKind::OBJECT16:
     case AllocKind::OBJECT16_BACKGROUND:
       return 16;
     default:
       MOZ_CRASH("Bad object alloc kind");
   }
 }
 
-static inline size_t GetGCKindSlots(AllocKind thingKind, const Class* clasp) {
+static inline size_t GetGCKindSlots(AllocKind thingKind, const JSClass* clasp) {
   size_t nslots = GetGCKindSlots(thingKind);
 
   /* An object's private data uses the space taken by its last fixed slot. */
   if (clasp->flags & JSCLASS_HAS_PRIVATE) {
     MOZ_ASSERT(nslots > 0);
     nslots--;
   }
 
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -2352,17 +2352,17 @@ bool BaselineCacheIRCompiler::emitGuardF
       Address flagAddr(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags());
       masm.branchTest32(Assembler::NonZero, flagAddr,
                         Imm32(BaselineFrame::HAS_ARGS_OBJ), failure->label());
     } break;
     case CallFlags::FunApplyArray: {
       // Ensure that args is an array object.
       masm.branchTestObject(Assembler::NotEqual, argsAddr, failure->label());
       masm.unboxObject(argsAddr, scratch);
-      const Class* clasp = &ArrayObject::class_;
+      const JSClass* clasp = &ArrayObject::class_;
       masm.branchTestObjClass(Assembler::NotEqual, scratch, clasp, scratch2,
                               scratch, failure->label());
 
       // Get the array elements and length
       Register elementsReg = scratch;
       masm.loadPtr(Address(scratch, NativeObject::offsetOfElements()),
                    elementsReg);
       Register calleeArgcReg = scratch2;
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -779,24 +779,24 @@ JSObject* BaselineInspector::getTemplate
         return result;
       }
     }
   }
 
   return nullptr;
 }
 
-JSObject* BaselineInspector::getTemplateObjectForClassHook(jsbytecode* pc,
-                                                           const Class* clasp) {
+JSObject* BaselineInspector::getTemplateObjectForClassHook(
+    jsbytecode* pc, const JSClass* clasp) {
   const ICEntry& entry = icEntryFromPC(pc);
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     if (ICStub::IsCacheIRKind(stub->kind())) {
       auto filter = [stub, clasp](CacheIRReader& args,
                                   const CacheIRStubInfo* info) {
-        return info->getStubField<Class*>(stub, args.stubOffset()) == clasp;
+        return info->getStubField<JSClass*>(stub, args.stubOffset()) == clasp;
       };
       JSObject* result = MaybeTemplateObject(
           stub, MetaTwoByteKind::ClassTemplateObject, filter);
       if (result) {
         return result;
       }
     }
   }
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -90,17 +90,17 @@ class BaselineInspector {
 
   bool hasSeenNegativeIndexGetElement(jsbytecode* pc);
   bool hasSeenNonIntegerIndex(jsbytecode* pc);
   bool hasSeenAccessedGetter(jsbytecode* pc);
   bool hasSeenDoubleResult(jsbytecode* pc);
 
   JSObject* getTemplateObject(jsbytecode* pc);
   JSObject* getTemplateObjectForNative(jsbytecode* pc, Native native);
-  JSObject* getTemplateObjectForClassHook(jsbytecode* pc, const Class* clasp);
+  JSObject* getTemplateObjectForClassHook(jsbytecode* pc, const JSClass* clasp);
 
   // Sometimes the group a template object will have is known, even if the
   // object itself isn't.
   ObjectGroup* getTemplateObjectGroup(jsbytecode* pc);
 
   JSFunction* getSingleCallee(jsbytecode* pc);
 
   LexicalEnvironmentObject* templateNamedLambdaObject();
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1649,17 +1649,17 @@ AttachDecision GetPropIRGenerator::tryAt
     case ProxyStubType::Generic:
       return tryAttachGenericProxy(obj, objId, id,
                                    /* handleDOMProxies = */ false);
   }
 
   MOZ_CRASH("Unexpected ProxyStubType");
 }
 
-static TypedThingLayout GetTypedThingLayout(const Class* clasp) {
+static TypedThingLayout GetTypedThingLayout(const JSClass* clasp) {
   if (IsTypedArrayClass(clasp)) {
     return Layout_TypedArray;
   }
   if (IsOutlineTypedObjectClass(clasp)) {
     return Layout_OutlineTypedObject;
   }
   if (IsInlineTypedObjectClass(clasp)) {
     return Layout_InlineTypedObject;
@@ -3671,17 +3671,17 @@ static bool CanAttachAddElement(NativeOb
   // Make sure the objects on the prototype don't have any indexed properties
   // or that such properties can't appear without a shape change.
   do {
     // The first two checks are also relevant to the receiver object.
     if (obj->isIndexed()) {
       return false;
     }
 
-    const Class* clasp = obj->getClass();
+    const JSClass* clasp = obj->getClass();
     if (clasp != &ArrayObject::class_ &&
         (clasp->getAddProperty() || clasp->getResolve() ||
          clasp->getOpsLookupProperty() || clasp->getOpsSetProperty())) {
       return false;
     }
 
     // If we're initializing a property instead of setting one, the objects
     // on the prototype are not relevant.
@@ -5439,18 +5439,18 @@ void CallIRGenerator::trackAttached(cons
     sp.valueProperty("thisval", thisval_);
     sp.valueProperty("argc", Int32Value(argc_));
   }
 #endif
 }
 
 // Class which holds a shape pointer for use when caches might reference data in
 // other zones.
-static const Class shapeContainerClass = {"ShapeContainer",
-                                          JSCLASS_HAS_RESERVED_SLOTS(1)};
+static const JSClass shapeContainerClass = {"ShapeContainer",
+                                            JSCLASS_HAS_RESERVED_SLOTS(1)};
 
 static const size_t SHAPE_CONTAINER_SLOT = 0;
 
 JSObject* jit::NewWrapperWithObjectShape(JSContext* cx,
                                          HandleNativeObject obj) {
   MOZ_ASSERT(cx->compartment() != obj->compartment());
 
   RootedObject wrapper(cx);
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -962,17 +962,17 @@ class MOZ_RAII CacheIRWriter : public JS
 
   void guardClass(ObjOperandId obj, GuardClassKind kind) {
     static_assert(sizeof(GuardClassKind) == sizeof(uint8_t),
                   "GuardClassKind must fit in a byte");
     writeOpWithOperandId(CacheOp::GuardClass, obj);
     buffer_.writeByte(uint32_t(kind));
   }
 
-  FieldOffset guardAnyClass(ObjOperandId obj, const Class* clasp) {
+  FieldOffset guardAnyClass(ObjOperandId obj, const JSClass* clasp) {
     writeOpWithOperandId(CacheOp::GuardAnyClass, obj);
     return addStubField(uintptr_t(clasp), StubField::Type::RawWord);
   }
 
   void guardFunctionIsNative(ObjOperandId obj) {
     writeOpWithOperandId(CacheOp::GuardFunctionIsNative, obj);
   }
 
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -957,17 +957,17 @@ template GCPtr<JSString*>& CacheIRStubIn
 template GCPtr<JSFunction*>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
 template GCPtr<JS::Symbol*>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
 template GCPtr<JS::Value>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
 template GCPtr<jsid>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
-template GCPtr<Class*>& CacheIRStubInfo::getStubField<ICStub>(
+template GCPtr<JSClass*>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
 template GCPtr<ArrayObject*>& CacheIRStubInfo::getStubField<ICStub>(
     ICStub* stub, uint32_t offset) const;
 
 template <typename T, typename V>
 static void InitGCPtr(uintptr_t* ptr, V val) {
   AsGCPtr<T>(ptr)->init(mozilla::BitwiseCast<T>(val));
 }
@@ -1633,17 +1633,17 @@ bool CacheIRCompiler::emitGuardClass() {
   Register obj = allocator.useRegister(masm, objId);
   AutoScratchRegister scratch(allocator, masm);
 
   FailurePath* failure;
   if (!addFailurePath(&failure)) {
     return false;
   }
 
-  const Class* clasp = nullptr;
+  const JSClass* clasp = nullptr;
   switch (reader.guardClassKind()) {
     case GuardClassKind::Array:
       clasp = &ArrayObject::class_;
       break;
     case GuardClassKind::MappedArguments:
       clasp = &MappedArgumentsObject::class_;
       break;
     case GuardClassKind::UnmappedArguments:
@@ -1704,17 +1704,17 @@ bool CacheIRCompiler::emitGuardSpecificN
   AutoScratchRegister scratch(allocator, masm);
 
   FailurePath* failure;
   if (!addFailurePath(&failure)) {
     return false;
   }
 
   // Ensure obj is a function.
-  const Class* clasp = &JSFunction::class_;
+  const JSClass* clasp = &JSFunction::class_;
   masm.branchTestObjClass(Assembler::NotEqual, obj, clasp, scratch, obj,
                           failure->label());
 
   // Ensure function native matches.
   masm.branchPtr(Assembler::NotEqual,
                  Address(obj, JSFunction::offsetOfNativeOrEnv()),
                  ImmPtr(nativeFunc), failure->label());
   return true;
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -890,19 +890,19 @@ class MOZ_RAII CacheIRCompiler {
   ObjectGroup* groupStubField(uint32_t offset) {
     MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
     return (ObjectGroup*)readStubWord(offset, StubField::Type::ObjectGroup);
   }
   JS::Compartment* compartmentStubField(uint32_t offset) {
     MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
     return (JS::Compartment*)readStubWord(offset, StubField::Type::RawWord);
   }
-  const Class* classStubField(uintptr_t offset) {
+  const JSClass* classStubField(uintptr_t offset) {
     MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
-    return (const Class*)readStubWord(offset, StubField::Type::RawWord);
+    return (const JSClass*)readStubWord(offset, StubField::Type::RawWord);
   }
   const void* proxyHandlerStubField(uintptr_t offset) {
     MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
     return (const void*)readStubWord(offset, StubField::Type::RawWord);
   }
   jsid idStubField(uint32_t offset) {
     MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
     return jsid::fromRawBits(readStubWord(offset, StubField::Type::Id));
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -12735,23 +12735,23 @@ void CodeGenerator::emitIsCallableOrCons
   masm.jump(&done);
 
   masm.bind(&notFunction);
 
   // Just skim proxies off. Their notion of isCallable()/isConstructor() is
   // more complicated.
   masm.branchTestClassIsProxy(true, output, failure);
 
-  masm.branchPtr(Assembler::NonZero, Address(output, offsetof(js::Class, cOps)),
+  masm.branchPtr(Assembler::NonZero, Address(output, offsetof(JSClass, cOps)),
                  ImmPtr(nullptr), &hasCOps);
   masm.move32(Imm32(0), output);
   masm.jump(&done);
 
   masm.bind(&hasCOps);
-  masm.loadPtr(Address(output, offsetof(js::Class, cOps)), output);
+  masm.loadPtr(Address(output, offsetof(JSClass, cOps)), output);
   size_t opsOffset = mode == Callable ? offsetof(JSClassOps, call)
                                       : offsetof(JSClassOps, construct);
   masm.cmpPtrSet(Assembler::NonZero, Address(output, opsOffset),
                  ImmPtr(nullptr), output);
 
   masm.bind(&done);
 }
 
@@ -12922,23 +12922,23 @@ void CodeGenerator::visitIsTypedArray(LI
     ool = oolCallVM<Fn, jit::IsPossiblyWrappedTypedArray>(
         lir, ArgList(object), StoreRegisterTo(output));
   }
 
   Label notTypedArray;
   Label done;
 
   static_assert(Scalar::Int8 == 0, "Int8 is the first typed array class");
-  const Class* firstTypedArrayClass =
+  const JSClass* firstTypedArrayClass =
       TypedArrayObject::classForType(Scalar::Int8);
 
   static_assert(
       (Scalar::BigUint64 - Scalar::Int8) == Scalar::MaxTypedArrayViewType - 1,
       "BigUint64 is the last typed array class");
-  const Class* lastTypedArrayClass =
+  const JSClass* lastTypedArrayClass =
       TypedArrayObject::classForType(Scalar::BigUint64);
 
   masm.loadObjClassUnsafe(object, output);
   masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass),
                  &notTypedArray);
   masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass),
                  &notTypedArray);
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5640,17 +5640,17 @@ AbortReasonOr<Ok> IonBuilder::jsop_sprea
   // leaked to user. The complications of spread call iterator behaviour are
   // handled when the user objects are expanded and copied into this hidden
   // array.
 
 #ifdef DEBUG
   // If we know class, ensure it is what we expected
   MDefinition* argument = current->peek(-1);
   if (TemporaryTypeSet* objTypes = argument->resultTypeSet()) {
-    if (const Class* clasp = objTypes->getKnownClass(constraints())) {
+    if (const JSClass* clasp = objTypes->getKnownClass(constraints())) {
       MOZ_ASSERT(clasp == &ArrayObject::class_);
     }
   }
 #endif
 
   MDefinition* argArr = current->pop();
   MDefinition* argThis = current->pop();
   MDefinition* argFunc = current->pop();
@@ -7679,32 +7679,32 @@ void IonBuilder::maybeMarkEmpty(MDefinit
     if (types) {
       ins->setResultTypeSet(types);
       return;
     }
   }
 }
 
 // Return whether property lookups can be performed effectlessly on clasp.
-static bool ClassHasEffectlessLookup(const Class* clasp) {
+static bool ClassHasEffectlessLookup(const JSClass* clasp) {
   return IsTypedObjectClass(clasp) ||
          (clasp->isNative() && !clasp->getOpsLookupProperty());
 }
 
 // Return whether an object might have a property for name which is not
 // accounted for by type information.
 static bool ObjectHasExtraOwnProperty(CompileRealm* realm,
                                       TypeSet::ObjectKey* object, jsid id) {
   // Some typed object properties are not reflected in type information.
   if (object->isGroup() && object->group()->maybeTypeDescr()) {
     return object->group()->typeDescr().hasProperty(realm->runtime()->names(),
                                                     id);
   }
 
-  const Class* clasp = object->clasp();
+  const JSClass* clasp = object->clasp();
 
   // Array |length| properties are not reflected in type information.
   if (clasp == &ArrayObject::class_) {
     return JSID_IS_ATOM(id, realm->runtime()->names().length);
   }
 
   // Resolve hooks can install new properties on objects on demand.
   JSObject* singleton = object->isSingleton() ? object->singleton() : nullptr;
@@ -7857,17 +7857,17 @@ JSObject* IonBuilder::testSingletonPrope
         if (!alloc().ensureBallast()) {
           return nullptr;
         }
 
         if (analysisContext) {
           key->ensureTrackedProperty(analysisContext, id);
         }
 
-        const Class* clasp = key->clasp();
+        const JSClass* clasp = key->clasp();
         if (!ClassHasEffectlessLookup(clasp) ||
             ObjectHasExtraOwnProperty(realm, key, id)) {
           return nullptr;
         }
         if (key->unknownProperties()) {
           return nullptr;
         }
         HeapTypeSetKey property = key->property(id);
@@ -7926,17 +7926,17 @@ AbortReasonOr<bool> IonBuilder::testNotD
         return abort(AbortReason::Alloc);
       }
 
       if (!key->hasStableClassAndProto(constraints()) ||
           key->unknownProperties()) {
         return false;
       }
 
-      const Class* clasp = key->clasp();
+      const JSClass* clasp = key->clasp();
       if (!ClassHasEffectlessLookup(clasp) ||
           ObjectHasExtraOwnProperty(realm, key, id)) {
         return false;
       }
 
       // If the object is a singleton, we can do a lookup now to avoid
       // unnecessary invalidations later on, in case the property types
       // have not yet been instantiated.
@@ -8866,30 +8866,30 @@ AbortReasonOr<Ok> IonBuilder::pushDerive
   current->push(derivedTypedObj);
 
   // Determine (if possible) the class/proto that `derivedTypedObj` will
   // have. For derived typed objects, the opacity will be the same as the
   // incoming object from which the derived typed object is, well, derived.
   // The prototype will be determined based on the type descriptor (and is
   // immutable).
   TemporaryTypeSet* objTypes = obj->resultTypeSet();
-  const Class* expectedClass = nullptr;
-  if (const Class* objClass =
+  const JSClass* expectedClass = nullptr;
+  if (const JSClass* objClass =
           objTypes ? objTypes->getKnownClass(constraints()) : nullptr) {
     MOZ_ASSERT(IsTypedObjectClass(objClass));
     expectedClass =
         GetOutlineTypedObjectClass(IsOpaqueTypedObjectClass(objClass));
   }
   const TypedProto* expectedProto = derivedPrediction.getKnownPrototype();
   MOZ_ASSERT_IF(expectedClass, IsTypedObjectClass(expectedClass));
 
   // Determine (if possible) the class/proto that the observed type set
   // describes.
   TemporaryTypeSet* observedTypes = bytecodeTypes(pc);
-  const Class* observedClass = observedTypes->getKnownClass(constraints());
+  const JSClass* observedClass = observedTypes->getKnownClass(constraints());
 
   // If expectedClass/expectedProto are both non-null (and hence known), we
   // can predict precisely what object group derivedTypedObj will have.
   // Therefore, if we observe that this group is already contained in the set
   // of observedTypes, we can skip the barrier.
   //
   // Barriers still wind up being needed in some relatively
   // rare cases:
@@ -9899,17 +9899,17 @@ AbortReasonOr<Ok> IonBuilder::initOrSetE
   // We can avoid worrying about holes in the IC if we know a priori we are safe
   // from them. If TI can guard that there are no indexed properties on the
   // prototype chain, we know that we aren't missing any setters by overwriting
   // the hole with another value.
   bool guardHoles;
   MOZ_TRY_VAR(guardHoles, ElementAccessHasExtraIndexedProperty(this, object));
 
   // Make sure the object being written to doesn't have copy on write elements.
-  const Class* clasp =
+  const JSClass* clasp =
       object->resultTypeSet()
           ? object->resultTypeSet()->getKnownClass(constraints())
           : nullptr;
   bool checkNative = !clasp || !clasp->isNative();
   object = addMaybeCopyElementsForWrite(object, checkNative);
 
   // Emit SetPropertyCache.
   bool strict = JSOp(*pc) == JSOP_STRICTSETELEM;
@@ -10505,17 +10505,17 @@ NativeObject* IonBuilder::commonPrototyp
       continue;
     }
 
     while (key) {
       if (key->unknownProperties()) {
         return nullptr;
       }
 
-      const Class* clasp = key->clasp();
+      const JSClass* clasp = key->clasp();
       if (!ClassHasEffectlessLookup(clasp)) {
         return nullptr;
       }
       JSObject* singleton = key->isSingleton() ? key->singleton() : nullptr;
       if (ObjectHasExtraOwnProperty(realm, key, id)) {
         if (!singleton || !singleton->is<GlobalObject>()) {
           return nullptr;
         }
@@ -10736,17 +10736,17 @@ AbortReasonOr<Ok> IonBuilder::annotateGe
       continue;
     }
     TypeSet::ObjectKey* key = TypeSet::ObjectKey::get(group);
     if (key->unknownProperties() || !key->proto().isObject()) {
       continue;
     }
     JSObject* proto = checkNurseryObject(key->proto().toObject());
 
-    const Class* clasp = key->clasp();
+    const JSClass* clasp = key->clasp();
     if (!ClassHasEffectlessLookup(clasp) ||
         ObjectHasExtraOwnProperty(realm, key, NameToId(name))) {
       continue;
     }
 
     HeapTypeSetKey ownTypes = key->property(NameToId(name));
     if (ownTypes.isOwnProperty(constraints())) {
       continue;
@@ -13742,17 +13742,17 @@ AbortReasonOr<Ok> IonBuilder::loadTypedO
   MOZ_TRY(loadTypedObjectData(typedObj, &owner, &ownerByteOffset));
 
   if (!ownerByteOffset.add(baseByteOffset)) {
     return abort(AbortReason::Disable,
                  "Overflow after adding the base offset.");
   }
 
   TemporaryTypeSet* ownerTypes = owner->resultTypeSet();
-  const Class* clasp =
+  const JSClass* clasp =
       ownerTypes ? ownerTypes->getKnownClass(constraints()) : nullptr;
   if (clasp && IsInlineTypedObjectClass(clasp)) {
     // Perform the load directly from the owner pointer.
     if (!ownerByteOffset.add(InlineTypedObject::offsetOfDataStart())) {
       return abort(AbortReason::Disable,
                    "Overflow after adding the data start.");
     }
     *ownerElements = owner;
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -833,21 +833,21 @@ class IonBuilder : public MIRGenerator,
   InliningResult inlineIsCallable(CallInfo& callInfo);
   InliningResult inlineIsConstructor(CallInfo& callInfo);
   InliningResult inlineIsObject(CallInfo& callInfo);
   InliningResult inlineToObject(CallInfo& callInfo);
   InliningResult inlineIsCrossRealmArrayConstructor(CallInfo& callInfo);
   InliningResult inlineToInteger(CallInfo& callInfo);
   InliningResult inlineToString(CallInfo& callInfo);
   InliningResult inlineDump(CallInfo& callInfo);
-  InliningResult inlineHasClass(CallInfo& callInfo, const Class* clasp,
-                                const Class* clasp2 = nullptr,
-                                const Class* clasp3 = nullptr,
-                                const Class* clasp4 = nullptr);
-  InliningResult inlineGuardToClass(CallInfo& callInfo, const Class* clasp);
+  InliningResult inlineHasClass(CallInfo& callInfo, const JSClass* clasp,
+                                const JSClass* clasp2 = nullptr,
+                                const JSClass* clasp3 = nullptr,
+                                const JSClass* clasp4 = nullptr);
+  InliningResult inlineGuardToClass(CallInfo& callInfo, const JSClass* clasp);
   InliningResult inlineIsConstructing(CallInfo& callInfo);
   InliningResult inlineSubstringKernel(CallInfo& callInfo);
   InliningResult inlineObjectHasPrototype(CallInfo& callInfo);
   InliningResult inlineFinishBoundFunctionInit(CallInfo& callInfo);
   InliningResult inlineIsPackedArray(CallInfo& callInfo);
   InliningResult inlineWasmCall(CallInfo& callInfo, JSFunction* target);
 
   // Testing functions.
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -677,17 +677,17 @@ bool IonCacheIRCompiler::emitGuardCompar
 }
 
 bool IonCacheIRCompiler::emitGuardAnyClass() {
   JitSpew(JitSpew_Codegen, __FUNCTION__);
   ObjOperandId objId = reader.objOperandId();
   Register obj = allocator.useRegister(masm, objId);
   AutoScratchRegister scratch(allocator, masm);
 
-  const Class* clasp = classStubField(reader.stubOffset());
+  const JSClass* clasp = classStubField(reader.stubOffset());
 
   FailurePath* failure;
   if (!addFailurePath(&failure)) {
     return false;
   }
 
   if (objectGuardNeedsSpectreMitigations(objId)) {
     masm.branchTestObjClass(Assembler::NotEqual, obj, clasp, scratch, obj,
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -624,17 +624,17 @@ IonBuilder::InliningResult IonBuilder::i
     MInstruction* byteOffset = addTypedArrayByteOffset(thisArg);
     current->push(byteOffset);
     return InliningStatus_Inlined;
   }
 
   // Try to optimize RegExp getters.
   RegExpFlags mask = RegExpFlag::NoFlags;
   if (RegExpObject::isOriginalFlagGetter(native, &mask)) {
-    const Class* clasp = thisTypes->getKnownClass(constraints());
+    const JSClass* clasp = thisTypes->getKnownClass(constraints());
     if (clasp != &RegExpObject::class_) {
       return InliningStatus_NotInlined;
     }
 
     MLoadFixedSlot* flags =
         MLoadFixedSlot::New(alloc(), thisArg, RegExpObject::flagsSlot());
     current->add(flags);
     flags->setResultType(MIRType::Int32);
@@ -815,17 +815,17 @@ IonBuilder::InliningResult IonBuilder::i
 
     MInstruction* setLength = setInitializedLength(array, initLength);
     MOZ_TRY(resumeAfter(setLength));
   }
 
   return InliningStatus_Inlined;
 }
 
-static bool IsArrayClass(const Class* clasp) {
+static bool IsArrayClass(const JSClass* clasp) {
   return clasp == &ArrayObject::class_;
 }
 
 IonBuilder::InliningResult IonBuilder::inlineArrayIsArray(CallInfo& callInfo) {
   if (callInfo.constructing() || callInfo.argc() != 1) {
     trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
     return InliningStatus_NotInlined;
   }
@@ -913,17 +913,17 @@ IonBuilder::InliningResult IonBuilder::i
       OBJECT_FLAG_SPARSE_INDEXES | OBJECT_FLAG_LENGTH_OVERFLOW |
       OBJECT_FLAG_ITERATED | OBJECT_FLAG_NON_EXTENSIBLE_ELEMENTS;
 
   MDefinition* obj = callInfo.thisArg();
   TemporaryTypeSet* thisTypes = obj->resultTypeSet();
   if (!thisTypes) {
     return InliningStatus_NotInlined;
   }
-  const Class* clasp = thisTypes->getKnownClass(constraints());
+  const JSClass* clasp = thisTypes->getKnownClass(constraints());
   if (clasp != &ArrayObject::class_) {
     return InliningStatus_NotInlined;
   }
   if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
     trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
     return InliningStatus_NotInlined;
   }
 
@@ -982,17 +982,17 @@ IonBuilder::InliningResult IonBuilder::i
   // for MArrayJoin can be notified to check for common empty and one-item
   // arrays.
   bool optimizeForArray = ([&]() {
     TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
     if (!thisTypes) {
       return false;
     }
 
-    const Class* clasp = thisTypes->getKnownClass(constraints());
+    const JSClass* clasp = thisTypes->getKnownClass(constraints());
     if (clasp != &ArrayObject::class_) {
       return false;
     }
 
     return true;
   })();
 
   callInfo.setImplicitlyUsedUnchecked();
@@ -1038,17 +1038,17 @@ IonBuilder::InliningResult IonBuilder::i
   if (obj->type() != MIRType::Object) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* thisTypes = obj->resultTypeSet();
   if (!thisTypes) {
     return InliningStatus_NotInlined;
   }
-  const Class* clasp = thisTypes->getKnownClass(constraints());
+  const JSClass* clasp = thisTypes->getKnownClass(constraints());
   if (clasp != &ArrayObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   bool hasIndexedProperty;
   MOZ_TRY_VAR(hasIndexedProperty,
               ElementAccessHasExtraIndexedProperty(this, obj));
   if (hasIndexedProperty) {
@@ -1169,17 +1169,17 @@ IonBuilder::InliningResult IonBuilder::i
   }
 
   // |this| must be a dense array.
   TemporaryTypeSet* thisTypes = obj->resultTypeSet();
   if (!thisTypes) {
     return InliningStatus_NotInlined;
   }
 
-  const Class* clasp = thisTypes->getKnownClass(constraints());
+  const JSClass* clasp = thisTypes->getKnownClass(constraints());
   if (clasp != &ArrayObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   // Watch out for extra indexed properties on the object or its prototype.
   bool hasIndexedProperty;
   MOZ_TRY_VAR(hasIndexedProperty,
               ElementAccessHasExtraIndexedProperty(this, obj));
@@ -2061,17 +2061,17 @@ IonBuilder::InliningResult IonBuilder::i
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* arrayTypes = array->resultTypeSet();
   if (!arrayTypes) {
     return InliningStatus_NotInlined;
   }
 
-  const Class* clasp = arrayTypes->getKnownClass(constraints());
+  const JSClass* clasp = arrayTypes->getKnownClass(constraints());
   if (clasp != &ArrayObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   // Only inline if the array uses dense storage.
   ObjectGroupFlags unhandledFlags = OBJECT_FLAG_SPARSE_INDEXES |
                                     OBJECT_FLAG_LENGTH_OVERFLOW |
                                     OBJECT_FLAG_NON_PACKED;
@@ -2321,17 +2321,17 @@ IonBuilder::InliningResult IonBuilder::i
   MDefinition* strArg = callInfo.getArg(1);
   MDefinition* lastIndexArg = callInfo.getArg(2);
 
   if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* rxTypes = rxArg->resultTypeSet();
-  const Class* clasp =
+  const JSClass* clasp =
       rxTypes ? rxTypes->getKnownClass(constraints()) : nullptr;
   if (clasp != &RegExpObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   if (strArg->type() != MIRType::String && strArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
@@ -2371,17 +2371,17 @@ IonBuilder::InliningResult IonBuilder::i
   MDefinition* strArg = callInfo.getArg(1);
   MDefinition* lastIndexArg = callInfo.getArg(2);
 
   if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* regexpTypes = rxArg->resultTypeSet();
-  const Class* clasp =
+  const JSClass* clasp =
       regexpTypes ? regexpTypes->getKnownClass(constraints()) : nullptr;
   if (clasp != &RegExpObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   if (strArg->type() != MIRType::String && strArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
@@ -2420,17 +2420,17 @@ IonBuilder::InliningResult IonBuilder::i
   MDefinition* strArg = callInfo.getArg(1);
   MDefinition* lastIndexArg = callInfo.getArg(2);
 
   if (rxArg->type() != MIRType::Object && rxArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* rxTypes = rxArg->resultTypeSet();
-  const Class* clasp =
+  const JSClass* clasp =
       rxTypes ? rxTypes->getKnownClass(constraints()) : nullptr;
   if (clasp != &RegExpObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   if (strArg->type() != MIRType::String && strArg->type() != MIRType::Value) {
     return InliningStatus_NotInlined;
   }
@@ -2466,17 +2466,18 @@ IonBuilder::InliningResult IonBuilder::i
   }
 
   MDefinition* arg = callInfo.getArg(0);
 
   bool isRegExpObjectKnown = false;
   bool isRegExpObjectConstant;
   if (arg->type() == MIRType::Object) {
     TemporaryTypeSet* types = arg->resultTypeSet();
-    const Class* clasp = types ? types->getKnownClass(constraints()) : nullptr;
+    const JSClass* clasp =
+        types ? types->getKnownClass(constraints()) : nullptr;
     if (clasp) {
       isRegExpObjectKnown = true;
       isRegExpObjectConstant = (clasp == &RegExpObject::class_);
     }
   } else if (!arg->mightBeType(MIRType::Object)) {
     // NB: This case only happens when Phi-nodes flow into IsRegExpObject.
     // IsRegExpObject itself will never be called with a non-Object value.
     isRegExpObjectKnown = true;
@@ -2809,17 +2810,17 @@ IonBuilder::InliningResult IonBuilder::i
   if (!res) {
     return InliningStatus_NotInlined;
   }
 
   // At this point we know we're going to inline this.
   callInfo.setImplicitlyUsedUnchecked();
 
   // Try to constant fold some common cases.
-  if (const Class* knownClass = types->getKnownClass(constraints())) {
+  if (const JSClass* knownClass = types->getKnownClass(constraints())) {
     if (knownClass == &PlainObject::class_) {
       pushConstant(StringValue(names().objectObject));
       return InliningStatus_Inlined;
     }
     if (IsArrayClass(knownClass)) {
       pushConstant(StringValue(names().objectArray));
       return InliningStatus_Inlined;
     }
@@ -2832,44 +2833,44 @@ IonBuilder::InliningResult IonBuilder::i
   MObjectClassToString* toString = MObjectClassToString::New(alloc(), arg);
   current->add(toString);
   current->push(toString);
 
   return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningResult IonBuilder::inlineHasClass(CallInfo& callInfo,
-                                                      const Class* clasp1,
-                                                      const Class* clasp2,
-                                                      const Class* clasp3,
-                                                      const Class* clasp4) {
+                                                      const JSClass* clasp1,
+                                                      const JSClass* clasp2,
+                                                      const JSClass* clasp3,
+                                                      const JSClass* clasp4) {
   MOZ_ASSERT(!callInfo.constructing());
   MOZ_ASSERT(callInfo.argc() == 1);
 
   if (callInfo.getArg(0)->type() != MIRType::Object) {
     return InliningStatus_NotInlined;
   }
   if (getInlineReturnType() != MIRType::Boolean) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
-  const Class* knownClass =
+  const JSClass* knownClass =
       types ? types->getKnownClass(constraints()) : nullptr;
   if (knownClass) {
     pushConstant(BooleanValue(knownClass == clasp1 || knownClass == clasp2 ||
                               knownClass == clasp3 || knownClass == clasp4));
   } else {
     MHasClass* hasClass1 = MHasClass::New(alloc(), callInfo.getArg(0), clasp1);
     current->add(hasClass1);
 
     if (!clasp2 && !clasp3 && !clasp4) {
       current->push(hasClass1);
     } else {
-      const Class* remaining[] = {clasp2, clasp3, clasp4};
+      const JSClass* remaining[] = {clasp2, clasp3, clasp4};
       MDefinition* last = hasClass1;
       for (size_t i = 0; i < ArrayLength(remaining); i++) {
         MHasClass* hasClass =
             MHasClass::New(alloc(), callInfo.getArg(0), remaining[i]);
         current->add(hasClass);
         MBitOr* either = MBitOr::New(alloc(), last, hasClass);
         either->infer(inspector, pc);
         current->add(either);
@@ -2880,31 +2881,31 @@ IonBuilder::InliningResult IonBuilder::i
       current->push(result);
     }
   }
 
   callInfo.setImplicitlyUsedUnchecked();
   return InliningStatus_Inlined;
 }
 
-IonBuilder::InliningResult IonBuilder::inlineGuardToClass(CallInfo& callInfo,
-                                                          const Class* clasp) {
+IonBuilder::InliningResult IonBuilder::inlineGuardToClass(
+    CallInfo& callInfo, const JSClass* clasp) {
   MOZ_ASSERT(!callInfo.constructing());
   MOZ_ASSERT(callInfo.argc() == 1);
 
   if (callInfo.getArg(0)->type() != MIRType::Object) {
     return InliningStatus_NotInlined;
   }
 
   if (getInlineReturnType() != MIRType::Object) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
-  const Class* knownClass =
+  const JSClass* knownClass =
       types ? types->getKnownClass(constraints()) : nullptr;
 
   if (knownClass && knownClass == clasp) {
     current->push(callInfo.getArg(0));
   } else {
     MGuardToClass* guardToClass =
         MGuardToClass::New(alloc(), callInfo.getArg(0), clasp);
     current->add(guardToClass);
@@ -2929,17 +2930,17 @@ IonBuilder::InliningResult IonBuilder::i
     return InliningStatus_NotInlined;
   }
 
   if (resultArg->type() != MIRType::Object) {
     return InliningStatus_NotInlined;
   }
 
   TemporaryTypeSet* resultTypes = resultArg->resultTypeSet();
-  const Class* resultClasp =
+  const JSClass* resultClasp =
       resultTypes ? resultTypes->getKnownClass(constraints()) : nullptr;
   if (resultClasp != &ArrayObject::class_) {
     return InliningStatus_NotInlined;
   }
 
   callInfo.setImplicitlyUsedUnchecked();
 
   MInstruction* next =
@@ -3071,17 +3072,17 @@ IonBuilder::InliningResult IonBuilder::i
     // Don't inline if the argument might be a wrapper.
     if (types->forAllClasses(constraints(), IsProxyClass) !=
         TemporaryTypeSet::ForAllResult::ALL_FALSE) {
       return InliningStatus_NotInlined;
     }
 
     // Don't inline if we saw mixed use of (Shared)ArrayBuffers and other
     // objects.
-    auto IsArrayBufferMaybeSharedClass = [](const Class* clasp) {
+    auto IsArrayBufferMaybeSharedClass = [](const JSClass* clasp) {
       return clasp == &ArrayBufferObject::class_ ||
              clasp == &SharedArrayBufferObject::class_;
     };
     switch (
         types->forAllClasses(constraints(), IsArrayBufferMaybeSharedClass)) {
       case TemporaryTypeSet::ForAllResult::ALL_FALSE:
         ins = MNewTypedArrayFromArray::New(
             alloc(), constraints(), templateObject,
@@ -3516,17 +3517,18 @@ IonBuilder::InliningResult IonBuilder::i
   MDefinition* arg = callInfo.getArg(0);
 
   // Try inlining with constant true/false: only objects may be callable at
   // all, and if we know the class check if it is callable.
   bool isCallableKnown = false;
   bool isCallableConstant;
   if (arg->type() == MIRType::Object) {
     TemporaryTypeSet* types = arg->resultTypeSet();
-    const Class* clasp = types ? types->getKnownClass(constraints()) : nullptr;
+    const JSClass* clasp =
+        types ? types->getKnownClass(constraints()) : nullptr;
     if (clasp && !clasp->isProxy()) {
       isCallableKnown = true;
       isCallableConstant = clasp->nonProxyCallable();
     }
   } else if (!arg->mightBeType(MIRType::Object)) {
     // Primitive (including undefined and null).
     isCallableKnown = true;
     isCallableConstant = false;
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -5644,17 +5644,17 @@ bool jit::ElementAccessIsDenseNative(Com
   }
 
   TemporaryTypeSet* types = obj->resultTypeSet();
   if (!types) {
     return false;
   }
 
   // Typed arrays are native classes but do not have dense elements.
-  const Class* clasp = types->getKnownClass(constraints);
+  const JSClass* clasp = types->getKnownClass(constraints);
   return clasp && clasp->isNative() && !IsTypedArrayClass(clasp);
 }
 
 bool jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints,
                                     MDefinition* obj, MDefinition* id,
                                     Scalar::Type* arrayType) {
   if (obj->mightBeType(MIRType::String)) {
     return false;
@@ -5984,17 +5984,17 @@ AbortReasonOr<bool> PrototypeHasIndexedP
   } while (obj);
 
   return false;
 }
 
 // Whether obj or any of its prototypes have an indexed property.
 AbortReasonOr<bool> jit::TypeCanHaveExtraIndexedProperties(
     IonBuilder* builder, TemporaryTypeSet* types) {
-  const Class* clasp = types->getKnownClass(builder->constraints());
+  const JSClass* clasp = types->getKnownClass(builder->constraints());
 
   // Note: typed arrays have indexed properties not accounted for by type
   // information, though these are all in bounds and will be accounted for
   // by JIT paths.
   if (!clasp ||
       (ClassCanHaveExtraProperties(clasp) && !IsTypedArrayClass(clasp))) {
     return true;
   }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10608,66 +10608,66 @@ class MIsObject : public MUnaryInstructi
 
   bool congruentTo(const MDefinition* ins) const override {
     return congruentIfOperandsEqual(ins);
   }
   AliasSet getAliasSet() const override { return AliasSet::None(); }
 };
 
 class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
-  const Class* class_;
-
-  MHasClass(MDefinition* object, const Class* clasp)
+  const JSClass* class_;
+
+  MHasClass(MDefinition* object, const JSClass* clasp)
       : MUnaryInstruction(classOpcode, object), class_(clasp) {
     MOZ_ASSERT(object->type() == MIRType::Object ||
                (object->type() == MIRType::Value &&
                 object->mightBeType(MIRType::Object)));
     setResultType(MIRType::Boolean);
     setMovable();
   }
 
  public:
   INSTRUCTION_HEADER(HasClass)
   TRIVIAL_NEW_WRAPPERS
   NAMED_OPERANDS((0, object))
 
-  const Class* getClass() const { return class_; }
+  const JSClass* getClass() const { return class_; }
   AliasSet getAliasSet() const override { return AliasSet::None(); }
   bool congruentTo(const MDefinition* ins) const override {
     if (!ins->isHasClass()) {
       return false;
     }
     if (getClass() != ins->toHasClass()->getClass()) {
       return false;
     }
     return congruentIfOperandsEqual(ins);
   }
 };
 
 class MGuardToClass : public MUnaryInstruction,
                       public SingleObjectPolicy::Data {
-  const Class* class_;
-
-  MGuardToClass(MDefinition* object, const Class* clasp)
+  const JSClass* class_;
+
+  MGuardToClass(MDefinition* object, const JSClass* clasp)
       : MUnaryInstruction(classOpcode, object), class_(clasp) {
     MOZ_ASSERT(object->type() == MIRType::Object);
     setResultType(MIRType::Object);
     setMovable();
 
     // We will bail out if the class type is incorrect, so we need to ensure we
     // don't eliminate this instruction
     setGuard();
   }
 
  public:
   INSTRUCTION_HEADER(GuardToClass)
   TRIVIAL_NEW_WRAPPERS
   NAMED_OPERANDS((0, object))
 
-  const Class* getClass() const { return class_; }
+  const JSClass* getClass() const { return class_; }
   AliasSet getAliasSet() const override { return AliasSet::None(); }
   bool congruentTo(const MDefinition* ins) const override {
     if (!ins->isGuardToClass()) {
       return false;
     }
     if (getClass() != ins->toGuardToClass()->getClass()) {
       return false;
     }
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -395,17 +395,17 @@ void MacroAssembler::branchIfObjectEmula
                                                      Label* slowCheck,
                                                      Label* label) {
   // The branches to out-of-line code here implement a conservative version
   // of the JSObject::isWrapper test performed in EmulatesUndefined.
   loadObjClassUnsafe(objReg, scratch);
 
   branchTestClassIsProxy(true, scratch, slowCheck);
 
-  Address flags(scratch, Class::offsetOfFlags());
+  Address flags(scratch, JSClass::offsetOfFlags());
   branchTest32(Assembler::NonZero, flags, Imm32(JSCLASS_EMULATES_UNDEFINED),
                label);
 }
 
 void MacroAssembler::branchFunctionKind(Condition cond,
                                         FunctionFlags::FunctionKind kind,
                                         Register fun, Register scratch,
                                         Label* label) {
@@ -417,34 +417,33 @@ void MacroAssembler::branchFunctionKind(
   int32_t mask = IMM32_16ADJ(FunctionFlags::FUNCTION_KIND_MASK);
   int32_t bit = IMM32_16ADJ(kind << FunctionFlags::FUNCTION_KIND_SHIFT);
   load32(address, scratch);
   and32(Imm32(mask), scratch);
   branch32(cond, scratch, Imm32(bit), label);
 }
 
 void MacroAssembler::branchTestObjClass(Condition cond, Register obj,
-                                        const js::Class* clasp,
-                                        Register scratch,
+                                        const JSClass* clasp, Register scratch,
                                         Register spectreRegToZero,
                                         Label* label) {
   MOZ_ASSERT(obj != scratch);
   MOZ_ASSERT(scratch != spectreRegToZero);
 
   loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
   branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp),
             label);
 
   if (JitOptions.spectreObjectMitigationsMisc) {
     spectreZeroRegister(cond, scratch, spectreRegToZero);
   }
 }
 
 void MacroAssembler::branchTestObjClassNoSpectreMitigations(
-    Condition cond, Register obj, const js::Class* clasp, Register scratch,
+    Condition cond, Register obj, const JSClass* clasp, Register scratch,
     Label* label) {
   loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
   branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp),
             label);
 }
 
 void MacroAssembler::branchTestObjClass(Condition cond, Register obj,
                                         const Address& clasp, Register scratch,
@@ -586,18 +585,18 @@ void MacroAssembler::branchTestObjGroupN
                                                             Label* label) {
   MOZ_ASSERT(obj != group);
   branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), group, label);
 }
 
 void MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp,
                                             Label* label) {
   branchTest32(proxy ? Assembler::NonZero : Assembler::Zero,
-               Address(clasp, Class::offsetOfFlags()), Imm32(JSCLASS_IS_PROXY),
-               label);
+               Address(clasp, JSClass::offsetOfFlags()),
+               Imm32(JSCLASS_IS_PROXY), label);
 }
 
 void MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object,
                                              Register scratch, Label* label) {
   loadObjClassUnsafe(object, scratch);
   branchTestClassIsProxy(proxy, scratch, label);
 }
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1424,25 +1424,25 @@ void MacroAssembler::typeOfObject(Regist
 
   // Proxies can emulate undefined and have complex isCallable behavior.
   branchTestClassIsProxy(true, scratch, slow);
 
   // JSFunctions are always callable.
   branchPtr(Assembler::Equal, scratch, ImmPtr(&JSFunction::class_), isCallable);
 
   // Objects that emulate undefined.
-  Address flags(scratch, Class::offsetOfFlags());
+  Address flags(scratch, JSClass::offsetOfFlags());
   branchTest32(Assembler::NonZero, flags, Imm32(JSCLASS_EMULATES_UNDEFINED),
                isUndefined);
 
   // Handle classes with a call hook.
-  branchPtr(Assembler::Equal, Address(scratch, offsetof(js::Class, cOps)),
+  branchPtr(Assembler::Equal, Address(scratch, offsetof(JSClass, cOps)),
             ImmPtr(nullptr), isObject);
 
-  loadPtr(Address(scratch, offsetof(js::Class, cOps)), scratch);
+  loadPtr(Address(scratch, offsetof(JSClass, cOps)), scratch);
   branchPtr(Assembler::Equal, Address(scratch, offsetof(JSClassOps, call)),
             ImmPtr(nullptr), isObject);
 
   jump(isCallable);
 }
 
 void MacroAssembler::loadJSContext(Register dest) {
   JitContext* jcx = GetJitContext();
@@ -2951,18 +2951,18 @@ void MacroAssembler::branchIfPretenuredG
   branchTest32(Assembler::NonZero, Address(group, ObjectGroup::offsetOfFlags()),
                Imm32(OBJECT_FLAG_PRE_TENURE), label);
   bind(&unknownProperties);
 }
 
 void MacroAssembler::branchIfNonNativeObj(Register obj, Register scratch,
                                           Label* label) {
   loadObjClassUnsafe(obj, scratch);
-  branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
-               Imm32(Class::NON_NATIVE), label);
+  branchTest32(Assembler::NonZero, Address(scratch, JSClass::offsetOfFlags()),
+               Imm32(JSClass::NON_NATIVE), label);
 }
 
 void MacroAssembler::branchIfInlineTypedObject(Register obj, Register scratch,
                                                Label* label) {
   loadObjClassUnsafe(obj, scratch);
   branchPtr(Assembler::Equal, scratch, ImmPtr(&InlineOpaqueTypedObject::class_),
             label);
   branchPtr(Assembler::Equal, scratch,
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1318,21 +1318,21 @@ class MacroAssembler : public MacroAssem
                                               Label* slowCheck, Label* label);
 
   // For all methods below: spectreRegToZero is a register that will be zeroed
   // on speculatively executed code paths (when the branch should be taken but
   // branch prediction speculates it isn't). Usually this will be the object
   // register but the caller may pass a different register.
 
   inline void branchTestObjClass(Condition cond, Register obj,
-                                 const js::Class* clasp, Register scratch,
+                                 const JSClass* clasp, Register scratch,
                                  Register spectreRegToZero, Label* label);
   inline void branchTestObjClassNoSpectreMitigations(Condition cond,
                                                      Register obj,
-                                                     const js::Class* clasp,
+                                                     const JSClass* clasp,
                                                      Register scratch,
                                                      Label* label);
 
   inline void branchTestObjClass(Condition cond, Register obj,
                                  const Address& clasp, Register scratch,
                                  Register spectreRegToZero, Label* label);
   inline void branchTestObjClassNoSpectreMitigations(Condition cond,
                                                      Register obj,
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -7,17 +7,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "js/Wrapper.h"
 #include "jsapi-tests/tests.h"
 #include "vm/JSObject.h"
 #include "vm/ProxyObject.h"
 
-const js::Class OuterWrapperClass = PROXY_CLASS_DEF(
+const JSClass OuterWrapperClass = PROXY_CLASS_DEF(
     "Proxy", JSCLASS_HAS_RESERVED_SLOTS(1) /* additional class flags */);
 
 static JSObject* wrap(JSContext* cx, JS::HandleObject toWrap,
                       JS::HandleObject target) {
   JSAutoRealm ar(cx, target);
   JS::RootedObject wrapper(cx, toWrap);
   if (!JS_WrapObject(cx, &wrapper)) {
     return nullptr;
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -145,22 +145,22 @@ static size_t DelegateObjectMoved(JSObje
   }
 
   MOZ_RELEASE_ASSERT(keyDelegate == old);
   keyDelegate = obj;
   return 0;
 }
 
 JSObject* newKey() {
-  static const js::Class keyClass = {
+  static const JSClass keyClass = {
       "keyWithDelegate", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
       JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC,
       JS_NULL_CLASS_EXT, JS_NULL_OBJECT_OPS};
 
-  JS::RootedObject key(cx, JS_NewObject(cx, Jsvalify(&keyClass)));
+  JS::RootedObject key(cx, JS_NewObject(cx, &keyClass));
   if (!key) {
     return nullptr;
   }
 
   return key;
 }
 
 JSObject* newCCW(JS::HandleObject sourceZone, JS::HandleObject destZone) {
@@ -204,29 +204,29 @@ JSObject* newDelegate() {
       nullptr, /* hasInstance */
       nullptr, /* construct */
       JS_GlobalObjectTraceHook,
   };
 
   static const js::ClassExtension delegateClassExtension = {
       DelegateObjectMoved};
 
-  static const js::Class delegateClass = {
+  static const JSClass delegateClass = {
       "delegate",
       JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1),
       &delegateClassOps,
       JS_NULL_CLASS_SPEC,
       &delegateClassExtension,
       JS_NULL_OBJECT_OPS};
 
   /* Create the global object. */
   JS::RealmOptions options;
-  JS::RootedObject global(
-      cx, JS_NewGlobalObject(cx, Jsvalify(&delegateClass), nullptr,
-                             JS::FireOnNewGlobalHook, options));
+  JS::RootedObject global(cx,
+                          JS_NewGlobalObject(cx, &delegateClass, nullptr,
+                                             JS::FireOnNewGlobalHook, options));
   if (!global) {
     return nullptr;
   }
 
   JS_SetReservedSlot(global, 0, JS::Int32Value(42));
   return global;
 }
 
--- a/js/src/jsapi-tests/testWindowNonConfigurable.cpp
+++ b/js/src/jsapi-tests/testWindowNonConfigurable.cpp
@@ -17,21 +17,21 @@ static bool windowProxy_defineProperty(J
   }
 
   return NativeDefineProperty(cx, obj.as<js::NativeObject>(), id, desc, result);
 }
 
 static const js::ObjectOps windowProxy_objectOps = {nullptr,
                                                     windowProxy_defineProperty};
 
-static const js::Class windowProxy_class = {
+static const JSClass windowProxy_class = {
     "WindowProxy", 0, nullptr, nullptr, nullptr, &windowProxy_objectOps};
 
 BEGIN_TEST(testWindowNonConfigurable) {
-  JS::RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&windowProxy_class)));
+  JS::RootedObject obj(cx, JS_NewObject(cx, &windowProxy_class));
   CHECK(obj);
   CHECK(JS_DefineProperty(cx, global, "windowProxy", obj, 0));
   JS::RootedValue v(cx);
   EVAL(
       "Object.defineProperty(windowProxy, 'bar', {value: 1, configurable: "
       "false})",
       &v);
   CHECK(v.isNull());  // This is the important bit!
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -915,17 +915,17 @@ JS_PUBLIC_API bool JS_ResolveStandardCla
   if (stdnm && GlobalObject::skipDeselectedConstructor(cx, stdnm->key)) {
     stdnm = nullptr;
   }
 
   // If this class is anonymous, then it doesn't exist as a global
   // property, so we won't resolve anything.
   JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
   if (key != JSProto_Null) {
-    const Class* clasp = ProtoKeyToClass(key);
+    const JSClass* clasp = ProtoKeyToClass(key);
     if (!clasp || clasp->specShouldDefineConstructor()) {
       if (!GlobalObject::ensureConstructor(cx, global, key)) {
         return false;
       }
 
       *resolved = true;
       return true;
     }
@@ -990,17 +990,17 @@ static bool EnumerateStandardClassesInTa
     if (!includeResolved && global->isStandardClassResolved(key)) {
       continue;
     }
 
     if (GlobalObject::skipDeselectedConstructor(cx, key)) {
       continue;
     }
 
-    if (const Class* clasp = ProtoKeyToClass(key)) {
+    if (const JSClass* clasp = ProtoKeyToClass(key)) {
       if (!clasp->specShouldDefineConstructor()) {
         continue;
       }
     }
 
     jsid id = NameToId(AtomStateOffsetToName(cx->names(), table[i].atomOffset));
     if (!properties.append(id)) {
       return false;
@@ -1565,43 +1565,43 @@ JS_PUBLIC_API JSObject* JS_InitClass(JSC
                                      const JSClass* clasp, JSNative constructor,
                                      unsigned nargs, const JSPropertySpec* ps,
                                      const JSFunctionSpec* fs,
                                      const JSPropertySpec* static_ps,
                                      const JSFunctionSpec* static_fs) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj, parent_proto);
-  return InitClass(cx, obj, parent_proto, Valueify(clasp), constructor, nargs,
-                   ps, fs, static_ps, static_fs);
+  return InitClass(cx, obj, parent_proto, clasp, constructor, nargs, ps, fs,
+                   static_ps, static_fs);
 }
 
 JS_PUBLIC_API bool JS_LinkConstructorAndPrototype(JSContext* cx,
                                                   HandleObject ctor,
                                                   HandleObject proto) {
   return LinkConstructorAndPrototype(cx, ctor, proto);
 }
 
 JS_PUBLIC_API const JSClass* JS_GetClass(JSObject* obj) {
-  return obj->getJSClass();
+  return obj->getClass();
 }
 
 JS_PUBLIC_API bool JS_InstanceOf(JSContext* cx, HandleObject obj,
                                  const JSClass* clasp, CallArgs* args) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 #ifdef DEBUG
   if (args) {
     cx->check(obj);
     cx->check(args->thisv(), args->calleev());
   }
 #endif
-  if (!obj || obj->getJSClass() != clasp) {
+  if (!obj || obj->getClass() != clasp) {
     if (args) {
-      ReportIncompatibleMethod(cx, *args, Valueify(clasp));
+      ReportIncompatibleMethod(cx, *args, clasp);
     }
     return false;
   }
   return true;
 }
 
 JS_PUBLIC_API bool JS_HasInstance(JSContext* cx, HandleObject obj,
                                   HandleValue value, bool* bp) {
@@ -1716,18 +1716,17 @@ JS_PUBLIC_API JSObject* JS_NewGlobalObje
                                            const JS::RealmOptions& options) {
   MOZ_RELEASE_ASSERT(
       cx->runtime()->hasInitializedSelfHosting(),
       "Must call JS::InitSelfHostedCode() before creating a global");
 
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
-  return GlobalObject::new_(cx, Valueify(clasp), principals, hookOption,
-                            options);
+  return GlobalObject::new_(cx, clasp, principals, hookOption, options);
 }
 
 JS_PUBLIC_API void JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global) {
   GlobalObject* globalObj = &global->as<GlobalObject>();
   Realm* globalRealm = globalObj->realm();
 
   // Off thread parsing and compilation tasks create a dummy global which is
   // then merged back into the host realm. Since it used to be a global, it
@@ -1769,41 +1768,39 @@ JS_PUBLIC_API void JS_FireOnNewGlobalObj
   // This infallibility will eat OOM and slow script, but if that happens
   // we'll likely run up into them again soon in a fallible context.
   cx->check(global);
   Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
   DebugAPI::onNewGlobalObject(cx, globalObject);
   cx->runtime()->ensureRealmIsRecordingAllocations(globalObject);
 }
 
-JS_PUBLIC_API JSObject* JS_NewObject(JSContext* cx, const JSClass* jsclasp) {
+JS_PUBLIC_API JSObject* JS_NewObject(JSContext* cx, const JSClass* clasp) {
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
-  const Class* clasp = Valueify(jsclasp);
   if (!clasp) {
     clasp = &PlainObject::class_; /* default class is Object */
   }
 
   MOZ_ASSERT(clasp != &JSFunction::class_);
   MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
   return NewBuiltinClassInstance(cx, clasp);
 }
 
 JS_PUBLIC_API JSObject* JS_NewObjectWithGivenProto(JSContext* cx,
-                                                   const JSClass* jsclasp,
+                                                   const JSClass* clasp,
                                                    HandleObject proto) {
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(proto);
 
-  const Class* clasp = Valueify(jsclasp);
   if (!clasp) {
     clasp = &PlainObject::class_; /* default class is Object */
   }
 
   MOZ_ASSERT(clasp != &JSFunction::class_);
   MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
   return NewObjectWithGivenProto(cx, clasp, proto);
@@ -1824,17 +1821,17 @@ JS_PUBLIC_API JSObject* JS_NewObjectForC
   CHECK_THREAD(cx);
 
   if (!ThrowIfNotConstructing(cx, args, clasp->name)) {
     return nullptr;
   }
 
   RootedObject newTarget(cx, &args.newTarget().toObject());
   cx->check(newTarget);
-  return CreateThis(cx, Valueify(clasp), newTarget);
+  return CreateThis(cx, clasp, newTarget);
 }
 
 JS_PUBLIC_API bool JS_IsNative(JSObject* obj) { return obj->isNative(); }
 
 JS_PUBLIC_API void JS::AssertObjectBelongsToCurrentThread(JSObject* obj) {
   JSRuntime* rt = obj->compartment()->runtimeFromAnyThread();
   MOZ_RELEASE_ASSERT(CurrentThreadCanAccessRuntime(rt));
 }
@@ -2917,24 +2914,22 @@ static bool DefineSelfHostedProperty(JSC
                setterValue.toObject().is<JSFunction>());
     setterFunc = &setterValue.toObject().as<JSFunction>();
   }
 
   return DefineAccessorPropertyById(cx, obj, id, getterFunc, setterFunc, attrs);
 }
 
 JS_PUBLIC_API JSObject* JS_DefineObject(JSContext* cx, HandleObject obj,
-                                        const char* name,
-                                        const JSClass* jsclasp,
+                                        const char* name, const JSClass* clasp,
                                         unsigned attrs) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj);
 
-  const Class* clasp = Valueify(jsclasp);
   if (!clasp) {
     clasp = &PlainObject::class_; /* default class is Object */
   }
 
   RootedObject nobj(cx, NewBuiltinClassInstance(cx, clasp));
   if (!nobj) {
     return nullptr;
   }
@@ -3070,17 +3065,17 @@ JS_PUBLIC_API bool JS::ObjectToCompleteP
   return true;
 }
 
 JS_PUBLIC_API void JS_SetAllNonReservedSlotsToUndefined(JS::HandleObject obj) {
   if (!obj->isNative()) {
     return;
   }
 
-  const Class* clasp = obj->getClass();
+  const JSClass* clasp = obj->getClass();
   unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp);
   unsigned numSlots = obj->as<NativeObject>().slotSpan();
   for (unsigned i = numReserved; i < numSlots; i++) {
     obj->as<NativeObject>().setSlot(i, UndefinedValue());