Merge mozilla-central to autoland
authorarthur.iakab <aiakab@mozilla.com>
Thu, 31 May 2018 01:07:47 +0300
changeset 474770 dac867294e82fae907893f64f53234cead4ec347
parent 474769 e5fce116c9fd936a75614e63cd438dded69b4932 (current diff)
parent 474756 3931f461c8e8668a264d52b51a4524aac39a7a16 (diff)
child 474771 4219d3de5e8b6f0bf166de92b71c6a3591780778
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone62.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 mozilla-central to autoland
dom/u2f/U2FUtil.h
layout/style/test/browser_newtab_share_rule_processors.js
layout/style/test/file_blank_doc_backend.html
layout/style/test/newtab_share_rule_processors.html
layout/style/test/test_blank_doc_backend.html
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4734,17 +4734,16 @@ var XULBrowserWindow = {
     return this.onProgressChange(aWebProgress, aRequest,
       aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress,
       aMaxTotalProgress);
   },
 
   // This function fires only for the currently selected tab.
   onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
     const nsIWebProgressListener = Ci.nsIWebProgressListener;
-    const nsIChannel = Ci.nsIChannel;
 
     let browser = gBrowser.selectedBrowser;
 
     if (aStateFlags & nsIWebProgressListener.STATE_START &&
         aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
 
       if (aRequest && aWebProgress.isTopLevel) {
         // clear out feed data
@@ -4767,17 +4766,17 @@ var XULBrowserWindow = {
       // This (thanks to the filter) is a network stop or the last
       // request stop outside of loading the document, stop throbbers
       // and progress bars and such
       if (aRequest) {
         let msg = "";
         let location;
         let canViewSource = true;
         // Get the URI either from a channel or a pseudo-object
-        if (aRequest instanceof nsIChannel || "URI" in aRequest) {
+        if (aRequest instanceof Ci.nsIChannel || "URI" in aRequest) {
           location = aRequest.URI;
 
           // For keyword URIs clear the user typed value since they will be changed into real URIs
           if (location.scheme == "keyword" && aWebProgress.isTopLevel)
             gBrowser.userTypedValue = null;
 
           canViewSource = location.scheme != "view-source";
 
@@ -7104,17 +7103,17 @@ var WebAuthnPromptHelper = {
     }
   },
 
   buildProceedAction(mgr, tid) {
     return {
       label: gNavigatorBundle.getString("webauthn.proceed"),
       accessKey: gNavigatorBundle.getString("webauthn.proceed.accesskey"),
       callback(state) {
-        mgr.resumeRegister(tid, !state.checkboxChecked);
+        mgr.resumeRegister(tid, state.checkboxChecked);
       }
     };
   },
 
   buildCancelAction(mgr, tid) {
     return {
       label: gNavigatorBundle.getString("webauthn.cancel"),
       accessKey: gNavigatorBundle.getString("webauthn.cancel.accesskey"),
--- a/browser/components/preferences/in-content/searchResults.xul
+++ b/browser/components/preferences/in-content/searchResults.xul
@@ -17,12 +17,12 @@
   <vbox class="no-results-container">
     <label id="sorry-message" data-l10n-id="search-results-empty-message">
       <html:span data-l10n-name="query" id="sorry-message-query"/>
     </label>
     <label id="need-help" data-l10n-id="search-results-help-link">
       <html:a class="text-link" data-l10n-name="url" target="_blank"></html:a>
     </label>
   </vbox>
-  <vbox class="no-results-container" align="center">
-    <image></image>
+  <vbox class="no-results-container no-results-image-container" align="center">
+    <image class="no-results-image"></image>
   </vbox>
 </groupbox>
--- a/browser/components/preferences/in-content/tests/siteData/browser_siteData.js
+++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData.js
@@ -151,76 +151,86 @@ add_task(async function() {
   // from minimal time differences, since we round up to minutes).
   let cookiesEnum1 = Services.cookies.getCookiesFromHost(uri.host);
   // We made two valid cookies for example.com.
   cookiesEnum1.getNext();
   let cookiesEnum2 = Services.cookies.getCookiesFromHost(uri2.host);
   let cookie1 = cookiesEnum1.getNext().QueryInterface(Ci.nsICookie2);
   let cookie2 = cookiesEnum2.getNext().QueryInterface(Ci.nsICookie2);
 
-  let formatter = new Services.intl.DateTimeFormat(undefined, {
+  let fullFormatter = new Services.intl.DateTimeFormat(undefined, {
     dateStyle: "short", timeStyle: "short",
   });
 
-  let creationDate1 = formatter.format(new Date(cookie1.lastAccessed / 1000));
-  let creationDate2 = formatter.format(new Date(cookie2.lastAccessed / 1000));
-
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
 
   // Open the site data manager and remove one site.
   await openSiteDataSettingsDialog();
+  let creationDate1 = new Date(cookie1.lastAccessed / 1000);
+  let creationDate1Formatted = fullFormatter.format(creationDate1);
+  let creationDate2 = new Date(cookie2.lastAccessed / 1000);
+  let creationDate2Formatted = fullFormatter.format(creationDate2);
   let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
-  await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1, creationDate2}, function(args) {
+  await ContentTask.spawn(gBrowser.selectedBrowser, {
+    creationDate1Formatted,
+    creationDate2Formatted,
+  }, function(args) {
     let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
 
     let siteItems = frameDoc.getElementsByTagName("richlistitem");
     is(siteItems.length, 2, "Should list two sites with cookies");
     let sitesList = frameDoc.getElementById("sitesList");
     let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`);
     let site2 = sitesList.querySelector(`richlistitem[host="example.org"]`);
 
     let columns = site1.querySelectorAll(".item-box > label");
+    let boxes = site1.querySelectorAll(".item-box");
     is(columns[0].value, "example.com", "Should show the correct host.");
     is(columns[1].value, "2", "Should show the correct number of cookies.");
     is(columns[2].value, "", "Should show no site data.");
-    is(columns[3].value, args.creationDate1, "Should show the correct date.");
+    is(/(now|second)/.test(columns[3].value), true, "Should show the relative date.");
+    is(boxes[3].getAttribute("tooltiptext"), args.creationDate1Formatted, "Should show the correct date.");
 
     columns = site2.querySelectorAll(".item-box > label");
+    boxes = site2.querySelectorAll(".item-box");
     is(columns[0].value, "example.org", "Should show the correct host.");
     is(columns[1].value, "1", "Should show the correct number of cookies.");
     is(columns[2].value, "", "Should show no site data.");
-    is(columns[3].value, args.creationDate2, "Should show the correct date.");
+    is(/(now|second)/.test(columns[3].value), true, "Should show the relative date.");
+    is(boxes[3].getAttribute("tooltiptext"), args.creationDate2Formatted, "Should show the correct date.");
 
     let removeBtn = frameDoc.getElementById("removeSelected");
     let saveBtn = frameDoc.getElementById("save");
     site2.click();
     removeBtn.doCommand();
     saveBtn.doCommand();
   });
   await removeDialogOpenPromise;
 
   await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri2.host) == 0, "Cookies from the first host should be cleared");
   is(Services.cookies.countCookiesFromHost(uri.host), 2, "Cookies from the second host should not be cleared");
 
   // Open the site data manager and remove another site.
   await openSiteDataSettingsDialog();
   let acceptRemovePromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
-  await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1}, function(args) {
+  await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1Formatted}, function(args) {
     let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
 
     let siteItems = frameDoc.getElementsByTagName("richlistitem");
     is(siteItems.length, 1, "Should list one site with cookies");
     let sitesList = frameDoc.getElementById("sitesList");
     let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`);
 
     let columns = site1.querySelectorAll(".item-box > label");
+    let boxes = site1.querySelectorAll(".item-box");
     is(columns[0].value, "example.com", "Should show the correct host.");
     is(columns[1].value, "2", "Should show the correct number of cookies.");
     is(columns[2].value, "", "Should show no site data.");
-    is(columns[3].value, args.creationDate1, "Should show the correct date.");
+    is(/(now|second)/.test(columns[3].value), true, "Should show the relative date.");
+    is(boxes[3].getAttribute("tooltiptext"), args.creationDate1Formatted, "Should show the correct date.");
 
     let removeBtn = frameDoc.getElementById("removeSelected");
     let saveBtn = frameDoc.getElementById("save");
     site1.click();
     removeBtn.doCommand();
     saveBtn.doCommand();
   });
   await acceptRemovePromise;
--- a/browser/components/preferences/siteDataSettings.js
+++ b/browser/components/preferences/siteDataSettings.js
@@ -26,30 +26,33 @@ let gSiteDataSettings = {
   _searchBox: null,
 
   _createSiteListItem(site) {
     let item = document.createElement("richlistitem");
     item.setAttribute("host", site.host);
     let container = document.createElement("hbox");
 
     // Creates a new column item with the specified relative width.
-    function addColumnItem(l10n, flexWidth) {
+    function addColumnItem(l10n, flexWidth, tooltipText) {
       let box = document.createElement("hbox");
       box.className = "item-box";
       box.setAttribute("flex", flexWidth);
       let label = document.createElement("label");
       label.setAttribute("crop", "end");
       if (l10n) {
         if (l10n.hasOwnProperty("raw")) {
           box.setAttribute("tooltiptext", l10n.raw);
           label.setAttribute("value", l10n.raw);
         } else {
           document.l10n.setAttributes(label, l10n.id, l10n.args);
         }
       }
+      if (tooltipText) {
+        box.setAttribute("tooltiptext", tooltipText);
+      }
       box.appendChild(label);
       container.appendChild(box);
     }
 
     // Add "Host" column.
     addColumnItem({raw: site.host}, "4");
 
     // Add "Cookies" column.
@@ -64,33 +67,39 @@ let gSiteDataSettings = {
         args: { value, unit }
       }, "2");
     } else {
       // Pass null to avoid showing "0KB" when there is no site data stored.
       addColumnItem(null, "2");
     }
 
     // Add "Last Used" column.
+    let formattedLastAccessed = site.lastAccessed > 0 ?
+      this._relativeTimeFormat.formatBestUnit(site.lastAccessed) : null;
+    let formattedFullDate = site.lastAccessed > 0 ?
+      this._absoluteTimeFormat.format(site.lastAccessed) : null;
     addColumnItem(site.lastAccessed > 0 ?
-      {raw: this._formatter.format(site.lastAccessed)} : null, "2");
+      { raw: formattedLastAccessed } : null, "2", formattedFullDate);
 
     item.appendChild(container);
     return item;
   },
 
   init() {
     function setEventListener(id, eventType, callback) {
       document.getElementById(id)
               .addEventListener(eventType, callback.bind(gSiteDataSettings));
     }
 
-    this._formatter = new Services.intl.DateTimeFormat(undefined, {
+    this._absoluteTimeFormat = new Services.intl.DateTimeFormat(undefined, {
       dateStyle: "short", timeStyle: "short",
     });
 
+    this._relativeTimeFormat = new Services.intl.RelativeTimeFormat(undefined, {});
+
     this._list = document.getElementById("sitesList");
     this._searchBox = document.getElementById("searchBox");
     SiteDataManager.getSites().then(sites => {
       this._sites = sites;
       let sortCol = document.querySelector("treecol[data-isCurrentSortCol=true]");
       this._sortSites(this._sites, sortCol);
       this._buildSitesList(this._sites);
       Services.obs.notifyObservers(null, "sitedata-settings-init");
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -17,16 +17,22 @@ if test "$OS_ARCH" = "WINNT"; then
   MOZ_MAINTENANCE_SERVICE=1
   if ! test "$HAVE_64BIT_BUILD"; then
     if test "$MOZ_UPDATE_CHANNEL" = "nightly" -o \
             "$MOZ_UPDATE_CHANNEL" = "nightly-try" -o \
             "$MOZ_UPDATE_CHANNEL" = "aurora" -o \
             "$MOZ_UPDATE_CHANNEL" = "beta" -o \
             "$MOZ_UPDATE_CHANNEL" = "release"; then
       if ! test "$MOZ_DEBUG"; then
+        if ! test "$USE_STUB_INSTALLER"; then
+          # Expect USE_STUB_INSTALLER from taskcluster for downstream task consistency
+          echo "ERROR: STUB installer expected to be enabled but"
+          echo "ERROR: USE_STUB_INSTALLER is not specified in the environment"
+          exit 1
+        fi
         MOZ_STUB_INSTALLER=1
       fi
     fi
   fi
 fi
 
 # Enable building ./signmar and running libmar signature tests
 MOZ_ENABLE_SIGNMAR=1
new file mode 100644
--- /dev/null
+++ b/browser/locales/l10n-onchange-changesets.json
@@ -0,0 +1,47 @@
+{
+    "en-CA": {
+        "platforms": [
+            "linux", 
+            "linux64", 
+            "macosx64", 
+            "win32", 
+            "win64"
+        ], 
+        "revision": "default"
+    }, 
+    "he": {
+        "platforms": [
+            "linux", 
+            "linux64", 
+            "macosx64", 
+            "win32", 
+            "win64"
+        ], 
+        "revision": "default"
+    }, 
+    "it": {
+        "platforms": [
+            "linux", 
+            "linux64", 
+            "macosx64", 
+            "win32", 
+            "win64"
+        ], 
+        "revision": "default"
+    }, 
+    "ja": {
+        "platforms": [
+            "linux", 
+            "linux64", 
+            "win32", 
+            "win64"
+        ], 
+        "revision": "default"
+    }, 
+    "ja-JP-mac": {
+        "platforms": [
+            "macosx64"
+        ], 
+        "revision": "default"
+    }
+}
new file mode 100644
--- /dev/null
+++ b/browser/locales/onchange-locales
@@ -0,0 +1,5 @@
+en-CA
+he
+it
+ja
+ja-JP-mac
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -141,16 +141,21 @@
 #identity-popup-security-descriptions > description,
 #identity-popup-securityView-body > description,
 #identity-popup-permissions-content > description,
 #tracking-protection-content > description {
   font-size: 110%;
   margin: 0;
 }
 
+#identity-popup-permissions-content > description,
+#tracking-protection-content > description {
+  color: var(--panel-disabled-color);
+}
+
 /* This element needs the pre-wrap because we add newlines to it in the code. */
 #identity-popup-content-supplemental {
   white-space: pre-wrap;
 }
 
 .identity-popup-headline {
   margin: 3px 0 4px;
   font-size: 150%;
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -868,21 +868,21 @@ menulist[indicator=true] > menupopup men
   margin: 0; /* Align with the margin of xul:label.menu-iconic-text */
 }
 
 #no-results-message > label {
   margin: 2px 0;
   line-height: 30px;
 }
 
-.no-results-container:nth-child(2) {
+.no-results-image-container {
   margin-top: 64px;
 }
 
-.no-results-container:nth-child(2) > image {
+.no-results-image {
   list-style-image: url("chrome://browser/skin/preferences/in-content/no-search-results.svg");
   width: 380px;
   height: 293px;
 }
 
 #no-results-message[query*=🔥🦊] {
   background-image: url("chrome://browser/skin/preferences/in-content/critters-postcard.jpg");
   background-size: contain;
--- a/build/sparse-profiles/taskgraph
+++ b/build/sparse-profiles/taskgraph
@@ -1,14 +1,16 @@
 %include build/sparse-profiles/mach
 
 [include]
 # These files are read as part of generating the taskgraph.
 path:browser/locales/l10n-changesets.json
+path:browser/locales/l10n-onchange-changesets.json
 path:mobile/locales/l10n-changesets.json
+path:mobile/locales/l10n-onchange-changesets.json
 path:browser/locales/shipped-locales
 path:browser/config/version_display.txt
 path:browser/config/version.txt
 
 # Lots of random files in here are read. Just pull in the whole thing.
 path:build/
 
 # TODO remove once bug 1402010 is resolved and test manifests aren't
--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -160,31 +160,23 @@ skip-if = (os == 'linux' && bits == 32 &
 [browser_markup_node_not_displayed_01.js]
 [browser_markup_node_not_displayed_02.js]
 [browser_markup_pagesize_01.js]
 [browser_markup_pagesize_02.js]
 [browser_markup_remove_xul_attributes.js]
 skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
 [browser_markup_search_01.js]
 [browser_markup_shadowdom.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_clickreveal.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_delete.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_maxchildren.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_mutations_shadow.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_navigation.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_noslot.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_shadowdom_slotupdate.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_markup_tag_delete_whitespace_node.js]
 [browser_markup_tag_edit_01.js]
 [browser_markup_tag_edit_02.js]
 [browser_markup_tag_edit_03.js]
 [browser_markup_tag_edit_04-backspace.js]
 [browser_markup_tag_edit_04-delete.js]
 [browser_markup_tag_edit_05.js]
 [browser_markup_tag_edit_06.js]
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -246,17 +246,16 @@ skip-if = (os == 'linux' && bits == 32 &
 [browser_rules_selector-highlighter-on-navigate.js]
 [browser_rules_selector-highlighter_01.js]
 [browser_rules_selector-highlighter_02.js]
 [browser_rules_selector-highlighter_03.js]
 [browser_rules_selector-highlighter_04.js]
 [browser_rules_selector-highlighter_05.js]
 [browser_rules_selector_highlight.js]
 [browser_rules_shadowdom_slot_rules.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_rules_shapes-toggle_01.js]
 [browser_rules_shapes-toggle_02.js]
 [browser_rules_shapes-toggle_03.js]
 [browser_rules_shapes-toggle_04.js]
 [browser_rules_shapes-toggle_05.js]
 [browser_rules_shapes-toggle_06.js]
 [browser_rules_shapes-toggle_07.js]
 [browser_rules_shorthand-overridden-lists.js]
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -55,17 +55,16 @@ support-files =
 [browser_inspector_breadcrumbs.js]
 [browser_inspector_breadcrumbs_highlight_hover.js]
 [browser_inspector_breadcrumbs_keybinding.js]
 [browser_inspector_breadcrumbs_keyboard_trap.js]
 skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
 [browser_inspector_breadcrumbs_mutations.js]
 [browser_inspector_breadcrumbs_namespaced.js]
 [browser_inspector_breadcrumbs_shadowdom.js]
-skip-if = !stylo # shadow DOM is only enabled with stylo.
 [browser_inspector_breadcrumbs_visibility.js]
 [browser_inspector_delete-selected-node-01.js]
 [browser_inspector_delete-selected-node-02.js]
 [browser_inspector_delete-selected-node-03.js]
 [browser_inspector_destroy-after-navigation.js]
 [browser_inspector_destroy-before-ready.js]
 [browser_inspector_expand-collapse.js]
 [browser_inspector_highlighter-01.js]
--- a/devtools/server/tests/mochitest/test_inspector-anonymous.html
+++ b/devtools/server/tests/mochitest/test_inspector-anonymous.html
@@ -18,18 +18,16 @@ window.onload = function() {
     require("devtools/shared/fronts/inspector");
   const {DocumentWalker: _documentWalker} =
     require("devtools/server/actors/inspector/document-walker");
 
   const nodeFilterConstants =
     require("devtools/shared/dom-node-filter-constants");
   const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
-  const isStylo = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.webcomponents.shadowdom.enabled", true]
   ]});
   SimpleTest.waitForExplicitFinish();
 
   let gWalker = null;
   let gInspectee = null;
 
@@ -144,18 +142,18 @@ window.onload = function() {
     ok(!before._form.isXBLAnonymous, "Child is not XBL anonymous");
     ok(!before._form.isShadowAnonymous, "Child is not shadow anonymous");
     ok(before._form.isNativeAnonymous, "Child is native anonymous");
 
     runNextTest();
   });
 
   addAsyncTest(async function testShadowAnonymous() {
-    // Stylo doesn't currently support shadow DOM (bug 1293844)
-    if (isStylo) {
+    if (true) {
+      // FIXME(bug 1465114)
       runNextTest();
       return;
     }
 
     info("Testing shadow DOM content.");
 
     let shadow = await gWalker.querySelector(gWalker.rootNode, "#shadow");
     let children = await gWalker.children(shadow);
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -26,23 +26,29 @@ class CustomElementUpgradeReaction final
 {
 public:
   explicit CustomElementUpgradeReaction(CustomElementDefinition* aDefinition)
     : mDefinition(aDefinition)
   {
     mIsUpgradeReaction = true;
   }
 
+  virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
+  {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mDefinition");
+    aCb.NoteNativeChild(mDefinition,
+      NS_CYCLE_COLLECTION_PARTICIPANT(CustomElementDefinition));
+  }
 private:
   virtual void Invoke(Element* aElement, ErrorResult& aRv) override
   {
     CustomElementRegistry::Upgrade(aElement, mDefinition, aRv);
   }
 
-  CustomElementDefinition* mDefinition;
+  RefPtr<CustomElementDefinition> mDefinition;
 };
 
 //-----------------------------------------------------
 // CustomElementCallbackReaction
 
 class CustomElementCallbackReaction final : public CustomElementReaction
 {
   public:
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -191,19 +191,17 @@ private:
   ~CustomElementDefinition() {}
 };
 
 class CustomElementReaction
 {
 public:
   virtual ~CustomElementReaction() = default;
   virtual void Invoke(Element* aElement, ErrorResult& aRv) = 0;
-  virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const
-  {
-  }
+  virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const = 0;
 
   bool IsUpgradeReaction()
   {
     return mIsUpgradeReaction;
   }
 
 protected:
   bool mIsUpgradeReaction = false;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1752,39 +1752,24 @@ Element::BindToTree(nsIDocument* aDocume
          child = child->GetNextSibling()) {
       rv = child->BindToTree(nullptr, shadowRoot,
                              shadowRoot->GetBindingParent(),
                              aCompileEventHandlers);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
-  // Pseudo-elements implemented by JS must have the NODE_IS_NATIVE_ANONYMOUS
-  // flag set on them. For C++-created pseudo-elements, this is done in
-  // nsCSSFrameConstructor::GetAnonymousContent, but any JS that creates
-  // pseudo-elements would run after that. So we set that flag here,
-  // when the element implementing the pseudo is inserted into the document.
-  // We maintain the invariant that any NAC-implemented pseudo-element's
-  // anonymous ancestors are also flagged as NAC, which the style system relies on.
-  if (aDocument) {
+  // FIXME(emilio): Why is this needed? The element shouldn't even be styled in
+  // the first place, we should style it properly eventually.
+  //
+  // Also, if this _is_ needed, then it's wrong and should use GetComposedDoc()
+  // to account for Shadow DOM.
+  if (aDocument && MayHaveAnimations()) {
     CSSPseudoElementType pseudoType = GetPseudoElementType();
-    if (pseudoType != CSSPseudoElementType::NotPseudo &&
-        nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType)) {
-      SetFlags(NODE_IS_NATIVE_ANONYMOUS);
-      nsIContent* parent = aParent;
-      while (parent && !parent->IsRootOfNativeAnonymousSubtree()) {
-        MOZ_ASSERT(parent->IsInNativeAnonymousSubtree());
-        parent->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
-        parent = parent->GetParent();
-      }
-      MOZ_ASSERT(parent);
-    }
-
-    if (MayHaveAnimations() &&
-        (pseudoType == CSSPseudoElementType::NotPseudo ||
+    if ((pseudoType == CSSPseudoElementType::NotPseudo ||
          pseudoType == CSSPseudoElementType::before ||
          pseudoType == CSSPseudoElementType::after) &&
         EffectSet::GetEffectSet(this, pseudoType)) {
       if (nsPresContext* presContext = aDocument->GetPresContext()) {
         presContext->EffectCompositor()->
           RequestRestyle(this, pseudoType,
                          EffectCompositor::RestyleType::Standard,
                          EffectCompositor::CascadeLevel::Animations);
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1441029.html
@@ -0,0 +1,1 @@
+<div is="div">
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -213,17 +213,17 @@ load 1352453.html
 pref(dom.IntersectionObserver.enabled,true) load 1353529.xul
 load 1368327.html
 pref(dom.IntersectionObserver.enabled,true) load 1369363.xul
 load 1370072.html
 pref(clipboard.autocopy,true) load 1370737.html
 pref(dom.IntersectionObserver.enabled,true) load 1370968.html
 load 1373750.html
 load 1377826.html
-skip-if(stylo&&isDebugBuild&&winWidget) load structured_clone_container_throws.html # Bug 1383845
+load structured_clone_container_throws.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
 load 1383478.html
 load 1383780.html
 pref(clipboard.autocopy,true) load 1385272-1.html
 load 1393806.html
 load 1396466.html
 load 1397795.html
@@ -234,13 +234,14 @@ load 1406109-1.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1324463.html
 pref(dom.webcomponents.customelements.enabled,true) load 1413815.html
 load 1411473.html
 pref(dom.webcomponents.shadowdom.enabled,false) load 1422931.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1419799.html
 skip-if(!browserIsRemote) pref(dom.webcomponents.customelements.enabled,true) pref(dom.disable_open_during_load,false) load 1419902.html # skip on non e10s loads, Bug 1419902
 pref(dom.webcomponents.shadowdom.enabled,true) load 1422883.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1428053.html
+pref(dom.webcomponents.customelements.enabled,true) load 1441029.html
 load 1449601.html
 load 1445670.html
 load 1458016.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1459688.html
 load 1460794.html
--- a/dom/base/mozAutoDocUpdate.h
+++ b/dom/base/mozAutoDocUpdate.h
@@ -47,40 +47,9 @@ private:
 #define MOZ_AUTO_DOC_UPDATE_PASTE2(tok,line) tok##line
 #define MOZ_AUTO_DOC_UPDATE_PASTE(tok,line) \
   MOZ_AUTO_DOC_UPDATE_PASTE2(tok,line)
 #define MOZ_AUTO_DOC_UPDATE(doc,notify) \
   mozAutoDocUpdate MOZ_AUTO_DOC_UPDATE_PASTE(_autoDocUpdater_, __LINE__) \
   (doc,notify)
 
 
-/**
- * Creates an update batch only under certain conditions.
- * Use this rather than mozAutoDocUpdate when you expect inner updates
- * to notify but you don't always want to spec cycles creating a batch.
- * This is needed to avoid having this batch always create a blocker,
- * but then have inner mozAutoDocUpdate call the last EndUpdate before.
- * we remove that blocker. See bug 423269.
- */
-class MOZ_STACK_CLASS mozAutoDocConditionalContentUpdateBatch
-{
-public:
-  mozAutoDocConditionalContentUpdateBatch(nsIDocument* aDocument,
-                                          bool aNotify) :
-    mDocument(aNotify ? aDocument : nullptr)
-  {
-    if (mDocument) {
-      mDocument->BeginUpdate();
-    }
-  }
-
-  ~mozAutoDocConditionalContentUpdateBatch()
-  {
-    if (mDocument) {
-      mDocument->EndUpdate();
-    }
-  }
-
-private:
-  nsCOMPtr<nsIDocument> mDocument;
-};
-
 #endif
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9871,16 +9871,19 @@ nsContentUtils::NewXULOrHTMLElement(Elem
   MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) ||
              nodeInfo->NamespaceEquals(kNameSpaceID_XUL),
              "Can only create XUL or XHTML elements.");
 
   nsAtom *name = nodeInfo->NameAtom();
   int32_t tag = eHTMLTag_unknown;
   bool isCustomElementName = false;
   if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+    if (aIsAtom && !nsContentUtils::IsNameWithDash(aIsAtom)) {
+      aIsAtom = nullptr;
+    }
     tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
     isCustomElementName = (tag == eHTMLTag_userdefined &&
                            nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML));
   } else { // kNameSpaceID_XUL
     if (aIsAtom) {
       // Make sure the customized built-in element to be constructed confirms
       // to our naming requirement, i.e. [is] must be a dashed name and
       // the tag name must not.
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4270,23 +4270,16 @@ nsDOMWindowUtils::EnsureDirtyRootFrame()
     return NS_ERROR_FAILURE;
   }
 
   presShell->FrameNeedsReflow(frame, nsIPresShell::eStyleChange,
                               NS_FRAME_IS_DIRTY);
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMWindowUtils::GetIsStyledByServo(bool* aStyledByServo)
-{
-  *aStyledByServo = true;
-  return NS_OK;
-}
-
 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsTranslationNodeList)
 NS_IMPL_RELEASE(nsTranslationNodeList)
 
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -197,17 +197,17 @@ public:
 
   /**
    * Makes this content anonymous
    * @see nsIAnonymousContentCreator
    */
   void SetIsNativeAnonymousRoot()
   {
     SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
-             NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS);
+             NODE_IS_NATIVE_ANONYMOUS_ROOT);
   }
 
   /**
    * Returns |this| if it is not chrome-only/native anonymous, otherwise
    * first non chrome-only/native anonymous ancestor.
    */
   nsIContent* FindFirstNonChromeOnlyAccessContent() const;
 
@@ -737,24 +737,16 @@ public:
     if (auto* lang = GetLang()) {
       aResult.Assign(nsDependentAtomString(lang));
       return true;
     }
 
     return false;
   }
 
-  // Returns true if this element is native-anonymous scrollbar content.
-  bool IsNativeScrollbarContent() const {
-    return IsNativeAnonymous() &&
-           IsAnyOfXULElements(nsGkAtoms::scrollbar,
-                              nsGkAtoms::resizer,
-                              nsGkAtoms::scrollcorner);
-  }
-
   // Overloaded from nsINode
   virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
 
   // Returns base URI for style attribute.
   nsIURI* GetBaseURIForStyleAttr() const;
 
   // Returns the URL data for style attribute.
   // If aSubjectPrincipal is passed, it should be the scripted principal
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -125,38 +125,17 @@ enum {
   // NOTE: Should only be used on nsIContent nodes
   NODE_IS_NATIVE_ANONYMOUS_ROOT =         NODE_FLAG_BIT(4),
 
   // Whether a binding manager may have a pointer to this
   NODE_MAY_BE_IN_BINDING_MNGR =           NODE_FLAG_BIT(5),
 
   NODE_IS_EDITABLE =                      NODE_FLAG_BIT(6),
 
-  // This node was created by layout as native anonymous content. This
-  // generally corresponds to things created by nsIAnonymousContentCreator,
-  // though there are exceptions (svg:use content does not have this flag
-  // set, and any non-nsIAnonymousContentCreator callers of
-  // SetIsNativeAnonymousRoot also get this flag).
-  //
-  // One very important aspect here is that this node is not transitive over
-  // the subtree (if you want that, use NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE).
-  // If Gecko code somewhere attaches children to a node with this bit set,
-  // the children will not have the bit themselves unless the calling code sets
-  // it explicitly. This means that XBL content bound to NAC doesn't get this
-  // bit, nor do nodes inserted by editor.
-  //
-  // For now, this bit exists primarily to control style inheritance behavior,
-  // since the nodes for which we set it are often used to implement pseudo-
-  // elements, which need to inherit style from a script-visible element.
-  //
-  // A more general principle for this bit might be this: If the node is entirely
-  // a detail of layout, is not script-observable in any way, and other engines
-  // might accomplish the same task with a nodeless layout frame, then the node
-  // should have this bit set.
-  NODE_IS_NATIVE_ANONYMOUS =              NODE_FLAG_BIT(7),
+  // Free bit here.
 
   // Whether the node participates in a shadow tree.
   NODE_IS_IN_SHADOW_TREE =                NODE_FLAG_BIT(8),
 
   // Node has an :empty or :-moz-only-whitespace selector
   NODE_HAS_EMPTY_SELECTOR =               NODE_FLAG_BIT(9),
 
   // A child of the node has a selector such that any insertion,
@@ -1268,25 +1247,16 @@ public:
     else {
       UnsetFlags(NODE_IS_EDITABLE);
     }
   }
 
   bool IsEditable() const;
 
   /**
-   * Returns true if |this| is native anonymous (i.e. created by
-   * nsIAnonymousContentCreator);
-   */
-  bool IsNativeAnonymous() const
-  {
-    return HasFlag(NODE_IS_NATIVE_ANONYMOUS);
-  }
-
-  /**
    * Returns true if |this| or any of its ancestors is native anonymous.
    */
   bool IsInNativeAnonymousSubtree() const
   {
 #ifdef DEBUG
     if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
       return true;
     }
--- a/dom/base/test/file_domwindowutils_animation.html
+++ b/dom/base/test/file_domwindowutils_animation.html
@@ -122,35 +122,33 @@ function test_getUnanimatedComputedStyle
     "NS_ERROR_INVALID_ARG",
     "FLUSH_LAYOUT option should throw");
 
   SimpleTest.doesThrow(
     () => utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_DISPLAY),
     "NS_ERROR_INVALID_ARG",
     "FLUSH_DISPLAY option should throw");
 
-  if (utils.isStyledByServo) {
-    SimpleTest.doesThrow(
-      () => utils.getUnanimatedComputedStyle(div, "::before", "opacity", utils.FLUSH_NONE),
-      "NS_ERROR_FAILURE",
-      "Non-existent pseudo should throw");
+  SimpleTest.doesThrow(
+    () => utils.getUnanimatedComputedStyle(div, "::before", "opacity", utils.FLUSH_NONE),
+    "NS_ERROR_FAILURE",
+    "Non-existent pseudo should throw");
 
-    // Flush styles since getUnanimatedComputedStyle flushes pending styles even
-    // with FLUSH_NONE option if the element hasn't yet styled.
-    getComputedStyle(div).opacity;
+  // Flush styles since getUnanimatedComputedStyle flushes pending styles even
+  // with FLUSH_NONE option if the element hasn't yet styled.
+  getComputedStyle(div).opacity;
 
-    div.style.opacity = "0";
-    is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_NONE),
-       "1",
-       "getUnanimatedComputedStyle with FLUSH_NONE should not flush pending styles");
+  div.style.opacity = "0";
+  is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_NONE),
+     "1",
+     "getUnanimatedComputedStyle with FLUSH_NONE should not flush pending styles");
 
-    is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_STYLE),
-       "0",
-       "getUnanimatedComputedStyle with FLUSH_STYLE should flush pending styles");
-  }
+  is(utils.getUnanimatedComputedStyle(div, null, "opacity", utils.FLUSH_STYLE),
+     "0",
+     "getUnanimatedComputedStyle with FLUSH_STYLE should flush pending styles");
 
   div.remove();
 
   test_needsFlushWithThrottledAnimations();
 }
 
 function checkUnanimatedComputedStyle(property, initialStyle, pseudoType,
                                       expectedBeforeAnimation,
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -647,16 +647,18 @@ skip-if = toolkit == 'android' #bug 9041
 [test_elementTraversal.html]
 [test_encodeToStringWithMaxLength.html]
 [test_encodeToStringWithRequiresReinitAfterOutput.html]
 [test_error.html]
 [test_EventSource_redirects.html]
 [test_eventsource_event_listener_leaks.html]
 [test_explicit_user_agent.html]
 skip-if = (toolkit == 'android') # Android: Bug 775227
+[test_find.html]
+skip-if = (toolkit == 'android') # Android: Bug 1465387
 [test_getAttribute_after_createAttribute.html]
 [test_getElementById.html]
 [test_getTranslationNodes.html]
 [test_getTranslationNodes_limit.html]
 [test_gsp-qualified.html]
 [test_gsp-quirks.html]
 [test_gsp-standards.html]
 [test_history_document_open.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_find.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const t = async_test("Test window.find / nsFind");
+
+function testFindable(isFindable, textToFind, docText, description) {
+  try{
+    const iframe = document.querySelector("iframe")
+    iframe.contentDocument.documentElement.innerHTML = docText;
+    iframe.contentWindow.getSelection().removeAllRanges();
+    assert_equals(
+      isFindable,
+      iframe.contentWindow.find(textToFind),
+      "Should be " + (isFindable ? "" : "not ") + "findable: " + description + ", text: " + textToFind
+    );
+  } catch (ex) {
+    assert_unreached(ex);
+  }
+}
+
+const INLINE_LIKE_DISPLAY_VALUES = [
+  "inline",
+  "inline-grid",
+  "inline-block",
+  "inline-flex",
+];
+
+const BLOCK_LIKE_DISPLAY_VALUES = [
+  "block",
+  "table",
+  "list-item",
+  "grid",
+  "flex",
+];
+
+window.runTests = t.step_func_done(function() {
+  testFindable(true, "me and me", `
+    me <div style="display: contents">and</div> me
+  `, "display: contents");
+
+  testFindable(true, "me me", `
+    me <div style="display: none">and</div> me
+  `, "display: none");
+
+  testFindable(false, "me and me", `
+    me <div style="display: none">and</div> me
+  `, "display: none");
+
+  for (const display of INLINE_LIKE_DISPLAY_VALUES) {
+    testFindable(true, "me and me", `
+      me <div style="display: ${display}">and</div> me
+    `, "div display: " + display);
+    testFindable(true, "me and me", `
+      me <span style="display: ${display}">and</span> me
+    `, "span display: " + display);
+  }
+
+  for (const display of BLOCK_LIKE_DISPLAY_VALUES) {
+    testFindable(false, "me and me", `
+      me <div style="display: ${display}">and</div> me
+    `, "div display: " + display);
+    testFindable(false, "me and me", `
+      me <span style="display: ${display}">and</span> me
+    `, "span display: " + display);
+  }
+
+  testFindable(false, "me and me", `
+    me <fieldset>and</fieldset> me
+  `);
+
+  testFindable(true, "This text should be visible", `
+    <div style="visibility: hidden">
+      <div style="visibility: visible">
+        This text should be visible
+      </div>
+    </div>
+  `);
+});
+</script>
+<iframe onload="runTests()" srcdoc="<!doctype html><html></html>"></iframe>
--- a/dom/canvas/test/test_canvas_font_setter.html
+++ b/dom/canvas/test/test_canvas_font_setter.html
@@ -25,19 +25,20 @@ cx.font = "bold 12px serif; background: 
 is(cx.font, "italic 16px sans-serif", "invalid font should be ignored");
 
 cx.font = "bold 12px/3.0 serif";
 is(cx.font, "bold 12px serif", "line-height should be dropped");
 cx.font = "inherit";
 is(cx.font, "bold 12px serif", "inherit should be ignored");
 cx.font = "boold 18px sans-serif";
 is(cx.font, "bold 12px serif", "syntax error should be ignored");
-let systemFontCheck = SpecialPowers.DOMWindowUtils.isStyledByServo ? is : todo_is;
+
+// FIXME(emilio): This disagrees with the WPT test: 2dcontext/text-styles/2d.text.font.parse.system.html
 cx.font = "menu";
-systemFontCheck(cx.font, "menu", "system fonts should work");
+is(cx.font, "menu", "system fonts should work");
 
 function textmeas() {
   return cx.measureText("hello").width;
 }
 
 cx.font = "66px serif";
 var w_at_66 = textmeas();
 cx.font = "20px serif";
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -137,20 +137,20 @@ support-files = test_bug1003432.js
 [test_bug1013412.html]
 [test_bug1017086_disable.html]
 support-files = bug1017086_inner.html
 [test_bug1017086_enable.html]
 support-files = bug1017086_inner.html
 [test_bug1079236.html]
 [test_bug1145910.html]
 [test_bug1150308.html]
-skip-if = true || stylo # bug 1293844, bug  1421545
+skip-if = true # bug  1421545
 [test_bug1248459.html]
 [test_bug1264380.html]
-run-if = (e10s && os != "win" && stylo) # Bug 1270043, crash at windows platforms; Bug1264380 comment 20, nsDragService::InvokeDragSessionImpl behaves differently among platform implementations in non-e10s mode which prevents us to check the validity of nsIDragService::getCurrentSession() consistently via synthesize mouse clicks in non-e10s mode.
+run-if = (e10s && os != "win") # Bug 1270043, crash at windows platforms; Bug1264380 comment 20, nsDragService::InvokeDragSessionImpl behaves differently among platform implementations in non-e10s mode which prevents us to check the validity of nsIDragService::getCurrentSession() consistently via synthesize mouse clicks in non-e10s mode.
 [test_bug1327798.html]
 subsuite = clipboard
 [test_clickevent_on_input.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_continuous_wheel_events.html]
 [test_dblclick_explicit_original_target.html]
 [test_dom_activate_event.html]
 [test_dom_keyboard_event.html]
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3173,17 +3173,18 @@ HTMLInputElement::Blur(ErrorResult& aErr
 void
 HTMLInputElement::Focus(ErrorResult& aError)
 {
   if (mType == NS_FORM_INPUT_NUMBER) {
     // Focus our anonymous text control, if we have one.
     nsNumberControlFrame* numberControlFrame =
       do_QueryFrame(GetPrimaryFrame());
     if (numberControlFrame) {
-      HTMLInputElement* textControl = numberControlFrame->GetAnonTextControl();
+      RefPtr<HTMLInputElement> textControl =
+        numberControlFrame->GetAnonTextControl();
       if (textControl) {
         textControl->Focus(aError);
         return;
       }
     }
   }
 
   if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
--- a/dom/html/test/test_fullscreen-api.html
+++ b/dom/html/test/test_fullscreen-api.html
@@ -71,22 +71,16 @@ var gLinuxE10sSkipList = [
 
 function shouldSkipTest(test) {
   if (SpecialPowers.Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).isHeadless &&
       test == "file_fullscreen-plugins.html") {
     todo(false, `${test} skipped due to bug 1409805`);
     return true;
   }
 
-  if (!SpecialPowers.DOMWindowUtils.isStyledByServo &&
-      test == "file_fullscreen-shadowdom.html") {
-    // Shadow DOM is stylo-only.
-    return true;
-  }
-
   if (!SpecialPowers.isMainProcess() &&
       navigator.platform.includes('Linux')) {
     for (let item of gLinuxE10sSkipList) {
       if (item.test == test) {
         todo(false, `${test} skipped due to ${item.reason}`);
         return true;
       }
     }
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1904,23 +1904,16 @@ interface nsIDOMWindowUtils : nsISupport
    * Calls FrameNeedsReflow on that root frame so that a layout flush
    * will be necessary.
    *
    * This should only be used for testing.
    */
   void ensureDirtyRootFrame();
 
   /**
-   * Whether the current document is styled by Servo's style engine.
-   *
-   * Always true, pending removal.
-   */
-  readonly attribute boolean isStyledByServo;
-
-  /**
    * Capture the contents of the current WebRender frame and
    * save them to a folder relative to the current working directory.
    */
   void wrCapture();
 
   // These consts are only for testing purposes.
   const long DEFAULT_MOUSE_POINTER_ID = 0;
   const long DEFAULT_PEN_POINTER_ID   = 1;
--- a/dom/smil/test/db_smilCSSFromBy.js
+++ b/dom/smil/test/db_smilCSSFromBy.js
@@ -3,18 +3,16 @@
 /* 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/. */
 
 /* testcase data for simple "from-by" animations of CSS properties */
 
 // NOTE: This js file requires db_smilCSSPropertyList.js
 
-const isServoEnabled = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
 // Lists of testcases for re-use across multiple properties of the same type
 var _fromByTestLists =
 {
   color: [
     new AnimTestcaseFromBy("rgb(10, 20, 30)", "currentColor",
                            { midComp: "rgb(35, 45, 55)",
                              toComp:  "rgb(60, 70, 80)"}),
     new AnimTestcaseFromBy("currentColor", "rgb(30, 20, 10)",
@@ -25,36 +23,30 @@ var _fromByTestLists =
                              // (rgb(10, 20, 30) * 0.2 * 0.5 + rgb(52, 54, 56) * 1.0 * 0.5) * (1 / 0.6)
                            { midComp: "rgba(45, 48, 52, 0.6)",
                              // (rgb(10, 20, 30) * 0.2 + rgb(50, 50, 50) * 1) / 1.0
                              toComp:  "rgb(52, 54, 56)"}),
 
     // The "from" and "by" values in the test case below overflow the maxium
     // color-channel values when added together.
     // (e.g. for red [ignoring alpha for now], 100 + 240 = 340 which is > 255)
+    //
     // The SVG Animation spec says we should clamp color values "as late as
     // possible" i.e. allow the channel overflow and clamp at paint-time.
     //
-    // Servo does this, and gives us:
+    // That gives us:
     //
     //   to-value = (rgb(100, 100, 100) * 0.6 + rgb(240, 240, 240) * 1.0)) * 1
     //            = rgb(300, 300, 300)
     //   midComp  = (rgb(100, 100, 100) * 0.6 * 0.5 + rgb(300, 300, 300) * 1.0 * 0.5) * (1 / 0.8)
     //            = rgb(225, 225, 225)
     //
-    // Gecko, however, clamps the "to" value and interpolates up to that
-    // clamped result giving:
-    //
-    //   midComp  = (rgb(100, 100, 100) * 0.6 * 0.5 + rgb(255, 255, 255) * 1.0 * 0.5) * (1 / 0.8)
-    //            = rgb(197, 197, 197)
     //
     new AnimTestcaseFromBy("rgba(100, 100, 100, 0.6)", "rgba(240, 240, 240, 1)",
-                           { midComp:
-                             isServoEnabled ? "rgba(225, 225, 225, 0.8)"
-                                            : "rgba(197, 197, 197, 0.8)",
+                           { midComp: "rgba(225, 225, 225, 0.8)",
                              toComp:  "rgb(255, 255, 255)"}),
   ],
   lengthNoUnits: [
     new AnimTestcaseFromBy("0", "50",  { fromComp: "0px", // 0 acts like 0px
                                          midComp:  "25px",
                                          toComp:   "50px"}),
     new AnimTestcaseFromBy("30", "10", { fromComp: "30px",
                                          midComp:  "35px",
--- a/dom/smil/test/mochitest.ini
+++ b/dom/smil/test/mochitest.ini
@@ -21,17 +21,17 @@ support-files =
 [test_smilCSSFontStretchRelative.xhtml]
 [test_smilCSSFromBy.xhtml]
 [test_smilCSSFromTo.xhtml]
 [test_smilCSSInherit.xhtml]
 disabled=until bug 501183 is fixed
 [test_smilCSSInvalidValues.xhtml]
 [test_smilCSSPaced.xhtml]
 [test_smilChangeAfterFrozen.xhtml]
-skip-if = stylo # bug 1358955.
+skip-if = true # bug 1358955.
 [test_smilConditionalProcessing.html]
 [test_smilContainerBinding.xhtml]
 [test_smilCrossContainer.xhtml]
 [test_smilDynamicDelayedBeginElement.xhtml]
 [test_smilExtDoc.xhtml]
 skip-if = toolkit == 'android'
 [test_smilFillMode.xhtml]
 [test_smilGetSimpleDuration.xhtml]
--- a/dom/tests/mochitest/webcomponents/test_shadowroot_style.html
+++ b/dom/tests/mochitest/webcomponents/test_shadowroot_style.html
@@ -8,20 +8,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="head.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a>
 <script>
 
-if (!SpecialPowers.DOMWindowUtils.isStyledByServo) {
-  SimpleTest.expectAssertions(3, 3); // GeckoRestyleManager stuff.
-}
-
 SimpleTest.waitForExplicitFinish();
 
 var content = '<div class="tall" id="bodydiv"></div>' +
               '<div id="container"></div>';
 setShadowDOMPrefAndCreateIframe(content)
   .then((aDocument) => {
     var iframeWin = aDocument.defaultView;
 
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -6,23 +6,19 @@
 
 #include "mozilla/dom/U2F.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/dom/WebAuthnTransactionChild.h"
 #include "mozilla/dom/WebAuthnUtil.h"
 #include "nsContentUtils.h"
-#include "nsICryptoHash.h"
 #include "nsIEffectiveTLDService.h"
-#include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsURLParsers.h"
-#include "U2FUtil.h"
-#include "hasht.h"
 
 using namespace mozilla::ipc;
 
 // Forward decl because of nsHTMLDocument.h's complex dependency on /layout/style
 class nsHTMLDocument {
 public:
   bool IsRegistrableDomainSuffixOfOrEqualTo(const nsAString& aHostSuffixString,
                                             const nsACString& aOrigHost);
@@ -124,69 +120,16 @@ RegisteredKeysToScopedCredentialList(con
     }
 
     WebAuthnScopedCredential c;
     c.id() = keyHandle;
     aList.AppendElement(c);
   }
 }
 
-static nsresult
-BuildTransactionHashes(const nsCString& aRpId,
-                       const nsCString& aClientDataJSON,
-                       /* out */ CryptoBuffer& aRpIdHash,
-                       /* out */ CryptoBuffer& aClientDataHash)
-{
-  nsresult srv;
-  nsCOMPtr<nsICryptoHash> hashService =
-    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv);
-  if (NS_FAILED(srv)) {
-    return srv;
-  }
-
-  if (!aRpIdHash.SetLength(SHA256_LENGTH, fallible)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  srv = HashCString(hashService, aRpId, aRpIdHash);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (!aClientDataHash.SetLength(SHA256_LENGTH, fallible)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  srv = HashCString(hashService, aClientDataJSON, aClientDataHash);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (MOZ_LOG_TEST(gU2FLog, LogLevel::Debug)) {
-    nsString base64;
-    Unused << NS_WARN_IF(NS_FAILED(aRpIdHash.ToJwkBase64(base64)));
-
-    MOZ_LOG(gU2FLog, LogLevel::Debug,
-            ("dom::U2FManager::RpID: %s", aRpId.get()));
-
-    MOZ_LOG(gU2FLog, LogLevel::Debug,
-            ("dom::U2FManager::Rp ID Hash (base64): %s",
-              NS_ConvertUTF16toUTF8(base64).get()));
-
-    Unused << NS_WARN_IF(NS_FAILED(aClientDataHash.ToJwkBase64(base64)));
-
-    MOZ_LOG(gU2FLog, LogLevel::Debug,
-            ("dom::U2FManager::Client Data JSON: %s", aClientDataJSON.get()));
-
-    MOZ_LOG(gU2FLog, LogLevel::Debug,
-            ("dom::U2FManager::Client Data Hash (base64): %s",
-              NS_ConvertUTF16toUTF8(base64).get()));
-  }
-
-  return NS_OK;
-}
-
 /***********************************************************************
  * U2F JavaScript API Implementation
  **********************************************************************/
 
 U2F::~U2F()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -275,27 +218,28 @@ U2F::Register(const nsAString& aAppId,
   nsString adjustedAppId(aAppId);
   if (!EvaluateAppID(mParent, mOrigin, U2FOperation::Register, adjustedAppId)) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
     ExecuteCallback(response, callback);
     return;
   }
 
-  // Produce the AppParam from the current AppID
-  nsCString cAppId = NS_ConvertUTF16toUTF8(adjustedAppId);
-
   nsAutoString clientDataJSON;
 
   // Pick the first valid RegisterRequest; we can only work with one.
+  CryptoBuffer challenge;
   for (const RegisterRequest& req : aRegisterRequests) {
     if (!req.mChallenge.WasPassed() || !req.mVersion.WasPassed() ||
         req.mVersion.Value() != kRequiredU2FVersion) {
       continue;
     }
+    if (!challenge.Assign(NS_ConvertUTF16toUTF8(req.mChallenge.Value()))) {
+      continue;
+    }
 
     nsresult rv = AssembleClientData(mOrigin, kFinishEnrollment,
                                      req.mChallenge.Value(), clientDataJSON);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       continue;
     }
   }
 
@@ -307,57 +251,38 @@ U2F::Register(const nsAString& aAppId,
     return;
   }
 
   // Build the exclusion list, if any
   nsTArray<WebAuthnScopedCredential> excludeList;
   RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
                                        excludeList);
 
-  auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
-
-  CryptoBuffer rpIdHash, clientDataHash;
-  if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
-                                       rpIdHash, clientDataHash))) {
-    RegisterResponse response;
-    response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
-    ExecuteCallback(response, callback);
-    return;
-  }
-
   if (!MaybeCreateBackgroundActor()) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
     ExecuteCallback(response, callback);
     return;
   }
 
   ListenForVisibilityEvents();
 
-  // Always blank for U2F
-  nsTArray<WebAuthnExtension> extensions;
-
-  // Default values for U2F.
-  WebAuthnAuthenticatorSelection authSelection(false /* requireResidentKey */,
-                                               false /* requireUserVerification */,
-                                               false /* requirePlatformAttachment */);
-
+  NS_ConvertUTF16toUTF8 clientData(clientDataJSON);
   uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
 
   WebAuthnMakeCredentialInfo info(mOrigin,
-                                  rpIdHash,
-                                  clientDataHash,
+                                  adjustedAppId,
+                                  challenge,
+                                  clientData,
                                   adjustedTimeoutMillis,
                                   excludeList,
-                                  extensions,
-                                  authSelection,
-                                  false /* RequestDirectAttestation */);
+                                  null_t() /* no extra info for U2F */);
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(U2FTransaction(clientData, Move(AsVariant(callback))));
+  mTransaction = Some(U2FTransaction(Move(AsVariant(callback))));
   mChild->SendRequestRegister(mTransaction.ref().mId, info);
 }
 
 void
 U2F::FinishMakeCredential(const uint64_t& aTransactionId,
                           const WebAuthnMakeCredentialResult& aResult)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -367,24 +292,30 @@ U2F::FinishMakeCredential(const uint64_t
     return;
   }
 
   if (NS_WARN_IF(!mTransaction.ref().HasRegisterCallback())) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
+  // A CTAP2 response.
+  if (aResult.RegistrationData().Length() == 0) {
+    RejectTransaction(NS_ERROR_ABORT);
+    return;
+  }
+
   CryptoBuffer clientDataBuf;
-  if (NS_WARN_IF(!clientDataBuf.Assign(mTransaction.ref().mClientData))) {
+  if (NS_WARN_IF(!clientDataBuf.Assign(aResult.ClientDataJSON()))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   CryptoBuffer regBuf;
-  if (NS_WARN_IF(!regBuf.Assign(aResult.RegBuffer()))) {
+  if (NS_WARN_IF(!regBuf.Assign(aResult.RegistrationData()))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   nsString clientDataBase64;
   nsString registrationDataBase64;
   nsresult rvClientData = clientDataBuf.ToJwkBase64(clientDataBase64);
   nsresult rvRegistrationData = regBuf.ToJwkBase64(registrationDataBase64);
@@ -450,56 +381,54 @@ U2F::Sign(const nsAString& aAppId,
                                    clientDataJSON);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
     ExecuteCallback(response, callback);
     return;
   }
 
-  // Build the key list, if any
-  nsTArray<WebAuthnScopedCredential> permittedList;
-  RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
-                                       permittedList);
-
-  auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
-
-  CryptoBuffer rpIdHash, clientDataHash;
-  if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
-                                       rpIdHash, clientDataHash))) {
+  CryptoBuffer challenge;
+  if (!challenge.Assign(NS_ConvertUTF16toUTF8(aChallenge))) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
     ExecuteCallback(response, callback);
     return;
   }
 
+  // Build the key list, if any
+  nsTArray<WebAuthnScopedCredential> permittedList;
+  RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
+                                       permittedList);
+
   if (!MaybeCreateBackgroundActor()) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
     ExecuteCallback(response, callback);
     return;
   }
 
   ListenForVisibilityEvents();
 
   // Always blank for U2F
   nsTArray<WebAuthnExtension> extensions;
 
+  NS_ConvertUTF16toUTF8 clientData(clientDataJSON);
   uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
 
   WebAuthnGetAssertionInfo info(mOrigin,
-                                rpIdHash,
-                                clientDataHash,
+                                adjustedAppId,
+                                challenge,
+                                clientData,
                                 adjustedTimeoutMillis,
                                 permittedList,
-                                false, /* requireUserVerification */
-                                extensions);
+                                null_t() /* no extra info for U2F */);
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(U2FTransaction(clientData, Move(AsVariant(callback))));
+  mTransaction = Some(U2FTransaction(Move(AsVariant(callback))));
   mChild->SendRequestSign(mTransaction.ref().mId, info);
 }
 
 void
 U2F::FinishGetAssertion(const uint64_t& aTransactionId,
                         const WebAuthnGetAssertionResult& aResult)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -509,30 +438,36 @@ U2F::FinishGetAssertion(const uint64_t& 
     return;
   }
 
   if (NS_WARN_IF(!mTransaction.ref().HasSignCallback())) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
+  // A CTAP2 response.
+  if (aResult.SignatureData().Length() == 0) {
+    RejectTransaction(NS_ERROR_ABORT);
+    return;
+  }
+
   CryptoBuffer clientDataBuf;
-  if (NS_WARN_IF(!clientDataBuf.Assign(mTransaction.ref().mClientData))) {
+  if (NS_WARN_IF(!clientDataBuf.Assign(aResult.ClientDataJSON()))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   CryptoBuffer credBuf;
-  if (NS_WARN_IF(!credBuf.Assign(aResult.CredentialID()))) {
+  if (NS_WARN_IF(!credBuf.Assign(aResult.KeyHandle()))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   CryptoBuffer sigBuf;
-  if (NS_WARN_IF(!sigBuf.Assign(aResult.SigBuffer()))) {
+  if (NS_WARN_IF(!sigBuf.Assign(aResult.SignatureData()))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   // Assemble a response object to return
   nsString clientDataBase64;
   nsString signatureDataBase64;
   nsString keyHandleBase64;
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -33,20 +33,18 @@ struct RegisterRequest;
 struct RegisteredKey;
 
 class U2FTransaction
 {
   typedef Variant<nsMainThreadPtrHandle<U2FRegisterCallback>,
                   nsMainThreadPtrHandle<U2FSignCallback>> U2FCallback;
 
 public:
-  explicit U2FTransaction(const nsCString& aClientData,
-                          const U2FCallback&& aCallback)
-    : mClientData(aClientData)
-    , mCallback(Move(aCallback))
+  explicit U2FTransaction(const U2FCallback&& aCallback)
+    : mCallback(Move(aCallback))
     , mId(NextId())
   {
     MOZ_ASSERT(mId > 0);
   }
 
   bool HasRegisterCallback() {
     return mCallback.is<nsMainThreadPtrHandle<U2FRegisterCallback>>();
   }
@@ -58,19 +56,16 @@ public:
   bool HasSignCallback() {
     return mCallback.is<nsMainThreadPtrHandle<U2FSignCallback>>();
   }
 
   auto& GetSignCallback() {
     return mCallback.as<nsMainThreadPtrHandle<U2FSignCallback>>();
   }
 
-  // Client data used to assemble reply objects.
-  nsCString mClientData;
-
   // The callback passed to the API.
   U2FCallback mCallback;
 
   // Unique transaction id.
   uint64_t mId;
 
 private:
   // Generates a unique id for new transactions. This doesn't have to be unique
deleted file mode 100644
--- a/dom/u2f/U2FUtil.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- 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/. */
-
-#ifndef mozilla_dom_U2FUtil_h
-#define mozilla_dom_U2FUtil_h
-
-namespace mozilla {
-namespace dom {
-
-static nsresult
-HashCString(nsICryptoHash* aHashService, const nsACString& aIn,
-            /* out */ CryptoBuffer& aOut)
-{
-  MOZ_ASSERT(aHashService);
-
-  nsresult rv = aHashService->Init(nsICryptoHash::SHA256);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  rv = aHashService->Update(
-    reinterpret_cast<const uint8_t*>(aIn.BeginReading()), aIn.Length());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  nsAutoCString fullHash;
-  // Passing false below means we will get a binary result rather than a
-  // base64-encoded string.
-  rv = aHashService->Finish(false, fullHash);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  aOut.Assign(fullHash);
-  return rv;
-}
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_U2FUtil_h
-
--- a/dom/u2f/moz.build
+++ b/dom/u2f/moz.build
@@ -5,17 +5,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
 
 EXPORTS.mozilla.dom += [
     'U2F.h',
     'U2FAuthenticator.h',
-    'U2FUtil.h',
 ]
 
 UNIFIED_SOURCES += [
     'U2F.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/dom/webauthn/PWebAuthnTransaction.ipdl
+++ b/dom/webauthn/PWebAuthnTransaction.ipdl
@@ -11,16 +11,18 @@
  * keys, etc) or interruption (another transaction was started in another
  * content process). Similarly, the content process can also request a cancel,
  * either triggered explicitly by the user/script or due to UI events like
  * selecting a different tab.
  */
 
 include protocol PBackground;
 
+using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
+
 namespace mozilla {
 namespace dom {
 
 struct WebAuthnAuthenticatorSelection {
   bool requireResidentKey;
   bool requireUserVerification;
   bool requirePlatformAttachment;
 };
@@ -41,47 +43,73 @@ union WebAuthnExtension {
 struct WebAuthnExtensionResultAppId {
   bool AppId;
 };
 
 union WebAuthnExtensionResult {
   WebAuthnExtensionResultAppId;
 };
 
-struct WebAuthnMakeCredentialInfo {
-  nsString Origin;
-  uint8_t[] RpIdHash;
-  uint8_t[] ClientDataHash;
-  uint32_t TimeoutMS;
-  WebAuthnScopedCredential[] ExcludeList;
+struct WebAuthnMakeCredentialExtraInfo {
   WebAuthnExtension[] Extensions;
   WebAuthnAuthenticatorSelection AuthenticatorSelection;
   bool RequestDirectAttestation;
 };
 
+union WebAuthnMaybeMakeCredentialExtraInfo {
+  WebAuthnMakeCredentialExtraInfo;
+  null_t;
+};
+
+struct WebAuthnMakeCredentialInfo {
+  nsString Origin;
+  nsString RpId;
+  uint8_t[] Challenge;
+  nsCString ClientDataJSON;
+  uint32_t TimeoutMS;
+  WebAuthnScopedCredential[] ExcludeList;
+  WebAuthnMaybeMakeCredentialExtraInfo Extra;
+};
+
 struct WebAuthnMakeCredentialResult {
-  uint8_t[] RegBuffer;
-  bool DirectAttestationPermitted;
+  nsCString ClientDataJSON;
+  uint8_t[] AttestationObject;
+  uint8_t[] KeyHandle;
+  /* Might be empty if the token implementation doesn't support CTAP1. */
+  uint8_t[] RegistrationData;
+};
+
+struct WebAuthnGetAssertionExtraInfo {
+  WebAuthnExtension[] Extensions;
+  bool RequireUserVerification;
+};
+
+union WebAuthnMaybeGetAssertionExtraInfo {
+  WebAuthnGetAssertionExtraInfo;
+  null_t;
 };
 
 struct WebAuthnGetAssertionInfo {
   nsString Origin;
-  uint8_t[] RpIdHash;
-  uint8_t[] ClientDataHash;
+  nsString RpId;
+  uint8_t[] Challenge;
+  nsCString ClientDataJSON;
   uint32_t TimeoutMS;
   WebAuthnScopedCredential[] AllowList;
-  bool RequireUserVerification;
-  WebAuthnExtension[] Extensions;
+  WebAuthnMaybeGetAssertionExtraInfo Extra;
 };
 
 struct WebAuthnGetAssertionResult {
-  uint8_t[] RpIdHash;
-  uint8_t[] CredentialID;
-  uint8_t[] SigBuffer;
+  nsCString ClientDataJSON;
+  uint8_t[] KeyHandle;
+  uint8_t[] Signature;
+  uint8_t[] AuthenticatorData;
   WebAuthnExtensionResult[] Extensions;
+  /* Might be empty if the token implementation doesn't support CTAP1. */
+  uint8_t[] SignatureData;
 };
 
 async protocol PWebAuthnTransaction {
   manager PBackground;
 
   parent:
     async RequestRegister(uint64_t aTransactionId, WebAuthnMakeCredentialInfo aTransactionInfo);
     async RequestSign(uint64_t aTransactionId, WebAuthnGetAssertionInfo aTransactionInfo);
--- a/dom/webauthn/U2FHIDTokenManager.cpp
+++ b/dom/webauthn/U2FHIDTokenManager.cpp
@@ -1,15 +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 "mozilla/dom/U2FHIDTokenManager.h"
+#include "mozilla/dom/WebAuthnUtil.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/StaticMutex.h"
 
 namespace mozilla {
 namespace dom {
 
 static StaticMutex gInstanceMutex;
 static U2FHIDTokenManager* gInstance;
@@ -46,17 +47,17 @@ u2f_sign_callback(uint64_t aTransactionI
   nsCOMPtr<nsIRunnable> r(NewRunnableMethod<UniquePtr<U2FResult>&&>(
       "U2FHIDTokenManager::HandleSignResult", gInstance,
       &U2FHIDTokenManager::HandleSignResult, Move(rv)));
 
   MOZ_ALWAYS_SUCCEEDS(gPBackgroundThread->Dispatch(r.forget(),
                                                    NS_DISPATCH_NORMAL));
 }
 
-U2FHIDTokenManager::U2FHIDTokenManager() : mTransactionId(0)
+U2FHIDTokenManager::U2FHIDTokenManager()
 {
   StaticMutexAutoLock lock(gInstanceMutex);
   mozilla::ipc::AssertIsOnBackgroundThread();
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(!gInstance);
 
   mU2FManager = rust_u2f_mgr_new();
   gPBackgroundThread = NS_GetCurrentThread();
@@ -79,17 +80,17 @@ U2FHIDTokenManager::Drop()
 
   // Release gInstanceMutex before we call U2FManager::drop(). It will wait
   // for the work queue thread to join, and that requires the
   // u2f_{register,sign}_callback to lock and return.
   rust_u2f_mgr_free(mU2FManager);
   mU2FManager = nullptr;
 
   // Reset transaction ID so that queued runnables exit early.
-  mTransactionId = 0;
+  mTransaction.reset();
 }
 
 // A U2F Register operation causes a new key pair to be generated by the token.
 // The token then returns the public key of the key pair, and a handle to the
 // private key, which is a fancy way of saying "key wrapped private key", as
 // well as the generated attestation certificate and a signature using that
 // certificate's private key.
 //
@@ -102,51 +103,66 @@ U2FHIDTokenManager::Drop()
 // 1      0x05
 // 65     public key
 // 1      key handle length
 // *      key handle
 // ASN.1  attestation certificate
 // *      attestation signature
 //
 RefPtr<U2FRegisterPromise>
-U2FHIDTokenManager::Register(const WebAuthnMakeCredentialInfo& aInfo)
+U2FHIDTokenManager::Register(const WebAuthnMakeCredentialInfo& aInfo,
+                             bool aForceNoneAttestation)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
   uint64_t registerFlags = 0;
 
-  const WebAuthnAuthenticatorSelection& sel = aInfo.AuthenticatorSelection();
+  if (aInfo.Extra().type() != WebAuthnMaybeMakeCredentialExtraInfo::Tnull_t) {
+    const auto& extra = aInfo.Extra().get_WebAuthnMakeCredentialExtraInfo();
+    const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection();
 
-  // Set flags for credential creation.
-  if (sel.requireResidentKey()) {
-    registerFlags |= U2F_FLAG_REQUIRE_RESIDENT_KEY;
+    // Set flags for credential creation.
+    if (sel.requireResidentKey()) {
+      registerFlags |= U2F_FLAG_REQUIRE_RESIDENT_KEY;
+    }
+    if (sel.requireUserVerification()) {
+      registerFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
+    }
+    if (sel.requirePlatformAttachment()) {
+      registerFlags |= U2F_FLAG_REQUIRE_PLATFORM_ATTACHMENT;
+    }
   }
-  if (sel.requireUserVerification()) {
-    registerFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
-  }
-  if (sel.requirePlatformAttachment()) {
-    registerFlags |= U2F_FLAG_REQUIRE_PLATFORM_ATTACHMENT;
+
+  CryptoBuffer rpIdHash, clientDataHash;
+  NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
+  nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(),
+                                       rpIdHash, clientDataHash);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
   ClearPromises();
-  mCurrentAppId = aInfo.RpIdHash();
-  mTransactionId = rust_u2f_mgr_register(mU2FManager,
-                                         registerFlags,
-                                         (uint64_t)aInfo.TimeoutMS(),
-                                         u2f_register_callback,
-                                         aInfo.ClientDataHash().Elements(),
-                                         aInfo.ClientDataHash().Length(),
-                                         aInfo.RpIdHash().Elements(),
-                                         aInfo.RpIdHash().Length(),
-                                         U2FKeyHandles(aInfo.ExcludeList()).Get());
+  mTransaction.reset();
+  uint64_t tid = rust_u2f_mgr_register(mU2FManager,
+                                       registerFlags,
+                                       (uint64_t)aInfo.TimeoutMS(),
+                                       u2f_register_callback,
+                                       clientDataHash.Elements(),
+                                       clientDataHash.Length(),
+                                       rpIdHash.Elements(),
+                                       rpIdHash.Length(),
+                                       U2FKeyHandles(aInfo.ExcludeList()).Get());
 
-  if (mTransactionId == 0) {
+  if (tid == 0) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
+  mTransaction = Some(Transaction(tid, rpIdHash, aInfo.ClientDataJSON(),
+                                  aForceNoneAttestation));
+
   return mRegisterPromise.Ensure(__func__);
 }
 
 // A U2F Sign operation creates a signature over the "param" arguments (plus
 // some other stuff) using the private key indicated in the key handle argument.
 //
 // The format of the signed data is as follows:
 //
@@ -161,93 +177,141 @@ U2FHIDTokenManager::Register(const WebAu
 //  4     Counter
 //  *     Signature
 //
 RefPtr<U2FSignPromise>
 U2FHIDTokenManager::Sign(const WebAuthnGetAssertionInfo& aInfo)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
-  uint64_t signFlags = 0;
-
-  // Set flags for credential requests.
-  if (aInfo.RequireUserVerification()) {
-    signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
+  CryptoBuffer rpIdHash, clientDataHash;
+  NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
+  nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(),
+                                       rpIdHash, clientDataHash);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
-  mCurrentAppId = aInfo.RpIdHash();
+  uint64_t signFlags = 0;
   nsTArray<nsTArray<uint8_t>> appIds;
-  appIds.AppendElement(mCurrentAppId);
+  appIds.AppendElement(rpIdHash);
+
+  if (aInfo.Extra().type() != WebAuthnMaybeGetAssertionExtraInfo::Tnull_t) {
+    const auto& extra = aInfo.Extra().get_WebAuthnGetAssertionExtraInfo();
 
-  // Process extensions.
-  for (const WebAuthnExtension& ext: aInfo.Extensions()) {
-    if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
-      appIds.AppendElement(ext.get_WebAuthnExtensionAppId().AppId());
+    // Set flags for credential requests.
+    if (extra.RequireUserVerification()) {
+      signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
+    }
+
+    // Process extensions.
+    for (const WebAuthnExtension& ext: extra.Extensions()) {
+      if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
+        appIds.AppendElement(ext.get_WebAuthnExtensionAppId().AppId());
+      }
     }
   }
 
   ClearPromises();
-  mTransactionId = rust_u2f_mgr_sign(mU2FManager,
-                                     signFlags,
-                                     (uint64_t)aInfo.TimeoutMS(),
-                                     u2f_sign_callback,
-                                     aInfo.ClientDataHash().Elements(),
-                                     aInfo.ClientDataHash().Length(),
-                                     U2FAppIds(appIds).Get(),
-                                     U2FKeyHandles(aInfo.AllowList()).Get());
-  if (mTransactionId == 0) {
+  mTransaction.reset();
+  uint64_t tid = rust_u2f_mgr_sign(mU2FManager,
+                                   signFlags,
+                                   (uint64_t)aInfo.TimeoutMS(),
+                                   u2f_sign_callback,
+                                   clientDataHash.Elements(),
+                                   clientDataHash.Length(),
+                                   U2FAppIds(appIds).Get(),
+                                   U2FKeyHandles(aInfo.AllowList()).Get());
+  if (tid == 0) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
+  mTransaction = Some(Transaction(tid, rpIdHash, aInfo.ClientDataJSON()));
+
   return mSignPromise.Ensure(__func__);
 }
 
 void
 U2FHIDTokenManager::Cancel()
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
   ClearPromises();
-  mTransactionId = rust_u2f_mgr_cancel(mU2FManager);
+  rust_u2f_mgr_cancel(mU2FManager);
+  mTransaction.reset();
 }
 
 void
 U2FHIDTokenManager::HandleRegisterResult(UniquePtr<U2FResult>&& aResult)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
-  if (aResult->GetTransactionId() != mTransactionId) {
+  if (mTransaction.isNothing() ||
+      aResult->GetTransactionId() != mTransaction.ref().mId) {
     return;
   }
 
   MOZ_ASSERT(!mRegisterPromise.IsEmpty());
 
   if (aResult->IsError()) {
     mRegisterPromise.Reject(aResult->GetError(), __func__);
     return;
   }
 
   nsTArray<uint8_t> registration;
   if (!aResult->CopyRegistration(registration)) {
     mRegisterPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
     return;
   }
 
-  // Will be set by the U2FTokenManager.
-  bool directAttestationPermitted = false;
-  WebAuthnMakeCredentialResult result(registration, directAttestationPermitted);
+  // Decompose the U2F registration packet
+  CryptoBuffer pubKeyBuf;
+  CryptoBuffer keyHandle;
+  CryptoBuffer attestationCertBuf;
+  CryptoBuffer signatureBuf;
+
+  CryptoBuffer regData;
+  regData.Assign(registration);
+
+  // Only handles attestation cert chains of length=1.
+  nsresult rv = U2FDecomposeRegistrationResponse(regData, pubKeyBuf, keyHandle,
+                                                 attestationCertBuf, signatureBuf);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mRegisterPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  CryptoBuffer rpIdHashBuf;
+  if (!rpIdHashBuf.Assign(mTransaction.ref().mRpIdHash)) {
+    mRegisterPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  CryptoBuffer attObj;
+  rv = AssembleAttestationObject(rpIdHashBuf, pubKeyBuf, keyHandle,
+                                 attestationCertBuf, signatureBuf,
+                                 mTransaction.ref().mForceNoneAttestation,
+                                 attObj);
+  if (NS_FAILED(rv)) {
+    mRegisterPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  WebAuthnMakeCredentialResult result(mTransaction.ref().mClientDataJSON,
+                                      attObj, keyHandle, regData);
   mRegisterPromise.Resolve(Move(result), __func__);
 }
 
 void
 U2FHIDTokenManager::HandleSignResult(UniquePtr<U2FResult>&& aResult)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
-  if (aResult->GetTransactionId() != mTransactionId) {
+  if (mTransaction.isNothing() ||
+      aResult->GetTransactionId() != mTransaction.ref().mId) {
     return;
   }
 
   MOZ_ASSERT(!mSignPromise.IsEmpty());
 
   if (aResult->IsError()) {
     mSignPromise.Reject(aResult->GetError(), __func__);
     return;
@@ -266,21 +330,58 @@ U2FHIDTokenManager::HandleSignResult(Uni
   }
 
   nsTArray<uint8_t> signature;
   if (!aResult->CopySignature(signature)) {
     mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
     return;
   }
 
+  CryptoBuffer rawSignatureBuf;
+  if (!rawSignatureBuf.Assign(signature)) {
+    mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
   nsTArray<WebAuthnExtensionResult> extensions;
 
-  if (appId != mCurrentAppId) {
+  if (appId != mTransaction.ref().mRpIdHash) {
     // Indicate to the RP that we used the FIDO appId.
     extensions.AppendElement(WebAuthnExtensionResultAppId(true));
   }
 
-  WebAuthnGetAssertionResult result(appId, keyHandle, signature, extensions);
+  CryptoBuffer signatureBuf;
+  CryptoBuffer counterBuf;
+  uint8_t flags = 0;
+  nsresult rv = U2FDecomposeSignResponse(rawSignatureBuf, flags, counterBuf,
+                                         signatureBuf);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  CryptoBuffer chosenAppIdBuf;
+  if (!chosenAppIdBuf.Assign(appId)) {
+    mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  // Preserve the two LSBs of the flags byte, UP and RFU1.
+  // See <https://github.com/fido-alliance/fido-2-specs/pull/519>
+  flags &= 0b11;
+
+  CryptoBuffer emptyAttestationData;
+  CryptoBuffer authenticatorData;
+  rv = AssembleAuthenticatorData(chosenAppIdBuf, flags, counterBuf,
+                                 emptyAttestationData, authenticatorData);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
+    return;
+  }
+
+  WebAuthnGetAssertionResult result(mTransaction.ref().mClientDataJSON,
+                                    keyHandle, signatureBuf, authenticatorData,
+                                    extensions, rawSignatureBuf);
   mSignPromise.Resolve(Move(result), __func__);
 }
 
 }
 }
--- a/dom/webauthn/U2FHIDTokenManager.h
+++ b/dom/webauthn/U2FHIDTokenManager.h
@@ -129,17 +129,18 @@ private:
 };
 
 class U2FHIDTokenManager final : public U2FTokenTransport
 {
 public:
   explicit U2FHIDTokenManager();
 
   RefPtr<U2FRegisterPromise>
-  Register(const WebAuthnMakeCredentialInfo& aInfo) override;
+  Register(const WebAuthnMakeCredentialInfo& aInfo,
+           bool aForceNoneAttestation) override;
 
   RefPtr<U2FSignPromise>
   Sign(const WebAuthnGetAssertionInfo& aInfo) override;
 
   void Cancel() override;
   void Drop() override;
 
   void HandleRegisterResult(UniquePtr<U2FResult>&& aResult);
@@ -148,19 +149,44 @@ public:
 private:
   ~U2FHIDTokenManager() { }
 
   void ClearPromises() {
     mRegisterPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
     mSignPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
+  class Transaction
+  {
+  public:
+    Transaction(uint64_t aId,
+                const nsTArray<uint8_t>& aRpIdHash,
+                const nsCString& aClientDataJSON,
+                bool aForceNoneAttestation = false)
+      : mId(aId)
+      , mRpIdHash(aRpIdHash)
+      , mClientDataJSON(aClientDataJSON)
+      , mForceNoneAttestation(aForceNoneAttestation)
+    { }
+
+    // The transaction ID.
+    uint64_t mId;
+
+    // The RP ID hash.
+    nsTArray<uint8_t> mRpIdHash;
+
+    // The clientData JSON.
+    nsCString mClientDataJSON;
+
+    // Whether we'll force "none" attestation.
+    bool mForceNoneAttestation;
+  };
+
   rust_u2f_manager* mU2FManager;
-  uint64_t mTransactionId;
-  nsTArray<uint8_t> mCurrentAppId;
+  Maybe<Transaction> mTransaction;
   MozPromiseHolder<U2FRegisterPromise> mRegisterPromise;
   MozPromiseHolder<U2FSignPromise> mSignPromise;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2FHIDTokenManager_h
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -578,39 +578,51 @@ U2FSoftTokenManager::IsRegistered(const 
 // 1      0x05
 // 65     public key
 // 1      key handle length
 // *      key handle
 // ASN.1  attestation certificate
 // *      attestation signature
 //
 RefPtr<U2FRegisterPromise>
-U2FSoftTokenManager::Register(const WebAuthnMakeCredentialInfo& aInfo)
+U2FSoftTokenManager::Register(const WebAuthnMakeCredentialInfo& aInfo,
+                              bool aForceNoneAttestation)
 {
   if (!mInitialized) {
     nsresult rv = Init();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return U2FRegisterPromise::CreateAndReject(rv, __func__);
     }
   }
 
-  const WebAuthnAuthenticatorSelection& sel = aInfo.AuthenticatorSelection();
+  if (aInfo.Extra().type() != WebAuthnMaybeMakeCredentialExtraInfo::Tnull_t) {
+    const auto& extra = aInfo.Extra().get_WebAuthnMakeCredentialExtraInfo();
+    const WebAuthnAuthenticatorSelection& sel = extra.AuthenticatorSelection();
 
-  // The U2F softtoken neither supports resident keys or
-  // user verification, nor is it a platform authenticator.
-  if (sel.requireResidentKey() ||
-      sel.requireUserVerification() ||
-      sel.requirePlatformAttachment()) {
-    return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
+    // The U2F softtoken neither supports resident keys or
+    // user verification, nor is it a platform authenticator.
+    if (sel.requireResidentKey() ||
+        sel.requireUserVerification() ||
+        sel.requirePlatformAttachment()) {
+      return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
+    }
+  }
+
+  CryptoBuffer rpIdHash, clientDataHash;
+  NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
+  nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(),
+                                       rpIdHash, clientDataHash);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
   // Optional exclusion list.
   for (const WebAuthnScopedCredential& cred: aInfo.ExcludeList()) {
     bool isRegistered = false;
-    nsresult rv = IsRegistered(cred.id(), aInfo.RpIdHash(), isRegistered);
+    nsresult rv = IsRegistered(cred.id(), rpIdHash, isRegistered);
     if (NS_FAILED(rv)) {
       return U2FRegisterPromise::CreateAndReject(rv, __func__);
     }
     if (isRegistered) {
       return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
     }
   }
 
@@ -618,17 +630,17 @@ U2FSoftTokenManager::Register(const WebA
   MOZ_ASSERT(mWrappingKey);
 
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   MOZ_ASSERT(slot.get());
 
   // Construct a one-time-use Attestation Certificate
   UniqueSECKEYPrivateKey attestPrivKey;
   UniqueCERTCertificate attestCert;
-  nsresult rv = GetAttestationCertificate(slot, attestPrivKey, attestCert);
+  rv = GetAttestationCertificate(slot, attestPrivKey, attestCert);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
   MOZ_ASSERT(attestCert);
   MOZ_ASSERT(attestPrivKey);
 
   // Generate a new keypair; the private will be wrapped into a Key Handle
   UniqueSECKEYPrivateKey privKey;
@@ -636,36 +648,36 @@ U2FSoftTokenManager::Register(const WebA
   rv = GenEcKeypair(slot, privKey, pubKey);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   // The key handle will be the result of keywrap(privKey, key=mWrappingKey)
   UniqueSECItem keyHandleItem =
     KeyHandleFromPrivateKey(slot, mWrappingKey,
-                            const_cast<uint8_t*>(aInfo.RpIdHash().Elements()),
-                            aInfo.RpIdHash().Length(), privKey);
+                            const_cast<uint8_t*>(rpIdHash.Elements()),
+                            rpIdHash.Length(), privKey);
   if (NS_WARN_IF(!keyHandleItem.get())) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   // Sign the challenge using the Attestation privkey (from attestCert)
   mozilla::dom::CryptoBuffer signedDataBuf;
-  if (NS_WARN_IF(!signedDataBuf.SetCapacity(1 + aInfo.RpIdHash().Length() +
-                                            aInfo.ClientDataHash().Length() +
+  if (NS_WARN_IF(!signedDataBuf.SetCapacity(1 + rpIdHash.Length() +
+                                            clientDataHash.Length() +
                                             keyHandleItem->len + kPublicKeyLen,
                                             mozilla::fallible))) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
   }
 
   // // It's OK to ignore the return values here because we're writing into
   // // pre-allocated space
   signedDataBuf.AppendElement(0x00, mozilla::fallible);
-  signedDataBuf.AppendElements(aInfo.RpIdHash(), mozilla::fallible);
-  signedDataBuf.AppendElements(aInfo.ClientDataHash(), mozilla::fallible);
+  signedDataBuf.AppendElements(rpIdHash, mozilla::fallible);
+  signedDataBuf.AppendElements(clientDataHash, mozilla::fallible);
   signedDataBuf.AppendSECItem(keyHandleItem.get());
   signedDataBuf.AppendSECItem(pubKey->u.ec.publicValue);
 
   ScopedAutoSECItem signatureItem;
   SECStatus srv = SEC_SignData(&signatureItem, signedDataBuf.Elements(),
                                signedDataBuf.Length(), attestPrivKey.get(),
                                SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
   if (NS_WARN_IF(srv != SECSuccess)) {
@@ -683,20 +695,46 @@ U2FSoftTokenManager::Register(const WebA
   }
   registrationBuf.AppendElement(0x05, mozilla::fallible);
   registrationBuf.AppendSECItem(pubKey->u.ec.publicValue);
   registrationBuf.AppendElement(keyHandleItem->len, mozilla::fallible);
   registrationBuf.AppendSECItem(keyHandleItem.get());
   registrationBuf.AppendSECItem(attestCert.get()->derCert);
   registrationBuf.AppendSECItem(signatureItem);
 
-  // Will be set by the U2FTokenManager.
-  bool directAttestationPermitted = false;
-  WebAuthnMakeCredentialResult result((nsTArray<uint8_t>(registrationBuf)),
-                                      directAttestationPermitted);
+  CryptoBuffer keyHandleBuf;
+  if (!keyHandleBuf.AppendSECItem(keyHandleItem.get())) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  CryptoBuffer attestCertBuf;
+  if (!attestCertBuf.AppendSECItem(attestCert.get()->derCert)) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  CryptoBuffer signatureBuf;
+  if (!signatureBuf.AppendSECItem(signatureItem)) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  CryptoBuffer pubKeyBuf;
+  if (!pubKeyBuf.AppendSECItem(pubKey->u.ec.publicValue)) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  CryptoBuffer attObj;
+  rv = AssembleAttestationObject(rpIdHash, pubKeyBuf, keyHandleBuf,
+                                 attestCertBuf, signatureBuf,
+                                 aForceNoneAttestation, attObj);
+  if (NS_FAILED(rv)) {
+    return U2FRegisterPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  WebAuthnMakeCredentialResult result(aInfo.ClientDataJSON(), attObj,
+                                      keyHandleBuf, registrationBuf);
   return U2FRegisterPromise::CreateAndResolve(Move(result), __func__);
 }
 
 bool
 U2FSoftTokenManager::FindRegisteredKeyHandle(const nsTArray<nsTArray<uint8_t>>& aAppIds,
                                              const nsTArray<WebAuthnScopedCredential>& aCredentials,
                                              /*out*/ nsTArray<uint8_t>& aKeyHandle,
                                              /*out*/ nsTArray<uint8_t>& aAppId)
@@ -737,49 +775,61 @@ U2FSoftTokenManager::Sign(const WebAuthn
 {
   if (!mInitialized) {
     nsresult rv = Init();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return U2FSignPromise::CreateAndReject(rv, __func__);
     }
   }
 
-  // The U2F softtoken doesn't support user verification.
-  if (aInfo.RequireUserVerification()) {
-    return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
+  CryptoBuffer rpIdHash, clientDataHash;
+  NS_ConvertUTF16toUTF8 rpId(aInfo.RpId());
+  nsresult rv = BuildTransactionHashes(rpId, aInfo.ClientDataJSON(),
+                                       rpIdHash, clientDataHash);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
   nsTArray<nsTArray<uint8_t>> appIds;
-  appIds.AppendElement(aInfo.RpIdHash());
+  appIds.AppendElement(rpIdHash);
+
+  if (aInfo.Extra().type() != WebAuthnMaybeGetAssertionExtraInfo::Tnull_t) {
+    const auto& extra = aInfo.Extra().get_WebAuthnGetAssertionExtraInfo();
 
-  // Process extensions.
-  for (const WebAuthnExtension& ext: aInfo.Extensions()) {
-    if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
-      appIds.AppendElement(ext.get_WebAuthnExtensionAppId().AppId());
+    // The U2F softtoken doesn't support user verification.
+    if (extra.RequireUserVerification()) {
+      return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
+    }
+
+    // Process extensions.
+    for (const WebAuthnExtension& ext: extra.Extensions()) {
+      if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
+        appIds.AppendElement(ext.get_WebAuthnExtensionAppId().AppId());
+      }
     }
   }
 
   nsTArray<uint8_t> chosenAppId;
   nsTArray<uint8_t> keyHandle;
 
   // Fail if we can't find a valid key handle.
   if (!FindRegisteredKeyHandle(appIds, aInfo.AllowList(), keyHandle, chosenAppId)) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
   }
 
   MOZ_ASSERT(mWrappingKey);
 
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   MOZ_ASSERT(slot.get());
 
-  if (NS_WARN_IF((aInfo.ClientDataHash().Length() != kParamLen) ||
+  if (NS_WARN_IF((clientDataHash.Length() != kParamLen) ||
                  (chosenAppId.Length() != kParamLen))) {
     MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
             ("Parameter lengths are wrong! challenge=%d app=%d expected=%d",
-             (uint32_t)aInfo.ClientDataHash().Length(),
+             (uint32_t)clientDataHash.Length(),
              (uint32_t)chosenAppId.Length(), kParamLen));
 
     return U2FSignPromise::CreateAndReject(NS_ERROR_ILLEGAL_VALUE, __func__);
   }
 
   // Decode the key handle
   UniqueSECKEYPrivateKey privKey =
     PrivateKeyFromKeyHandle(slot, mWrappingKey,
@@ -815,18 +865,18 @@ U2FSoftTokenManager::Sign(const WebAuthn
 
   // It's OK to ignore the return values here because we're writing into
   // pre-allocated space
   signedDataBuf.AppendElements(chosenAppId.Elements(),
                                chosenAppId.Length(),
                                mozilla::fallible);
   signedDataBuf.AppendElement(0x01, mozilla::fallible);
   signedDataBuf.AppendSECItem(counterItem);
-  signedDataBuf.AppendElements(aInfo.ClientDataHash().Elements(),
-                               aInfo.ClientDataHash().Length(),
+  signedDataBuf.AppendElements(clientDataHash.Elements(),
+                               clientDataHash.Length(),
                                mozilla::fallible);
 
   if (MOZ_LOG_TEST(gNSSTokenLog, LogLevel::Debug)) {
     nsAutoCString base64;
     nsresult rv = Base64URLEncode(signedDataBuf.Length(), signedDataBuf.Elements(),
                                   Base64URLEncodePaddingPolicy::Omit, base64);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return U2FSignPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
@@ -842,37 +892,61 @@ U2FSoftTokenManager::Sign(const WebAuthn
                                SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
   if (NS_WARN_IF(srv != SECSuccess)) {
     MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
             ("Signature failure: %d", PORT_GetError()));
     return U2FSignPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   // Assemble the signature data into a buffer for return
-  mozilla::dom::CryptoBuffer signatureBuf;
-  if (NS_WARN_IF(!signatureBuf.SetCapacity(1 + counterItem.len + signatureItem.len,
+  mozilla::dom::CryptoBuffer signatureDataBuf;
+  if (NS_WARN_IF(!signatureDataBuf.SetCapacity(1 + counterItem.len + signatureItem.len,
                                            mozilla::fallible))) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
   }
 
   // It's OK to ignore the return values here because we're writing into
   // pre-allocated space
-  signatureBuf.AppendElement(0x01, mozilla::fallible);
-  signatureBuf.AppendSECItem(counterItem);
-  signatureBuf.AppendSECItem(signatureItem);
+  signatureDataBuf.AppendElement(0x01, mozilla::fallible);
+  signatureDataBuf.AppendSECItem(counterItem);
+  signatureDataBuf.AppendSECItem(signatureItem);
 
-  nsTArray<uint8_t> signature(signatureBuf);
   nsTArray<WebAuthnExtensionResult> extensions;
 
-  if (chosenAppId != aInfo.RpIdHash()) {
+  if (chosenAppId != rpIdHash) {
     // Indicate to the RP that we used the FIDO appId.
     extensions.AppendElement(WebAuthnExtensionResultAppId(true));
   }
 
-  WebAuthnGetAssertionResult result(chosenAppId, keyHandle, signature, extensions);
+  CryptoBuffer counterBuf;
+  if (!counterBuf.AppendSECItem(counterItem)) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
+  }
+
+  CryptoBuffer signatureBuf;
+  if (!signatureBuf.AppendSECItem(signatureItem)) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
+  }
+
+  CryptoBuffer chosenAppIdBuf;
+  if (!chosenAppIdBuf.Assign(chosenAppId)) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
+  }
+
+  CryptoBuffer authenticatorData;
+  CryptoBuffer emptyAttestationData;
+  rv = AssembleAuthenticatorData(chosenAppIdBuf, 0x01, counterBuf,
+                                 emptyAttestationData, authenticatorData);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  WebAuthnGetAssertionResult result(aInfo.ClientDataJSON(), keyHandle,
+                                    signatureBuf, authenticatorData,
+                                    extensions, signatureDataBuf);
   return U2FSignPromise::CreateAndResolve(Move(result), __func__);
 }
 
 void
 U2FSoftTokenManager::Cancel()
 {
   // This implementation is sync, requests can't be aborted.
 }
--- a/dom/webauthn/U2FSoftTokenManager.h
+++ b/dom/webauthn/U2FSoftTokenManager.h
@@ -19,17 +19,18 @@ namespace mozilla {
 namespace dom {
 
 class U2FSoftTokenManager final : public U2FTokenTransport
 {
 public:
   explicit U2FSoftTokenManager(uint32_t aCounter);
 
   RefPtr<U2FRegisterPromise>
-  Register(const WebAuthnMakeCredentialInfo& aInfo) override;
+  Register(const WebAuthnMakeCredentialInfo& aInfo,
+           bool aForceNoneAttestation) override;
 
   RefPtr<U2FSignPromise>
   Sign(const WebAuthnGetAssertionInfo& aInfo) override;
 
   void Cancel() override;
 
 private:
   ~U2FSoftTokenManager() {}
--- a/dom/webauthn/U2FTokenManager.cpp
+++ b/dom/webauthn/U2FTokenManager.cpp
@@ -9,21 +9,17 @@
 #include "mozilla/dom/U2FHIDTokenManager.h"
 #include "mozilla/dom/U2FSoftTokenManager.h"
 #include "mozilla/dom/PWebAuthnTransactionParent.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/dom/WebAuthnUtil.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Unused.h"
-#include "hasht.h"
-#include "nsICryptoHash.h"
 #include "nsTextFormatter.h"
-#include "pkix/Input.h"
-#include "pkixutil.h"
 
 // Not named "security.webauth.u2f_softtoken_counter" because setting that
 // name causes the window.u2f object to disappear until preferences get
 // reloaded, as its pref is a substring!
 #define PREF_U2F_NSSTOKEN_COUNTER "security.webauth.softtoken_counter"
 #define PREF_WEBAUTHN_SOFTTOKEN_ENABLED "security.webauth.webauthn_enable_softtoken"
 #define PREF_WEBAUTHN_USBTOKEN_ENABLED "security.webauth.webauthn_enable_usbtoken"
 #define PREF_WEBAUTHN_ALLOW_DIRECT_ATTESTATION "security.webauth.webauthn_testing_allow_direct_attestation"
@@ -298,70 +294,66 @@ U2FTokenManager::Register(PWebAuthnTrans
   mTransactionParent = aTransactionParent;
   mTokenManagerImpl = GetTokenManagerImpl();
 
   if (!mTokenManagerImpl) {
     AbortTransaction(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
     return;
   }
 
-  // Check if all the supplied parameters are syntactically well-formed and
-  // of the correct length. If not, return an error code equivalent to
-  // UnknownError and terminate the operation.
+  mLastTransactionId = aTransactionId;
 
-  if ((aTransactionInfo.RpIdHash().Length() != SHA256_LENGTH) ||
-      (aTransactionInfo.ClientDataHash().Length() != SHA256_LENGTH)) {
-    AbortTransaction(aTransactionId, NS_ERROR_DOM_UNKNOWN_ERR);
+  // Determine whether direct attestation was requested.
+  bool directAttestationRequested = false;
+  if (aTransactionInfo.Extra().type() == WebAuthnMaybeMakeCredentialExtraInfo::TWebAuthnMakeCredentialExtraInfo) {
+    const auto& extra = aTransactionInfo.Extra().get_WebAuthnMakeCredentialExtraInfo();
+    directAttestationRequested = extra.RequestDirectAttestation();
+  }
+
+  // Start a register request immediately if direct attestation
+  // wasn't requested or the test pref is set.
+  if (!directAttestationRequested ||
+      U2FPrefManager::Get()->GetAllowDirectAttestationForTesting()) {
+    // Force "none" attestation when "direct" attestation wasn't requested.
+    DoRegister(aTransactionInfo, !directAttestationRequested);
     return;
   }
 
-  mLastTransactionId = aTransactionId;
-
   // If the RP request direct attestation, ask the user for permission and
   // store the transaction info until the user proceeds or cancels.
-  // Might be overriden by a pref for testing purposes.
-  if (aTransactionInfo.RequestDirectAttestation() &&
-      !U2FPrefManager::Get()->GetAllowDirectAttestationForTesting()) {
-    NS_ConvertUTF16toUTF8 origin(aTransactionInfo.Origin());
-    SendPromptNotification(kRegisterDirectPromptNotifcation,
-                           aTransactionId,
-                           origin.get());
+  NS_ConvertUTF16toUTF8 origin(aTransactionInfo.Origin());
+  SendPromptNotification(kRegisterDirectPromptNotifcation,
+                         aTransactionId,
+                         origin.get());
 
-    MOZ_ASSERT(mPendingRegisterInfo.isNothing());
-    mPendingRegisterInfo = Some(aTransactionInfo);
-  } else {
-    DoRegister(aTransactionInfo);
-  }
+  MOZ_ASSERT(mPendingRegisterInfo.isNothing());
+  mPendingRegisterInfo = Some(aTransactionInfo);
 }
 
 void
-U2FTokenManager::DoRegister(const WebAuthnMakeCredentialInfo& aInfo)
+U2FTokenManager::DoRegister(const WebAuthnMakeCredentialInfo& aInfo,
+                            bool aForceNoneAttestation)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
   MOZ_ASSERT(mLastTransactionId > 0);
 
   // Show a prompt that lets the user cancel the ongoing transaction.
   NS_ConvertUTF16toUTF8 origin(aInfo.Origin());
   SendPromptNotification(kRegisterPromptNotifcation,
                          mLastTransactionId,
                          origin.get());
 
   uint64_t tid = mLastTransactionId;
   mozilla::TimeStamp startTime = mozilla::TimeStamp::Now();
-  bool requestDirectAttestation = aInfo.RequestDirectAttestation();
 
   mTokenManagerImpl
-    ->Register(aInfo)
+    ->Register(aInfo, aForceNoneAttestation)
     ->Then(GetCurrentThreadSerialEventTarget(), __func__,
-          [tid, startTime, requestDirectAttestation](WebAuthnMakeCredentialResult&& aResult) {
+          [tid, startTime](WebAuthnMakeCredentialResult&& aResult) {
             U2FTokenManager* mgr = U2FTokenManager::Get();
-            // The token manager implementations set DirectAttestationPermitted
-            // to false by default. Override this here with information from
-            // the JS prompt.
-            aResult.DirectAttestationPermitted() = requestDirectAttestation;
             mgr->MaybeConfirmRegister(tid, aResult);
             Telemetry::ScalarAdd(
               Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
               NS_LITERAL_STRING("U2FRegisterFinish"), 1);
             Telemetry::AccumulateTimeDelta(
               Telemetry::WEBAUTHN_CREATE_CREDENTIAL_MS,
               startTime);
           },
@@ -407,22 +399,16 @@ U2FTokenManager::Sign(PWebAuthnTransacti
   mTransactionParent = aTransactionParent;
   mTokenManagerImpl = GetTokenManagerImpl();
 
   if (!mTokenManagerImpl) {
     AbortTransaction(aTransactionId, NS_ERROR_DOM_NOT_ALLOWED_ERR);
     return;
   }
 
-  if ((aTransactionInfo.RpIdHash().Length() != SHA256_LENGTH) ||
-      (aTransactionInfo.ClientDataHash().Length() != SHA256_LENGTH)) {
-    AbortTransaction(aTransactionId, NS_ERROR_DOM_UNKNOWN_ERR);
-    return;
-  }
-
   // Show a prompt that lets the user cancel the ongoing transaction.
   NS_ConvertUTF16toUTF8 origin(aTransactionInfo.Origin());
   SendPromptNotification(kSignPromptNotifcation,
                          aTransactionId,
                          origin.get());
 
   uint64_t tid = mLastTransactionId = aTransactionId;
   mozilla::TimeStamp startTime = mozilla::TimeStamp::Now();
@@ -482,53 +468,49 @@ U2FTokenManager::Cancel(PWebAuthnTransac
   mTokenManagerImpl->Cancel();
   ClearTransaction();
 }
 
 // nsIU2FTokenManager
 
 NS_IMETHODIMP
 U2FTokenManager::ResumeRegister(uint64_t aTransactionId,
-                                bool aPermitDirectAttestation)
+                                bool aForceNoneAttestation)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gBackgroundThread) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIRunnable> r(NewRunnableMethod<uint64_t, bool>(
       "U2FTokenManager::RunResumeRegister", this,
       &U2FTokenManager::RunResumeRegister, aTransactionId,
-      aPermitDirectAttestation));
+      aForceNoneAttestation));
 
   return gBackgroundThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 U2FTokenManager::RunResumeRegister(uint64_t aTransactionId,
-                                   bool aPermitDirectAttestation)
+                                   bool aForceNoneAttestation)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
 
   if (NS_WARN_IF(mPendingRegisterInfo.isNothing())) {
     return;
   }
 
   if (mLastTransactionId != aTransactionId) {
     return;
   }
 
-  // Forward whether the user opted into direct attestation.
-  mPendingRegisterInfo.ref().RequestDirectAttestation() =
-    aPermitDirectAttestation;
-
   // Resume registration and cleanup.
-  DoRegister(mPendingRegisterInfo.ref());
+  DoRegister(mPendingRegisterInfo.ref(), aForceNoneAttestation);
   mPendingRegisterInfo.reset();
 }
 
 NS_IMETHODIMP
 U2FTokenManager::Cancel(uint64_t aTransactionId)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/webauthn/U2FTokenManager.h
+++ b/dom/webauthn/U2FTokenManager.h
@@ -46,25 +46,26 @@ public:
   static void Initialize();
 private:
   U2FTokenManager();
   ~U2FTokenManager() { }
   RefPtr<U2FTokenTransport> GetTokenManagerImpl();
   void AbortTransaction(const uint64_t& aTransactionId, const nsresult& aError);
   void ClearTransaction();
   // Step two of "Register", kicking off the actual transaction.
-  void DoRegister(const WebAuthnMakeCredentialInfo& aInfo);
+  void DoRegister(const WebAuthnMakeCredentialInfo& aInfo,
+                  bool aForceNoneAttestation);
   void MaybeConfirmRegister(const uint64_t& aTransactionId,
                             const WebAuthnMakeCredentialResult& aResult);
   void MaybeAbortRegister(const uint64_t& aTransactionId, const nsresult& aError);
   void MaybeConfirmSign(const uint64_t& aTransactionId,
                         const WebAuthnGetAssertionResult& aResult);
   void MaybeAbortSign(const uint64_t& aTransactionId, const nsresult& aError);
   // The main thread runnable function for "nsIU2FTokenManager.ResumeRegister".
-  void RunResumeRegister(uint64_t aTransactionId, bool aPermitDirectAttestation);
+  void RunResumeRegister(uint64_t aTransactionId, bool aForceNoneAttestation);
   // The main thread runnable function for "nsIU2FTokenManager.Cancel".
   void RunCancel(uint64_t aTransactionId);
   // Sends a "webauthn-prompt" observer notification with the given data.
   template<typename ...T>
   void SendPromptNotification(const char16_t* aFormat, T... aArgs);
   // The main thread runnable function for "SendPromptNotification".
   void RunSendPromptNotification(nsString aJSON);
   // Using a raw pointer here, as the lifetime of the IPC object is managed by
--- a/dom/webauthn/U2FTokenTransport.h
+++ b/dom/webauthn/U2FTokenTransport.h
@@ -23,17 +23,18 @@ typedef MozPromise<WebAuthnGetAssertionR
 
 class U2FTokenTransport
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(U2FTokenTransport);
   U2FTokenTransport() {}
 
   virtual RefPtr<U2FRegisterPromise>
-  Register(const WebAuthnMakeCredentialInfo& aInfo) = 0;
+  Register(const WebAuthnMakeCredentialInfo& aInfo,
+           bool aForceNoneAttestation) = 0;
 
   virtual RefPtr<U2FSignPromise>
   Sign(const WebAuthnGetAssertionInfo& aInfo) = 0;
 
   virtual void Cancel() = 0;
 
   virtual void Drop() { }
 
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -1,46 +1,33 @@
 /* -*- 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 "hasht.h"
 #include "nsHTMLDocument.h"
-#include "nsICryptoHash.h"
-#include "nsNetCID.h"
 #include "nsThreadUtils.h"
 #include "WebAuthnCoseIdentifiers.h"
 #include "mozilla/dom/AuthenticatorAttestationResponse.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PWebAuthnTransaction.h"
-#include "mozilla/dom/U2FUtil.h"
-#include "mozilla/dom/WebAuthnCBORUtil.h"
 #include "mozilla/dom/WebAuthnManager.h"
 #include "mozilla/dom/WebAuthnTransactionChild.h"
 #include "mozilla/dom/WebAuthnUtil.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
 /***********************************************************************
- * Protocol Constants
- **********************************************************************/
-
-const uint8_t FLAG_TUP = 0x01; // Test of User Presence required
-const uint8_t FLAG_AT = 0x40; // Authenticator Data is provided
-const uint8_t FLAG_UV = 0x04; // User was Verified (biometrics, etc.); this
-                              // flag is not possible with U2F devices
-
-/***********************************************************************
  * Statics
  **********************************************************************/
 
 namespace {
 static mozilla::LazyLogModule gWebAuthnManagerLog("webauthnmanager");
 }
 
 NS_IMPL_ISUPPORTS(WebAuthnManager, nsIDOMEventListener);
@@ -266,37 +253,16 @@ WebAuthnManager::MakeCredential(const Pu
   }
 
   // <https://w3c.github.io/webauthn/#sctn-appid-extension>
   if (aOptions.mExtensions.mAppid.WasPassed()) {
     promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return promise.forget();
   }
 
-  CryptoBuffer rpIdHash;
-  if (!rpIdHash.SetLength(SHA256_LENGTH, fallible)) {
-    promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
-    return promise.forget();
-  }
-
-  nsresult srv;
-  nsCOMPtr<nsICryptoHash> hashService =
-    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  srv = HashCString(hashService, rpId, rpIdHash);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-
   // TODO: Move this logic into U2FTokenManager in Bug 1409220.
 
   // Process each element of mPubKeyCredParams using the following steps, to
   // produce a new sequence acceptableParams.
   nsTArray<PublicKeyCredentialParameters> acceptableParams;
   for (size_t a = 0; a < aOptions.mPubKeyCredParams.Length(); ++a) {
     // Let current be the currently selected element of
     // mPubKeyCredParams.
@@ -346,31 +312,19 @@ WebAuthnManager::MakeCredential(const Pu
 
   CryptoBuffer challenge;
   if (!challenge.Assign(aOptions.mChallenge)) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
   nsAutoCString clientDataJSON;
-  srv = AssembleClientData(origin, challenge,
-                           NS_LITERAL_STRING("webauthn.create"),
-                           aOptions.mExtensions, clientDataJSON);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  CryptoBuffer clientDataHash;
-  if (!clientDataHash.SetLength(SHA256_LENGTH, fallible)) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  srv = HashCString(hashService, clientDataJSON, clientDataHash);
+  nsresult srv = AssembleClientData(origin, challenge,
+                                    NS_LITERAL_STRING("webauthn.create"),
+                                    aOptions.mExtensions, clientDataJSON);
   if (NS_WARN_IF(NS_FAILED(srv))) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
   nsTArray<WebAuthnScopedCredential> excludeList;
   for (const auto& s: aOptions.mExcludeCredentials) {
     WebAuthnScopedCredential c;
@@ -405,39 +359,38 @@ WebAuthnManager::MakeCredential(const Pu
   bool requestDirectAttestation =
     attestation == AttestationConveyancePreference::Direct;
 
   // Create and forward authenticator selection criteria.
   WebAuthnAuthenticatorSelection authSelection(selection.mRequireResidentKey,
                                                requireUserVerification,
                                                requirePlatformAttachment);
 
+  WebAuthnMakeCredentialExtraInfo extra(extensions,
+                                        authSelection,
+                                        requestDirectAttestation);
+
   WebAuthnMakeCredentialInfo info(origin,
-                                  rpIdHash,
-                                  clientDataHash,
+                                  NS_ConvertUTF8toUTF16(rpId),
+                                  challenge,
+                                  clientDataJSON,
                                   adjustedTimeout,
                                   excludeList,
-                                  extensions,
-                                  authSelection,
-                                  requestDirectAttestation);
+                                  extra);
 
   ListenForVisibilityEvents();
 
   AbortSignal* signal = nullptr;
   if (aSignal.WasPassed()) {
     signal = &aSignal.Value();
     Follow(signal);
   }
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(WebAuthnTransaction(promise,
-                                          rpIdHash,
-                                          clientDataJSON,
-                                          signal));
-
+  mTransaction = Some(WebAuthnTransaction(promise, signal));
   mChild->SendRequestRegister(mTransaction.ref().mId, info);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 WebAuthnManager::GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
                               const Optional<OwningNonNull<AbortSignal>>& aSignal)
@@ -497,55 +450,30 @@ WebAuthnManager::GetAssertion(const Publ
   }
 
   CryptoBuffer rpIdHash;
   if (!rpIdHash.SetLength(SHA256_LENGTH, fallible)) {
     promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
     return promise.forget();
   }
 
-  nsresult srv;
-  nsCOMPtr<nsICryptoHash> hashService =
-    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  srv = HashCString(hashService, rpId, rpIdHash);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
   // Use assertionChallenge, callerOrigin and rpId, along with the token binding
   // key associated with callerOrigin (if any), to create a ClientData structure
   // representing this request. Choose a hash algorithm for hashAlg and compute
   // the clientDataJSON and clientDataHash.
   CryptoBuffer challenge;
   if (!challenge.Assign(aOptions.mChallenge)) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
   nsAutoCString clientDataJSON;
-  srv = AssembleClientData(origin, challenge, NS_LITERAL_STRING("webauthn.get"),
-                           aOptions.mExtensions, clientDataJSON);
-  if (NS_WARN_IF(NS_FAILED(srv))) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  CryptoBuffer clientDataHash;
-  if (!clientDataHash.SetLength(SHA256_LENGTH, fallible)) {
-    promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
-    return promise.forget();
-  }
-
-  srv = HashCString(hashService, clientDataJSON, clientDataHash);
+  nsresult srv = AssembleClientData(origin, challenge,
+                                    NS_LITERAL_STRING("webauthn.get"),
+                                    aOptions.mExtensions, clientDataJSON);
   if (NS_WARN_IF(NS_FAILED(srv))) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
   nsTArray<WebAuthnScopedCredential> allowList;
   for (const auto& s: aOptions.mAllowCredentials) {
     if (s.mType == PublicKeyCredentialType::Public_key) {
@@ -603,49 +531,48 @@ WebAuthnManager::GetAssertion(const Publ
 
     CryptoBuffer appIdHash;
     if (!appIdHash.SetLength(SHA256_LENGTH, fallible)) {
       promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
       return promise.forget();
     }
 
     // We need the SHA-256 hash of the appId.
-    nsresult srv = HashCString(hashService, NS_ConvertUTF16toUTF8(appId), appIdHash);
+    srv = HashCString(NS_ConvertUTF16toUTF8(appId), appIdHash);
     if (NS_WARN_IF(NS_FAILED(srv))) {
       promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
       return promise.forget();
     }
 
     // Append the hash and send it to the backend.
     extensions.AppendElement(WebAuthnExtensionAppId(appIdHash));
   }
 
+  WebAuthnGetAssertionExtraInfo extra(extensions, requireUserVerification);
+
   WebAuthnGetAssertionInfo info(origin,
-                                rpIdHash,
-                                clientDataHash,
+                                NS_ConvertUTF8toUTF16(rpId),
+                                challenge,
+                                clientDataJSON,
                                 adjustedTimeout,
                                 allowList,
-                                requireUserVerification,
-                                extensions);
+                                extra);
 
   ListenForVisibilityEvents();
 
   AbortSignal* signal = nullptr;
   if (aSignal.WasPassed()) {
     signal = &aSignal.Value();
     Follow(signal);
   }
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(WebAuthnTransaction(promise,
-                                          rpIdHash,
-                                          clientDataJSON,
-                                          signal));
+  mTransaction = Some(WebAuthnTransaction(promise, signal));
+  mChild->SendRequestSign(mTransaction.ref().mId, info);
 
-  mChild->SendRequestSign(mTransaction.ref().mId, info);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 WebAuthnManager::Store(const Credential& aCredential)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -671,130 +598,48 @@ WebAuthnManager::FinishMakeCredential(co
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Check for a valid transaction.
   if (mTransaction.isNothing() || mTransaction.ref().mId != aTransactionId) {
     return;
   }
 
-  CryptoBuffer regData;
-  if (NS_WARN_IF(!regData.Assign(aResult.RegBuffer().Elements(),
-                                 aResult.RegBuffer().Length()))) {
-    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  mozilla::dom::CryptoBuffer aaguidBuf;
-  if (NS_WARN_IF(!aaguidBuf.SetCapacity(16, mozilla::fallible))) {
-    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-  // FIDO U2F devices have no AAGUIDs, so they'll be all zeros until we add
-  // support for CTAP2 devices.
-  for (int i=0; i<16; i++) {
-    aaguidBuf.AppendElement(0x00, mozilla::fallible);
-  }
-
-  // Decompose the U2F registration packet
-  CryptoBuffer pubKeyBuf;
-  CryptoBuffer keyHandleBuf;
-  CryptoBuffer attestationCertBuf;
-  CryptoBuffer signatureBuf;
-
-  // Only handles attestation cert chains of length=1.
-  nsresult rv = U2FDecomposeRegistrationResponse(regData, pubKeyBuf, keyHandleBuf,
-                                                 attestationCertBuf, signatureBuf);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    RejectTransaction(rv);
-    return;
-  }
-  MOZ_ASSERT(keyHandleBuf.Length() <= 0xFFFF);
-
-  nsAutoString keyHandleBase64Url;
-  rv = keyHandleBuf.ToJwkBase64(keyHandleBase64Url);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    RejectTransaction(rv);
-    return;
-  }
-
   CryptoBuffer clientDataBuf;
-  if (!clientDataBuf.Assign(mTransaction.ref().mClientData)) {
-    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  CryptoBuffer rpIdHashBuf;
-  if (!rpIdHashBuf.Assign(mTransaction.ref().mRpIdHash)) {
+  if (NS_WARN_IF(!clientDataBuf.Assign(aResult.ClientDataJSON()))) {
     RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  // Construct the public key object
-  CryptoBuffer pubKeyObj;
-  rv = CBOREncodePublicKeyObj(pubKeyBuf, pubKeyObj);
-  if (NS_FAILED(rv)) {
-    RejectTransaction(rv);
-    return;
-  }
-
-  // During create credential, counter is always 0 for U2F
-  // See https://github.com/w3c/webauthn/issues/507
-  mozilla::dom::CryptoBuffer counterBuf;
-  if (NS_WARN_IF(!counterBuf.SetCapacity(4, mozilla::fallible))) {
+  CryptoBuffer attObjBuf;
+  if (NS_WARN_IF(!attObjBuf.Assign(aResult.AttestationObject()))) {
     RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  counterBuf.AppendElement(0x00, mozilla::fallible);
-  counterBuf.AppendElement(0x00, mozilla::fallible);
-  counterBuf.AppendElement(0x00, mozilla::fallible);
-  counterBuf.AppendElement(0x00, mozilla::fallible);
 
-  // Construct the Attestation Data, which slots into the end of the
-  // Authentication Data buffer.
-  CryptoBuffer attDataBuf;
-  rv = AssembleAttestationData(aaguidBuf, keyHandleBuf, pubKeyObj, attDataBuf);
-  if (NS_FAILED(rv)) {
-    RejectTransaction(rv);
+  CryptoBuffer keyHandleBuf;
+  if (NS_WARN_IF(!keyHandleBuf.Assign(aResult.KeyHandle()))) {
+    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  mozilla::dom::CryptoBuffer authDataBuf;
-  // attDataBuf always contains data, so per [1] we have to set the AT flag.
-  // [1] https://w3c.github.io/webauthn/#sec-authenticator-data
-  const uint8_t flags = FLAG_TUP | FLAG_AT;
-  rv = AssembleAuthenticatorData(rpIdHashBuf, flags, counterBuf, attDataBuf,
-                                 authDataBuf);
-  if (NS_FAILED(rv)) {
-    RejectTransaction(rv);
-    return;
-  }
-
-  // Direct attestation might have been requested by the RP. This will
-  // be true only if the user consented via the permission UI.
-  CryptoBuffer attObj;
-  if (aResult.DirectAttestationPermitted()) {
-    rv = CBOREncodeFidoU2FAttestationObj(authDataBuf, attestationCertBuf,
-                                         signatureBuf, attObj);
-  } else {
-    rv = CBOREncodeNoneAttestationObj(authDataBuf, attObj);
-  }
-
-  if (NS_FAILED(rv)) {
+  nsAutoString keyHandleBase64Url;
+  nsresult rv = keyHandleBuf.ToJwkBase64(keyHandleBase64Url);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     RejectTransaction(rv);
     return;
   }
 
   // Create a new PublicKeyCredential object and populate its fields with the
   // values returned from the authenticator as well as the clientDataJSON
   // computed earlier.
   RefPtr<AuthenticatorAttestationResponse> attestation =
       new AuthenticatorAttestationResponse(mParent);
   attestation->SetClientDataJSON(clientDataBuf);
-  attestation->SetAttestationObject(attObj);
+  attestation->SetAttestationObject(attObjBuf);
 
   RefPtr<PublicKeyCredential> credential =
       new PublicKeyCredential(mParent);
   credential->SetId(keyHandleBase64Url);
   credential->SetType(NS_LITERAL_STRING("public-key"));
   credential->SetRawId(keyHandleBuf);
   credential->SetResponse(attestation);
 
@@ -808,67 +653,42 @@ WebAuthnManager::FinishGetAssertion(cons
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Check for a valid transaction.
   if (mTransaction.isNothing() || mTransaction.ref().mId != aTransactionId) {
     return;
   }
 
-  CryptoBuffer tokenSignatureData;
-  if (NS_WARN_IF(!tokenSignatureData.Assign(aResult.SigBuffer().Elements(),
-                                            aResult.SigBuffer().Length()))) {
+  CryptoBuffer clientDataBuf;
+  if (!clientDataBuf.Assign(aResult.ClientDataJSON())) {
     RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  CryptoBuffer clientDataBuf;
-  if (!clientDataBuf.Assign(mTransaction.ref().mClientData)) {
-    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
-    return;
-  }
-
-  CryptoBuffer rpIdHashBuf;
-  if (!rpIdHashBuf.Assign(aResult.RpIdHash())) {
+  CryptoBuffer credentialBuf;
+  if (!credentialBuf.Assign(aResult.KeyHandle())) {
     RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   CryptoBuffer signatureBuf;
-  CryptoBuffer counterBuf;
-  uint8_t flags = 0;
-  nsresult rv = U2FDecomposeSignResponse(tokenSignatureData, flags, counterBuf,
-                                         signatureBuf);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    RejectTransaction(rv);
+  if (!signatureBuf.Assign(aResult.Signature())) {
+    RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  // Preserve the two LSBs of the flags byte, UP and RFU1.
-  // See <https://github.com/fido-alliance/fido-2-specs/pull/519>
-  flags &= 0b11;
-
-  CryptoBuffer attestationDataBuf;
   CryptoBuffer authenticatorDataBuf;
-  rv = AssembleAuthenticatorData(rpIdHashBuf, flags, counterBuf,
-                                 /* deliberately empty */ attestationDataBuf,
-                                 authenticatorDataBuf);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    RejectTransaction(rv);
-    return;
-  }
-
-  CryptoBuffer credentialBuf;
-  if (!credentialBuf.Assign(aResult.CredentialID())) {
+  if (!authenticatorDataBuf.Assign(aResult.AuthenticatorData())) {
     RejectTransaction(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   nsAutoString credentialBase64Url;
-  rv = credentialBuf.ToJwkBase64(credentialBase64Url);
+  nsresult rv = credentialBuf.ToJwkBase64(credentialBase64Url);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     RejectTransaction(rv);
     return;
   }
 
   // If any authenticator returns success:
 
   // Create a new PublicKeyCredential object named value and populate its fields
--- a/dom/webauthn/WebAuthnManager.h
+++ b/dom/webauthn/WebAuthnManager.h
@@ -43,37 +43,27 @@
 
 namespace mozilla {
 namespace dom {
 
 class WebAuthnTransaction
 {
 public:
   WebAuthnTransaction(const RefPtr<Promise>& aPromise,
-                      const nsTArray<uint8_t>& aRpIdHash,
-                      const nsCString& aClientData,
                       AbortSignal* aSignal)
     : mPromise(aPromise)
-    , mRpIdHash(aRpIdHash)
-    , mClientData(aClientData)
     , mSignal(aSignal)
     , mId(NextId())
   {
     MOZ_ASSERT(mId > 0);
   }
 
   // JS Promise representing the transaction status.
   RefPtr<Promise> mPromise;
 
-  // The RP ID hash.
-  nsTArray<uint8_t> mRpIdHash;
-
-  // Client data used to assemble reply objects.
-  nsCString mClientData;
-
   // An optional AbortSignal instance.
   RefPtr<AbortSignal> mSignal;
 
   // Unique transaction id.
   uint64_t mId;
 
 private:
   // Generates a unique id for new transactions. This doesn't have to be unique
--- a/dom/webauthn/WebAuthnUtil.cpp
+++ b/dom/webauthn/WebAuthnUtil.cpp
@@ -13,16 +13,19 @@ namespace mozilla {
 namespace dom {
 
 // Bug #1436078 - Permit Google Accounts. Remove in Bug #1436085 in Jan 2023.
 NS_NAMED_LITERAL_STRING(kGoogleAccountsAppId1,
   "https://www.gstatic.com/securitykey/origins.json");
 NS_NAMED_LITERAL_STRING(kGoogleAccountsAppId2,
   "https://www.gstatic.com/securitykey/a/google.com/origins.json");
 
+const uint8_t FLAG_TUP = 0x01; // Test of User Presence required
+const uint8_t FLAG_AT = 0x40; // Authenticator Data is provided
+
 bool
 EvaluateAppID(nsPIDOMWindowInner* aParent, const nsString& aOrigin,
               const U2FOperation& aOp, /* in/out */ nsString& aAppId)
 {
   // Facet is the specification's way of referring to the web origin.
   nsAutoCString facetString = NS_ConvertUTF16toUTF8(aOrigin);
   nsCOMPtr<nsIURI> facetUri;
   if (NS_FAILED(NS_NewURI(getter_AddRefs(facetUri), facetString))) {
@@ -189,16 +192,84 @@ AssembleAttestationData(const CryptoBuff
   attestationDataBuf.AppendElement((keyHandleBuf.Length() >> 0) & 0xFF,
                                    mozilla::fallible);
   attestationDataBuf.AppendElements(keyHandleBuf, mozilla::fallible);
   attestationDataBuf.AppendElements(pubKeyObj, mozilla::fallible);
   return NS_OK;
 }
 
 nsresult
+AssembleAttestationObject(const CryptoBuffer& aRpIdHash,
+                          const CryptoBuffer& aPubKeyBuf,
+                          const CryptoBuffer& aKeyHandleBuf,
+                          const CryptoBuffer& aAttestationCertBuf,
+                          const CryptoBuffer& aSignatureBuf,
+                          bool aForceNoneAttestation,
+                          /* out */ CryptoBuffer& aAttestationObjBuf)
+{
+  // Construct the public key object
+  CryptoBuffer pubKeyObj;
+  nsresult rv = CBOREncodePublicKeyObj(aPubKeyBuf, pubKeyObj);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  mozilla::dom::CryptoBuffer aaguidBuf;
+  if (NS_WARN_IF(!aaguidBuf.SetCapacity(16, mozilla::fallible))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  // FIDO U2F devices have no AAGUIDs, so they'll be all zeros until we add
+  // support for CTAP2 devices.
+  for (int i=0; i<16; i++) {
+    aaguidBuf.AppendElement(0x00, mozilla::fallible);
+  }
+
+  // During create credential, counter is always 0 for U2F
+  // See https://github.com/w3c/webauthn/issues/507
+  mozilla::dom::CryptoBuffer counterBuf;
+  if (NS_WARN_IF(!counterBuf.SetCapacity(4, mozilla::fallible))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  counterBuf.AppendElement(0x00, mozilla::fallible);
+  counterBuf.AppendElement(0x00, mozilla::fallible);
+  counterBuf.AppendElement(0x00, mozilla::fallible);
+  counterBuf.AppendElement(0x00, mozilla::fallible);
+
+  // Construct the Attestation Data, which slots into the end of the
+  // Authentication Data buffer.
+  CryptoBuffer attDataBuf;
+  rv = AssembleAttestationData(aaguidBuf, aKeyHandleBuf, pubKeyObj, attDataBuf);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  CryptoBuffer authDataBuf;
+  // attDataBuf always contains data, so per [1] we have to set the AT flag.
+  // [1] https://w3c.github.io/webauthn/#sec-authenticator-data
+  const uint8_t flags = FLAG_TUP | FLAG_AT;
+  rv = AssembleAuthenticatorData(aRpIdHash, flags, counterBuf, attDataBuf,
+                                 authDataBuf);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Direct attestation might have been requested by the RP.
+  // The user might override this and request anonymization anyway.
+  if (aForceNoneAttestation) {
+    rv = CBOREncodeNoneAttestationObj(authDataBuf, aAttestationObjBuf);
+  } else {
+    rv = CBOREncodeFidoU2FAttestationObj(authDataBuf, aAttestationCertBuf,
+                                         aSignatureBuf, aAttestationObjBuf);
+  }
+
+  return rv;
+}
+
+nsresult
 U2FDecomposeSignResponse(const CryptoBuffer& aResponse,
                          /* out */ uint8_t& aFlags,
                          /* out */ CryptoBuffer& aCounterBuf,
                          /* out */ CryptoBuffer& aSignatureBuf)
 {
   if (aResponse.Length() < 5) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -318,10 +389,94 @@ U2FDecomposeECKey(const CryptoBuffer& aP
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   MOZ_ASSERT(input.AtEnd());
   return NS_OK;
 }
 
+static nsresult
+HashCString(nsICryptoHash* aHashService,
+            const nsACString& aIn,
+            /* out */ CryptoBuffer& aOut)
+{
+  MOZ_ASSERT(aHashService);
+
+  nsresult rv = aHashService->Init(nsICryptoHash::SHA256);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = aHashService->Update(
+    reinterpret_cast<const uint8_t*>(aIn.BeginReading()), aIn.Length());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsAutoCString fullHash;
+  // Passing false below means we will get a binary result rather than a
+  // base64-encoded string.
+  rv = aHashService->Finish(false, fullHash);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (NS_WARN_IF(!aOut.Assign(fullHash))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+HashCString(const nsACString& aIn, /* out */ CryptoBuffer& aOut)
+{
+  nsresult srv;
+  nsCOMPtr<nsICryptoHash> hashService =
+    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv);
+  if (NS_FAILED(srv)) {
+    return srv;
+  }
+
+  srv = HashCString(hashService, aIn, aOut);
+  if (NS_WARN_IF(NS_FAILED(srv))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+BuildTransactionHashes(const nsCString& aRpId,
+                       const nsCString& aClientDataJSON,
+                       /* out */ CryptoBuffer& aRpIdHash,
+                       /* out */ CryptoBuffer& aClientDataHash)
+{
+  nsresult srv;
+  nsCOMPtr<nsICryptoHash> hashService =
+    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv);
+  if (NS_FAILED(srv)) {
+    return srv;
+  }
+
+  if (!aRpIdHash.SetLength(SHA256_LENGTH, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  srv = HashCString(hashService, aRpId, aRpIdHash);
+  if (NS_WARN_IF(NS_FAILED(srv))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!aClientDataHash.SetLength(SHA256_LENGTH, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  srv = HashCString(hashService, aClientDataJSON, aClientDataHash);
+  if (NS_WARN_IF(NS_FAILED(srv))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+
 }
 }
--- a/dom/webauthn/WebAuthnUtil.h
+++ b/dom/webauthn/WebAuthnUtil.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_dom_WebAuthnUtil_h
 #define mozilla_dom_WebAuthnUtil_h
 
 /*
  * Utility functions used by both WebAuthnManager and U2FTokenManager.
  */
 
 #include "mozilla/dom/CryptoBuffer.h"
-#include "pkix/Input.h"
 
 namespace mozilla {
 namespace dom {
 
 enum class U2FOperation
 {
   Register,
   Sign
@@ -30,39 +29,47 @@ EvaluateAppID(nsPIDOMWindowInner* aParen
 nsresult
 AssembleAuthenticatorData(const CryptoBuffer& rpIdHashBuf,
                           const uint8_t flags,
                           const CryptoBuffer& counterBuf,
                           const CryptoBuffer& attestationDataBuf,
                           /* out */ CryptoBuffer& authDataBuf);
 
 nsresult
-AssembleAttestationData(const CryptoBuffer& aaguidBuf,
-                        const CryptoBuffer& keyHandleBuf,
-                        const CryptoBuffer& pubKeyObj,
-                        /* out */ CryptoBuffer& attestationDataBuf);
+AssembleAttestationObject(const CryptoBuffer& aRpIdHash,
+                          const CryptoBuffer& aPubKeyBuf,
+                          const CryptoBuffer& aKeyHandleBuf,
+                          const CryptoBuffer& aAttestationCertBuf,
+                          const CryptoBuffer& aSignatureBuf,
+                          bool aForceNoneAttestation,
+                          /* out */ CryptoBuffer& aAttestationObjBuf);
 
 nsresult
 U2FDecomposeSignResponse(const CryptoBuffer& aResponse,
                          /* out */ uint8_t& aFlags,
                          /* out */ CryptoBuffer& aCounterBuf,
                          /* out */ CryptoBuffer& aSignatureBuf);
 
 nsresult
 U2FDecomposeRegistrationResponse(const CryptoBuffer& aResponse,
                                  /* out */ CryptoBuffer& aPubKeyBuf,
                                  /* out */ CryptoBuffer& aKeyHandleBuf,
                                  /* out */ CryptoBuffer& aAttestationCertBuf,
                                  /* out */ CryptoBuffer& aSignatureBuf);
 
 nsresult
-ReadToCryptoBuffer(pkix::Reader& aSrc, /* out */ CryptoBuffer& aDest,
-                   uint32_t aLen);
-
-nsresult
 U2FDecomposeECKey(const CryptoBuffer& aPubKeyBuf,
                   /* out */ CryptoBuffer& aXcoord,
                   /* out */ CryptoBuffer& aYcoord);
 
+nsresult
+HashCString(const nsACString& aIn, /* out */ CryptoBuffer& aOut);
+
+nsresult
+BuildTransactionHashes(const nsCString& aRpId,
+                       const nsCString& aClientDataJSON,
+                       /* out */ CryptoBuffer& aRpIdHash,
+                       /* out */ CryptoBuffer& aClientDataHash);
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_WebAuthnUtil_h
--- a/dom/webauthn/nsIU2FTokenManager.idl
+++ b/dom/webauthn/nsIU2FTokenManager.idl
@@ -17,21 +17,20 @@
 interface nsIU2FTokenManager : nsISupports
 {
     /**
      * Resumes the current WebAuthn/U2F transaction if that matches the given
      * transaction ID. This is used only when direct attestation was requested
      * and we have to wait for user input to proceed.
      *
      * @param aTransactionID : The ID of the transaction to resume.
-     * @param aPermitDirectAttestation : Whether direct attestation was
-     *                                   permitted by the user.
+     * @param aForceNoneAttestation : The user might enforce none attestation.
      */
     void resumeRegister(in uint64_t aTransactionID,
-                        in bool aPermitDirectAttestation);
+                        in bool aForceNoneAttestation);
 
     /**
      * Cancels the current WebAuthn/U2F transaction if that matches the given
      * transaction ID.
      *
      * @param aTransactionID : The ID of the transaction to cancel.
      */
     void cancel(in uint64_t aTransactionID);
--- a/dom/webauthn/tests/test_webauthn_attestation_conveyance.html
+++ b/dom/webauthn/tests/test_webauthn_attestation_conveyance.html
@@ -93,18 +93,17 @@
         .then(verifyAnonymizedCertificate)
         .catch(arrivingHereIsBad);
 
       // Request indirect attestation, which is the same as none.
       await requestMakeCredential("indirect")
         .then(verifyAnonymizedCertificate)
         .catch(arrivingHereIsBad);
 
-      // Request direct attestation, which should prompt for user intervention,
-      // once 1430150 lands.
+      // Request direct attestation, which will prompt for user intervention.
       await requestMakeCredential("direct")
         .then(verifyDirectCertificate)
         .catch(arrivingHereIsBad);
     });
 
     // Test failure cases for make credential.
     add_task(async () => {
       // Request a platform authenticator.
--- a/dom/webauthn/u2f-hid-rs/src/capi.rs
+++ b/dom/webauthn/u2f-hid-rs/src/capi.rs
@@ -257,16 +257,14 @@ pub unsafe extern "C" fn rust_u2f_mgr_si
     if res.is_ok() {
         tid
     } else {
         0
     }
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn rust_u2f_mgr_cancel(mgr: *mut U2FManager) -> u64 {
+pub unsafe extern "C" fn rust_u2f_mgr_cancel(mgr: *mut U2FManager) {
     if !mgr.is_null() {
         // Ignore return value.
         let _ = (*mgr).cancel();
     }
-
-    new_tid()
 }
--- a/dom/webauthn/u2f-hid-rs/src/u2fhid-capi.h
+++ b/dom/webauthn/u2f-hid-rs/src/u2fhid-capi.h
@@ -73,17 +73,17 @@ uint64_t rust_u2f_mgr_sign(rust_u2f_mana
                            uint64_t flags,
                            uint64_t timeout,
                            rust_u2f_callback,
                            const uint8_t* challenge_ptr,
                            size_t challenge_len,
                            const rust_u2f_app_ids* app_ids,
                            const rust_u2f_key_handles* khs);
 
-uint64_t rust_u2f_mgr_cancel(rust_u2f_manager* mgr);
+void rust_u2f_mgr_cancel(rust_u2f_manager* mgr);
 
 
 /// U2FAppIds functions.
 
 rust_u2f_app_ids* rust_u2f_app_ids_new();
 void rust_u2f_app_ids_add(rust_u2f_app_ids* ids,
                           const uint8_t* id,
                           size_t id_len);
--- a/image/test/crashtests/crashtests.list
+++ b/image/test/crashtests/crashtests.list
@@ -1,19 +1,19 @@
 # Bug 668068 - Maximum (256) width and height icons that we currently interpret as 0-width and 0-height.
 load 256-height.ico
 load 256-width.ico
 
 load 83804-1.gif
 load 89341-1.gif
 load 463696.bmp
 load 570451.png
-# Bug 1390704 - Skip on stylo+debug because it triggers a quadratic behavior that makes it take
+# Bug 1390704 - Skip on debug because it triggers a quadratic behavior that makes it take
 # so much time that it can trip on the reftest timeout of 5 minutes.
-skip-if(Android||(stylo&&isDebugBuild)) load 694165-1.xhtml
+skip-if(Android||isDebugBuild) load 694165-1.xhtml
 load 681190.html
 load 732319-1.html
 load 844403-1.html
 load 856616.gif
 load 944353.jpg
 load 1205923-1.html
 # Ensure we handle detecting that an image is animated, then failing to decode
 # it. (See bug 1210745.)
--- a/js/public/Id.h
+++ b/js/public/Id.h
@@ -22,20 +22,25 @@
 
 #include "jstypes.h"
 
 #include "js/HeapAPI.h"
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
+// All jsids with the low bit set are integer ids. This means the other type
+// tags must all be even.
+#define JSID_TYPE_INT_BIT                0x1
+
+// Use 0 for JSID_TYPE_STRING to avoid a bitwise op for atom <-> id conversions.
 #define JSID_TYPE_STRING                 0x0
-#define JSID_TYPE_INT                    0x1
 #define JSID_TYPE_VOID                   0x2
 #define JSID_TYPE_SYMBOL                 0x4
+#define JSID_TYPE_EMPTY                  0x6
 #define JSID_TYPE_MASK                   0x7
 
 struct jsid
 {
     size_t asBits;
 
     constexpr jsid() : asBits(JSID_TYPE_VOID) {}
 
@@ -52,40 +57,42 @@ struct jsid
 
 // Avoid using canonical 'id' for jsid parameters since this is a magic word in
 // Objective-C++ which, apparently, wants to be able to #include jsapi.h.
 #define id iden
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_STRING(jsid id)
 {
-    return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
+    return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_STRING;
 }
 
 static MOZ_ALWAYS_INLINE JSString*
 JSID_TO_STRING(jsid id)
 {
+    // Use XOR instead of `& ~JSID_TYPE_MASK` because small immediates can be
+    // encoded more efficiently on some platorms.
     MOZ_ASSERT(JSID_IS_STRING(id));
-    return (JSString*)JSID_BITS(id);
+    return (JSString*)(JSID_BITS(id) ^ JSID_TYPE_STRING);
 }
 
 /**
  * Only JSStrings that have been interned via the JSAPI can be turned into
  * jsids by API clients.
  *
  * N.B. if a jsid is backed by a string which has not been interned, that
  * string must be appropriately rooted to avoid being collected by the GC.
  */
 JS_PUBLIC_API(jsid)
 INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str);
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_INT(jsid id)
 {
-    return !!(JSID_BITS(id) & JSID_TYPE_INT);
+    return !!(JSID_BITS(id) & JSID_TYPE_INT_BIT);
 }
 
 static MOZ_ALWAYS_INLINE int32_t
 JSID_TO_INT(jsid id)
 {
     MOZ_ASSERT(JSID_IS_INT(id));
     uint32_t bits = static_cast<uint32_t>(JSID_BITS(id)) >> 1;
     return static_cast<int32_t>(bits);
@@ -100,33 +107,32 @@ INT_FITS_IN_JSID(int32_t i)
     return i >= 0;
 }
 
 static MOZ_ALWAYS_INLINE jsid
 INT_TO_JSID(int32_t i)
 {
     jsid id;
     MOZ_ASSERT(INT_FITS_IN_JSID(i));
-    uint32_t bits = (static_cast<uint32_t>(i) << 1) | JSID_TYPE_INT;
+    uint32_t bits = (static_cast<uint32_t>(i) << 1) | JSID_TYPE_INT_BIT;
     JSID_BITS(id) = static_cast<size_t>(bits);
     return id;
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_SYMBOL(jsid id)
 {
-    return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_SYMBOL &&
-           JSID_BITS(id) != JSID_TYPE_SYMBOL;
+    return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_SYMBOL;
 }
 
 static MOZ_ALWAYS_INLINE JS::Symbol*
 JSID_TO_SYMBOL(jsid id)
 {
     MOZ_ASSERT(JSID_IS_SYMBOL(id));
-    return (JS::Symbol*)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
+    return (JS::Symbol*)(JSID_BITS(id) ^ JSID_TYPE_SYMBOL);
 }
 
 static MOZ_ALWAYS_INLINE jsid
 SYMBOL_TO_JSID(JS::Symbol* sym)
 {
     jsid id;
     MOZ_ASSERT(sym != nullptr);
     MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0);
@@ -149,29 +155,31 @@ JSID_TO_GCTHING(jsid id)
         return JS::GCCellPtr(thing, JS::TraceKind::String);
     MOZ_ASSERT(JSID_IS_SYMBOL(id));
     return JS::GCCellPtr(thing, JS::TraceKind::Symbol);
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_VOID(const jsid id)
 {
-    MOZ_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
-                 JSID_BITS(id) == JSID_TYPE_VOID);
-    return (size_t)JSID_BITS(id) == JSID_TYPE_VOID;
+    MOZ_ASSERT_IF((JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
+                  JSID_BITS(id) == JSID_TYPE_VOID);
+    return JSID_BITS(id) == JSID_TYPE_VOID;
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_EMPTY(const jsid id)
 {
-    return (size_t)JSID_BITS(id) == JSID_TYPE_SYMBOL;
+    MOZ_ASSERT_IF((JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_EMPTY,
+                  JSID_BITS(id) == JSID_TYPE_EMPTY);
+    return JSID_BITS(id) == JSID_TYPE_EMPTY;
 }
 
 constexpr const jsid JSID_VOID;
-extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
+constexpr const jsid JSID_EMPTY = jsid::fromRawBits(JSID_TYPE_EMPTY);
 
 extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
 extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
 
 namespace JS {
 
 template <>
 struct GCPolicy<jsid>
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -4246,23 +4246,26 @@ GCRuntime::prepareZonesForCollection(JS:
 
         zone->setPreservingCode(false);
     }
 
     // Discard JIT code more aggressively if the process is approaching its
     // executable code limit.
     bool canAllocateMoreCode = jit::CanLikelyAllocateMoreExecutableMemory();
 
-    for (RealmsIter r(rt, WithAtoms); !r.done(); r.next()) {
-        r->unmark();
-        JSCompartment* comp = JS::GetCompartmentForRealm(r);
-        comp->scheduledForDestruction = false;
-        comp->maybeAlive = r->shouldTraceGlobal() || !r->zone()->isGCScheduled();
-        if (shouldPreserveJITCode(r, currentTime, reason, canAllocateMoreCode))
-            r->zone()->setPreservingCode(true);
+    for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
+        c->scheduledForDestruction = false;
+        c->maybeAlive = false;
+        for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {
+            r->unmark();
+            if (r->shouldTraceGlobal() || !r->zone()->isGCScheduled())
+                c->maybeAlive = true;
+            if (shouldPreserveJITCode(r, currentTime, reason, canAllocateMoreCode))
+                r->zone()->setPreservingCode(true);
+        }
     }
 
     if (!cleanUpEverything && canAllocateMoreCode) {
         jit::JitActivationIterator activation(rt->mainContextFromOwnThread());
         if (!activation.done())
             activation->compartment()->zone()->setPreservingCode(true);
     }
 
@@ -4493,17 +4496,17 @@ GCRuntime::markCompartments()
             }
         }
     }
 
     /* Set scheduleForDestruction based on maybeAlive. */
 
     for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) {
         MOZ_ASSERT(!comp->scheduledForDestruction);
-        if (!comp->maybeAlive && !JS::GetRealmForCompartment(comp)->isAtomsRealm())
+        if (!comp->maybeAlive && !comp->zone()->isAtomsZone())
             comp->scheduledForDestruction = true;
     }
 }
 
 void
 GCRuntime::updateMallocCountersOnGCStart()
 {
     // Update the malloc counters for any zones we are collecting.
@@ -7955,19 +7958,25 @@ js::NewRealm(JSContext* cx, JSPrincipals
 
     ScopedJSDeletePtr<Realm> realm(cx->new_<Realm>(zone, options));
     if (!realm || !realm->init(cx))
         return nullptr;
 
     // Set up the principals.
     JS_SetCompartmentPrincipals(JS::GetCompartmentForRealm(realm), principals);
 
+    JSCompartment* comp = realm->compartment();
+    if (!comp->realms().append(realm)) {
+        ReportOutOfMemory(cx);
+        return nullptr;
+    }
+
     AutoLockGC lock(rt);
 
-    if (!zone->compartments().append(JS::GetCompartmentForRealm(realm.get()))) {
+    if (!zone->compartments().append(comp)) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
     if (zoneHolder) {
         if (!rt->gc.zones().append(zone)) {
             ReportOutOfMemory(cx);
             return nullptr;
@@ -8474,23 +8483,26 @@ js::gc::CheckHashTablesAfterMovingGC(JSR
 
         JS::AutoCheckCannotGC nogc;
         for (auto baseShape = zone->cellIter<BaseShape>(); !baseShape.done(); baseShape.next()) {
             if (ShapeTable* table = baseShape->maybeTable(nogc))
                 table->checkAfterMovingGC();
         }
     }
 
-    for (RealmsIter r(rt, SkipAtoms); !r.done(); r.next()) {
-        r->checkObjectGroupTablesAfterMovingGC();
-        r->dtoaCache.checkCacheAfterMovingGC();
-        JS::GetCompartmentForRealm(r)->checkWrapperMapAfterMovingGC();
-        r->checkScriptMapsAfterMovingGC();
-        if (r->debugEnvs())
-            r->debugEnvs()->checkHashTablesAfterMovingGC();
+    for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
+        c->checkWrapperMapAfterMovingGC();
+
+        for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {
+            r->checkObjectGroupTablesAfterMovingGC();
+            r->dtoaCache.checkCacheAfterMovingGC();
+            r->checkScriptMapsAfterMovingGC();
+            if (r->debugEnvs())
+                r->debugEnvs()->checkHashTablesAfterMovingGC();
+        }
     }
 }
 #endif
 
 JS_PUBLIC_API(void)
 JS::PrepareZoneForGC(Zone* zone)
 {
     zone->scheduleGC();
--- a/js/src/gc/PublicIterators.h
+++ b/js/src/gc/PublicIterators.h
@@ -9,16 +9,17 @@
  */
 
 #ifndef gc_PublicIterators_h
 #define gc_PublicIterators_h
 
 #include "mozilla/Maybe.h"
 
 #include "gc/Zone.h"
+#include "vm/JSCompartment.h"
 
 namespace js {
 
 // Using the atoms zone without holding the exclusive access lock is dangerous
 // because worker threads may be using it simultaneously. Therefore, it's
 // better to skip the atoms zone when iterating over zones. If you need to
 // iterate over the atoms zone, consider taking the exclusive access lock first.
 enum ZoneSelector {
@@ -102,36 +103,84 @@ struct CompartmentsInZoneIter
     CompartmentsInZoneIter()
       : zone(nullptr), it(nullptr)
     {}
 
     // This is for the benefit of CompartmentsIterT::comp.
     friend class mozilla::Maybe<CompartmentsInZoneIter>;
 };
 
-// Note: this class currently assumes there's a single realm per compartment.
+class RealmsInCompartmentIter
+{
+    JSCompartment* comp;
+    JS::Realm** it;
+
+  public:
+    explicit RealmsInCompartmentIter(JSCompartment* comp)
+      : comp(comp)
+    {
+        it = comp->realms().begin();
+    }
+
+    bool done() const {
+        MOZ_ASSERT(it);
+        return it < comp->realms().begin() ||
+               it >= comp->realms().end();
+    }
+    void next() {
+        MOZ_ASSERT(!done());
+        it++;
+    }
+
+    JS::Realm* get() const {
+        MOZ_ASSERT(!done());
+        return *it;
+    }
+
+    operator JS::Realm*() const { return get(); }
+    JS::Realm* operator->() const { return get(); }
+};
+
 class RealmsInZoneIter
 {
     CompartmentsInZoneIter comp;
+    mozilla::Maybe<RealmsInCompartmentIter> realm;
 
   public:
     explicit RealmsInZoneIter(JS::Zone* zone)
       : comp(zone)
-    {}
+    {
+        settleOnCompartment();
+    }
+
+    void settleOnCompartment() {
+        if (!comp.done()) {
+            realm.emplace(comp.get());
+            MOZ_ASSERT(!realm->done(), "compartment must have at least one realm");
+        }
+    }
 
     bool done() const {
+        MOZ_ASSERT(comp.done() == realm.isNothing());
         return comp.done();
     }
     void next() {
         MOZ_ASSERT(!done());
-        comp.next();
+
+        realm->next();
+
+        if (realm->done()) {
+            realm.reset();
+            comp.next();
+            settleOnCompartment();
+        }
     }
 
     JS::Realm* get() const {
-        return JS::GetRealmForCompartment(comp.get());
+        return realm->get();
     }
 
     operator JS::Realm*() const { return get(); }
     JS::Realm* operator->() const { return get(); }
 };
 
 // This iterator iterates over all the compartments in a given set of zones. The
 // set of zones is determined by iterating ZoneIterT.
--- a/js/src/jit-test/tests/wasm/memory-bulk.js
+++ b/js/src/jit-test/tests/wasm/memory-bulk.js
@@ -78,24 +78,32 @@ function funcBody(func) {
     return body;
 }
 
 function bodySection(bodies) {
     var body = varU32(bodies.length).concat(...bodies);
     return { name: codeId, body };
 }
 
+function memorySection(initialSize) {
+    var body = [];
+    body.push(...varU32(1));           // number of memories
+    body.push(...varU32(0x0));         // for now, no maximum
+    body.push(...varU32(initialSize));
+    return { name: memoryId, body };
+}
+
 const v2vSig = {args:[], ret:VoidCode};
 const v2vSigSection = sigSection([v2vSig]);
 
 // Prefixed opcodes
 
 function checkMiscPrefixed(opcode, expect_failure) {
     let binary = moduleWithSections(
-           [v2vSigSection, declSection([0]),
+           [v2vSigSection, declSection([0]), memorySection(1),
             bodySection(
                 [funcBody(
                     {locals:[],
                      body:[0x41, 0x0, 0x41, 0x0, 0x41, 0x0, // 3 x const.i32 0
                            MiscPrefix, opcode]})])]);
     if (expect_failure) {
         assertErrorMessage(() => new WebAssembly.Module(binary),
                            WebAssembly.CompileError, /unrecognized opcode/);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2213,17 +2213,17 @@ CodeGenerator::visitRegExpMatcher(LRegEx
     MOZ_ASSERT(RegExpMatcherLastIndexReg != JSReturnReg);
 #endif
 
     masm.reserveStack(RegExpReservedStack);
 
     OutOfLineRegExpMatcher* ool = new(alloc()) OutOfLineRegExpMatcher(lir);
     addOutOfLineCode(ool, lir->mir());
 
-    const JitRealm* jitRealm = gen->compartment->jitRealm();
+    const JitRealm* jitRealm = gen->realm->jitRealm();
     JitCode* regExpMatcherStub = jitRealm->regExpMatcherStubNoBarrier(&realmStubsToReadBarrier_);
     masm.call(regExpMatcherStub);
     masm.branchTestUndefined(Assembler::Equal, JSReturnOperand, ool->entry());
     masm.bind(ool->rejoin());
 
     masm.freeStack(RegExpReservedStack);
 }
 
@@ -2363,17 +2363,17 @@ CodeGenerator::visitRegExpSearcher(LRegE
     MOZ_ASSERT(RegExpTesterStringReg != ReturnReg);
     MOZ_ASSERT(RegExpTesterLastIndexReg != ReturnReg);
 
     masm.reserveStack(RegExpReservedStack);
 
     OutOfLineRegExpSearcher* ool = new(alloc()) OutOfLineRegExpSearcher(lir);
     addOutOfLineCode(ool, lir->mir());
 
-    const JitRealm* jitRealm = gen->compartment->jitRealm();
+    const JitRealm* jitRealm = gen->realm->jitRealm();
     JitCode* regExpSearcherStub = jitRealm->regExpSearcherStubNoBarrier(&realmStubsToReadBarrier_);
     masm.call(regExpSearcherStub);
     masm.branch32(Assembler::Equal, ReturnReg, Imm32(RegExpSearcherResultFailed), ool->entry());
     masm.bind(ool->rejoin());
 
     masm.freeStack(RegExpReservedStack);
 }
 
@@ -2500,17 +2500,17 @@ CodeGenerator::visitRegExpTester(LRegExp
 
     MOZ_ASSERT(RegExpTesterRegExpReg != ReturnReg);
     MOZ_ASSERT(RegExpTesterStringReg != ReturnReg);
     MOZ_ASSERT(RegExpTesterLastIndexReg != ReturnReg);
 
     OutOfLineRegExpTester* ool = new(alloc()) OutOfLineRegExpTester(lir);
     addOutOfLineCode(ool, lir->mir());
 
-    const JitRealm* jitRealm = gen->compartment->jitRealm();
+    const JitRealm* jitRealm = gen->realm->jitRealm();
     JitCode* regExpTesterStub = jitRealm->regExpTesterStubNoBarrier(&realmStubsToReadBarrier_);
     masm.call(regExpTesterStub);
 
     masm.branch32(Assembler::Equal, ReturnReg, Imm32(RegExpTesterResultFailed), ool->entry());
     masm.bind(ool->rejoin());
 }
 
 class OutOfLineRegExpPrototypeOptimizable : public OutOfLineCodeBase<CodeGenerator>
@@ -4042,20 +4042,20 @@ CodeGenerator::maybeEmitGlobalBarrierChe
     // compartment, because we bake in a pointer to realm->globalWriteBarriered
     // and doing that would be invalid for other realms because they could be
     // collected before the Ion code is discarded.
 
     if (!maybeGlobal->isConstant())
         return;
 
     JSObject* obj = &maybeGlobal->toConstant()->toObject();
-    if (gen->compartment->maybeGlobal() != obj)
+    if (gen->realm->maybeGlobal() != obj)
         return;
 
-    auto addr = AbsoluteAddress(gen->compartment->addressOfGlobalWriteBarriered());
+    auto addr = AbsoluteAddress(gen->realm->addressOfGlobalWriteBarriered());
     masm.branch32(Assembler::NotEqual, addr, Imm32(0), ool->rejoin());
 }
 
 template <class LPostBarrierType, MIRType nurseryType>
 void
 CodeGenerator::visitPostWriteBarrierCommon(LPostBarrierType* lir, OutOfLineCode* ool)
 {
     addOutOfLineCode(ool, lir->mir());
@@ -5629,17 +5629,17 @@ CodeGenerator::emitDebugForceBailing(LIn
     if (!lir->snapshot())
         return;
     if (lir->isStart())
         return;
     if (lir->isOsiPoint())
         return;
 
     masm.comment("emitDebugForceBailing");
-    const void* bailAfterAddr = gen->compartment->zone()->addressOfIonBailAfter();
+    const void* bailAfterAddr = gen->realm->zone()->addressOfIonBailAfter();
 
     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
 
     Label done, notBail, bail;
     masm.branch32(Assembler::Equal, AbsoluteAddress(bailAfterAddr), Imm32(0), &done);
     {
         Register temp = regs.takeAny();
 
@@ -8198,17 +8198,17 @@ static const VMFunction ConcatStringsInf
     FunctionInfo<ConcatStringsFn>(ConcatStrings<CanGC>, "ConcatStrings");
 
 void
 CodeGenerator::emitConcat(LInstruction* lir, Register lhs, Register rhs, Register output)
 {
     OutOfLineCode* ool = oolCallVM(ConcatStringsInfo, lir, ArgList(lhs, rhs),
                                    StoreRegisterTo(output));
 
-    const JitRealm* jitRealm = gen->compartment->jitRealm();
+    const JitRealm* jitRealm = gen->realm->jitRealm();
     JitCode* stringConcatStub = jitRealm->stringConcatStubNoBarrier(&realmStubsToReadBarrier_);
     masm.call(stringConcatStub);
     masm.branchTestPtr(Assembler::Zero, output, output, ool->entry());
 
     masm.bind(ool->rejoin());
 }
 
 void
@@ -10290,17 +10290,17 @@ CodeGenerator::link(JSContext* cx, Compi
     // removed from the relevant lists by this point. Don't allow GC here.
     JS::AutoAssertNoGC nogc(cx);
 
     RootedScript script(cx, gen->info().script());
     OptimizationLevel optimizationLevel = gen->optimizationInfo().level();
 
     // Perform any read barriers which were skipped while compiling the
     // script, which may have happened off-thread.
-    const JitRealm* jr = gen->compartment->jitRealm();
+    const JitRealm* jr = gen->realm->jitRealm();
     jr->performStubReadBarriers(realmStubsToReadBarrier_);
     jr->performSIMDTemplateReadBarriers(simdTemplatesToReadBarrier_);
 
     // We finished the new IonScript. Invalidate the current active IonScript,
     // so we can replace it with this new (probably higher optimized) version.
     if (script->hasIonScript()) {
         MOZ_ASSERT(script->ionScript()->isRecompiling());
         // Do a normal invalidate, except don't cancel offThread compilations,
@@ -13220,17 +13220,17 @@ CodeGenerator::visitRandom(LRandom* ins)
 #ifdef JS_PUNBOX64
     Register64 s0Reg(ToRegister(ins->temp1()));
     Register64 s1Reg(ToRegister(ins->temp2()));
 #else
     Register64 s0Reg(ToRegister(ins->temp1()), ToRegister(ins->temp2()));
     Register64 s1Reg(ToRegister(ins->temp3()), ToRegister(ins->temp4()));
 #endif
 
-    const void* rng = gen->compartment->addressOfRandomNumberGenerator();
+    const void* rng = gen->realm->addressOfRandomNumberGenerator();
     masm.movePtr(ImmPtr(rng), tempReg);
 
     static_assert(sizeof(XorShift128PlusRNG) == 2 * sizeof(uint64_t),
                   "Code below assumes XorShift128PlusRNG contains two uint64_t values");
 
     Address state0Addr(tempReg, XorShift128PlusRNG::offsetOfState0());
     Address state1Addr(tempReg, XorShift128PlusRNG::offsetOfState1());
 
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -225,84 +225,84 @@ CompileZone::nurseryExists()
 void
 CompileZone::setMinorGCShouldCancelIonCompilations()
 {
     MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
     JSRuntime* rt = zone()->runtimeFromMainThread();
     rt->gc.storeBuffer().setShouldCancelIonCompilations();
 }
 
-JSCompartment*
-CompileCompartment::compartment()
+JS::Realm*
+CompileRealm::realm()
 {
-    return reinterpret_cast<JSCompartment*>(this);
+    return reinterpret_cast<JS::Realm*>(this);
 }
 
-/* static */ CompileCompartment*
-CompileCompartment::get(JSCompartment* comp)
+/* static */ CompileRealm*
+CompileRealm::get(JS::Realm* realm)
 {
-    return reinterpret_cast<CompileCompartment*>(comp);
+    return reinterpret_cast<CompileRealm*>(realm);
 }
 
 CompileZone*
-CompileCompartment::zone()
+CompileRealm::zone()
 {
-    return CompileZone::get(compartment()->zone());
+    return CompileZone::get(realm()->zone());
 }
 
 CompileRuntime*
-CompileCompartment::runtime()
+CompileRealm::runtime()
 {
-    return CompileRuntime::get(compartment()->runtimeFromAnyThread());
+    return CompileRuntime::get(realm()->runtimeFromAnyThread());
 }
 
 const void*
-CompileCompartment::addressOfRandomNumberGenerator()
+CompileRealm::addressOfRandomNumberGenerator()
 {
-    return JS::GetRealmForCompartment(compartment())->addressOfRandomNumberGenerator();
+    return realm()->addressOfRandomNumberGenerator();
 }
 
 const JitRealm*
-CompileCompartment::jitRealm()
+CompileRealm::jitRealm()
 {
-    return JS::GetRealmForCompartment(compartment())->jitRealm();
+    return realm()->jitRealm();
 }
 
 const GlobalObject*
-CompileCompartment::maybeGlobal()
+CompileRealm::maybeGlobal()
 {
     // This uses unsafeUnbarrieredMaybeGlobal() so as not to trigger the read
     // barrier on the global from off thread.  This is safe because we
     // abort Ion compilation when we GC.
-    return JS::GetRealmForCompartment(compartment())->unsafeUnbarrieredMaybeGlobal();
+    return realm()->unsafeUnbarrieredMaybeGlobal();
 }
 
 const uint32_t*
-CompileCompartment::addressOfGlobalWriteBarriered()
+CompileRealm::addressOfGlobalWriteBarriered()
 {
-    return &JS::GetRealmForCompartment(compartment())->globalWriteBarriered;
+    return &realm()->globalWriteBarriered;
 }
 
 bool
-CompileCompartment::hasAllocationMetadataBuilder()
+CompileRealm::hasAllocationMetadataBuilder()
 {
-    return JS::GetRealmForCompartment(compartment())->hasAllocationMetadataBuilder();
+    return realm()->hasAllocationMetadataBuilder();
 }
 
 // Note: This function is thread-safe because setSingletonAsValue sets a boolean
 // variable to false, and this boolean variable has no way to be resetted to
 // true. So even if there is a concurrent write, this concurrent write will
 // always have the same value.  If there is a concurrent read, then we will
 // clone a singleton instead of using the value which is baked in the JSScript,
 // and this would be an unfortunate allocation, but this will not change the
 // semantics of the JavaScript code which is executed.
 void
-CompileCompartment::setSingletonsAsValues()
+CompileRealm::setSingletonsAsValues()
 {
-    JS::GetRealmForCompartment(compartment())->behaviors().setSingletonsAsValues();
+    realm()->behaviors().setSingletonsAsValues();
 }
 
 JitCompileOptions::JitCompileOptions()
   : cloneSingletons_(false),
     profilerSlowAssertionsEnabled_(false),
     offThreadCompilationAvailable_(false)
 {
 }
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -84,22 +84,22 @@ class CompileZone
 
     bool nurseryExists();
     bool canNurseryAllocateStrings();
     void setMinorGCShouldCancelIonCompilations();
 };
 
 class JitRealm;
 
-class CompileCompartment
+class CompileRealm
 {
-    JSCompartment* compartment();
+    JS::Realm* realm();
 
   public:
-    static CompileCompartment* get(JSCompartment* comp);
+    static CompileRealm* get(JS::Realm* realm);
 
     CompileZone* zone();
     CompileRuntime* runtime();
 
     const void* addressOfRandomNumberGenerator();
 
     const JitRealm* jitRealm();
 
--- a/js/src/jit/EagerSimdUnbox.cpp
+++ b/js/src/jit/EagerSimdUnbox.cpp
@@ -95,17 +95,17 @@ UnboxSimdPhi(const JitRealm* jitRealm, M
 
         use->replaceProducer(box);
     }
 }
 
 bool
 EagerSimdUnbox(MIRGenerator* mir, MIRGraph& graph)
 {
-    const JitRealm* jitRealm = mir->compartment->jitRealm();
+    const JitRealm* jitRealm = mir->realm->jitRealm();
     for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
         if (mir->shouldCancel("Eager Simd Unbox"))
             return false;
 
         for (MInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
             if (!ins->isSimdUnbox())
                 continue;
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -98,32 +98,32 @@ jit::GetJitContext()
 }
 
 JitContext*
 jit::MaybeGetJitContext()
 {
     return CurrentJitContext();
 }
 
-JitContext::JitContext(CompileRuntime* rt, CompileCompartment* comp, TempAllocator* temp)
+JitContext::JitContext(CompileRuntime* rt, CompileRealm* realm, TempAllocator* temp)
   : cx(nullptr),
     temp(temp),
     runtime(rt),
-    compartment(comp),
+    realm(realm),
     prev_(CurrentJitContext()),
     assemblerCount_(0)
 {
     SetJitContext(this);
 }
 
 JitContext::JitContext(JSContext* cx, TempAllocator* temp)
   : cx(cx),
     temp(temp),
     runtime(CompileRuntime::get(cx->runtime())),
-    compartment(CompileCompartment::get(cx->compartment())),
+    realm(CompileRealm::get(cx->realm())),
     prev_(CurrentJitContext()),
     assemblerCount_(0)
 {
     SetJitContext(this);
 }
 
 JitContext::JitContext(TempAllocator* temp)
   : JitContext(nullptr, nullptr, temp)
@@ -2086,17 +2086,17 @@ IonCompile(JSContext* cx, JSScript* scri
     CompilerConstraintList* constraints = NewCompilerConstraintList(*temp);
     if (!constraints)
         return AbortReason::Alloc;
 
     const OptimizationInfo* optimizationInfo = IonOptimizations.get(optimizationLevel);
     const JitCompileOptions options(cx);
 
     IonBuilder* builder = alloc->new_<IonBuilder>((JSContext*) nullptr,
-                                                  CompileCompartment::get(cx->compartment()),
+                                                  CompileRealm::get(cx->realm()),
                                                   options, temp, graph, constraints,
                                                   inspector, info, optimizationInfo,
                                                   baselineFrameInspector);
     if (!builder)
         return AbortReason::Alloc;
 
     if (cx->runtime()->gc.storeBuffer().cancelIonCompilations())
         builder->setNotSafeForMinorGC();
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -44,39 +44,39 @@ using mozilla::Ok;
 
 static_assert(sizeof(AbortReasonOr<Ok>) <= sizeof(uintptr_t),
     "Unexpected size of AbortReasonOr<Ok>");
 static_assert(sizeof(AbortReasonOr<bool>) <= sizeof(uintptr_t),
     "Unexpected size of AbortReasonOr<bool>");
 
 // A JIT context is needed to enter into either an JIT method or an instance
 // of a JIT compiler. It points to a temporary allocator and the active
-// JSContext, either of which may be nullptr, and the active compartment, which
+// JSContext, either of which may be nullptr, and the active realm, which
 // will not be nullptr.
 
 class JitContext
 {
   public:
     JitContext(JSContext* cx, TempAllocator* temp);
-    JitContext(CompileRuntime* rt, CompileCompartment* comp, TempAllocator* temp);
+    JitContext(CompileRuntime* rt, CompileRealm* realm, TempAllocator* temp);
     explicit JitContext(TempAllocator* temp);
     JitContext();
     ~JitContext();
 
     // Running context when executing on the main thread. Not available during
     // compilation.
     JSContext* cx;
 
     // Allocator for temporary memory during compilation.
     TempAllocator* temp;
 
-    // Wrappers with information about the current runtime/compartment for use
+    // Wrappers with information about the current runtime/realm for use
     // during compilation.
     CompileRuntime* runtime;
-    CompileCompartment* compartment;
+    CompileRealm* realm;
 
     int getNextAssemblerId() {
         return assemblerCount_++;
     }
   private:
     JitContext* prev_;
     int assemblerCount_;
 };
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4242,17 +4242,17 @@ jit::AnalyzeNewScriptDefiniteProperties(
     if (!constraints) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     BaselineInspector inspector(script);
     const JitCompileOptions options(cx);
 
-    IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
+    IonBuilder builder(cx, CompileRealm::get(cx->realm()), options, &temp, &graph, constraints,
                        &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
 
     AbortReasonOr<Ok> buildResult = builder.build();
     if (buildResult.isErr()) {
         AbortReason reason = buildResult.unwrapErr();
         if (cx->isThrowingOverRecursed() || cx->isThrowingOutOfMemory())
             return false;
         if (reason == AbortReason::Alloc) {
@@ -4488,17 +4488,17 @@ jit::AnalyzeArgumentsUsage(JSContext* cx
     if (!constraints) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     BaselineInspector inspector(script);
     const JitCompileOptions options(cx);
 
-    IonBuilder builder(nullptr, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
+    IonBuilder builder(nullptr, CompileRealm::get(cx->realm()), options, &temp, &graph, constraints,
                        &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
 
     AbortReasonOr<Ok> buildResult = builder.build();
     if (buildResult.isErr()) {
         AbortReason reason = buildResult.unwrapErr();
         if (cx->isThrowingOverRecursed() || cx->isThrowingOutOfMemory())
             return false;
         if (reason == AbortReason::Alloc) {
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -110,24 +110,24 @@ jit::NewBaselineFrameInspector(TempAlloc
     for (size_t i = 0; i < frame->numValueSlots(); i++) {
         TypeSet::Type type = TypeSet::GetMaybeUntrackedValueType(*frame->valueSlot(i));
         inspector->varTypes.infallibleAppend(type);
     }
 
     return inspector;
 }
 
-IonBuilder::IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
+IonBuilder::IonBuilder(JSContext* analysisContext, CompileRealm* realm,
                        const JitCompileOptions& options, TempAllocator* temp,
                        MIRGraph* graph, CompilerConstraintList* constraints,
                        BaselineInspector* inspector, CompileInfo* info,
                        const OptimizationInfo* optimizationInfo,
                        BaselineFrameInspector* baselineFrame, size_t inliningDepth,
                        uint32_t loopDepth)
-  : MIRGenerator(comp, options, temp, graph, info, optimizationInfo),
+  : MIRGenerator(realm, options, temp, graph, info, optimizationInfo),
     backgroundCodegen_(nullptr),
     actionableAbortScript_(nullptr),
     actionableAbortPc_(nullptr),
     actionableAbortMessage_(nullptr),
     rootList_(nullptr),
     analysisContext(analysisContext),
     baselineFrame_(baselineFrame),
     constraints_(constraints),
@@ -1871,17 +1871,17 @@ IonBuilder::inspectOpcode(JSOp op)
         return Ok();
 
       case JSOP_STRING:
         pushConstant(StringValue(info().getAtom(pc)));
         return Ok();
 
       case JSOP_SYMBOL: {
         unsigned which = GET_UINT8(pc);
-        JS::Symbol* sym = compartment->runtime()->wellKnownSymbols().get(which);
+        JS::Symbol* sym = realm->runtime()->wellKnownSymbols().get(which);
         pushConstant(SymbolValue(sym));
         return Ok();
       }
 
       case JSOP_ZERO:
         pushConstant(Int32Value(0));
         return Ok();
 
@@ -3788,17 +3788,17 @@ IonBuilder::inlineScriptedCall(CallInfo&
                                                      inlineScriptTree);
     if (!info)
         return abort(AbortReason::Alloc);
 
     MIRGraphReturns returns(alloc());
     AutoAccumulateReturns aar(graph(), returns);
 
     // Build the graph.
-    IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
+    IonBuilder inlineBuilder(analysisContext, realm, options, &alloc(), &graph(), constraints(),
                              &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
                              loopDepth_);
     AbortReasonOr<Ok> result = inlineBuilder.buildInline(this, outerResumePoint, callInfo);
     if (result.isErr()) {
         if (analysisContext && analysisContext->isExceptionPending()) {
             JitSpew(JitSpew_IonAbort, "Inline builder raised exception.");
             MOZ_ASSERT(result.unwrapErr() == AbortReason::Error);
             return Err(result.unwrapErr());
@@ -4960,17 +4960,17 @@ IonBuilder::createThisScriptedBaseline(M
         return nullptr;
 
     JSObject* templateObject = inspector->getTemplateObject(pc);
     if (!templateObject)
         return nullptr;
     if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
         return nullptr;
 
-    Shape* shape = target->lookupPure(compartment->runtime()->names().prototype);
+    Shape* shape = target->lookupPure(realm->runtime()->names().prototype);
     if (!shape || !shape->isDataProperty())
         return nullptr;
 
     Value protov = target->getSlot(shape->slot());
     if (!protov.isObject())
         return nullptr;
 
     JSObject* proto = checkNurseryObject(&protov.toObject());
@@ -5448,17 +5448,17 @@ IonBuilder::testShouldDOMCall(TypeSet* i
 {
     if (!func->isNative() || !func->hasJitInfo())
         return false;
 
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassHasProtoAtDepth instanceChecker =
-        compartment->runtime()->DOMcallbacks()->instanceClassMatchesProto;
+        realm->runtime()->DOMcallbacks()->instanceClassMatchesProto;
 
     const JSJitInfo* jinfo = func->jitInfo();
     if (jinfo->type() != opType)
         return false;
 
     for (unsigned i = 0; i < inTypes->getObjectCount(); i++) {
         TypeSet::ObjectKey* key = inTypes->getObject(i);
         if (!key)
@@ -6973,31 +6973,31 @@ ClassHasEffectlessLookup(const Class* cl
     return (clasp == &UnboxedPlainObject::class_) ||
            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(CompileCompartment* comp, TypeSet::ObjectKey* object, jsid id)
+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(comp->runtime()->names(), id);
+        return object->group()->typeDescr().hasProperty(realm->runtime()->names(), id);
 
     const Class* clasp = object->clasp();
 
     // Array |length| properties are not reflected in type information.
     if (clasp == &ArrayObject::class_)
-        return JSID_IS_ATOM(id, comp->runtime()->names().length);
+        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;
-    return ClassMayResolveId(comp->runtime()->names(), clasp, id, singleton);
+    return ClassMayResolveId(realm->runtime()->names(), clasp, id, singleton);
 }
 
 void
 IonBuilder::insertRecompileCheck()
 {
     // No need for recompile checks if this is the highest optimization level.
     OptimizationLevel curLevel = optimizationInfo().level();
     if (IonOptimizations.isLastLevel(curLevel))
@@ -7049,17 +7049,17 @@ IonBuilder::testSingletonProperty(JSObje
 
         HeapTypeSetKey property = objKey->property(id);
         if (property.isOwnProperty(constraints())) {
             if (obj->isSingleton())
                 return property.singleton(constraints());
             return nullptr;
         }
 
-        if (ObjectHasExtraOwnProperty(compartment, objKey, id))
+        if (ObjectHasExtraOwnProperty(realm, objKey, id))
             return nullptr;
 
         obj = checkNurseryObject(obj->staticPrototype());
     }
 
     return nullptr;
 }
 
@@ -7111,17 +7111,17 @@ IonBuilder::testSingletonPropertyTypes(M
         for (unsigned i = 0; i < types->getObjectCount(); i++) {
             TypeSet::ObjectKey* key = types->getObject(i);
             if (!key)
                 continue;
             if (analysisContext)
                 key->ensureTrackedProperty(analysisContext, id);
 
             const Class* clasp = key->clasp();
-            if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, id))
+            if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(realm, key, id))
                 return nullptr;
             if (key->unknownProperties())
                 return nullptr;
             HeapTypeSetKey property = key->property(id);
             if (property.isOwnProperty(constraints()))
                 return nullptr;
 
             if (JSObject* proto = checkNurseryObject(key->proto().toObjectOrNull())) {
@@ -7167,17 +7167,17 @@ IonBuilder::testNotDefinedProperty(MDefi
         while (true) {
             if (!alloc().ensureBallast())
                 return abort(AbortReason::Alloc);
 
             if (!key->hasStableClassAndProto(constraints()) || key->unknownProperties())
                 return false;
 
             const Class* clasp = key->clasp();
-            if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, id))
+            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.
             if (key->isSingleton() &&
                 key->singleton()->is<NativeObject>() &&
                 key->singleton()->as<NativeObject>().lookupPure(id))
@@ -7444,17 +7444,17 @@ IonBuilder::loadStaticSlot(JSObject* sta
 
     return loadSlot(obj, slot, NumFixedSlots(staticObject), rvalType, barrier, types);
 }
 
 // Whether a write of the given value may need a post-write barrier for GC purposes.
 bool
 IonBuilder::needsPostBarrier(MDefinition* value)
 {
-    CompileZone* zone = compartment->zone();
+    CompileZone* zone = realm->zone();
     if (!zone->nurseryExists())
         return false;
     if (value->mightBeType(MIRType::Object))
         return true;
     if (value->mightBeType(MIRType::String) && zone->canNurseryAllocateStrings())
         return true;
     return false;
 }
@@ -7571,21 +7571,21 @@ IonBuilder::jsop_getgname(PropertyName* 
     // cases *exactly* like Baseline, because it's invalid to add an Ion IC or
     // VM call (that might trigger invalidation) if there's no Baseline IC for
     // this op.
     if (name == names().undefined) {
         pushConstant(UndefinedValue());
         return Ok();
     }
     if (name == names().NaN) {
-        pushConstant(compartment->runtime()->NaNValue());
+        pushConstant(realm->runtime()->NaNValue());
         return Ok();
     }
     if (name == names().Infinity) {
-        pushConstant(compartment->runtime()->positiveInfinityValue());
+        pushConstant(realm->runtime()->positiveInfinityValue());
         return Ok();
     }
 
     if (JSObject* obj = testGlobalLexicalBinding(name)) {
         bool emitted = false;
         MOZ_TRY(getStaticName(&emitted, obj, name));
         if (emitted)
             return Ok();
@@ -9771,17 +9771,17 @@ IonBuilder::commonPrototypeWithGetterSet
         while (key) {
             if (key->unknownProperties())
                 return nullptr;
 
             const Class* clasp = key->clasp();
             if (!ClassHasEffectlessLookup(clasp))
                 return nullptr;
             JSObject* singleton = key->isSingleton() ? key->singleton() : nullptr;
-            if (ObjectHasExtraOwnProperty(compartment, key, NameToId(name))) {
+            if (ObjectHasExtraOwnProperty(realm, key, NameToId(name))) {
                 if (!singleton || !singleton->is<GlobalObject>())
                     return nullptr;
                 *guardGlobal = true;
             }
 
             // Look for a getter/setter on the class itself which may need
             // to be called.
             if (isGetter && clasp->getOpsGetProperty())
@@ -9978,17 +9978,17 @@ IonBuilder::annotateGetPropertyCache(MDe
         if (!group)
             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();
-        if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, NameToId(name)))
+        if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(realm, key, NameToId(name)))
             continue;
 
         HeapTypeSetKey ownTypes = key->property(NameToId(name));
         if (ownTypes.isOwnProperty(constraints()))
             continue;
 
         JSObject* singleton = testSingletonProperty(proto, NameToId(name));
         if (!singleton || !singleton->is<JSFunction>())
@@ -12113,17 +12113,17 @@ IonBuilder::jsop_object(JSObject* obj)
 {
     if (options.cloneSingletons()) {
         MCloneLiteral* clone = MCloneLiteral::New(alloc(), constant(ObjectValue(*obj)));
         current->add(clone);
         current->push(clone);
         return resumeAfter(clone);
     }
 
-    compartment->setSingletonsAsValues();
+    realm->setSingletonsAsValues();
     pushConstant(ObjectValue(*obj));
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::jsop_classconstructor()
 {
     MClassConstructor* constructor = MClassConstructor::New(alloc(), pc);
@@ -13037,17 +13037,17 @@ IonBuilder::jsop_instanceof()
 
         Value funProto = script()->global().getPrototype(JSProto_Function);
         if (!funProto.isObject() || rhsObject->staticPrototype() != &funProto.toObject())
             break;
 
         // If the user has supplied their own @@hasInstance method we shouldn't
         // clobber it.
         JSFunction* fun = &rhsObject->as<JSFunction>();
-        const WellKnownSymbols* symbols = &compartment->runtime()->wellKnownSymbols();
+        const WellKnownSymbols* symbols = &realm->runtime()->wellKnownSymbols();
         if (!js::FunctionHasDefaultHasInstance(fun, *symbols))
             break;
 
         // Ensure that we will bail if the @@hasInstance property or [[Prototype]]
         // change.
         TypeSet::ObjectKey* rhsKey = TypeSet::ObjectKey::get(rhsObject);
         if (!rhsKey->hasStableClassAndProto(constraints()))
             break;
@@ -13624,17 +13624,17 @@ IonBuilder::setPropTryReferenceTypedObje
 JSObject*
 IonBuilder::checkNurseryObject(JSObject* obj)
 {
     // If we try to use any nursery pointers during compilation, make sure that
     // the main thread will cancel this compilation before performing a minor
     // GC. All constants used during compilation should either go through this
     // function or should come from a type set (which has a similar barrier).
     if (obj && IsInsideNursery(obj)) {
-        compartment->zone()->setMinorGCShouldCancelIonCompilations();
+        realm->zone()->setMinorGCShouldCancelIonCompilations();
         IonBuilder* builder = this;
         while (builder) {
             builder->setNotSafeForMinorGC();
             builder = builder->callerBuilder_;
         }
     }
 
     return obj;
@@ -13736,17 +13736,17 @@ IonBuilder::convertToBoolean(MDefinition
     current->add(result);
 
     return result;
 }
 
 void
 IonBuilder::trace(JSTracer* trc)
 {
-    if (!compartment->runtime()->runtimeMatches(trc->runtime()))
+    if (!realm->runtime()->runtimeMatches(trc->runtime()))
         return;
 
     MOZ_ASSERT(rootList_);
     rootList_->trace(trc);
 }
 
 size_t
 IonBuilder::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -40,17 +40,17 @@ NewBaselineFrameInspector(TempAllocator*
 using CallTargets = Vector<JSFunction*, 6, JitAllocPolicy>;
 
 class IonBuilder
   : public MIRGenerator,
     public mozilla::LinkedListElement<IonBuilder>
 {
 
   public:
-    IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
+    IonBuilder(JSContext* analysisContext, CompileRealm* realm,
                const JitCompileOptions& options, TempAllocator* temp,
                MIRGraph* graph, CompilerConstraintList* constraints,
                BaselineInspector* inspector, CompileInfo* info,
                const OptimizationInfo* optimizationInfo, BaselineFrameInspector* baselineFrame,
                size_t inliningDepth = 0, uint32_t loopDepth = 0);
 
     // Callers of build() and buildInline() should always check whether the
     // call overrecursed, if false is returned.  Overrecursion is not
@@ -963,17 +963,17 @@ class IonBuilder
     CompilerConstraintList* constraints() {
         return constraints_;
     }
 
     bool isInlineBuilder() const {
         return callerBuilder_ != nullptr;
     }
 
-    const JSAtomState& names() { return compartment->runtime()->names(); }
+    const JSAtomState& names() { return realm->runtime()->names(); }
 
     bool hadActionableAbort() const {
         MOZ_ASSERT(!actionableAbortScript_ ||
                    (actionableAbortPc_ && actionableAbortMessage_));
         return actionableAbortScript_ != nullptr;
     }
 
     TraceLoggerThread *traceLogger() {
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -2572,17 +2572,17 @@ IonBuilder::inlineObjectToString(CallInf
         return InliningStatus_NotInlined;
 
     // Don't optimize if this might be a proxy.
     using ForAllResult = TemporaryTypeSet::ForAllResult;
     if (types->forAllClasses(constraints(), IsProxyClass) != ForAllResult::ALL_FALSE)
         return InliningStatus_NotInlined;
 
     // Make sure there's no Symbol.toStringTag property.
-    jsid toStringTag = SYMBOL_TO_JSID(compartment->runtime()->wellKnownSymbols().toStringTag);
+    jsid toStringTag = SYMBOL_TO_JSID(realm->runtime()->wellKnownSymbols().toStringTag);
     bool res;
     MOZ_TRY_VAR(res, testNotDefinedProperty(arg, toStringTag));
     if (!res)
         return InliningStatus_NotInlined;
 
     // At this point we know we're going to inline this.
     callInfo.setImplicitlyUsedUnchecked();
 
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -29,17 +29,17 @@ namespace js {
 namespace jit {
 
 class MIRGraph;
 class OptimizationInfo;
 
 class MIRGenerator
 {
   public:
-    MIRGenerator(CompileCompartment* compartment, const JitCompileOptions& options,
+    MIRGenerator(CompileRealm* realm, const JitCompileOptions& options,
                  TempAllocator* alloc, MIRGraph* graph,
                  const CompileInfo* info, const OptimizationInfo* optimizationInfo);
 
     void initMinWasmHeapLength(uint32_t init) {
         minWasmHeapLength_ = init;
     }
 
     TempAllocator& alloc() {
@@ -170,17 +170,17 @@ class MIRGenerator
 
     // When aborting with AbortReason::PreliminaryObjects, all groups with
     // preliminary objects which haven't been analyzed yet.
     const ObjectGroupVector& abortedPreliminaryGroups() const {
         return abortedPreliminaryGroups_;
     }
 
   public:
-    CompileCompartment* compartment;
+    CompileRealm* realm;
     CompileRuntime* runtime;
 
   protected:
     const CompileInfo* info_;
     const OptimizationInfo* optimizationInfo_;
     TempAllocator* alloc_;
     MIRGraph* graph_;
     AbortReasonOr<Ok> offThreadStatus_;
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -12,38 +12,38 @@
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "wasm/WasmTypes.h"
 
 using namespace js;
 using namespace js::jit;
 using mozilla::Swap;
 
-MIRGenerator::MIRGenerator(CompileCompartment* compartment, const JitCompileOptions& options,
+MIRGenerator::MIRGenerator(CompileRealm* realm, const JitCompileOptions& options,
                            TempAllocator* alloc, MIRGraph* graph, const CompileInfo* info,
                            const OptimizationInfo* optimizationInfo)
-  : compartment(compartment),
-    runtime(compartment ? compartment->runtime() : nullptr),
+  : realm(realm),
+    runtime(realm ? realm->runtime() : nullptr),
     info_(info),
     optimizationInfo_(optimizationInfo),
     alloc_(alloc),
     graph_(graph),
     offThreadStatus_(Ok()),
     abortedPreliminaryGroups_(*alloc_),
     cancelBuild_(false),
     wasmMaxStackArgBytes_(0),
     needsOverrecursedCheck_(false),
     needsStaticStackAlignment_(false),
     usesSimd_(false),
     cachedUsesSimd_(false),
     modifiesFrameArguments_(false),
     instrumentedProfiling_(false),
     instrumentedProfilingIsCached_(false),
     safeForMinorGC_(true),
-    stringsCanBeInNursery_(compartment ? compartment->zone()->canNurseryAllocateStrings() : false),
+    stringsCanBeInNursery_(realm ? realm->zone()->canNurseryAllocateStrings() : false),
     minWasmHeapLength_(0),
     options(options),
     gs_(alloc)
 { }
 
 bool
 MIRGenerator::usesSimd()
 {
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -630,17 +630,17 @@ MacroAssembler::branchTestProxyHandlerFa
     Address familyAddr(scratch, BaseProxyHandler::offsetOfFamily());
     branchPtr(cond, familyAddr, ImmPtr(handlerp), label);
 }
 
 void
 MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label)
 {
     MOZ_ASSERT(cond == Zero || cond == NonZero);
-    CompileZone* zone = GetJitContext()->compartment->zone();
+    CompileZone* zone = GetJitContext()->realm->zone();
     AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier());
     branchTest32(cond, needsBarrierAddr, Imm32(0x1), label);
 }
 
 void
 MacroAssembler::branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why,
                                      Label* label)
 {
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -818,19 +818,19 @@ MacroAssembler::checkAllocatorState(Labe
 
 #ifdef JS_GC_ZEAL
     // Don't execute the inline path if gc zeal or tracing are active.
     branch32(Assembler::NotEqual,
              AbsoluteAddress(GetJitContext()->runtime->addressOfGCZealModeBits()), Imm32(0),
              fail);
 #endif
 
-    // Don't execute the inline path if the compartment has an object metadata callback,
+    // Don't execute the inline path if the realm has an object metadata callback,
     // as the metadata to use for the object may vary between executions of the op.
-    if (GetJitContext()->compartment->hasAllocationMetadataBuilder())
+    if (GetJitContext()->realm->hasAllocationMetadataBuilder())
         jump(fail);
 }
 
 bool
 MacroAssembler::shouldNurseryAllocate(gc::AllocKind allocKind, gc::InitialHeap initialHeap)
 {
     // Note that Ion elides barriers on writes to objects known to be in the
     // nursery, so any allocation that can be made into the nursery must be made
@@ -854,17 +854,17 @@ MacroAssembler::nurseryAllocateObject(Re
     // interpreter.
     if (nDynamicSlots >= Nursery::MaxNurseryBufferSize / sizeof(Value)) {
         jump(fail);
         return;
     }
 
     // No explicit check for nursery.isEnabled() is needed, as the comparison
     // with the nursery's end will always fail in such cases.
-    CompileZone* zone = GetJitContext()->compartment->zone();
+    CompileZone* zone = GetJitContext()->realm->zone();
     int thingSize = int(gc::Arena::thingSize(allocKind));
     int totalSize = thingSize + nDynamicSlots * sizeof(HeapSlot);
     MOZ_ASSERT(totalSize % gc::CellAlignBytes == 0);
     loadPtr(AbsoluteAddress(zone->addressOfNurseryPosition()), result);
     computeEffectiveAddress(Address(result, totalSize), temp);
     branchPtr(Assembler::Below, AbsoluteAddress(zone->addressOfNurseryCurrentEnd()), temp, fail);
     storePtr(temp, AbsoluteAddress(zone->addressOfNurseryPosition()));
 
@@ -873,17 +873,17 @@ MacroAssembler::nurseryAllocateObject(Re
         storePtr(temp, Address(result, NativeObject::offsetOfSlots()));
     }
 }
 
 // Inlined version of FreeSpan::allocate. This does not fill in slots_.
 void
 MacroAssembler::freeListAllocate(Register result, Register temp, gc::AllocKind allocKind, Label* fail)
 {
-    CompileZone* zone = GetJitContext()->compartment->zone();
+    CompileZone* zone = GetJitContext()->realm->zone();
     int thingSize = int(gc::Arena::thingSize(allocKind));
 
     Label fallback;
     Label success;
 
     // Load the first and last offsets of |zone|'s free list for |allocKind|.
     // If there is no room remaining in the span, fall back to get the next one.
     loadPtr(AbsoluteAddress(zone->addressOfFreeList(allocKind)), temp);
@@ -927,17 +927,17 @@ MacroAssembler::callMallocStub(size_t nb
     MOZ_ASSERT(nbytes <= INT32_MAX);
 
     if (regZone != result)
         push(regZone);
     if (regNBytes != result)
         push(regNBytes);
 
     move32(Imm32(nbytes), regNBytes);
-    movePtr(ImmPtr(GetJitContext()->compartment->zone()), regZone);
+    movePtr(ImmPtr(GetJitContext()->realm->zone()), regZone);
     call(GetJitContext()->runtime->jitRuntime()->mallocStub());
     if (regReturn != result)
         movePtr(regReturn, result);
 
     if (regNBytes != result)
         pop(regNBytes);
     if (regZone != result)
         pop(regZone);
@@ -1036,17 +1036,17 @@ void
 MacroAssembler::nurseryAllocateString(Register result, Register temp, gc::AllocKind allocKind,
                                       Label* fail)
 {
     MOZ_ASSERT(IsNurseryAllocable(allocKind));
 
     // No explicit check for nursery.isEnabled() is needed, as the comparison
     // with the nursery's end will always fail in such cases.
 
-    CompileZone* zone = GetJitContext()->compartment->zone();
+    CompileZone* zone = GetJitContext()->realm->zone();
     int thingSize = int(gc::Arena::thingSize(allocKind));
     int totalSize = js::Nursery::stringHeaderSize() + thingSize;
     MOZ_ASSERT(totalSize % gc::CellAlignBytes == 0);
 
     // The nursery position (allocation pointer) and the nursery end are stored
     // very close to each other. In practice, the zone will probably be close
     // (within 32 bits) as well. If so, use relative offsets between them, to
     // avoid multiple 64-bit immediate loads.
@@ -2912,17 +2912,18 @@ MacroAssembler::Push(jsid id, Register s
         // If we're pushing a gcthing, then we can't just push the tagged jsid
         // value since the GC won't have any idea that the push instruction
         // carries a reference to a gcthing.  Need to unpack the pointer,
         // push it using ImmGCPtr, and then rematerialize the id at runtime.
 
         if (JSID_IS_STRING(id)) {
             JSString* str = JSID_TO_STRING(id);
             MOZ_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
-            MOZ_ASSERT(JSID_TYPE_STRING == 0x0);
+            static_assert(JSID_TYPE_STRING == 0,
+                          "need to orPtr JSID_TYPE_STRING tag if it's not 0");
             Push(ImmGCPtr(str));
         } else {
             MOZ_ASSERT(JSID_IS_SYMBOL(id));
             JS::Symbol* sym = JSID_TO_SYMBOL(id);
             movePtr(ImmGCPtr(sym), scratchReg);
             orPtr(Imm32(JSID_TYPE_SYMBOL), scratchReg);
             Push(scratchReg);
         }
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -152,18 +152,18 @@ struct Imm64
     inline Imm32 firstHalf() const;
     inline Imm32 secondHalf() const;
 };
 
 #ifdef DEBUG
 static inline bool
 IsCompilingWasm()
 {
-    // wasm compilation pushes a JitContext with a null JSCompartment.
-    return GetJitContext()->compartment == nullptr;
+    // wasm compilation pushes a JitContext with a null Realm.
+    return GetJitContext()->realm == nullptr;
 }
 #endif
 
 // Pointer to be embedded as an immediate in an instruction.
 struct ImmPtr
 {
     void* value;
 
--- a/js/src/jit/shared/CodeGenerator-shared-inl.h
+++ b/js/src/jit/shared/CodeGenerator-shared-inl.h
@@ -408,16 +408,16 @@ CodeGeneratorShared::verifyStoreDisassem
     verifyHeapAccessDisassembly(begin, end, false, type, mem, alloc);
 }
 
 inline bool
 CodeGeneratorShared::isGlobalObject(JSObject* object)
 {
     // Calling object->is<GlobalObject>() is racy because this relies on
     // checking the group and this can be changed while we are compiling off the
-    // main thread.
-    return object == gen->compartment->maybeGlobal();
+    // main thread. Note that we only check for the script realm's global here.
+    return object == gen->realm->maybeGlobal();
 }
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_CodeGenerator_shared_inl_h */
--- a/js/src/jsapi-tests/testJitMinimalFunc.h
+++ b/js/src/jsapi-tests/testJitMinimalFunc.h
@@ -38,17 +38,17 @@ struct MinimalFunc : MinimalAlloc
     MIRGraph graph;
     MIRGenerator mir;
     uint32_t numParams;
 
     MinimalFunc()
       : options(),
         info(0),
         graph(&alloc),
-        mir(static_cast<CompileCompartment*>(nullptr), options, &alloc, &graph,
+        mir(static_cast<CompileRealm*>(nullptr), options, &alloc, &graph,
             &info, static_cast<const OptimizationInfo*>(nullptr)),
         numParams(0)
     { }
 
     MBasicBlock* createEntryBlock()
     {
         MBasicBlock* block = MBasicBlock::New(graph, info, nullptr, MBasicBlock::NORMAL);
         graph.addBlock(block);
--- a/js/src/jsapi-tests/testSavedStacks.cpp
+++ b/js/src/jsapi-tests/testSavedStacks.cpp
@@ -10,18 +10,17 @@
 #include "builtin/TestingFunctions.h"
 #include "jsapi-tests/tests.h"
 #include "vm/ArrayObject.h"
 #include "vm/JSCompartment.h"
 #include "vm/SavedStacks.h"
 
 BEGIN_TEST(testSavedStacks_withNoStack)
 {
-    JSCompartment* compartment = js::GetContextCompartment(cx);
-    JS::Realm* realm = JS::GetRealmForCompartment(compartment);
+    JS::Realm* realm = cx->realm();
     realm->setAllocationMetadataBuilder(&js::SavedStacks::metadataBuilder);
     JS::RootedObject obj(cx, js::NewDenseEmptyArray(cx));
     realm->setAllocationMetadataBuilder(nullptr);
     return true;
 }
 END_TEST(testSavedStacks_withNoStack)
 
 BEGIN_TEST(testSavedStacks_ApiDefaultValues)
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -27,20 +27,16 @@ bool JSAPITest::init()
     if (!global)
         return false;
     JS::EnterRealm(cx, global);
     return true;
 }
 
 void JSAPITest::uninit()
 {
-    if (oldCompartment) {
-        JS::LeaveRealm(cx, JS::GetRealmForCompartment(oldCompartment));
-        oldCompartment = nullptr;
-    }
     if (global) {
         JS::LeaveRealm(cx, nullptr);
         global = nullptr;
     }
     if (cx) {
         JS_EndRequest(cx);
         destroyContext();
         cx = nullptr;
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -68,19 +68,18 @@ class JSAPITest
   public:
     static JSAPITest* list;
     JSAPITest* next;
 
     JSContext* cx;
     JS::PersistentRootedObject global;
     bool knownFail;
     JSAPITestString msgs;
-    JSCompartment* oldCompartment;
 
-    JSAPITest() : cx(nullptr), knownFail(false), oldCompartment(nullptr) {
+    JSAPITest() : cx(nullptr), knownFail(false) {
         next = list;
         list = this;
     }
 
     virtual ~JSAPITest() {
         MOZ_RELEASE_ASSERT(!cx);
         MOZ_RELEASE_ASSERT(!global);
     }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4609,17 +4609,17 @@ JS_GetLatin1FlatStringChars(const JS::Au
 
 extern JS_PUBLIC_API(const char16_t*)
 JS_GetTwoByteFlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str);
 
 static MOZ_ALWAYS_INLINE JSFlatString*
 JSID_TO_FLAT_STRING(jsid id)
 {
     MOZ_ASSERT(JSID_IS_STRING(id));
-    return (JSFlatString*)(JSID_BITS(id));
+    return (JSFlatString*)JSID_TO_STRING(id);
 }
 
 static MOZ_ALWAYS_INLINE JSFlatString*
 JS_ASSERT_STRING_IS_FLAT(JSString* str)
 {
     MOZ_ASSERT(JS_StringIsFlat(str));
     return (JSFlatString*)str;
 }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -2666,42 +2666,42 @@ bool IdMatchesAtom(jsid id, JSString* at
  *   to do any dynamic checks.
  *
  * Thus, it is only the rare third case which needs this function, which
  * handles any JSAtom* that is known not to be representable with an int jsid.
  */
 static MOZ_ALWAYS_INLINE jsid
 NON_INTEGER_ATOM_TO_JSID(JSAtom* atom)
 {
-    MOZ_ASSERT(((size_t)atom & 0x7) == 0);
-    jsid id = JSID_FROM_BITS((size_t)atom);
+    MOZ_ASSERT(((size_t)atom & JSID_TYPE_MASK) == 0);
+    jsid id = JSID_FROM_BITS((size_t)atom | JSID_TYPE_STRING);
     MOZ_ASSERT(js::detail::IdMatchesAtom(id, atom));
     return id;
 }
 
 static MOZ_ALWAYS_INLINE jsid
 NON_INTEGER_ATOM_TO_JSID(JSString* atom)
 {
-    MOZ_ASSERT(((size_t)atom & 0x7) == 0);
-    jsid id = JSID_FROM_BITS((size_t)atom);
+    MOZ_ASSERT(((size_t)atom & JSID_TYPE_MASK) == 0);
+    jsid id = JSID_FROM_BITS((size_t)atom | JSID_TYPE_STRING);
     MOZ_ASSERT(js::detail::IdMatchesAtom(id, atom));
     return id;
 }
 
 /* All strings stored in jsids are atomized, but are not necessarily property names. */
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_ATOM(jsid id)
 {
     return JSID_IS_STRING(id);
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_ATOM(jsid id, JSAtom* atom)
 {
-    return id == JSID_FROM_BITS((size_t)atom);
+    return id == NON_INTEGER_ATOM_TO_JSID(atom);
 }
 
 static MOZ_ALWAYS_INLINE JSAtom*
 JSID_TO_ATOM(jsid id)
 {
     return (JSAtom*)JSID_TO_STRING(id);
 }
 
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -1966,17 +1966,17 @@ HelperThread::handleIonWorkload(AutoLock
 
         TraceLoggerThread* logger = TraceLoggerForCurrentThread();
         TraceLoggerEvent event(TraceLogger_AnnotateScripts, builder->script());
         AutoTraceLog logScript(logger, event);
         AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
 
         AutoSetContextRuntime ascr(rt);
         jit::JitContext jctx(jit::CompileRuntime::get(rt),
-                             jit::CompileCompartment::get(builder->script()->compartment()),
+                             jit::CompileRealm::get(builder->script()->realm()),
                              &builder->alloc());
         builder->setBackgroundCodegen(jit::CompileBackEnd(builder));
     }
 
     FinishOffThreadIonCompile(builder, locked);
 
     // Ping the main thread so that the compiled code can be incorporated at the
     // next interrupt callback.
--- a/js/src/vm/Id.cpp
+++ b/js/src/vm/Id.cpp
@@ -2,14 +2,12 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "js/Id.h"
 #include "js/RootingAPI.h"
 
-const jsid JSID_EMPTY = jsid::fromRawBits(size_t(JSID_TYPE_SYMBOL));
-
 static const jsid voidIdValue = JSID_VOID;
 static const jsid emptyIdValue = JSID_EMPTY;
 const JS::HandleId JSID_VOIDHANDLE = JS::HandleId::fromMarkedLocation(&voidIdValue);
 const JS::HandleId JSID_EMPTYHANDLE = JS::HandleId::fromMarkedLocation(&emptyIdValue);
--- a/js/src/vm/JSAtom-inl.h
+++ b/js/src/vm/JSAtom-inl.h
@@ -23,17 +23,17 @@ inline jsid
 AtomToId(JSAtom* atom)
 {
     JS_STATIC_ASSERT(JSID_INT_MIN == 0);
 
     uint32_t index;
     if (atom->isIndex(&index) && index <= JSID_INT_MAX)
         return INT_TO_JSID(int32_t(index));
 
-    return JSID_FROM_BITS(size_t(atom));
+    return JSID_FROM_BITS(size_t(atom) | JSID_TYPE_STRING);
 }
 
 // Use the NameToId method instead!
 inline jsid
 AtomToId(PropertyName* name) = delete;
 
 MOZ_ALWAYS_INLINE bool
 ValueToIntId(const Value& v, jsid* id)
--- a/js/src/vm/JSAtom.cpp
+++ b/js/src/vm/JSAtom.cpp
@@ -580,17 +580,17 @@ js::IndexToIdSlow(JSContext* cx, uint32_
     char16_t buf[UINT32_CHAR_BUFFER_LENGTH];
     RangedPtr<char16_t> end(ArrayEnd(buf), buf, ArrayEnd(buf));
     RangedPtr<char16_t> start = BackfillIndexInCharBuffer(index, end);
 
     JSAtom* atom = AtomizeChars(cx, start.get(), end - start);
     if (!atom)
         return false;
 
-    idp.set(JSID_FROM_BITS((size_t)atom));
+    idp.set(JSID_FROM_BITS((size_t)atom | JSID_TYPE_STRING));
     return true;
 }
 
 template <AllowGC allowGC>
 static JSAtom*
 ToAtomSlow(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType arg)
 {
     MOZ_ASSERT(!arg.isString());
--- a/js/src/vm/JSCompartment.cpp
+++ b/js/src/vm/JSCompartment.cpp
@@ -779,18 +779,18 @@ Realm::sweepAfterMinorGC()
     objects_.sweepAfterMinorGC();
 }
 
 void
 JSCompartment::sweepAfterMinorGC(JSTracer* trc)
 {
     crossCompartmentWrappers.sweepAfterMinorGC(trc);
 
-    Realm* realm = JS::GetRealmForCompartment(this);
-    realm->sweepAfterMinorGC();
+    for (RealmsInCompartmentIter r(this); !r.done(); r.next())
+        r->sweepAfterMinorGC();
 }
 
 void
 Realm::sweepSavedStacks()
 {
     savedStacks_.sweep();
 }
 
@@ -938,18 +938,18 @@ Realm::fixupAfterMovingGC()
     fixupScriptMapsAfterMovingGC();
 }
 
 void
 JSCompartment::fixupAfterMovingGC()
 {
     MOZ_ASSERT(zone()->isGCCompacting());
 
-    Realm* realm = JS::GetRealmForCompartment(this);
-    realm->fixupAfterMovingGC();
+    for (RealmsInCompartmentIter r(this); !r.done(); r.next())
+        r->fixupAfterMovingGC();
 
     // Sweep the wrapper map to update values (wrapper objects) in this
     // compartment that may have been moved.
     sweepCrossCompartmentWrappers();
 }
 
 void
 Realm::fixupGlobal()
--- a/js/src/vm/JSCompartment.h
+++ b/js/src/vm/JSCompartment.h
@@ -554,16 +554,19 @@ struct JSCompartment
 {
   protected:
     JS::Zone*                    zone_;
     JSRuntime*                   runtime_;
 
   private:
     js::WrapperMap crossCompartmentWrappers;
 
+    using RealmVector = js::Vector<JS::Realm*, 1, js::SystemAllocPolicy>;
+    RealmVector realms_;
+
   public:
     /*
      * During GC, stores the head of a list of incoming pointers from gray cells.
      *
      * The objects in the list are either cross-compartment wrappers, or
      * debugger wrapper objects.  The list link is either in the second extra
      * slot for the former, or a special slot for the latter.
      */
@@ -587,16 +590,20 @@ struct JSCompartment
     }
 
     // Note: Unrestricted access to the zone's runtime from an arbitrary
     // thread can easily lead to races. Use this method very carefully.
     JSRuntime* runtimeFromAnyThread() const {
         return runtime_;
     }
 
+    RealmVector& realms() {
+        return realms_;
+    }
+
     void assertNoCrossCompartmentWrappers() {
         MOZ_ASSERT(crossCompartmentWrappers.empty());
     }
 
   protected:
     void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                 size_t* crossCompartmentWrappersArg);
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -219,18 +219,22 @@ JSRuntime::init(JSContext* cx, uint32_t 
     if (!atomsZone || !atomsZone->init(true))
         return false;
 
     JS::RealmOptions options;
     ScopedJSDeletePtr<Realm> atomsRealm(js_new<Realm>(atomsZone.get(), options));
     if (!atomsRealm || !atomsRealm->init(nullptr))
         return false;
 
+    JSCompartment* atomsComp = atomsRealm->compartment();
+    if (!atomsComp->realms().append(atomsRealm))
+        return false;
+
     gc.atomsZone = atomsZone.get();
-    if (!atomsZone->compartments().append(atomsRealm->compartment()))
+    if (!atomsZone->compartments().append(atomsComp))
         return false;
 
     atomsRealm->setIsSystem(true);
     atomsRealm->setIsAtomsRealm();
 
     atomsZone.forget();
     this->atomsRealm_ = atomsRealm.forget();
 
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -134,31 +134,33 @@ class AsmJSGlobal
     struct CacheablePod {
         Which which_;
         union V {
             struct {
                 VarInitKind initKind_;
                 union U {
                     ValType importType_;
                     Val val_;
+                    U() : val_(Val()) {}
                 } u;
             } var;
             uint32_t ffiIndex_;
             Scalar::Type viewType_;
             AsmJSMathBuiltinFunction mathBuiltinFunc_;
             AsmJSAtomicsBuiltinFunction atomicsBuiltinFunc_;
             SimdType simdCtorType_;
             struct {
                 SimdType type_;
                 SimdOperation which_;
             } simdOp;
             struct {
                 ConstantKind kind_;
                 double value_;
             } constant;
+            V() : ffiIndex_(0) {}
         } u;
     } pod;
     CacheableChars field_;
 
     friend class ModuleValidator;
 
   public:
     AsmJSGlobal() = default;
@@ -7675,17 +7677,17 @@ ValidateGlobalVariable(JSContext* cx, co
       case AsmJSGlobal::InitImport: {
         RootedValue v(cx);
         if (!GetDataProperty(cx, importVal, global.field(), &v))
             return false;
 
         if (!v.isPrimitive() && !HasPureCoercion(cx, v))
             return LinkFail(cx, "Imported values must be primitives");
 
-        switch (global.varInitImportType()) {
+        switch (global.varInitImportType().code()) {
           case ValType::I32: {
             int32_t i32;
             if (!ToInt32(cx, v, &i32))
                 return false;
             *val = Val(uint32_t(i32));
             return true;
           }
           case ValType::I64:
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -156,17 +156,20 @@ class AstSig : public AstBase
         return name_;
     }
     bool operator==(const AstSig& rhs) const {
         return ret() == rhs.ret() && EqualContainers(args(), rhs.args());
     }
 
     typedef const AstSig& Lookup;
     static HashNumber hash(Lookup sig) {
-        return AddContainerToHash(sig.args(), HashNumber(sig.ret()));
+        HashNumber hn = HashNumber(sig.ret());
+        for (ValType vt : sig.args())
+            hn = mozilla::AddToHash(hn, vt.code());
+        return hn;
     }
     static bool match(const AstSig* lhs, Lookup rhs) {
         return *lhs == rhs;
     }
 };
 
 const uint32_t AstNodeUnknownOffset = 0;
 
@@ -796,17 +799,17 @@ class AstFunc : public AstNode
 class AstGlobal : public AstNode
 {
     AstName name_;
     bool isMutable_;
     ValType type_;
     Maybe<AstExpr*> init_;
 
   public:
-    AstGlobal() : isMutable_(false), type_(ValType(TypeCode::Limit))
+    AstGlobal() : isMutable_(false), type_(ValType())
     {}
 
     explicit AstGlobal(AstName name, ValType type, bool isMutable,
                        const Maybe<AstExpr*>& init = Maybe<AstExpr*>())
       : name_(name), isMutable_(isMutable), type_(type), init_(init)
     {}
 
     AstName name() const { return name_; }
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1042,17 +1042,17 @@ BaseLocalIter::settle()
           default:
             MOZ_CRASH("Argument type");
         }
         return;
     }
 
     MOZ_ASSERT(argsIter_.done());
     if (index_ < locals_.length()) {
-        switch (locals_[index_]) {
+        switch (locals_[index_].code()) {
           case ValType::I32:
           case ValType::I64:
           case ValType::F32:
           case ValType::F64:
           case ValType::AnyRef:
             mirType_ = ToMIRType(locals_[index_]);
             frameOffset_ = pushLocal(MIRTypeToSize(mirType_));
             break;
@@ -3625,17 +3625,17 @@ class BaseCompiler final : public BaseCo
     // entry for stackArgAreaSize() and for how to pass arguments...
     //
     // But at least we could reduce the cost of stackArgAreaSize() by
     // first reading the argument types into a (reusable) vector, then
     // we have the outgoing size at low cost, and then we can pass
     // args based on the info we read.
 
     void passArg(ValType type, const Stk& arg, FunctionCall* call) {
-        switch (type) {
+        switch (type.code()) {
           case ValType::I32: {
             ABIArg argLoc = call->abi.next(MIRType::Int32);
             if (argLoc.kind() == ABIArg::Stack) {
                 ScratchI32 scratch(*this);
                 loadI32(arg, scratch);
                 masm.store32(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
             } else {
                 loadI32(arg, RegI32(argLoc.gpr()));
@@ -7164,17 +7164,17 @@ BaseCompiler::emitBranchSetup(BranchStat
         latentIntCmp_ = Assembler::NotEqual;
         latentType_ = ValType::I32;
         b->i32.lhs = popI32();
         b->i32.rhsImm = true;
         b->i32.imm = 0;
         break;
       }
       case LatentOp::Compare: {
-        switch (latentType_) {
+        switch (latentType_.code()) {
           case ValType::I32: {
             if (popConstI32(&b->i32.imm)) {
                 b->i32.lhs = popI32();
                 b->i32.rhsImm = true;
             } else {
                 pop2xI32(&b->i32.lhs, &b->i32.rhs);
                 b->i32.rhsImm = false;
             }
@@ -7195,17 +7195,17 @@ BaseCompiler::emitBranchSetup(BranchStat
           }
           default: {
             MOZ_CRASH("Unexpected type for LatentOp::Compare");
           }
         }
         break;
       }
       case LatentOp::Eqz: {
-        switch (latentType_) {
+        switch (latentType_.code()) {
           case ValType::I32: {
             latentIntCmp_ = Assembler::Equal;
             b->i32.lhs = popI32();
             b->i32.rhsImm = true;
             b->i32.imm = 0;
             break;
           }
           case ValType::I64: {
@@ -7224,17 +7224,17 @@ BaseCompiler::emitBranchSetup(BranchStat
     }
 
     maybeUnreserveJoinReg(b->resultType);
 }
 
 void
 BaseCompiler::emitBranchPerform(BranchState* b)
 {
-    switch (latentType_) {
+    switch (latentType_.code()) {
       case ValType::I32: {
         if (b->i32.rhsImm) {
             jumpConditionalWithJoinReg(b, latentIntCmp_, b->i32.lhs, Imm32(b->i32.imm));
         } else {
             jumpConditionalWithJoinReg(b, latentIntCmp_, b->i32.lhs, b->i32.rhs);
             freeI32(b->i32.rhs);
         }
         freeI32(b->i32.lhs);
@@ -8091,17 +8091,17 @@ BaseCompiler::emitGetLocal()
 
     if (deadCode_)
         return true;
 
     // Local loads are pushed unresolved, ie, they may be deferred
     // until needed, until they may be affected by a store, or until a
     // sync.  This is intended to reduce register pressure.
 
-    switch (locals_[slot]) {
+    switch (locals_[slot].code()) {
       case ValType::I32:
         pushLocalI32(slot);
         break;
       case ValType::I64:
         pushLocalI64(slot);
         break;
       case ValType::F64:
         pushLocalF64(slot);
@@ -8122,17 +8122,17 @@ BaseCompiler::emitGetLocal()
 template<bool isSetLocal>
 bool
 BaseCompiler::emitSetOrTeeLocal(uint32_t slot)
 {
     if (deadCode_)
         return true;
 
     bceLocalIsUpdated(slot);
-    switch (locals_[slot]) {
+    switch (locals_[slot].code()) {
       case ValType::I32: {
         RegI32 rv = popI32();
         syncLocal(slot);
         fr.storeLocalI32(rv, localFromSlot(slot, MIRType::Int32));
         if (isSetLocal)
             freeI32(rv);
         else
             pushI32(rv);
@@ -8214,17 +8214,17 @@ BaseCompiler::emitGetGlobal()
 
     if (deadCode_)
         return true;
 
     const GlobalDesc& global = env_.globals[id];
 
     if (global.isConstant()) {
         Val value = global.constantValue();
-        switch (value.type()) {
+        switch (value.type().code()) {
           case ValType::I32:
             pushI32(value.i32());
             break;
           case ValType::I64:
             pushI64(value.i64());
             break;
           case ValType::F32:
             pushF32(value.f32());
@@ -8233,17 +8233,17 @@ BaseCompiler::emitGetGlobal()
             pushF64(value.f64());
             break;
           default:
             MOZ_CRASH("Global constant type");
         }
         return true;
     }
 
-    switch (global.type()) {
+    switch (global.type().code()) {
       case ValType::I32: {
         RegI32 rv = needI32();
         ScratchI32 tmp(*this);
         masm.load32(addressOfGlobalVar(global, tmp), rv);
         pushI32(rv);
         break;
       }
       case ValType::I64: {
@@ -8282,17 +8282,17 @@ BaseCompiler::emitSetGlobal()
     if (!iter_.readSetGlobal(&id, &unused_value))
         return false;
 
     if (deadCode_)
         return true;
 
     const GlobalDesc& global = env_.globals[id];
 
-    switch (global.type()) {
+    switch (global.type().code()) {
       case ValType::I32: {
         RegI32 rv = popI32();
         ScratchI32 tmp(*this);
         masm.store32(rv, addressOfGlobalVar(global, tmp));
         freeI32(rv);
         break;
       }
       case ValType::I64: {
@@ -8448,17 +8448,17 @@ BaseCompiler::maybeLoadTlsForAccess(cons
 bool
 BaseCompiler::loadCommon(MemoryAccessDesc* access, ValType type)
 {
     AccessCheck check;
 
     RegI32 tls, temp1, temp2, temp3;
     needLoadTemps(*access, &temp1, &temp2, &temp3);
 
-    switch (type) {
+    switch (type.code()) {
       case ValType::I32: {
         RegI32 rp = popMemoryAccess(access, &check);
 #ifdef JS_CODEGEN_ARM
         RegI32 rv = IsUnaligned(*access) ? needI32() : rp;
 #else
         RegI32 rv = rp;
 #endif
         tls = maybeLoadTlsForAccess(check);
@@ -8537,17 +8537,17 @@ BaseCompiler::emitLoad(ValType type, Sca
 bool
 BaseCompiler::storeCommon(MemoryAccessDesc* access, ValType resultType)
 {
     AccessCheck check;
 
     RegI32 tls;
     RegI32 temp = needStoreTemp(*access, resultType);
 
-    switch (resultType) {
+    switch (resultType.code()) {
       case ValType::I32: {
         RegI32 rv = popI32();
         RegI32 rp = popMemoryAccess(access, &check);
         tls = maybeLoadTlsForAccess(check);
         if (!store(access, &check, tls, rp, AnyReg(rv), temp))
             return false;
         freeI32(rp);
         freeI32(rv);
@@ -8625,17 +8625,17 @@ BaseCompiler::emitSelect()
     }
 
     // I32 condition on top, then false, then true.
 
     Label done;
     BranchState b(&done);
     emitBranchSetup(&b);
 
-    switch (NonAnyToValType(type)) {
+    switch (NonAnyToValType(type).code()) {
       case ValType::I32: {
         RegI32 r, rs;
         pop2xI32(&r, &rs);
         emitBranchPerform(&b);
         moveI32(rs, r);
         masm.bind(&done);
         freeI32(rs);
         pushI32(r);
@@ -9146,17 +9146,17 @@ BaseCompiler::emitWait(ValType type, uin
     Nothing nothing;
     LinearMemoryAddress<Nothing> addr;
     if (!iter_.readWait(&addr, type, byteSize, &nothing, &nothing))
         return false;
 
     if (deadCode_)
         return true;
 
-    switch (type) {
+    switch (type.code()) {
       case ValType::I32:
         emitInstanceCall(lineOrBytecode, SigPIIL_, ExprType::I32, SymbolicAddress::WaitI32);
         break;
       case ValType::I64:
         emitInstanceCall(lineOrBytecode, SigPILL_, ExprType::I32, SymbolicAddress::WaitI64);
         break;
       default:
         MOZ_CRASH();
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -69,40 +69,16 @@ enum class TypeCode
     Func                                 = 0x60,  // SLEB128(-0x20)
 
     // Special code representing the block signature ()->()
     BlockVoid                            = 0x40,  // SLEB128(-0x40)
 
     Limit                                = 0x80
 };
 
-enum class ValType
-{
-    I32                                  = uint8_t(TypeCode::I32),
-    I64                                  = uint8_t(TypeCode::I64),
-    F32                                  = uint8_t(TypeCode::F32),
-    F64                                  = uint8_t(TypeCode::F64),
-
-    AnyRef                               = uint8_t(TypeCode::AnyRef),
-
-    // ------------------------------------------------------------------------
-    // The rest of these types are currently only emitted internally when
-    // compiling asm.js and are rejected by wasm validation.
-
-    I8x16                                = uint8_t(TypeCode::I8x16),
-    I16x8                                = uint8_t(TypeCode::I16x8),
-    I32x4                                = uint8_t(TypeCode::I32x4),
-    F32x4                                = uint8_t(TypeCode::F32x4),
-    B8x16                                = uint8_t(TypeCode::B8x16),
-    B16x8                                = uint8_t(TypeCode::B16x8),
-    B32x4                                = uint8_t(TypeCode::B32x4)
-};
-
-typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
-
 // The representation of a null reference value throughout the compiler.
 
 static const intptr_t NULLREF_VALUE = intptr_t((void*)nullptr);
 
 enum class DefinitionKind
 {
     Function                             = 0x00,
     Table                                = 0x01,
--- a/js/src/wasm/WasmBuiltins.cpp
+++ b/js/src/wasm/WasmBuiltins.cpp
@@ -344,17 +344,17 @@ CoerceInPlace_JitEntry(int funcExportInd
 {
     JSContext* cx = CallingActivation()->cx();
 
     const Code& code = tlsData->instance->code();
     const FuncExport& fe = code.metadata(code.stableTier()).funcExports[funcExportIndex];
 
     for (size_t i = 0; i < fe.sig().args().length(); i++) {
         HandleValue arg = HandleValue::fromMarkedLocation(&argv[i]);
-        switch (fe.sig().args()[i]) {
+        switch (fe.sig().args()[i].code()) {
           case ValType::I32: {
             int32_t i32;
             if (!ToInt32(cx, arg, &i32))
                 return false;
             argv[i] = Int32Value(i32);
             break;
           }
           case ValType::F32:
@@ -1049,17 +1049,17 @@ ToBuiltinABIFunctionType(const Sig& sig)
       case ExprType::F64: abiType = ArgType_Double << RetType_Shift; break;
       default: return Nothing();
     }
 
     if ((args.length() + 1) > (sizeof(uint32_t) * 8 / ArgType_Shift))
         return Nothing();
 
     for (size_t i = 0; i < args.length(); i++) {
-        switch (args[i]) {
+        switch (args[i].code()) {
           case ValType::F32: abiType |= (ArgType_Float32 << (ArgType_Shift * (i + 1))); break;
           case ValType::F64: abiType |= (ArgType_Double << (ArgType_Shift * (i + 1))); break;
           default: return Nothing();
         }
     }
 
     return Some(ABIFunctionType(abiType));
 }
--- a/js/src/wasm/WasmCode.cpp
+++ b/js/src/wasm/WasmCode.cpp
@@ -551,17 +551,17 @@ LazyStubSegment::create(const CodeTier& 
         return nullptr;
 
     return segment;
 }
 
 bool
 LazyStubSegment::hasSpace(size_t bytes) const
 {
-    MOZ_ASSERT(bytes % MPROTECT_PAGE_SIZE == 0);
+    MOZ_ASSERT(AlignBytesNeeded(bytes) == bytes);
     return bytes <= length() &&
            usedBytes_ <= length() - bytes;
 }
 
 bool
 LazyStubSegment::addStubs(size_t codeLength, const Uint32Vector& funcExportIndices,
                           const FuncExportVector& funcExports, const CodeRangeVector& codeRanges,
                           uint8_t** codePtr, size_t* indexFirstInsertedCodeRange)
--- a/js/src/wasm/WasmCode.h
+++ b/js/src/wasm/WasmCode.h
@@ -502,27 +502,25 @@ using UniqueMetadataTier = UniquePtr<Met
 using UniqueLazyStubSegment = UniquePtr<LazyStubSegment>;
 using LazyStubSegmentVector = Vector<UniqueLazyStubSegment, 0, SystemAllocPolicy>;
 
 class LazyStubSegment : public CodeSegment
 {
     CodeRangeVector codeRanges_;
     size_t usedBytes_;
 
-    static constexpr size_t MPROTECT_PAGE_SIZE = 4 * 1024;
-
   public:
     LazyStubSegment(UniqueCodeBytes bytes, size_t length)
       : CodeSegment(Move(bytes), length, CodeSegment::Kind::LazyStubs),
         usedBytes_(0)
     {}
 
     static UniqueLazyStubSegment create(const CodeTier& codeTier, size_t codeLength);
 
-    static size_t AlignBytesNeeded(size_t bytes) { return AlignBytes(bytes, MPROTECT_PAGE_SIZE); }
+    static size_t AlignBytesNeeded(size_t bytes) { return AlignBytes(bytes, gc::SystemPageSize()); }
 
     bool hasSpace(size_t bytes) const;
     bool addStubs(size_t codeLength, const Uint32Vector& funcExportIndices,
                   const FuncExportVector& funcExports, const CodeRangeVector& codeRanges,
                   uint8_t** codePtr, size_t* indexFirstInsertedCodeRange);
 
     const CodeRangeVector& codeRanges() const { return codeRanges_; }
     const CodeRange* lookupRange(const void* pc) const;
--- a/js/src/wasm/WasmDebug.cpp
+++ b/js/src/wasm/WasmDebug.cpp
@@ -554,17 +554,17 @@ DebugState::debugGetResultType(uint32_t 
 
 bool
 DebugState::getGlobal(Instance& instance, uint32_t globalIndex, MutableHandleValue vp)
 {
     const GlobalDesc& global = metadata().globals[globalIndex];
 
     if (global.isConstant()) {
         Val value = global.constantValue();
-        switch (value.type()) {
+        switch (value.type().code()) {
           case ValType::I32:
             vp.set(Int32Value(value.i32()));
             break;
           case ValType::I64:
           // Just display as a Number; it's ok if we lose some precision
             vp.set(NumberValue((double)value.i64()));
             break;
           case ValType::F32:
@@ -578,17 +578,17 @@ DebugState::getGlobal(Instance& instance
         }
         return true;
     }
 
     uint8_t* globalData = instance.globalData();
     void* dataPtr = globalData + global.offset();
     if (global.isIndirect())
         dataPtr = *static_cast<void**>(dataPtr);
-    switch (global.type()) {
+    switch (global.type().code()) {
       case ValType::I32: {
         vp.set(Int32Value(*static_cast<int32_t*>(dataPtr)));
         break;
       }
       case ValType::I64: {
         // Just display as a Number; it's ok if we lose some precision
         vp.set(NumberValue((double)*static_cast<int64_t*>(dataPtr)));
         break;
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -118,17 +118,17 @@ Instance::callImport(JSContext* cx, uint
 
     if (fi.sig().hasI64ArgOrRet()) {
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
         return false;
     }
 
     MOZ_ASSERT(fi.sig().args().length() == argc);
     for (size_t i = 0; i < argc; i++) {
-        switch (fi.sig().args()[i]) {
+        switch (fi.sig().args()[i].code()) {
           case ValType::I32:
             args[i].set(Int32Value(*(int32_t*)&argv[i]));
             break;
           case ValType::F32:
             args[i].set(JS::CanonicalizedDoubleValue(*(float*)&argv[i]));
             break;
           case ValType::F64:
             args[i].set(JS::CanonicalizedDoubleValue(*(double*)&argv[i]));
@@ -196,17 +196,17 @@ Instance::callImport(JSContext* cx, uint
     if (fi.sig().temporarilyUnsupportedAnyRef())
         return true;
 
     const ValTypeVector& importArgs = fi.sig().args();
 
     size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
     for (uint32_t i = 0; i < numKnownArgs; i++) {
         TypeSet::Type type = TypeSet::UnknownType();
-        switch (importArgs[i]) {
+        switch (importArgs[i].code()) {
           case ValType::I32:    type = TypeSet::Int32Type(); break;
           case ValType::F32:    type = TypeSet::DoubleType(); break;
           case ValType::F64:    type = TypeSet::DoubleType(); break;
           case ValType::AnyRef: MOZ_CRASH("case guarded above");
           case ValType::I64:    MOZ_CRASH("NYI");
           case ValType::I8x16:  MOZ_CRASH("NYI");
           case ValType::I16x8:  MOZ_CRASH("NYI");
           case ValType::I32x4:  MOZ_CRASH("NYI");
@@ -766,17 +766,17 @@ Instance::callExport(JSContext* cx, uint
     // have length >= 1).
     Vector<ExportArg, 8> exportArgs(cx);
     if (!exportArgs.resize(Max<size_t>(1, func.sig().args().length())))
         return false;
 
     RootedValue v(cx);
     for (unsigned i = 0; i < func.sig().args().length(); ++i) {
         v = i < args.length() ? args[i] : UndefinedValue();
-        switch (func.sig().arg(i)) {
+        switch (func.sig().arg(i).code()) {
           case ValType::I32:
             if (!ToInt32(cx, v, (int32_t*)&exportArgs[i]))
                 return false;
             break;
           case ValType::I64:
             MOZ_CRASH("unexpected i64 flowing into callExport");
           case ValType::F32:
             if (!RoundFloat32(cx, v, (float*)&exportArgs[i]))
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -201,17 +201,17 @@ class FunctionCompiler
         // Set up a parameter that receives the hidden TLS pointer argument.
         tlsPointer_ = MWasmParameter::New(alloc(), ABIArg(WasmTlsReg), MIRType::Pointer);
         curBlock_->add(tlsPointer_);
         if (!mirGen_.ensureBallast())
             return false;
 
         for (size_t i = args.length(); i < locals_.length(); i++) {
             MInstruction* ins = nullptr;
-            switch (locals_[i]) {
+            switch (locals_[i].code()) {
               case ValType::I32:
                 ins = MConstant::New(alloc(), Int32Value(0), MIRType::Int32);
                 break;
               case ValType::I64:
                 ins = MConstant::NewInt64(alloc(), 0);
                 break;
               case ValType::F32:
                 ins = MConstant::New(alloc(), Float32Value(0.f), MIRType::Float32);
@@ -2300,17 +2300,17 @@ EmitGetGlobal(FunctionCompiler& f)
                                            global.isIndirect(), ToMIRType(global.type())));
         return true;
     }
 
     Val value = global.constantValue();
     MIRType mirType = ToMIRType(value.type());
 
     MDefinition* result;
-    switch (value.type()) {
+    switch (value.type().code()) {
       case ValType::I32:
         result = f.constant(Int32Value(value.i32()), mirType);
         break;
       case ValType::I64:
         result = f.constant(int64_t(value.i64()));
         break;
       case ValType::F32:
         result = f.constant(value.f32());
@@ -2966,17 +2966,17 @@ EmitSimdShift(FunctionCompiler& f, ValTy
 
     f.iter().setResult(f.binarySimdShift(lhs, rhs, op));
     return true;
 }
 
 static ValType
 SimdToLaneType(ValType type)
 {
-    switch (type) {
+    switch (type.code()) {
       case ValType::I8x16:
       case ValType::I16x8:
       case ValType::I32x4:  return ValType::I32;
       case ValType::F32x4:  return ValType::F32;
       case ValType::B8x16:
       case ValType::B16x8:
       case ValType::B32x4:  return ValType::I32; // Boolean lanes are Int32 in asm.
       case ValType::I32:
@@ -3072,17 +3072,17 @@ EmitSimdShuffle(FunctionCompiler& f, Val
 
     f.iter().setResult(f.shuffleSimd(lhs, rhs, lanes, ToMIRType(simdType)));
     return true;
 }
 
 static inline Scalar::Type
 SimdExprTypeToViewType(ValType type, unsigned* defaultNumElems)
 {
-    switch (type) {
+    switch (type.code()) {
         case ValType::I8x16: *defaultNumElems = 16; return Scalar::Int8x16;
         case ValType::I16x8: *defaultNumElems = 8; return Scalar::Int16x8;
         case ValType::I32x4: *defaultNumElems = 4; return Scalar::Int32x4;
         case ValType::F32x4: *defaultNumElems = 4; return Scalar::Float32x4;
         default:              break;
     }
     MOZ_CRASH("type not handled in SimdExprTypeToViewType");
 }
@@ -3215,17 +3215,17 @@ EmitSimdBooleanChainedCtor(FunctionCompi
 
     f.iter().setResult(val);
     return true;
 }
 
 static bool
 EmitSimdCtor(FunctionCompiler& f, ValType type)
 {
-    switch (type) {
+    switch (type.code()) {
       case ValType::I8x16:
         return EmitSimdChainedCtor(f, type, MIRType::Int8x16, SimdConstant::SplatX16(0));
       case ValType::I16x8:
         return EmitSimdChainedCtor(f, type, MIRType::Int16x8, SimdConstant::SplatX8(0));
       case ValType::I32x4: {
         DefVector args;
         if (!f.iter().readSimdCtor(ValType::I32, 4, type, &args))
             return false;
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -107,17 +107,17 @@ wasm::HasSupport(JSContext* cx)
     return cx->options().wasm() &&
            HasCompilerSupport(cx) &&
            HasAvailableCompilerTier(cx);
 }
 
 bool
 wasm::ToWebAssemblyValue(JSContext* cx, ValType targetType, HandleValue v, Val* val)
 {
-    switch (targetType) {
+    switch (targetType.code()) {
       case ValType::I32: {
         int32_t i32;
         if (!ToInt32(cx, v, &i32))
             return false;
         *val = Val(uint32_t(i32));
         return true;
       }
       case ValType::F32: {
@@ -138,17 +138,17 @@ wasm::ToWebAssemblyValue(JSContext* cx, 
         MOZ_CRASH("unexpected import value type, caller must guard");
       }
     }
 }
 
 Value
 wasm::ToJSValue(const Val& val)
 {
-    switch (val.type()) {
+    switch (val.type().code()) {
       case ValType::I32:
         return Int32Value(val.i32());
       case ValType::F32:
         return DoubleValue(JS::CanonicalizeNaN(double(val.f32())));
       case ValType::F64:
         return DoubleValue(JS::CanonicalizeNaN(val.f64()));
       default:
         MOZ_CRASH("unexpected type when translating to a JS value");
@@ -212,40 +212,42 @@ GetImports(JSContext* cx,
             return false;
         }
 
         RootedObject obj(cx, &v.toObject());
         if (!GetProperty(cx, obj, import.field.get(), &v))
             return false;
 
         switch (import.kind) {
-          case DefinitionKind::Function:
+          case DefinitionKind::Function: {
             if (!IsFunctionObject(v))
                 return ThrowBadImportType(cx, import.field.get(), "Function");
 
             if (!funcImports.append(&v.toObject().as<JSFunction>()))
                 return false;
 
             break;
-          case DefinitionKind::Table:
+          }
+          case DefinitionKind::Table: {
             if (!v.isObject() || !v.toObject().is<WasmTableObject>())
                 return ThrowBadImportType(cx, import.field.get(), "Table");
 
             MOZ_ASSERT(!tableImport);
             tableImport.set(&v.toObject().as<WasmTableObject>());
             break;
-          case DefinitionKind::Memory:
+          }
+          case DefinitionKind::Memory: {
             if (!v.isObject() || !v.toObject().is<WasmMemoryObject>())
                 return ThrowBadImportType(cx, import.field.get(), "Memory");
 
             MOZ_ASSERT(!memoryImport);
             memoryImport.set(&v.toObject().as<WasmMemoryObject>());
             break;
-
-          case DefinitionKind::Global:
+          }
+          case DefinitionKind::Global: {
             Val val;
             const uint32_t index = globalIndex++;
             const GlobalDesc& global = globals[index];
             MOZ_ASSERT(global.importIndex() == index);
 
             if (v.isObject() && v.toObject().is<WasmGlobalObject>()) {
                 RootedWasmGlobalObject obj(cx, &v.toObject().as<WasmGlobalObject>());
 
@@ -279,16 +281,19 @@ GetImports(JSContext* cx,
                 if (!ToWebAssemblyValue(cx, global.type(), v, &val))
                     return false;
             } else {
                 return ThrowBadImportType(cx, import.field.get(), "Number");
             }
 
             if (!globalImportValues->append(val))
                 return false;
+
+            break;
+          }
         }
     }
 
     MOZ_ASSERT(globalIndex == globals.length() || !globals[globalIndex].isImport());
 
     return true;
 }
 
@@ -2117,32 +2122,32 @@ WasmGlobalObject::finalize(FreeOp*, JSOb
 
 /* static */ WasmGlobalObject*
 WasmGlobalObject::create(JSContext* cx, const Val& val, bool isMutable)
 {
     UniquePtr<Cell> cell = js::MakeUnique<Cell>();
     if (!cell)
         return nullptr;
 
-    switch (val.type()) {
+    switch (val.type().code()) {
       case ValType::I32: cell->i32 = val.i32(); break;
       case ValType::I64: cell->i64 = val.i64(); break;
       case ValType::F32: cell->f32 = val.f32(); break;
       case ValType::F64: cell->f64 = val.f64(); break;
       default:           MOZ_CRASH();
     }
 
     RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmGlobal).toObject());
 
     AutoSetNewObjectMetadata metadata(cx);
     RootedWasmGlobalObject obj(cx, NewObjectWithGivenProto<WasmGlobalObject>(cx, proto));
     if (!obj)
         return nullptr;
 
-    obj->initReservedSlot(TYPE_SLOT, Int32Value(int32_t(val.type())));
+    obj->initReservedSlot(TYPE_SLOT, Int32Value(int32_t(val.type().bitsUnsafe())));
     obj->initReservedSlot(MUTABLE_SLOT, JS::BooleanValue(isMutable));
     obj->initReservedSlot(CELL_SLOT, PrivateValue(cell.release()));
 
     return obj;
 }
 
 /* static */ bool
 WasmGlobalObject::construct(JSContext* cx, unsigned argc, Value* vp)
@@ -2196,17 +2201,17 @@ WasmGlobalObject::construct(JSContext* c
     // Guard against control flow mistakes below failing to set |globalVal|.
     Val globalVal = Val(uint32_t(0));
     if (args.length() >= 2) {
         RootedValue valueVal(cx, args.get(1));
 
         if (!ToWebAssemblyValue(cx, globalType, valueVal, &globalVal))
             return false;
     } else {
-        switch (globalType) {
+        switch (globalType.code()) {
           case ValType::I32: /* set above */ break;
           case ValType::F32: globalVal = Val(float(0.0));  break;
           case ValType::F64: globalVal = Val(double(0.0)); break;
           default: MOZ_CRASH();
         }
     }
 
     WasmGlobalObject* global = WasmGlobalObject::create(cx, globalVal, isMutable);
@@ -2221,17 +2226,17 @@ static bool
 IsGlobal(HandleValue v)
 {
     return v.isObject() && v.toObject().is<WasmGlobalObject>();
 }
 
 /* static */ bool
 WasmGlobalObject::valueGetterImpl(JSContext* cx, const CallArgs& args)
 {
-    switch (args.thisv().toObject().as<WasmGlobalObject>().type()) {
+    switch (args.thisv().toObject().as<WasmGlobalObject>().type().code()) {
       case ValType::I32:
       case ValType::F32:
       case ValType::F64:
         args.rval().set(args.thisv().toObject().as<WasmGlobalObject>().value());
         return true;
       case ValType::I64:
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64_TYPE);
         return false;
@@ -2261,17 +2266,17 @@ WasmGlobalObject::valueSetterImpl(JSCont
         return false;
     }
 
     Val val;
     if (!ToWebAssemblyValue(cx, global->type(), args.get(0), &val))
         return false;
 
     Cell* cell = global->cell();
-    switch (global->type()) {
+    switch (global->type().code()) {
       case ValType::I32: cell->i32 = val.i32(); break;
       case ValType::F32: cell->f32 = val.f32(); break;
       case ValType::F64: cell->f64 = val.f64(); break;
       default:           MOZ_CRASH();
     }
 
     args.rval().setUndefined();
     return true;
@@ -2298,31 +2303,31 @@ const JSFunctionSpec WasmGlobalObject::m
 };
 
 const JSFunctionSpec WasmGlobalObject::static_methods[] =
 { JS_FS_END };
 
 ValType
 WasmGlobalObject::type() const
 {
-    return static_cast<ValType>(getReservedSlot(TYPE_SLOT).toInt32());
+    return ValType::fromBitsUnsafe(getReservedSlot(TYPE_SLOT).toInt32());
 }
 
 bool
 WasmGlobalObject::isMutable() const
 {
     return getReservedSlot(MUTABLE_SLOT).toBoolean();
 }
 
 Val
 WasmGlobalObject::val() const
 {
     Cell* cell = this->cell();
     Val val;
-    switch (type()) {
+    switch (type().code()) {
       case ValType::I32: val = Val(uint32_t(cell->i32)); break;
       case ValType::I64: val = Val(uint64_t(cell->i64)); break;
       case ValType::F32: val = Val(cell->f32); break;
       case ValType::F64: val = Val(cell->f64); break;
       default:           MOZ_CRASH();
     }
     return val;
 }
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -57,24 +57,24 @@ enum class StackType
     AnyRef = uint8_t(ValType::AnyRef),
 
     Any    = uint8_t(TypeCode::Limit),
 };
 
 static inline StackType
 ToStackType(ValType type)
 {
-    return StackType(type);
+    return StackType(type.bitsUnsafe());
 }
 
 static inline ValType
 NonAnyToValType(StackType type)
 {
     MOZ_ASSERT(type != StackType::Any);
-    return ValType(type);
+    return ValType::fromTypeCode(uint32_t(type));
 }
 
 static inline bool
 IsRefType(StackType st)
 {
     return IsRefType(NonAnyToValType(st));
 }
 
@@ -1672,17 +1672,17 @@ OpIter<Policy>::readB32x4Const(I32x4* i3
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readRefNull()
 {
     MOZ_ASSERT(Classify(op_) == OpKind::RefNull);
     uint8_t valType;
-    if (!d_.readValType(&valType) || ValType(valType) != ValType::AnyRef)
+    if (!d_.readValType(&valType) || valType != uint8_t(ValType::AnyRef))
         return fail("unknown nullref type");
     return push(StackType::AnyRef);
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::popCallArgs(const ValTypeVector& expectedTypes, ValueVector* values)
 {
@@ -2238,16 +2238,19 @@ OpIter<Policy>::readSimdCtor(ValType ele
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readMemCopy(Value* dest, Value* src, Value* len)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::MemCopy);
 
+    if (!env_.usesMemory())
+        return fail("can't touch memory without memory");
+
     if (!popWithType(ValType::I32, len))
         return false;
 
     if (!popWithType(ValType::I32, src))
         return false;
 
     if (!popWithType(ValType::I32, dest))
         return false;
@@ -2256,16 +2259,19 @@ OpIter<Policy>::readMemCopy(Value* dest,
 }
 
 template <typename Policy>
 inline bool
 OpIter<Policy>::readMemFill(Value* start, Value* val, Value* len)
 {
     MOZ_ASSERT(Classify(op_) == OpKind::MemFill);
 
+    if (!env_.usesMemory())
+        return fail("can't touch memory without memory");
+
     if (!popWithType(ValType::I32, len))
         return false;
 
     if (!popWithType(ValType::I32, val))
         return false;
 
     if (!popWithType(ValType::I32, start))
         return false;
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -631,17 +631,17 @@ GenerateJitEntry(MacroAssembler& masm, s
     // - the second loop will unbox the arguments into the right registers.
     Label oolCall;
     for (size_t i = 0; i < fe.sig().args().length(); i++) {
         unsigned jitArgOffset = frameSize + JitFrameLayout::offsetOfActualArg(i);
         Address jitArgAddr(sp, jitArgOffset);
         masm.loadValue(jitArgAddr, scratchV);
 
         Label next;
-        switch (fe.sig().args()[i]) {
+        switch (fe.sig().args()[i].code()) {
           case ValType::I32: {
             ScratchTagScope tag(masm, scratchV);
             masm.splitTagForTest(scratchV, tag);
 
             // For int32 inputs, just skip.
             masm.branchTestInt32(Assembler::Equal, tag, &next);
 
             // For double inputs, unbox, truncate and store back.
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -141,25 +141,26 @@ class WasmToken
         Wait,
         Wake,
         Invalid
     };
   private:
     Kind kind_;
     const char16_t* begin_;
     const char16_t* end_;
-    union {
+    union U {
         uint32_t index_;
         uint64_t uint_;
         int64_t sint_;
         FloatLiteralKind floatLiteralKind_;
         ValType valueType_;
         Op op_;
         MiscOp miscOp_;
         ThreadOp threadOp_;
+        U() : index_(0) {}
     } u;
   public:
     WasmToken()
       : kind_(Kind::Invalid),
         begin_(nullptr),
         end_(nullptr),
         u()
     { }
@@ -2263,17 +2264,17 @@ ParseFloatLiteral(WasmParseContext& c, W
 
     return new (c.lifo) AstConst(Val(Float(result)));
 }
 
 static AstConst*
 ParseConst(WasmParseContext& c, WasmToken constToken)
 {
     WasmToken val = c.ts.get();
-    switch (constToken.valueType()) {
+    switch (constToken.valueType().code()) {
       case ValType::I32: {
         switch (val.kind()) {
           case WasmToken::Index:
             return new(c.lifo) AstConst(Val(val.index()));
           case WasmToken::SignedInteger: {
             CheckedInt<int32_t> sint = val.sint();
             if (!sint.isValid())
                 break;
@@ -4760,17 +4761,17 @@ EncodeCallIndirect(Encoder& e, AstCallIn
         return false;
 
     return true;
 }
 
 static bool
 EncodeConst(Encoder& e, AstConst& c)
 {
-    switch (c.val().type()) {
+    switch (c.val().type().code()) {
       case ValType::I32:
         return e.writeOp(Op::I32Const) &&
                e.writeVarS32(c.val().i32());
       case ValType::I64:
         return e.writeOp(Op::I64Const) &&
                e.writeVarS64(c.val().i64());
       case ValType::F32:
         return e.writeOp(Op::F32Const) &&
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -49,17 +49,17 @@ using mozilla::MakeEnumeratedRange;
 // Another sanity check.
 
 static_assert(MaxMemoryInitialPages <= ArrayBufferObject::MaxBufferByteLength / PageSize,
               "Memory sizing constraint");
 
 void
 Val::writePayload(uint8_t* dst) const
 {
-    switch (type_) {
+    switch (type_.code()) {
       case ValType::I32:
       case ValType::F32:
         memcpy(dst, &u.i32_, sizeof(u.i32_));
         return;
       case ValType::I64:
       case ValType::F64:
         memcpy(dst, &u.i64_, sizeof(u.i64_));
         return;
@@ -176,17 +176,17 @@ static const unsigned sTagBits = 1;
 static const unsigned sReturnBit = 1;
 static const unsigned sLengthBits = 4;
 static const unsigned sTypeBits = 3;
 static const unsigned sMaxTypes = (sTotalBits - sTagBits - sReturnBit - sLengthBits) / sTypeBits;
 
 static bool
 IsImmediateType(ValType vt)
 {
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I32:
       case ValType::I64:
       case ValType::F32:
       case ValType::F64:
       case ValType::AnyRef:
         return true;
       case ValType::I8x16:
       case ValType::I16x8:
@@ -199,17 +199,17 @@ IsImmediateType(ValType vt)
     }
     MOZ_CRASH("bad ValType");
 }
 
 static unsigned
 EncodeImmediateType(ValType vt)
 {
     static_assert(4 < (1 << sTypeBits), "fits");
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I32:
         return 0;
       case ValType::I64:
         return 1;
       case ValType::F32:
         return 2;
       case ValType::F64:
         return 3;
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -159,22 +159,149 @@ struct ShareableBase : AtomicRefCounted<
         if (p)
             return 0;
         bool ok = seen->add(p, self);
         (void)ok;  // oh well
         return mallocSizeOf(self) + self->sizeOfExcludingThis(mallocSizeOf);
     }
 };
 
+enum class ExprType;
+
+class ValType
+{
+    struct {
+        uint32_t code_ : 8;           // If code_ is InvalidCode then the ValType is invalid
+        uint32_t refTypeIndex_ : 24;  // If code_ is not Ref then this must be NoIndex
+    };
+
+    static const uint32_t InvalidCode  = uint32_t(TypeCode::Limit);
+    static const uint32_t NoIndex = 0xFFFFFF;
+
+  public:
+    enum Code {
+        I32    = uint8_t(TypeCode::I32),
+        I64    = uint8_t(TypeCode::I64),
+        F32    = uint8_t(TypeCode::F32),
+        F64    = uint8_t(TypeCode::F64),
+
+        AnyRef = uint8_t(TypeCode::AnyRef),
+
+        // ------------------------------------------------------------------------
+        // The rest of these types are currently only emitted internally when
+        // compiling asm.js and are rejected by wasm validation.
+
+        I8x16  = uint8_t(TypeCode::I8x16),
+        I16x8  = uint8_t(TypeCode::I16x8),
+        I32x4  = uint8_t(TypeCode::I32x4),
+        F32x4  = uint8_t(TypeCode::F32x4),
+        B8x16  = uint8_t(TypeCode::B8x16),
+        B16x8  = uint8_t(TypeCode::B16x8),
+        B32x4  = uint8_t(TypeCode::B32x4)
+    };
+
+    ValType()
+      : code_(InvalidCode), refTypeIndex_(NoIndex)
+    {}
+
+    MOZ_IMPLICIT ValType(ValType::Code c)
+      : code_(uint32_t(c)), refTypeIndex_(NoIndex)
+    {
+        assertValid();
+    }
+
+    explicit inline ValType(ExprType t);
+
+    static ValType fromTypeCode(uint32_t code) {
+        return ValType(code, NoIndex);
+    }
+
+    static ValType fromBitsUnsafe(uint32_t bits) {
+        // This will change once we have Ref types.
+        return ValType(bits & 255, NoIndex);
+    }
+
+    bool isValid() const {
+        return code_ != InvalidCode;
+    }
+
+    Code code() const {
+        return Code(code_);
+    }
+    uint32_t refTypeIndex() const {
+        return refTypeIndex_;
+    }
+
+    uint32_t bitsUnsafe() const {
+        // This will change once we have Ref types.
+        return code_;
+    }
+
+    bool operator ==(const ValType& that) const {
+        return code_ == that.code_ && refTypeIndex_ == that.refTypeIndex_;
+    }
+    bool operator !=(const ValType& that) const {
+        return !(*this == that);
+    }
+    bool operator ==(ValType::Code that) const {
+        // This will change once we have Ref types.
+        return code_ == uint32_t(that) && refTypeIndex_ == NoIndex;
+    }
+    bool operator !=(ValType::Code that) const {
+        return !(*this == that);
+    }
+
+  private:
+    ValType(uint32_t code, uint32_t refTypeIndex)
+      : code_(code),
+        refTypeIndex_(refTypeIndex)
+    {
+        // 8-bit field.  Invalid values have their own constructor and should
+        // not appear here.
+        MOZ_ASSERT(code <= 0xFF && code != InvalidCode);
+        // 24-bit field.
+        MOZ_ASSERT(refTypeIndex <= 0xFFFFFF);
+
+        assertValid();
+    }
+
+    void assertValid() const {
+#ifdef DEBUG
+        // This will change once we have Ref types.
+        MOZ_ASSERT(refTypeIndex_ == NoIndex);
+        switch (code_) {
+          case uint8_t(Code::I32):
+          case uint8_t(Code::I64):
+          case uint8_t(Code::F32):
+          case uint8_t(Code::F64):
+          case uint8_t(Code::AnyRef):
+          case uint8_t(Code::I8x16):
+          case uint8_t(Code::I16x8):
+          case uint8_t(Code::I32x4):
+          case uint8_t(Code::F32x4):
+          case uint8_t(Code::B8x16):
+          case uint8_t(Code::B16x8):
+          case uint8_t(Code::B32x4):
+          case InvalidCode:
+            break;
+          default:
+            MOZ_CRASH("Invalid code");
+        }
+#endif
+    }
+};
+
+typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
+
 // ValType utilities
 
 static inline unsigned
 SizeOf(ValType vt)
 {
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I32:
       case ValType::F32:
         return 4;
       case ValType::I64:
       case ValType::F64:
         return 8;
       case ValType::I8x16:
       case ValType::I16x8:
@@ -188,17 +315,17 @@ SizeOf(ValType vt)
         MOZ_CRASH("unexpected anyref");
     }
     MOZ_CRASH("Invalid ValType");
 }
 
 static inline bool
 IsSimdType(ValType vt)
 {
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I8x16:
       case ValType::I16x8:
       case ValType::I32x4:
       case ValType::F32x4:
       case ValType::B8x16:
       case ValType::B16x8:
       case ValType::B32x4:
         return true;
@@ -206,17 +333,17 @@ IsSimdType(ValType vt)
         return false;
     }
 }
 
 static inline uint32_t
 NumSimdElements(ValType vt)
 {
     MOZ_ASSERT(IsSimdType(vt));
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I8x16:
       case ValType::B8x16:
         return 16;
       case ValType::I16x8:
       case ValType::B16x8:
         return 8;
       case ValType::I32x4:
       case ValType::F32x4:
@@ -226,17 +353,17 @@ NumSimdElements(ValType vt)
         MOZ_CRASH("Unhandled SIMD type");
     }
 }
 
 static inline ValType
 SimdElementType(ValType vt)
 {
     MOZ_ASSERT(IsSimdType(vt));
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I8x16:
       case ValType::I16x8:
       case ValType::I32x4:
         return ValType::I32;
       case ValType::F32x4:
         return ValType::F32;
       case ValType::B8x16:
       case ValType::B16x8:
@@ -246,17 +373,17 @@ SimdElementType(ValType vt)
         MOZ_CRASH("Unhandled SIMD type");
     }
 }
 
 static inline ValType
 SimdBoolType(ValType vt)
 {
     MOZ_ASSERT(IsSimdType(vt));
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I8x16:
       case ValType::B8x16:
         return ValType::B8x16;
       case ValType::I16x8:
       case ValType::B16x8:
         return ValType::B16x8;
       case ValType::I32x4:
       case ValType::F32x4:
@@ -271,17 +398,17 @@ static inline bool
 IsSimdBoolType(ValType vt)
 {
     return vt == ValType::B8x16 || vt == ValType::B16x8 || vt == ValType::B32x4;
 }
 
 static inline jit::MIRType
 ToMIRType(ValType vt)
 {
-    switch (vt) {
+    switch (vt.code()) {
       case ValType::I32:    return jit::MIRType::Int32;
       case ValType::I64:    return jit::MIRType::Int64;
       case ValType::F32:    return jit::MIRType::Float32;
       case ValType::F64:    return jit::MIRType::Double;
       case ValType::AnyRef: return jit::MIRType::Pointer;
       case ValType::I8x16:  return jit::MIRType::Int8x16;
       case ValType::I16x8:  return jit::MIRType::Int16x8;
       case ValType::I32x4:  return jit::MIRType::Int32x4;
@@ -326,33 +453,39 @@ enum class ExprType
     F32x4  = uint8_t(TypeCode::F32x4),
     B8x16  = uint8_t(TypeCode::B8x16),
     B16x8  = uint8_t(TypeCode::B16x8),
     B32x4  = uint8_t(TypeCode::B32x4),
 
     Limit  = uint8_t(TypeCode::Limit)
 };
 
+inline ValType::ValType(ExprType t)
+  : code_(uint32_t(t)), refTypeIndex_(NoIndex)
+{
+    assertValid();
+}
+
 static inline bool
 IsVoid(ExprType et)
 {
     return et == ExprType::Void;
 }
 
 static inline ValType
 NonVoidToValType(ExprType et)
 {
     MOZ_ASSERT(!IsVoid(et));
     return ValType(et);
 }
 
 static inline ExprType
 ToExprType(ValType vt)
 {
-    return ExprType(vt);
+    return ExprType(vt.bitsUnsafe());
 }
 
 static inline bool
 IsSimdType(ExprType et)
 {
     return IsVoid(et) ? false : IsSimdType(ValType(et));
 }
 
@@ -574,17 +707,20 @@ class Sig
         return args_.appendAll(rhs.args_);
     }
 
     ValType arg(unsigned i) const { return args_[i]; }
     const ValTypeVector& args() const { return args_; }
     const ExprType& ret() const { return ret_; }
 
     HashNumber hash() const {
-        return AddContainerToHash(args_, HashNumber(ret_));
+        HashNumber hn = HashNumber(ret_);
+        for (const ValType& vt : args_)
+            hn = mozilla::AddToHash(hn, HashNumber(vt.code()));
+        return hn;
     }
     bool operator==(const Sig& rhs) const {
         return ret() == rhs.ret() && EqualContainers(args(), rhs.args());
     }
     bool operator!=(const Sig& rhs) const {
         return !(*this == rhs);
     }
 
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -339,17 +339,17 @@ Decoder::skipNameSubsection()
 
 bool
 wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
 {
     if (locals.length() > MaxLocals)
         return false;
 
     uint32_t numLocalEntries = 0;
-    ValType prev = ValType(TypeCode::Limit);
+    ValType prev;
     for (ValType t : locals) {
         if (t != prev) {
             numLocalEntries++;
             prev = t;
         }
     }
 
     if (!e.writeVarU32(numLocalEntries))
@@ -384,33 +384,33 @@ DecodeValType(Decoder& d, ModuleKind kin
     if (!d.readValType(&unchecked))
         return false;
 
     switch (unchecked) {
       case uint8_t(ValType::I32):
       case uint8_t(ValType::F32):
       case uint8_t(ValType::F64):
       case uint8_t(ValType::I64):
-        *type = ValType(unchecked);
+        *type = ValType::fromTypeCode(unchecked);
         return true;
       case uint8_t(ValType::AnyRef):
         if (gcTypesEnabled == HasGcTypes::False)
             break;
-        *type = ValType(unchecked);
+        *type = ValType::fromTypeCode(unchecked);
         return true;
       case uint8_t(ValType::I8x16):
       case uint8_t(ValType::I16x8):
       case uint8_t(ValType::I32x4):
       case uint8_t(ValType::F32x4):
       case uint8_t(ValType::B8x16):
       case uint8_t(ValType::B16x8):
       case uint8_t(ValType::B32x4):
         if (kind != ModuleKind::AsmJS)
             return d.fail("bad type");
-        *type = ValType(unchecked);
+        *type = ValType::fromTypeCode(unchecked);
         return true;
       default:
         break;
     }
     return d.fail("bad type");
 }
 
 bool
@@ -1235,17 +1235,17 @@ DecodeTableLimits(Decoder& d, TableDescV
         return d.fail("already have default table");
 
     return tables->emplaceBack(TableKind::AnyFunction, limits);
 }
 
 static bool
 GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable)
 {
-    switch (type) {
+    switch (type.code()) {
       case ValType::I32:
       case ValType::F32:
       case ValType::F64:
       case ValType::I64:
         break;
       default:
         return d.fail("unexpected variable type in global import/export");
     }
--- a/js/src/wasm/WasmValidate.h
+++ b/js/src/wasm/WasmValidate.h
@@ -264,18 +264,18 @@ class Encoder
     MOZ_MUST_USE bool writeVarU64(uint64_t i) {
         return writeVarU<uint64_t>(i);
     }
     MOZ_MUST_USE bool writeVarS64(int64_t i) {
         return writeVarS<int64_t>(i);
     }
     MOZ_MUST_USE bool writeValType(ValType type) {
         static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
-        MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
-        return writeFixedU8(uint8_t(type));
+        MOZ_ASSERT(size_t(type.bitsUnsafe()) < size_t(TypeCode::Limit));
+        return writeFixedU8(uint8_t(type.bitsUnsafe()));
     }
     MOZ_MUST_USE bool writeBlockType(ExprType type) {
         static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
         MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
         return writeFixedU8(uint8_t(type));
     }
     MOZ_MUST_USE bool writeOp(Op op) {
         static_assert(size_t(Op::Limit) == 256, "fits");
@@ -667,17 +667,17 @@ class Decoder
         return uncheckedReadVarU<uint64_t>();
     }
     int64_t uncheckedReadVarS64() {
         int64_t i64 = 0;
         MOZ_ALWAYS_TRUE(readVarS64(&i64));
         return i64;
     }
     ValType uncheckedReadValType() {
-        return (ValType)uncheckedReadFixedU8();
+        return ValType::fromTypeCode(uncheckedReadFixedU8());
     }
     Op uncheckedReadOp() {
         static_assert(size_t(Op::Limit) == 256, "fits");
         uint8_t u8 = uncheckedReadFixedU8();
         return u8 != UINT8_MAX
                ? Op(u8)
                : Op(uncheckedReadFixedU8() + UINT8_MAX);
     }
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -105,17 +105,17 @@ load 344057-1.xhtml
 load 344064-1.html
 load 344300-1.html
 load 344300-2.html
 load 344340-1.xul
 load 347898-1.html
 load 348126-1.html
 load 348688-1.html
 load 348708-1.xhtml
-asserts(1) asserts-if(stylo,0) load 348729-1.html # bug 548836
+load 348729-1.html
 load 349095-1.xhtml
 load 350128-1.xhtml
 load 350267-1.html
 load 354133-1.html
 load 354766-1.xhtml
 load 354771-1.xul
 load 355989-1.xhtml
 load 355993-1.xhtml
@@ -261,17 +261,17 @@ load 444863-1.html
 load 444925-1.xul
 load 444967-1.html
 load 446328.html
 load 448488-1.html
 load 448543-1.html
 load 448543-2.html
 load 448543-3.html
 load 450319-1.xhtml
-asserts(1) asserts-if(stylo&&Android,2) load 453894-1.xhtml # Bug 398043
+asserts(1) asserts-if(Android,2) load 453894-1.xhtml # Bug 398043
 load 454751-1.xul
 load 455063-1.html
 load 455063-2.html
 load 455063-3.html
 load 455171-4.html
 load 455623-1.html # bug 1323652
 load 457362-1.xhtml
 load 457514.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4146,24 +4146,16 @@ ConnectAnonymousTreeDescendants(nsIConte
     NS_ASSERTION(content, "null anonymous content?");
 
     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
 
     aParent->AppendChildTo(content, false);
   }
 }
 
-static void
-SetNativeAnonymousBitOnDescendants(nsIContent* aRoot)
-{
-  for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
-    curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
-  }
-}
-
 nsresult
 nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
                                            nsIFrame* aParentFrame,
                                            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
 {
   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
   if (!creator)
     return NS_OK;
@@ -4177,38 +4169,22 @@ nsCSSFrameConstructor::GetAnonymousConte
   uint32_t count = aContent.Length();
   for (uint32_t i=0; i < count; i++) {
     // get our child's content and set its parent to our content
     nsIContent* content = aContent[i].mContent;
     NS_ASSERTION(content, "null anonymous content?");
 
     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
 
-    LayoutFrameType parentFrameType = aParentFrame->Type();
-    if (parentFrameType == LayoutFrameType::SVGUse) {
+    if (aParentFrame->IsSVGUseFrame()) {
       // least-surprise CSS binding until we do the SVG specified
       // cascading rules for <svg:use> - bug 265894
       content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
     } else {
       content->SetIsNativeAnonymousRoot();
-      // Don't mark descendants of the custom content container
-      // as native anonymous.  When canvas custom content is initially
-      // created and appended to the custom content container, in
-      // nsIDocument::InsertAnonymousContent, it is not considered native
-      // anonymous content.  But if we end up reframing the root element,
-      // we will re-create the nsCanvasFrame, and we would end up in here,
-      // marking it as NAC.  Existing uses of canvas custom content would
-      // break if it becomes NAC (since each element starts inheriting
-      // styles from its closest non-NAC ancestor, rather than from its
-      // parent).
-      if (!(parentFrameType == LayoutFrameType::Canvas &&
-            content == static_cast<nsCanvasFrame*>(aParentFrame)
-                         ->GetCustomContentContainer())) {
-        SetNativeAnonymousBitOnDescendants(content);
-      }
     }
 
     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
 
     // If the parent is in a shadow tree, make sure we don't
     // bind with a document because shadow roots and its descendants
     // are not in document.
     nsIDocument* bindDocument =
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -20,17 +20,17 @@ load 309322-1.html
 load 309322-2.html
 load 309322-3.html
 load 309322-4.html
 load 310556-1.xhtml
 load 321224.xul
 load 322780-1.xul
 load 323381-1.html
 load 323381-2.html
-asserts-if(gtkWidget,1) asserts-if(Android&&asyncPan,1) asserts-if(stylo&&gtkWidget&&!isDebugBuild,1) load 323386-1.html # Bug 718883
+asserts-if(gtkWidget,1) asserts-if(Android&&asyncPan,1) load 323386-1.html # Bug 718883
 load 323389-1.html
 load 323389-2.html
 load 323493-1.html
 load 323495-1.html
 load 324318-1.html
 load 328946-1.html
 load 331284-1.xhtml
 load 331292.html
@@ -408,17 +408,17 @@ load 547843-1.xhtml
 load 551635-1.html
 load 553504-1.xhtml
 load 564368-1.xhtml
 load 564968.xhtml
 load 569193-1.html
 load 570160.html
 load 570289-1.html
 load 571618-1.svg
-asserts(1) asserts-if(stylo,0-1) load 571975-1.html # bug 574889
+asserts(0-1) load 571975-1.html # bug 574889
 load 571995.xhtml
 load 574958.xhtml
 asserts(0-6) load 578977.html # bug 757305
 load 580504-1.xhtml
 load 585598-1.xhtml
 load 586806-1.html
 load 586806-2.html
 load 586806-3.html
@@ -530,17 +530,17 @@ load 836895.html
 load 837007.xhtml
 load 840787.html
 load 840818.html
 load 842132-1.html
 load 842166.html
 load 844529-1.html
 load 847130.xhtml
 load 847208.html
-asserts-if(Android,2) asserts-if(Android&&asyncPan,4) asserts-if(!Android,4) asserts-if(stylo,4) load 847209.html # bug 847368
+asserts-if(Android,2) asserts-if(Android&&asyncPan,4) asserts-if(!Android,4) load 847209.html # bug 847368
 load 847211-1.html
 load 849603.html
 load 849987.html
 asserts(0-12) load 850931.html # bug 569193
 load 851396-1.html
 load 854263-1.html
 load 862185.html
 load 862947-1.html
@@ -572,17 +572,17 @@ load 973701-2.xhtml
 load 986899.html
 load 1001233.html
 load 1001258-1.html
 load 1001994.html
 load 1003441.xul
 load 1015562.html
 asserts(1-2) load 1015563-1.html
 asserts(1-2) load 1015563-2.html
-asserts(11) asserts-if(stylo&&Android,274) load 1015844.html # bug 574889, bug 1374479
+asserts(11) asserts-if(Android,274) load 1015844.html # bug 574889, bug 1374479
 pref(font.size.inflation.minTwips,200) load 1032450.html
 load 1032613-1.svg
 load 1032613-2.html
 load 1037903.html
 load 1039454-1.html
 load 1042489.html
 load 1054010-1.html
 load 1058954-1.html
@@ -639,18 +639,18 @@ load text-overflow-bug671796.xhtml
 load text-overflow-bug713610.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 asserts(1-4) load 1225005.html # bug 682647 and bug 448083
 load 1233191.html
 load 1234701-1.html
 load 1234701-2.html
 load 1271765.html
-asserts(2) asserts-if(stylo&&Android,1) load 1272983-1.html # bug 586628
-asserts(2) asserts-if(stylo&&Android,1) load 1272983-2.html # bug 586628
+asserts(2) asserts-if(Android,1) load 1272983-1.html # bug 586628
+asserts(2) asserts-if(Android,1) load 1272983-2.html # bug 586628
 load 1275059.html
 load 1278007.html
 load 1278080.html
 load 1279814.html
 skip-if(webrender) load large-border-radius-dashed.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dashed2.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dotted.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dotted2.html # see bug 1409243, not handled by webrender
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9822,37 +9822,32 @@ GetCorrectedParent(const nsIFrame* aFram
   // Table wrappers are always anon boxes; if we're in here for an outer
   // table, that actually means its the _inner_ table that wants to
   // know its parent. So get the pseudo of the inner in that case.
   nsAtom* pseudo = aFrame->Style()->GetPseudo();
   if (pseudo == nsCSSAnonBoxes::tableWrapper) {
     pseudo = aFrame->PrincipalChildList().FirstChild()->Style()->GetPseudo();
   }
 
-  // Prevent NAC from inheriting NAC. This partially duplicates the logic
-  // implemented in nsCSSFrameConstructor::AddFCItemsForAnonymousContent, and is
-  // necessary so that restyle inherits style in the same way as the initial
-  // styling performed in frame construction.
-  //
-  // It would be nice to put it in CorrectStyleParentFrame and therefore share
-  // it, but that would lose the information of whether the _child_ is NAC,
-  // since CorrectStyleParentFrame only knows about the prospective _parent_.
-  // This duplication and complexity will go away when we fully switch to the
-  // Servo style system, where all this can be handled much more naturally.
-  //
-  // We need to take special care not to disrupt the style inheritance of frames
-  // whose content is NAC but who implement a pseudo (like an anonymous
-  // box, or a non-NAC-backed pseudo like ::first-line) that does not match the
-  // one that the NAC implements, if any.
-  nsIContent* content = aFrame->GetContent();
-  Element* element =
-    content && content->IsElement() ? content->AsElement() : nullptr;
-  if (element && element->IsNativeAnonymous() && !element->IsNativeScrollbarContent() &&
-      element->GetPseudoElementType() == aFrame->Style()->GetPseudoType()) {
-    while (parent->GetContent() && parent->GetContent()->IsNativeAnonymous()) {
+  // Prevent a NAC pseudo-element from inheriting from its NAC parent, and
+  // inherit from the NAC generator element instead.
+  if (pseudo) {
+    MOZ_ASSERT(aFrame->GetContent());
+    Element* element =
+      aFrame->GetContent()->IsElement()
+        ? aFrame->GetContent()->AsElement() : nullptr;
+    // Make sure to avoid doing the fixup for non-element-backed pseudos like
+    // ::first-line and such.
+    if (element &&
+        !element->IsRootOfNativeAnonymousSubtree() &&
+        element->GetPseudoElementType() == aFrame->Style()->GetPseudoType()) {
+      while (parent->GetContent() &&
+             !parent->GetContent()->IsRootOfAnonymousSubtree()) {
+        parent = parent->GetInFlowParent();
+      }
       parent = parent->GetInFlowParent();
     }
   }
 
   return nsFrame::CorrectStyleParentFrame(parent, pseudo);
 }
 
 /* static */
--- a/layout/inspector/tests/test_getRelativeRuleLine.html
+++ b/layout/inspector/tests/test_getRelativeRuleLine.html
@@ -23,21 +23,19 @@
 
      #test {
        color: blue;
      }
   </style>
   <script type="application/javascript">
   const InspectorUtils = SpecialPowers.InspectorUtils;
 
-  const supportsRuleColumn = SpecialPowers.DOMWindowUtils.isStyledByServo ? 14
-                                                                          : 15;
   let tests = [
     { sheetNo: 0, ruleNo: 0, lineNo: 1, columnNo: 1 },
-    { sheetNo: 1, ruleNo: 0, lineNo: 2, columnNo: supportsRuleColumn },
+    { sheetNo: 1, ruleNo: 0, lineNo: 2, columnNo: 14 },
     { sheetNo: 1, ruleNo: 1, lineNo: 8, columnNo: 5 },
     { sheetNo: 2, ruleNo: 0, lineNo: 1, columnNo: 1 },
     { sheetNo: 2, ruleNo: 1, lineNo: 0, columnNo: 1 },
     { sheetNo: 3, ruleNo: 0, lineNo: 5, columnNo: 6 },
   ];
 
   function doTest() {
     document.styleSheets[2].insertRule("body{}", 1);
--- a/layout/reftests/border-image/reftest.list
+++ b/layout/reftests/border-image/reftest.list
@@ -31,17 +31,17 @@ fails-if(Android) fails-if(usesRepeatRes
 == border-image-width-1b.html border-image-width-1-ref.html
 == border-image-width-1c.html border-image-width-1-ref.html
 == border-image-width-large.html border-image-width-large-ref.html
 == border-image-outset-1a.html border-image-outset-1-ref.html
 == border-image-outset-1b.html border-image-outset-1-ref.html
 == border-image-outset-1c.html border-image-outset-1-ref.html
 == border-image-nofill-1.html border-image-nofill-1-ref.html
 == border-image-outset-resize-1.html border-image-outset-resize-1-ref.html
-fuzzy-if(asyncPan&&!layersGPUAccelerated,140,514) fuzzy-if(winWidget&&stylo,144,448) == border-image-outset-move-1.html border-image-outset-move-1-ref.html
+fuzzy-if(asyncPan&&!layersGPUAccelerated,140,514) fuzzy-if(winWidget,144,448) == border-image-outset-move-1.html border-image-outset-move-1-ref.html
 == border-image-style-none.html border-image-style-none-ref.html
 == border-image-style-none-length.html border-image-style-none-length-ref.html
 == border-image-style-none-auto.html border-image-style-none-auto-ref.html
 
 # border images with gradients
 fuzzy-if(webrender,1-1,1488-1804) == border-image-linear-gradient.html border-image-linear-gradient-ref.html
 fuzzy(1,98) fuzzy-if(skiaContent,1,350) fuzzy-if(webrender,1-2,37234-37537) == border-image-linear-gradient-slice-1.html border-image-linear-gradient-slice-1-ref.html
 fuzzy(1,149) fuzzy-if(OSX,1,10595) fuzzy-if(webrender,1-3,24999-25121) == border-image-linear-gradient-slice-2.html border-image-linear-gradient-slice-2-ref.html
--- a/layout/reftests/border-radius/reftest.list
+++ b/layout/reftests/border-radius/reftest.list
@@ -46,17 +46,17 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(
 fuzzy-if(true,1,20) fuzzy-if(d2d,72,196) fuzzy-if(cocoaWidget,1,180) fuzzy-if(Android,140,237) == clipping-4-canvas.html clipping-4-ref.html # bug 732535
 fuzzy-if(Android,5,54) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,10) fuzzy-if(skiaContent,1,172) == clipping-4-image.html clipping-4-ref.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,10) fuzzy-if(skiaContent,1,77) == clipping-4-overflow-hidden.html clipping-4-ref.html
 == clipping-5-canvas.html clipping-5-refc.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-5-image.html clipping-5-refi.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(skiaContent,1,77) == clipping-5-overflow-hidden.html clipping-5-ref.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(Android,5,21) fuzzy-if(skiaContent,1,97) == clipping-5-refi.html clipping-5-ref.html
 fuzzy-if(true,1,7) fuzzy-if(d2d,55,95) fuzzy-if(cocoaWidget,1,99) fuzzy-if(Android,99,115) fuzzy-if(skiaContent,1,77) == clipping-5-refc.html clipping-5-ref.html # bug 732535
-fuzzy-if(winWidget,105,71) fuzzy-if(Android,8,469) fuzzy-if(skiaContent,21,74) fuzzy-if(d3d11&&advancedLayers,120,319) fuzzy-if(winWidget&&stylo,144,335) fuzzy-if(webrender&&cocoaWidget,98-98,279-279) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical
+fuzzy-if(winWidget,105,71) fuzzy-if(Android,8,469) fuzzy-if(skiaContent,21,74) fuzzy-if(d3d11&&advancedLayers,120,319) fuzzy-if(winWidget,144,335) fuzzy-if(webrender&&cocoaWidget,98-98,279-279) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical
 fuzzy-if(true,2,29) fuzzy-if(d2d,46,71) fuzzy-if(Android,255,586) fuzzy-if(skiaContent,28,96) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures).
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html
 fuzzy-if(cocoaWidget,1,4) fuzzy-if(d2d,59,342) fuzzy-if(d3d11&&advancedLayers&&!d2d,30,3) == intersecting-clipping-1-canvas.html intersecting-clipping-1-refc.html
 == intersecting-clipping-1-image.html intersecting-clipping-1-refi.html
 == intersecting-clipping-1-overflow-hidden.html intersecting-clipping-1-ref.html
 fuzzy-if(Android,5,105) fuzzy-if(d2d,1,20) fuzzy-if(skiaContent,1,300) == intersecting-clipping-1-refi.html intersecting-clipping-1-ref.html
 fuzzy-if(true,1,33) fuzzy-if(d2d,59,350) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android,124,440) fuzzy-if(skiaContent,1,135) fuzzy-if(d3d11&&advancedLayers,81,353) == intersecting-clipping-1-refc.html intersecting-clipping-1-ref.html # bug 732535
 
--- a/layout/reftests/css-animations/reftest.list
+++ b/layout/reftests/css-animations/reftest.list
@@ -1,12 +1,12 @@
 == screen-animations.html screen-animations-ref.html
 != screen-animations.html screen-animations-notref.html
-skip-if(stylo) fails == print-no-animations.html print-no-animations-ref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests. Bug 1374154 for stylo
-skip-if(stylo) fails != print-no-animations.html print-no-animations-notref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests. Bug 1374154 for stylo
+fails == print-no-animations.html print-no-animations-ref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests.
+fails != print-no-animations.html print-no-animations-notref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests.
 == animate-opacity.html animate-opacity-ref.html
 == animate-preserves3d.html animate-preserves3d-ref.html
 == animation-initially-out-of-view-with-delay.html animation-initially-out-of-view-with-delay-ref.html
 == animation-on-empty-height-frame.html about:blank
 == in-visibility-hidden-animation.html in-visibility-hidden-animation-ref.html
 == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html
 == partially-out-of-view-animation.html partially-out-of-view-animation-ref.html
 == animate-display-table-opacity.html animate-display-table-opacity-ref.html
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -200,17 +200,17 @@ fuzzy-if(skiaContent,1,2) == fallback-co
 == filter-bounds-02.svg pass.svg
 # This pref is normally on by default, but we turn it off in reftest runs to
 # disable an unnecessary security-check. This reftest is actually testing that
 # the security check works, though, so it needs the pref to be turned on:
 fails-if(Android) pref(security.fileuri.strict_origin_policy,true) == filter-extref-differentOrigin-01.svg pass.svg # Bug 695385
 == filter-foreignObject-01.svg pass.svg
 == filter-in-mask-01.svg pass.svg
 == filter-invalidation-01.svg pass.svg
-fuzzy(71,817) fails-if(winWidget&&stylo) fuzzy-if(webrender&&cocoaWidget,67-67,887-887) == filter-on-continuation-box-01.html filter-on-continuation-box-ref.html
+fuzzy(71,817) fails-if(winWidget) fuzzy-if(webrender&&cocoaWidget,67-67,887-887) == filter-on-continuation-box-01.html filter-on-continuation-box-ref.html
 == filter-result-01.svg filter-result-01-ref.svg
 == filter-scaled-01.svg pass.svg
 fuzzy-if(skiaContent,1,500) == filter-scaled-02.html filter-scaled-02-ref.html
 == filter-translated-01.svg filter-translated-01-ref.svg
 == filter-use-element-01.svg pass.svg
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||skiaContent,1,800000) == filters-and-group-opacity-01.svg filters-and-group-opacity-01-ref.svg
 
 == foreignObject-01.svg pass.svg
--- a/layout/reftests/svg/smil/style/reftest.list
+++ b/layout/reftests/svg/smil/style/reftest.list
@@ -109,18 +109,19 @@ fails == anim-css-strokedasharray-1.svg 
 == anim-css-strokewidth-1-by-no-no.svg        anim-css-strokewidth-1-ref.svg
 == anim-css-strokewidth-1-from-by-no-no.svg   anim-css-strokewidth-1-ref.svg
 == anim-css-strokewidth-1-from-to-no-no.svg   anim-css-strokewidth-1-ref.svg
 == anim-css-strokewidth-1-to-no-no.svg        anim-css-strokewidth-1-ref.svg
 
 # 'stroke-width' property, from/by/to with percent values
 # XXXdholbert the mixed pct + px tests fail right now, because we need calc()
 # in order to interpolate between pct and non-pct values, and we don't yet
-# support calc() for stroke-width & other SVG-specific properties. (Bug 1258270
-# for gecko, Bug 1386967 for stylo)
+# support calc() for stroke-width & other SVG-specific properties.
+#
+# Bug 1258270 and 1386967
 == anim-css-strokewidth-1-by-pct-pct.svg                          anim-css-strokewidth-1-ref.svg
 fails == anim-css-strokewidth-1-by-pct-px.svg                     anim-css-strokewidth-1-ref.svg
 fails == anim-css-strokewidth-1-by-px-pct.svg                     anim-css-strokewidth-1-ref.svg
 fails-if(webrender) == anim-css-strokewidth-1-from-by-pct-pct.svg anim-css-strokewidth-1-ref.svg # bug 1459418
 fails == anim-css-strokewidth-1-from-by-pct-px.svg                anim-css-strokewidth-1-ref.svg
 fails == anim-css-strokewidth-1-from-by-px-pct.svg                anim-css-strokewidth-1-ref.svg
 fails-if(webrender) == anim-css-strokewidth-1-from-to-pct-pct.svg anim-css-strokewidth-1-ref.svg # bug 1459418
 fails == anim-css-strokewidth-1-from-to-pct-px.svg                anim-css-strokewidth-1-ref.svg
--- a/layout/reftests/w3c-css/failures.list
+++ b/layout/reftests/w3c-css/failures.list
@@ -160,18 +160,16 @@ fails css-writing-modes/line-box-height-
 fails css-writing-modes/line-box-height-vlr-021.xht
 fails css-writing-modes/line-box-height-vlr-023.xht
 fails css-writing-modes/line-box-height-vrl-002.xht
 fails css-writing-modes/line-box-height-vrl-004.xht
 fails css-writing-modes/line-box-height-vrl-010.xht
 fails css-writing-modes/line-box-height-vrl-012.xht
 
 # Bug 1258635 - text-combine-upright: digits
-# Using skip because there are mismatch tests which would unexpectedly
-# pass with "fails-if(!stylo)".
 skip css-writing-modes/full-width-003.html
 skip css-writing-modes/text-combine-upright-value-digits?-001.html
 skip css-writing-modes/text-combine-upright-value-digits?-002.html
 
 # Bug 1220353
 fails css-writing-modes/vertical-alignment-vlr-023.xht
 fails css-writing-modes/vertical-alignment-vlr-025.xht
 fails css-writing-modes/vertical-alignment-vrl-022.xht
@@ -180,17 +178,16 @@ fails css-writing-modes/vertical-alignme
 # Bug 1102175
 fails css-writing-modes/wm-propagation-body-*.xht
 
 css-writing-modes/text-combine-upright-layout-rules-001.html
 
 #### CSS Multi-column 1 ##############################################
 
 # Fuzzy annotations for multicol tests are due to AA differences.
-# fails-if(!stylo) annotations need to be triaged later. (Bug 1299006)
 fails-if(winWidget||OSX) css-multicol/multicol-block-no-clip-001.xht
 fails-if(winWidget||OSX) css-multicol/multicol-block-no-clip-002.xht
 fails css-multicol/multicol-br-inside-avoidcolumn-001.xht
 fails css-multicol/multicol-break-000.xht
 fails css-multicol/multicol-break-001.xht
 fuzzy(135,1008) fails-if(webrender&&cocoaWidget) css-multicol/multicol-clip-001.xht
 fuzzy(135,770) css-multicol/multicol-clip-002.xht
 fuzzy(135,467) fails-if(webrender&&cocoaWidget) css-multicol/multicol-collapsing-001.xht
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -20,17 +20,17 @@ load 411603-1.html
 load 412588-1.html
 load 413274-1.xhtml
 load 416461-1.xul
 load 418007-1.xhtml
 load 431705-1.xul
 load 432561-1.html
 load 437170-1.html
 load 437532-1.html
-skip-if(Android&&stylo&&isDebugBuild) load 439184-1.html # Bug 1411522
+skip-if(Android&&isDebugBuild) load 439184-1.html # Bug 1411522
 load 444237-1.html
 load 444848-1.html
 load 447776-1.html
 load 447783-1.html
 load 448161-1.html
 load 448161-2.html
 load 452150-1.xhtml
 load 456196.html
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -175,17 +175,17 @@ nsDOMCSSAttributeDeclaration::SetSMILVal
   MOZ_ASSERT(mIsSMILOverride);
   // No need to do the ActiveLayerTracker / ScrollLinkedEffectDetector bits,
   // since we're in a SMIL animation anyway, no need to try to detect we're a
   // scripted animation.
   DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
   if (!olddecl) {
     return NS_ERROR_NOT_AVAILABLE;
   }
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
+  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
   bool changed = nsSMILCSSValueType::SetPropertyValues(aValue, *decl);
   if (changed) {
     SetCSSDeclaration(decl);
   }
   return NS_OK;
 }
 
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -111,17 +111,17 @@ nsDOMCSSDeclaration::SetCssText(const ns
     return;
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
+  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
 
   ParsingEnvironment servoEnv =
     GetParsingEnvironment(aSubjectPrincipal);
   if (!servoEnv.mUrlExtraData) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
@@ -253,17 +253,17 @@ nsDOMCSSDeclaration::ModifyDeclaration(n
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
+  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
 
   bool changed;
   ParsingEnvironment servoEnv =
     GetParsingEnvironment(aSubjectPrincipal);
   if (!servoEnv.mUrlExtraData) {
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -320,17 +320,17 @@ nsDOMCSSDeclaration::RemovePropertyInter
     return NS_OK; // no decl, so nothing to remove
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
+  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
 
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
   if (!decl->RemovePropertyByID(aPropID)) {
     return NS_OK;
   }
   return SetCSSDeclaration(decl);
 }
 
@@ -342,16 +342,16 @@ nsDOMCSSDeclaration::RemovePropertyInter
     return NS_OK; // no decl, so nothing to remove
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
+  mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
 
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
   if (!decl->RemoveProperty(aPropertyName)) {
     return NS_OK;
   }
   return SetCSSDeclaration(decl);
 }
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -155,18 +155,16 @@ input::placeholder,
 textarea::placeholder,
 input > .preview-div
 textarea > .preview-div {
   overflow: auto;
   border: 0px !important;
   padding: inherit !important;
   margin: 0px;
   text-decoration: inherit;
-  text-decoration-color: inherit;
-  text-decoration-style: inherit;
   display: inline-block;
   ime-mode: inherit;
   resize: inherit;
   -moz-control-character-visibility: visible;
   overflow-clip-box: inherit;
 }
 
 input > .anonymous-div,
@@ -1055,16 +1053,18 @@ input[type=number]::-moz-number-text {
   -moz-user-modify: read-write;
   /* This pseudo-element is also an 'input' element (nested inside and
    * distinct from the <input type=number> element) so we need to prevent the
    * explicit setting of 'text-align' by the general CSS rule for 'input'
    * above. We want to inherit its value from its <input type=number>
    * ancestor, not have that general CSS rule reset it.
    */
   text-align: inherit;
+  text-decoration: inherit;
+  ime-mode: inherit;
   flex: 1;
   min-inline-size: 0;
   padding: 0;
   border: 0;
   margin: 0;
 }
 
 input[type=number]::-moz-number-spin-box {
--- a/layout/style/test/browser.ini
+++ b/layout/style/test/browser.ini
@@ -1,17 +1,14 @@
 [DEFAULT]
 support-files =
   bug453896_iframe.html
   media_queries_iframe.html
-  newtab_share_rule_processors.html
   mapped.css
   mapped.css^headers^
   mapped2.css
   mapped2.css^headers^
   sourcemap_css.html
 
 [browser_bug453896.js]
-[browser_newtab_share_rule_processors.js]
-skip-if = stylo # Gecko-specific test
 [browser_sourcemap.js]
 [browser_sourcemap_comment.js]
 [browser_sourceurl_comment.js]
deleted file mode 100644
--- a/layout/style/test/browser_newtab_share_rule_processors.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var theTab;
-var theBrowser;
-
-function listener(evt) {
-  if (evt.target == theBrowser.contentDocument) {
-    doTest();
-  }
-}
-
-function test() {
-  waitForExplicitFinish();
-  var testURL = getRootDirectory(gTestPath) + "newtab_share_rule_processors.html";
-  theTab = BrowserTestUtils.addTab(gBrowser, testURL);
-  theBrowser = gBrowser.getBrowserForTab(theTab);
-  theBrowser.addEventListener("load", listener, true);
-}
-
-function doTest() {
-  theBrowser.removeEventListener("load", listener, true);
-  var winUtils = theBrowser.contentWindow
-    .QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIDOMWindowUtils);
-  if (winUtils.isStyledByServo) {
-    todo(false, "should update this test to check that Servo is also " +
-                "correctly sharing CascadeData");
-  } else {
-    // The initial set of agent-level sheets should have a rule processor that's
-    // also being used by another document.
-    ok(winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AGENT_SHEET),
-       "agent sheet rule processor is used by multiple style sets");
-    // Document-level sheets currently never get shared rule processors.
-    ok(!winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AUTHOR_SHEET),
-       "author sheet rule processor is not used by multiple style sets");
-    // Adding a unique style sheet to the agent level will cause it to have a
-    // rule processor that is unique.
-    theBrowser.contentWindow.wrappedJSObject.addAgentSheet();
-    ok(!winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AGENT_SHEET),
-       "agent sheet rule processor is not used by multiple style sets after " +
-       "having a unique sheet added to it");
-  }
-  gBrowser.removeTab(theTab);
-  finish();
-}
--- a/layout/style/test/chrome/chrome.ini
+++ b/layout/style/test/chrome/chrome.ini
@@ -16,12 +16,12 @@ support-files =
 [test_bug1160724.xul]
 [test_bug535806.xul]
 [test_chrome_only_media_queries.html]
 [test_display_mode.html]
 tags = fullscreen
 [test_display_mode_reflow.html]
 tags = fullscreen
 [test_hover.html]
-skip-if = stylo # bug 1346353
+skip-if = true # bug 1346353
 [test_moz_document_rules.html]
 [test_stylesheet_clone_import_rule.html]
 support-files = import_useless1.css import_useless2.css
--- a/layout/style/test/chrome/test_bug1371453.html
+++ b/layout/style/test/chrome/test_bug1371453.html
@@ -17,18 +17,17 @@ runTest();
 
 async function runTest() {
   document.getElementsByTagName("link")[1].sheet.insertRule('@import url("blahblah")', 0);
 
   // Await and then process the event we expect to arrive.
   let event = await ContentTaskUtils.waitForEvent(document, "StyleRuleAdded", true);
   is(event.rule.type, CSSRule.IMPORT_RULE, "Got expected import rule.");
 
-  let non_stylo_todo_isnot = SpecialPowers.DOMWindowUtils.isStyledByServo ? isnot : todo_isnot;
-  non_stylo_todo_isnot(event.rule.styleSheet, null, "Import rule contains a stylesheet.");
+  isnot(event.rule.styleSheet, null, "Import rule contains a stylesheet.");
 
   isnot(event.rule.media, null, "Import rule contains a media list.");
 
   is(event.rule.href, "blahblah", "Import rule contains expected href.");
 
   SimpleTest.finish();
 }
 
deleted file mode 100644
--- a/layout/style/test/file_blank_doc_backend.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<iframe></iframe>
-<script>
-let iframe = document.querySelector("iframe");
-iframe.contentDocument.writeln("<style></style>");
-iframe.contentDocument.close();
-opener.finish(window, iframe.contentWindow);
-</script>
--- a/layout/style/test/file_specified_value_serialization_individual_transforms.html
+++ b/layout/style/test/file_specified_value_serialization_individual_transforms.html
@@ -12,22 +12,16 @@
 const is = opener.is.bind(opener);
 function finish() {
   const o = opener;
   self.close();
   o.SimpleTest.finish();
 }
 
 function runTest() {
-  // The individual transform functions are not implemented in the Gecko style
-  // system.
-  if (!SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    return;
-  }
-
   // Test for rotate property serialization.
   [
     [" 90deg ", "90deg"],
     [" 100grad ", "100grad"],
     [" 100gRaD ", "100grad"],
     [" 0.25turn  ", "0.25turn"],
     [" 0.25tUrN  ", "0.25turn"],
     [" 1.57RaD  ", "1.57rad"],
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -65,18 +65,16 @@ support-files = Ahem.ttf file_animations
 [test_animations_variable_changes.html]
 [test_animations_with_disabled_properties.html]
 support-files = file_animations_with_disabled_properties.html
 [test_any_dynamic.html]
 [test_asyncopen2.html]
 [test_at_rule_parse_serialize.html]
 [test_attribute_selector_eof_behavior.html]
 [test_background_blend_mode.html]
-[test_blank_doc_backend.html]
-support-files = file_blank_doc_backend.html
 [test_box_size_keywords.html]
 [test_bug73586.html]
 [test_bug74880.html]
 [test_bug98997.html]
 [test_bug160403.html]
 [test_bug200089.html]
 [test_bug221428.html]
 [test_bug229915.html]
deleted file mode 100644
--- a/layout/style/test/newtab_share_rule_processors.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<style>
-p { color: blue; }
-</style>
-<p>Hello</p>
-<script>
-
-var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
-  .getService(Ci.nsIStyleSheetService);
-var io = Cc["@mozilla.org/network/io-service;1"]
-  .getService(Ci.nsIIOService);
-var winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-  .getInterface(Ci.nsIDOMWindowUtils);
-
-function addAgentSheet() {
-  var sheetURI = io.newURI("data:text/css,p{background-color:yellow}");
-  var sheet = sss.preloadSheet(sheetURI, Ci.nsIStyleSheetService.AGENT_SHEET);
-  winUtils.addSheet(sheet, Ci.nsIDOMWindowUtils.AGENT_SHEET);
-}
-</script>
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -222,17 +222,23 @@ var validGradientAndElementValues = [
   "radial-gradient(at left calc(25px), red, blue)",
   "radial-gradient(at calc(-25%) top, red, blue)",
   "radial-gradient(at left calc(-25%), red, blue)",
   "radial-gradient(at calc(-25px) top, red, blue)",
   "radial-gradient(at left calc(-25px), red, blue)",
   "radial-gradient(at calc(100px + -25%) top, red, blue)",
   "radial-gradient(at left calc(100px + -25%), red, blue)",
   "radial-gradient(at calc(100px + -25px) top, red, blue)",
-  "radial-gradient(at left calc(100px + -25px), red, blue)"
+  "radial-gradient(at left calc(100px + -25px), red, blue)",
+
+  "-webkit-linear-gradient(top, red, blue)",
+  "-moz-linear-gradient(top, red, blue)",
+  "-moz-linear-gradient(center 0%, red, blue)",
+  "-moz-linear-gradient(50% top, red, blue)",
+  "-moz-linear-gradient(50% 0%, red, blue)",
 ];
 var invalidGradientAndElementValues = [
   "-moz-element(#a:1)",
   "-moz-element(a#a)",
   "-moz-element(#a a)",
   "-moz-element(#a+a)",
   "-moz-element(#a())",
   /* no quirks mode colors */
@@ -313,17 +319,18 @@ var invalidGradientAndElementValues = [
   "radial-gradient(99deg, cover, red, blue)",
   "radial-gradient(-1.2345rad, circle, red, blue)",
   "radial-gradient(399grad, ellipse closest-corner, red, blue)",
   "radial-gradient(399grad, farthest-side circle, red, blue)",
 
   "radial-gradient(top left 99deg, cover, red, blue)",
   "radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
   "radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
-  "radial-gradient(45px 399grad, farthest-side circle, red, blue)"
+  "radial-gradient(45px 399grad, farthest-side circle, red, blue)",
+  "radial-gradient(circle red, blue)",
 ];
 var unbalancedGradientAndElementValues = [
   "-moz-element(#a()",
 ];
 
 var basicShapeSVGBoxValues = [
   "fill-box",
   "stroke-box",
@@ -497,42 +504,16 @@ var basicShapeUnbalancedValues = [
   "inset(1px 2px",
   "inset(1px 2px 3px",
   "inset(1px 2px 3px 4px",
   "inset(1px 2px 3px 4px round 5px",
   "inset(1px 2px 3px 4px round 5px / 6px",
 ];
 
 
-// Gradient values that are incorrectly accepted in Gecko, but are correctly
-// rejected with Servo's style-system backend (stylo):
-let gradientsNewlyRejectedInStylo = [
-  "radial-gradient(circle red, blue)",
-];
-
-// Gradient values that are consistently serialized in Stylo but not
-// in Gecko. Gecko drops the prefix during roundtrip.
-let gradientsValidInStyloBrokenInGecko = [
-  "-webkit-linear-gradient(top, red, blue)",
-  "-moz-linear-gradient(top, red, blue)",
-  "-moz-linear-gradient(center 0%, red, blue)",
-  "-moz-linear-gradient(50% top, red, blue)",
-  "-moz-linear-gradient(50% 0%, red, blue)",
-];
-
-if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-  invalidGradientAndElementValues.push(...gradientsNewlyRejectedInStylo);
-  validGradientAndElementValues.push(...gradientsValidInStyloBrokenInGecko);
-} else {
-  // NOTE: These are technically invalid, but Gecko's CSS parser thinks they're
-  // valid. So, if we're using Gecko's style system, we add them to the
-  // "valid" list, so we can at least detect if the behavior changes.
-  validGradientAndElementValues.push(...gradientsNewlyRejectedInStylo);
-}
-
 if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
   // Extend gradient lists with valid/invalid webkit-prefixed expressions:
   validGradientAndElementValues.push(
     // 2008 GRADIENTS: -webkit-gradient()
     // ----------------------------------
     // linear w/ no color stops (valid) and a variety of position values:
     "-webkit-gradient(linear, 1 2, 3 4)",
     "-webkit-gradient(linear,1 2,3 4)", // (no extra space)
@@ -3514,17 +3495,17 @@ var gCSSProperties = {
     applies_to_placeholder: true,
     initial_values: [ "normal" ],
     other_values: [
       "'liga' on", "'liga'", "\"liga\" 1", "'liga', 'clig' 1",
       "\"liga\" off", "\"liga\" 0", '"cv01" 3, "cv02" 4',
       '"cswh", "smcp" off, "salt" 4', '"cswh" 1, "smcp" off, "salt" 4',
       '"cswh" 0, \'blah\', "liga", "smcp" off, "salt" 4',
       '"liga"        ,"smcp" 0         , "blah"',
-      '"ab\\"c"', '"ab\\\\c"'
+      '"ab\\"c"', '"ab\\\\c"', "'vert' calc(2)"
     ],
     invalid_values: [
       'liga', 'liga 1', 'liga normal', '"liga" normal', 'normal liga',
       'normal "liga"', 'normal, "liga"', '"liga=1"', "'foobar' on",
       '"blahblah" 0', '"liga" 3.14', '"liga" 1 3.14', '"liga" 1 normal',
       '"liga" 1 off', '"liga" on off', '"liga" , 0 "smcp"', '"liga" "smcp"'
     ]
   },
@@ -6242,18 +6223,17 @@ function get_computed_value(cs, property
     }
     return results.join(" ; ");
   }
   if (info.get_computed)
     return info.get_computed(cs, property);
   return cs.getPropertyValue(property);
 }
 
-if (SpecialPowers.DOMWindowUtils.isStyledByServo &&
-    IsCSSPropertyPrefEnabled("layout.css.individual-transform.enabled")) {
+if (IsCSSPropertyPrefEnabled("layout.css.individual-transform.enabled")) {
   gCSSProperties.rotate = {
     domProp: "rotate",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
     other_values: [ "45deg", "45grad", "72rad", "0.25turn", ".57rad",
                     "0 0 0 0rad", "0 0 1 45deg", "0 0 1 0rad",
                     /* valid calc() values */
@@ -6366,24 +6346,18 @@ if (IsCSSPropertyPrefEnabled("layout.css
     applies_to_first_letter: true,
     applies_to_first_line: true,
     applies_to_placeholder: true,
     initial_values: [ "auto" ],
     other_values: [ "none" ],
     invalid_values: [ "on" ]
   };
   gCSSProperties["font"].subproperties.push("font-optical-sizing");
-  if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    gCSSProperties["font-variation-settings"].other_values
-      .push("'vert' calc(2.5)");
-  }
-}
-
-if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-  gCSSProperties["font-feature-settings"].other_values.push("'vert' calc(2)");
+  gCSSProperties["font-variation-settings"].other_values
+    .push("'vert' calc(2.5)");
 }
 
 if (IsCSSPropertyPrefEnabled("layout.css.frames-timing.enabled")) {
   gCSSProperties["animation-timing-function"].other_values.push(
     "frames(2)", "frames(1000)", "frames( 2 )");
   gCSSProperties["animation-timing-function"].invalid_values.push(
     "frames(1)", "frames(-2)", "frames", "frames()", "frames(,)",
     "frames(a)", "frames(2.0)", "frames(2.5)", "frames(2 3)");
@@ -6517,16 +6491,17 @@ if (IsCSSPropertyPrefEnabled("layout.css
       "grayscale(0)",
       "grayscale(50%)",
       "grayscale(1)",
       "grayscale(1.0)",
       "grayscale(2)",
       "grayscale(350%)",
       "grayscale(4.567)",
 
+      "hue-rotate(0)",
       "hue-rotate(0deg)",
       "hue-rotate(90deg)",
       "hue-rotate(540deg)",
       "hue-rotate(-90deg)",
       "hue-rotate(10grad)",
       "hue-rotate(1.6rad)",
       "hue-rotate(-1.6rad)",
       "hue-rotate(0.5turn)",
@@ -6673,25 +6648,16 @@ if (IsCSSPropertyPrefEnabled("layout.css
       "sepia(0.5 0.5)",
       "sepia(0.5,)",
       "sepia(0.5, 0.5)",
       "sepia(#my-filter)",
       "sepia(10px)",
       "sepia(-1)",
     ]
   };
-
-  // See https://github.com/w3c/fxtf-drafts/issues/228.
-  //
-  // This is updated in Stylo but not Gecko.
-  if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    gCSSProperties["filter"].other_values.push("hue-rotate(0)");
-  } else {
-    gCSSProperties["filter"].invalid_values.push("hue-rotate(0)");
-  }
 }
 
 var isGridTemplateSubgridValueEnabled =
   IsCSSPropertyPrefEnabled("layout.css.grid-template-subgrid-value.enabled");
 
 gCSSProperties["display"].other_values.push("grid", "inline-grid");
 gCSSProperties["grid-auto-flow"] = {
   domProp: "gridAutoFlow",
--- a/layout/style/test/test_align_justify_computed_values.html
+++ b/layout/style/test/test_align_justify_computed_values.html
@@ -164,67 +164,61 @@ function main() {
   var child = document.getElementById("display");
   var abs = document.getElementById("absChild");
   is(getComputedAlignItems(elem), 'normal', "default align-items value for block container");
   is(getComputedAlignSelf(child), 'auto', "default align-self value for block child");
   is(getComputedAlignSelf(abs), 'auto', "default align-self value for block container abs.pos. child");
   elem.style.alignItems = "end";
   is(getComputedAlignSelf(child), 'auto', "align-self:auto value persists for block child");
   is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for block container abs.pos. child");
-  if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    elem.style.alignItems = "left";
-    is(getComputedAlignItems(elem), 'end', "align-items:left is an invalid declaration");
-    is(getComputedAlignSelf(child), 'auto', "align-self:auto persists for block child");
-    is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for block container abs.pos. child");
-    elem.style.alignItems = "right";
-    is(getComputedAlignItems(elem), 'end', "align-items:right is an invalid declaration");
-    is(getComputedAlignSelf(child), 'auto', "align-self:auto value persists for block child");
-    is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for block container abs.pos. child");
-  }
+  elem.style.alignItems = "left";
+  is(getComputedAlignItems(elem), 'end', "align-items:left is an invalid declaration");
+  is(getComputedAlignSelf(child), 'auto', "align-self:auto persists for block child");
+  is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for block container abs.pos. child");
+  elem.style.alignItems = "right";
+  is(getComputedAlignItems(elem), 'end', "align-items:right is an invalid declaration");
+  is(getComputedAlignSelf(child), 'auto', "align-self:auto value persists for block child");
+  is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for block container abs.pos. child");
 
   //// Flexbox tests
   function testFlexAlignItemsSelf(elem) {
     var item = elem.firstChild;
     var abs = elem.children[1];
     is(getComputedAlignItems(elem), 'normal', "default align-items value for flex container");
     is(getComputedAlignSelf(item), 'auto', "default align-self value for flex item");
     is(getComputedAlignSelf(abs), 'auto', "default align-self value for flex container abs.pos. child");
     elem.style.alignItems = "flex-end";
     is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for flex container child");
     is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for flex container abs.pos. child");
-    if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-      elem.style.alignItems = "left";
-      is(getComputedAlignItems(elem), 'flex-end', "align-items:left is an invalid declaration");
-    }
+    elem.style.alignItems = "left";
+    is(getComputedAlignItems(elem), 'flex-end', "align-items:left is an invalid declaration");
     elem.style.alignItems = "";
   }
   testFlexAlignItemsSelf(document.getElementById("flexContainer"));
   testFlexAlignItemsSelf(document.getElementById("flexContainerGrid"));
 
   //// Grid tests
   function testGridAlignItemsSelf(elem) {
     var item = elem.firstChild;
     var abs = elem.children[1];
     is(getComputedAlignItems(elem), 'normal', "default align-items value for grid container");
     is(getComputedAlignSelf(item), 'auto', "default align-self value for grid item");
     is(getComputedAlignSelf(abs), 'auto', "default align-self value for grid container abs.pos. child");
     elem.style.alignItems = "end";
     is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for grid container child");
     is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for grid container abs.pos. child");
 
-    if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-      elem.style.alignItems = "left";
-      is(getComputedAlignItems(elem), 'end', "align-items:left is an invalid declaration");
-      is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for grid container child");
-      is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for grid container abs.pos. child");
-      elem.style.alignItems = "right";
-      is(getComputedAlignItems(elem), 'end', "align-items:right is an invalid declaration");
-      is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for grid container child");
-      is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for grid container abs.pos. child");
-    }
+    elem.style.alignItems = "left";
+    is(getComputedAlignItems(elem), 'end', "align-items:left is an invalid declaration");
+    is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for grid container child");
+    is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for grid container abs.pos. child");
+    elem.style.alignItems = "right";
+    is(getComputedAlignItems(elem), 'end', "align-items:right is an invalid declaration");
+    is(getComputedAlignSelf(item), 'auto', "align-self:auto value persists for grid container child");
+    is(getComputedAlignSelf(abs), 'auto', "align-self:auto value persists for grid container abs.pos. child");
 
     item.style.alignSelf = "";
     abs.style.alignSelf = "";
     elem.style.alignItems = "";
     item.style.alignSelf = "";
   }
   testGridAlignItemsSelf(document.getElementById("gridContainer"));
   testGridAlignItemsSelf(document.getElementById("gridContainerFlex"));
@@ -338,24 +332,22 @@ function main() {
   var child = document.getElementById("display");
   var abs = document.getElementById("absChild");
   is(getComputedAlignContent(elem), 'normal', "default align-content value for block container");
   is(getComputedAlignContent(child), 'normal', "default align-content value for block child");
   is(getComputedAlignContent(abs), 'normal', "default align-content value for block container abs.pos. child");
   elem.style.alignContent = "end";
   is(getComputedAlignContent(child), 'normal', "default align-content isn't affected by parent align-content value for in-flow child");
   is(getComputedAlignContent(abs), 'normal', "default align-content isn't affected by parent align-content value for block container abs.pos. child");
-  if (SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    elem.style.alignContent = "left";
-    is(getComputedAlignContent(elem), 'end', "align-content:left isn't a valid declaration");
-    is(getComputedAlignContent(abs), 'normal', "default align-content isn't affected by parent align-content value for block container abs.pos. child");
-    elem.style.alignContent = "right";
-    is(getComputedAlignContent(elem), 'end', "align-content:right isn't a valid declaration");
-    is(getComputedAlignContent(abs), 'normal', "default align-content isn't affected by parent align-content value for block container abs.pos. child");
-  }
+  elem.style.alignContent = "left";
+  is(getComputedAlignContent(elem), 'end', "align-content:left isn't a valid declaration");
+  is(getComputedAlignContent(abs), 'normal', "default align-content isn't affected by parent align-content value for block container abs.pos. child");
+  elem.style.alignContent = "right";
+  is(getComputedAlignContent(elem), 'end', "align-content:right isn't a valid declaration");
+  is(getComputedAlignContent(abs), 'normal', "default align-content isn't affected by parent align-content value for block container abs.pos. child");
   elem.style.alignContent = "";
 
   //// Flexbox tests
   function testFlexAlignContent(elem) {
     var item = elem.firstChild;
     var abs = elem.children[1];
     is(getComputedAlignContent(elem), 'normal', "default align-content value for flex container");
     is(getComputedAlignContent(item), 'normal', "default align-content value for flex item");
deleted file mode 100644
--- a/layout/style/test/test_blank_doc_backend.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test backend of blank document</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<iframe></iframe>
-<pre id="log">
-<script>
-SimpleTest.waitForExplicitFinish();
-let win = window.open("file_blank_doc_backend.html", "", "width=500,height=500");
-function finish(parentWin, iframeWin) {
-  let parentDOMUtils = SpecialPowers.getDOMWindowUtils(parentWin);
-  let iframeDOMUtils = SpecialPowers.getDOMWindowUtils(iframeWin);
-  is(parentDOMUtils.isStyledByServo, iframeDOMUtils.isStyledByServo,
-     "Blank document backend should match the parent document");
-  win.close();
-  SimpleTest.finish();
-};
-</script>
-</pre>
-</body>
-</html>
--- a/layout/style/test/test_grid_shorthand_serialization.html
+++ b/layout/style/test/test_grid_shorthand_serialization.html
@@ -21,18 +21,16 @@ var initial_values = {
     gridTemplateColumns: "none",
     gridAutoFlow: "row",
     gridAutoRows: "auto",
     gridAutoColumns: "auto",
     gridRowGap: "0px",
     gridColumnGap: "0px",
 };
 
-const isStylo = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
 // For various specified values of the grid-template subproperties,
 // test the serialization of the shorthand.
 var grid_template_test_cases = [
     {
         gridTemplateColumns: "100px",
         shorthand: "none / 100px",
     },
     {
@@ -65,23 +63,23 @@ var grid_template_test_cases = [
     {
         gridTemplateAreas: "\"a\"",
         gridTemplateRows: "[foo] 20px [bar]",
         shorthand: "[foo] \"a\" 20px [bar]",
     },
     {
         gridTemplateAreas: "\"a\"",
         gridTemplateRows: "[foo] repeat(1, 20px) [bar]",
-        shorthand: isStylo ? "" : "[foo] \"a\" 20px [bar]",
+        shorthand: "",
     },
     {
         gridTemplateAreas: "\"a a\"",
         gridTemplateColumns: "repeat(2, 100px)",
         gridTemplateRows: "auto",
-        shorthand: isStylo ? "" : "\"a a\" auto / 100px 100px",
+        shorthand: "",
     },
     // Combinations of longhands that make the shorthand non-serializable:
     {
         gridTemplateAreas: "\"a\"",
         gridTemplateRows: "20px 100px",
         shorthand: "",
     },
     {
--- a/layout/style/test/test_keyframes_vendor_prefix.html
+++ b/layout/style/test/test_keyframes_vendor_prefix.html
@@ -57,18 +57,16 @@ function addDiv(t, attrs) {
   if (t && typeof t.add_cleanup === 'function') {
     t.add_cleanup(function() {
       div.remove();
     });
   }
   return div;
 }
 
-const isStylo = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
 test(function(t) {
   addStyle(t,
     { '@-webkit-keyframes anim': 'from,to { color: rgb(0, 255, 0); }' });
 
   var div = addDiv(t, { style: 'animation: anim 100s' });
 
   assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
 }, '-webkit- prefix keyframes');
@@ -105,38 +103,26 @@ test(function(t) {
     { '@-webkit-KEYFRAMES anim': 'from,to { color: rgb(0, 255, 0); }' });
 
   var div = addDiv(t, { style: 'animation: anim 100s' });
 
   assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
 }, '-webkit- prefix KEYFRAMES');
 
 test(function(t) {
-  if (!isStylo) {
-    // FIXME: Bug 1312918: later prefixed rule incorrectly overrides earlier
-    // non-prefixed on gecko.
-    return;
-  }
-
   addStyle(t,
     { '@keyframes anim':         'from,to { color: rgb(0, 255, 0); }',
       '@-webkit-keyframes anim': 'from,to { color: rgb(255, 0, 0); }' });
 
   var div = addDiv(t, { style: 'animation: anim 100s' });
 
   assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
 }, '-webkit-keyframes should not override earlier non-prefix keyframes');
 
 test(function(t) {
-  if (!isStylo) {
-    // FIXME: Bug 1312918: later prefixed rule incorrectly overrides earlier
-    // non-prefixed on gecko.
-    return;
-  }
-
   addStyle(t,
     { '@keyframes anim':      'from,to { color: rgb(0, 255, 0); }',
       '@-moz-keyframes anim': 'from,to { color: rgb(255, 0, 0); }' });
 
   var div = addDiv(t, { style: 'animation: anim 100s' });
 
   assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
 }, '-moz-keyframes should not override earlier non-prefix keyframes');
--- a/layout/style/test/test_parser_diagnostics_unprintables.html
+++ b/layout/style/test/test_parser_diagnostics_unprintables.html
@@ -13,18 +13,16 @@
 >Mozilla Bug 229827</a>
 <style id="testbench"></style>
 <script type="application/javascript">
 // This test has intimate knowledge of how to get the CSS parser to
 // emit diagnostics that contain text under control of the user.
 // That's not the point of the test, though; the point is only that
 // *that text* is properly escaped.
 
-const isStylo = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
 SpecialPowers.wrap(document).docShell.cssErrorReportingEnabled = true;
 
 // There is one "pattern" for each code path through the error reporter
 // that might need to escape some kind of user-supplied text.
 // Each "pattern" is tested once with each of the "substitution"s below:
 // <t>, <i>, and <s> are replaced by the t:, i:, and s: fields of
 // each substitution object in turn.
 let patterns = [
@@ -38,33 +36,21 @@ let patterns = [
   { i: "@namespace fnord #<t>;",   o: "within @namespace: \u2018#<i>\u2019" },
   // _Function
   { i: "@namespace fnord <t>();",  o: "within @namespace: \u2018<i>(\u2019" },
   // _Dimension
   { i: "@namespace fnord 14<t>;",  o: "within @namespace: \u201814<i>\u2019" },
   // _AtKeyword
   { i: "x{@<t>: }",        o: "declaration but found \u2018@<i>\u2019." },
   // _String
-  { i: "x{ '<t>'}" ,       o: isStylo ? 'declaration but found \u2018"<s>"\u2019.'
-                                      : "declaration but found \u2018'<s>'\u2019." },
+  { i: "x{ '<t>'}" ,       o: 'declaration but found \u2018"<s>"\u2019.' },
   // _Bad_String
-  { i: "x{ '<t>\n}",       o: isStylo ? 'declaration but found \u2018"<s>\u2019.'
-                                      : "declaration but found \u2018'<s>\u2019." },
+  { i: "x{ '<t>\n}",       o: 'declaration but found \u2018"<s>\u2019.' },
 ];
 
-// Stylo's CSS parser only reports the 'url(' token, not the actual bad URL.
-if (!isStylo) {
-  patterns.push(
-    // _URL
-    { i: "x{ url('<t>')}",   o: "declaration but found \u2018url('<s>')\u2019." })
-  patterns.push(
-    // _Bad_URL
-    { i: "x{ url('<t>'.)}" , o: "declaration but found \u2018url('<s>'\u2019." });
-}
-
 // Blocks of characters to test, and how they should be escaped when
 // they appear in identifiers and string constants.
 const substitutions = [
   // ASCII printables that _can_ normally appear in identifiers,
   // so should of course _not_ be escaped.
   { t: "-_0123456789",               i: "-_0123456789",
                                      s: "-_0123456789" },
   { t: "abcdefghijklmnopqrstuvwxyz", i: "abcdefghijklmnopqrstuvwxyz",
@@ -96,17 +82,17 @@ const substitutions = [
   { t: "-\\36 ", i: "-\\36 ", s: "-6" },
   { t: "-\\37 ", i: "-\\37 ", s: "-7" },
   { t: "-\\38 ", i: "-\\38 ", s: "-8" },
   { t: "-\\39 ", i: "-\\39 ", s: "-9" },
 
   // ASCII printables that must be escaped in identifiers.
   // Most of these should not be escaped in strings.
   { t: "\\!\\\"\\#\\$",   i: "\\!\\\"\\#\\$",   s: "!\\\"#$" },
-  { t: "\\%\\&\\'\\(",    i: "\\%\\&\\'\\(",    s: isStylo ? "%&'(" : "%&\\'(" },
+  { t: "\\%\\&\\'\\(",    i: "\\%\\&\\'\\(",    s: "%&'(" },
   { t: "\\)\\*\\+\\,",    i: "\\)\\*\\+\\,",    s: ")*+," },
   { t: "\\.\\/\\:\\;",    i: "\\.\\/\\:\\;",    s: "./:;" },
   { t: "\\<\\=\\>\\?",    i: "\\<\\=\\>\\?",    s: "<=>?", },
   { t: "\\@\\[\\\\\\]",   i: "\\@\\[\\\\\\]",   s: "@[\\\\]" },
   { t: "\\^\\`\\{\\}\\~", i: "\\^\\`\\{\\}\\~", s: "^`{}~" },
 
   // U+0000 - U+0020 (C0 controls, space)
   // U+000A LINE FEED, U+000C FORM FEED, and U+000D CARRIAGE RETURN
--- a/layout/style/test/test_property_database.html
+++ b/layout/style/test/test_property_database.html
@@ -26,31 +26,21 @@
  * the autogenerated css_properties.js to make sure that everything in
  * css_properties.js is in property_database.js.
  *
  * This prevents CSS properties from being added to the code without
  * also being put under the minimal test coverage provided by the tests
  * that use property_database.js.
  */
 
-const gServoOnlyProperties = [
-  'rotate',
-  'scale',
-  'translate',
-];
-
 for (var idx in gLonghandProperties) {
   var prop = gLonghandProperties[idx];
   if (prop.pref && !IsCSSPropertyPrefEnabled(prop.pref)) {
     continue;
   }
-  if (!SpecialPowers.DOMWindowUtils.isStyledByServo &&
-      gServoOnlyProperties.includes(prop.name)) {
-    continue;
-  }
   var present = prop.name in gCSSProperties;
   ok(present,
      "'" + prop.name + "' listed in gCSSProperties");
   if (present) {
     is(gCSSProperties[prop.name].type, CSS_TYPE_LONGHAND,
        "'" + prop.name + "' listed as CSS_TYPE_LONGHAND");
     is(gCSSProperties[prop.name].domProp, prop.prop,
        "'" + prop.name + "' listed with correct DOM property name");
--- a/layout/style/test/test_specified_value_serialization.html
+++ b/layout/style/test/test_specified_value_serialization.html
@@ -117,34 +117,23 @@
     [ "-webkit-linear-gradient(10deg, red, blue)",
       "-webkit-linear-gradient(10deg, red, blue)",
       "-webkit-linear-gradient with angled legacy-gradient-line" ],
 
     // Linear gradient with box corner (needs prefixed syntax):
     [ "-webkit-linear-gradient(top left, red, blue)",
       "-webkit-linear-gradient(left top, red, blue)",
       "-webkit-linear-gradient with box corner" ],
+
+    // Servo keeps the original prefix form which is closer to other impls.
+    [ "-webkit-radial-gradient(contain, red, blue)",
+      "-webkit-radial-gradient(center center, closest-side, red, blue)",
+      "-webkit-radial-gradient with legacy 'contain' keyword" ],
   ];
 
-  if (!SpecialPowers.DOMWindowUtils.isStyledByServo) {
-    // Radial gradients (should be serialized using modern unprefixed style):
-    backgroundImages.push([
-      "-webkit-radial-gradient(contain, red, blue)",
-      "radial-gradient(closest-side, red, blue)",
-      "-webkit-radial-gradient with legacy 'contain' keyword",
-    ]);
-  } else {
-    // Servo keeps the original prefix form which is closer to other impls.
-    backgroundImages.push([
-      "-webkit-radial-gradient(contain, red, blue)",
-      "-webkit-radial-gradient(center center, closest-side, red, blue)",
-      "-webkit-radial-gradient with legacy 'contain' keyword",
-    ]);
-  }
-
   var frame_container = document.getElementById("display");
   var p = document.createElement("p");
   frame_container.appendChild(p);
 
   for (var i = 0; i < backgroundImages.length; ++i) {
     var test = backgroundImages[i];
     p.style.backgroundImage = test[0];
     is(p.style.backgroundImage, test[1],
--- a/layout/style/test/test_system_font_serialization.html
+++ b/layout/style/test/test_system_font_serialization.html
@@ -52,23 +52,16 @@ is(e.style.font, "message-box", "font ge
 e.setAttribute("style", "font-weight:bold;font:caption;line-height:3;");
 is(e.style.cssText, "font: caption; line-height: 3;", "serialize system font and font-family");
 is(e.style.font, "", "font getter should be empty");
 
 e.setAttribute("style", "font: menu; font-weight: -moz-use-system-font");
 is(e.style.cssText, "font: menu;", "serialize system font alone");
 is(e.style.font, "menu", "font getter returns value");
 
-// Servo doesn't support parsing -moz-use-system-font
-if (!SpecialPowers.DOMWindowUtils.isStyledByServo) {
-  e.setAttribute("style", "font: menu; font-weight: -moz-use-system-font !important");
-  is(e.style.cssText, "font: menu; font-weight: -moz-use-system-font !important;", "serialize system font and subproperty that is important");
-  is(e.style.font, "", "font getter returns nothing");
-}
-
 e.setAttribute("style", "font: inherit; font-family: Helvetica;");
 EXPECTED_DECLS = [
   "font-family: Helvetica;",
   "font-feature-settings: inherit;",
   "font-kerning: inherit;",
   "font-language-override: inherit;",
   "font-size-adjust: inherit;",
   "font-size: inherit;",
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -54,19 +54,16 @@ function has_num(str)
 function any_unit_to_num(str)
 {
     return Number(String(str).match(/^([\d.]+)/)[1]);
 }
 
 var FUNC_NEGATIVE = "cubic-bezier(0.25, -2, 0.75, 1)";
 var FUNC_OVERONE = "cubic-bezier(0.25, 0, 0.75, 3)";
 
-// After resolving Bug 1387080, we can remove this variable.
-const isServo = SpecialPowers.DOMWindowUtils.isStyledByServo;
-
 var supported_properties = {
     "border-bottom-left-radius": [ test_radius_transition ],
     "border-bottom-right-radius": [ test_radius_transition ],
     "border-top-left-radius": [ test_radius_transition ],
     "border-top-right-radius": [ test_radius_transition ],
     "-moz-box-flex": [ test_float_zeroToOne_transition,
                        test_float_aboveOne_transition,
                        test_float_zeroToOne_clamped ],
@@ -312,18 +309,17 @@ if (SpecialPowers.getBoolPref("layout.cs
   supported_properties["shape-outside"] =
     [ test_basic_shape_or_url_transition ];
 }
 
 if (IsCSSPropertyPrefEnabled("layout.css.font-variations.enabled")) {
   supported_properties["font-variation-settings"] = [ test_font_variations_transition ];
 }
 
-if (IsCSSPropertyPrefEnabled("layout.css.individual-transform.enabled") &&
-    SpecialPowers.DOMWindowUtils.isStyledByServo) {
+if (IsCSSPropertyPrefEnabled("layout.css.individual-transform.enabled")) {
   supported_properties["rotate"] = [ test_rotate_transition ];
   supported_properties["scale"] = [ test_scale_transition ];
   supported_properties["translate"] = [ test_translate_transition ];
 }
 
 if (IsCSSPropertyPrefEnabled("layout.css.scrollbar-colors.enabled")) {
   supported_properties["scrollbar-face-color"] = [
     test_color_transition,
@@ -654,50 +650,42 @@ var transformTests = [
 // Bug 1313619: Add some tests for two basic shapes with an explicit
 // reference-box and a default one.
 const basicShapesTests = [
   { start: "none", end: "none",
     expected: ["none"] },
   // none to shape
   { start: "none",
     end: "circle(500px at 500px 500px) border-box",
-    expected:
-      isServo ? ["circle", ["500px at 500px 500px"], "border-box"]
-              : ["circle", ["500px at calc(500px + 0%) calc(500px + 0%)"], "border-box"]
+    expected: ["circle", ["500px at 500px 500px"], "border-box"]
   },
   { start: "none",
     end: "ellipse(500px 500px at 500px 500px) border-box",
-    expected:
-      isServo ? ["ellipse", ["500px 500px at 500px 500px"], "border-box"]
-              : ["ellipse", ["500px 500px at calc(500px + 0%) calc(500px + 0%)"], "border-box"]
+    expected: ["ellipse", ["500px 500px at 500px 500px"], "border-box"]
   },
   { start: "none",
     end: "polygon(evenodd, 500px 500px, 500px 500px) border-box",
     expected: ["polygon", ["evenodd, 500px 500px, 500px 500px"], "border-box"]
   },
   { start: "none",
     end: "inset(500px 500px 500px 500px round 500px 500px) border-box",
     expected: ["inset", ["500px round 500px"], "border-box"]
   },
   // matching functions
   { start: "circle(100px)", end: "circle(500px)",
     expected: ["circle", ["200px at 50% 50%"]] },
   { start: "ellipse(100px 100px)", end: "ellipse(500px 500px)",
     expected: ["ellipse", ["200px 200px at 50% 50%"]] },
   { start: "circle(100px at 100px 100px) border-box",
     end: "circle(500px at 500px 500px) border-box",
-    expected:
-      isServo ? ["circle", ["200px at 200px 200px"], "border-box"]
-              : ["circle", ["200px at calc(200px + 0%) calc(200px + 0%)"], "border-box"]
+    expected: ["circle", ["200px at 200px 200px"], "border-box"]
   },
   { start: "ellipse(100px 100px at 100px 100px) border-box",
     end: "ellipse(500px 500px at 500px 500px) border-box",
-    expected:
-      isServo ? ["ellipse", ["200px 200px at 200px 200px"], "border-box"]
-              : ["ellipse", ["200px 200px at calc(200px + 0%) calc(200px + 0%)"], "border-box"]
+    expected: ["ellipse", ["200px 200px at 200px 200px"], "border-box"]
   },
   { start: "polygon(evenodd, 100px 100px, 100px 100px) border-box",
     end: "polygon(evenodd, 500px 500px, 500px 500px) border-box",
     expected: ["polygon", ["evenodd, 200px 200px, 200px 200px"], "border-box"]
   },
   { start: "inset(100px 100px 100px 100px round 100px 100px) border-box",
     end: "inset(500px 500px 500px 500px round 500px 500px) border-box",
     expected: ["inset", ["200px round 200px"], "border-box"]
@@ -758,40 +746,34 @@ const basicShapesTests = [
     expected: ["ellipse", ["500px 500px at 50% 50%"]] },
   { start: "ellipse(500px 500px)", end: "ellipse(farthest-side farthest-side)",
     expected: ["ellipse", ["farthest-side farthest-side at 50% 50%"]] },
   { start: "ellipse(500px 500px)", end: "ellipse(closest-side closest-side)",
     expected: ["ellipse", ["closest-side closest-side at 50% 50%"]] },
   // mismatching boxes
   { start: "circle(100px at 100px 100px) border-box",
     end: "circle(500px at 500px 500px) content-box",
-    expected:
-      isServo ? ["circle", ["500px at 500px 500px"], "content-box"]
-              : ["circle", ["500px at calc(500px + 0%) calc(500px + 0%)"], "content-box"]
+    expected: ["circle", ["500px at 500px 500px"], "content-box"]
   },
   { start: "ellipse(100px 100px at 100px 100px) border-box",
     end: "ellipse(500px 500px at 500px 500px) content-box",
-    expected:
-      isServo ? ["ellipse", ["500px 500px at 500px 500px"], "content-box"]
-              : ["ellipse", ["500px 500px at calc(500px + 0%) calc(500px + 0%)"], "content-box"]
+    expected: ["ellipse", ["500px 500px at 500px 500px"], "content-box"]
   },
   { start: "polygon(evenodd, 100px 100px, 100px 100px) border-box",
     end: "polygon(evenodd, 500px 500px, 500px 500px) content-box",
     expected: ["polygon", ["evenodd, 500px 500px, 500px 500px"], "content-box"]
   },
   { start: "inset(100px 100px 100px 100px round 100px 100px) border-box",
     end: "inset(500px 500px 500px 500px round 500px 500px) content-box",
     expected: ["inset", ["500px round 500px"], "content-box"]
   },
   // mismatching functions
   { start: "circle(100px at 100px 100px) border-box",
     end: "ellipse(500px 500px at 500px 500px) border-box",
-    expected:
-      isServo ? ["ellipse", ["500px 500px at 500px 500px"], "border-box"]
-              : ["ellipse", ["500px 500px at calc(500px + 0%) calc(500px + 0%)"], "border-box"]
+    expected: ["ellipse", ["500px 500px at 500px 500px"], "border-box"]
   },
   { start: "inset(0px round 20px)", end: "ellipse(500px 500px)",
     expected: ["ellipse", ["500px 500px at 50% 50%"]]
   },
   // shape to reference box
   { start: "circle(20px)", end: "content-box", expected: ["content-box"] },
   { start: "content-box", end: "circle(20px)", expected: ["circle", ["20px at 50% 50%"]] },
   // url to shape
--- a/layout/tools/reftest/manifest.jsm
+++ b/layout/tools/reftest/manifest.jsm
@@ -317,26 +317,24 @@ function ReadManifest(aURL, aFilter)
                 (fuzzy_delta.min > 0 || fuzzy_pixels.min > 0)) {
                 throw "Error in manifest file " + aURL.spec + " line " + lineNo + ": minimum fuzz must be zero for tests of type " + items[0];
             }
 
             var type = items[0];
             if (g.compareRetainedDisplayLists) {
                 type = TYPE_REFTEST_EQUAL;
 
-                // We expect twice as many assertion failures when running in
-                // styloVsGecko mode because we run each test twice: once in
-                // Stylo mode and once in Gecko mode.
+                // We expect twice as many assertion failures when comparing
+                // tests because we run each test twice.
                 minAsserts *= 2;
                 maxAsserts *= 2;
 
-                // Skip the test if it is expected to fail in both Stylo and
-                // Gecko modes. It would unexpectedly "pass" in styloVsGecko
-                // mode when comparing the two failures, which is not a useful
-                // result.
+                // Skip the test if it is expected to fail in both modes.
+                // It would unexpectedly "pass" in comparison mode mode when
+                // comparing the two failures, which is not a useful result.
                 if (expected_status === EXPECTED_FAIL ||
                     expected_status === EXPECTED_RANDOM) {
                     expected_status = EXPECTED_DEATH;
                 }
             }
 
             AddTestItem({ type: type,
                           expected: expected_status,
@@ -477,19 +475,16 @@ function BuildConditionSandbox(aURL) {
 #else
     sandbox.webrtc = false;
 #endif
 
 let retainedDisplayListsEnabled = prefs.getBoolPref("layout.display-list.retain", false);
 sandbox.retainedDisplayLists = retainedDisplayListsEnabled && !g.compareRetainedDisplayLists;
 sandbox.compareRetainedDisplayLists = g.compareRetainedDisplayLists;
 
-// TODO(emilio): Remove the remaining reftest expectations that mention stylo.
-sandbox.stylo = true;
-
     sandbox.skiaPdf = false;
 
 #ifdef RELEASE_OR_BETA
     sandbox.release_or_beta = true;
 #else
     sandbox.release_or_beta = false;
 #endif
 
--- a/layout/xul/crashtests/crashtests.list
+++ b/layout/xul/crashtests/crashtests.list
@@ -50,17 +50,17 @@ load 384491-1.xhtml
 load 384871-1.html
 load 386642.xul
 load 387033-1.xhtml
 load 387080-1.xul
 load 391974-1.html
 load 394120-1.xhtml
 load 397293.xhtml # bug 1323652
 load 397304-1.html
-asserts-if(stylo,0-2) load 398326-1.xhtml # bug 1324660
+load 398326-1.xhtml
 load 399013.xul
 load 400779-1.xhtml
 load 402912-1.xhtml
 load 404192.xhtml
 load 407152.xul
 load 408904-1.xul
 load 412479-1.xhtml
 load 415394-1.xhtml
@@ -71,17 +71,17 @@ load 431738.xhtml
 load 432058-1.xul
 load 432068-1.xul
 load 432068-2.xul
 load 433296-1.xul
 load 433429.xul
 load 452185.html
 load 460900-1.xul
 load 464149-1.xul
-asserts-if(winWidget,1) asserts-if(Android,0-1) asserts-if(stylo,0-1) load 464407-1.xhtml # Bug 450974 on win, Bug 1267054 on Android, bug 718883 for stylo
+asserts(0-1) load 464407-1.xhtml # Bugs 450974, 1267054, 718883
 load 467080.xul
 load 467481-1.xul
 load 470063-1.html
 load 470272.html
 load 472189.xul
 load 475133.html
 load 488210-1.xhtml
 load 495728-1.xul
new file mode 100644
--- /dev/null
+++ b/media/webrtc/gn-configs/ppc64_False_ppc64_linux.json
@@ -0,0 +1,6538 @@
+{
+    "gn_gen_args": {
+        "host_cpu": "ppc64",
+        "is_debug": false,
+        "target_cpu": "ppc64",
+        "target_os": "linux"
+    },
+    "mozbuild_args": {
+        "CPU_ARCH": "ppc64",
+        "HOST_CPU_ARCH": "ppc64",
+        "MOZ_DEBUG": null,
+        "OS_TARGET": "Linux"
+    },
+    "sandbox_vars": {
+        "COMPILE_FLAGS": {
+            "WARNINGS_AS_ERRORS": []
+        },
+        "FINAL_LIBRARY": "webrtc"
+    },
+    "targets": {
+        "//webrtc/api:audio_mixer_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc/base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/api/audio/audio_mixer.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/api:call_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/api:audio_mixer_api",
+                "//webrtc/api:transport_api",
+                "//webrtc/base:rtc_base_approved",
+                "//webrtc/modules/audio_coding:audio_decoder_factory_interface",
+                "//webrtc/modules/audio_coding:audio_encoder_interface"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/api/call/audio_sink.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/api:transport_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/api/call/transport.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/api:video_frame_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc/base:rtc_base_approved",
+                "//webrtc/system_wrappers:system_wrappers"
+            ],
+            "include_dirs": [
+                "/media/libyuv/libyuv/include/",
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//webrtc/api/video/i420_buffer.cc",
+                "//webrtc/api/video/i420_buffer.h",
+                "//webrtc/api/video/video_frame.cc",
+                "//webrtc/api/video/video_frame.h",
+                "//webrtc/api/video/video_frame_buffer.h",
+                "//webrtc/api/video/video_rotation.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/audio/utility:audio_frame_operations": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/base:rtc_base_approved",
+                "//webrtc/modules/audio_coding:audio_format_conversion"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/audio/utility/audio_frame_operations.cc",
+                "//webrtc/audio/utility/audio_frame_operations.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/audio:audio": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_BUILD_LIBEVENT"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/api:audio_mixer_api",
+                "//webrtc/api:call_api",
+                "//webrtc/base:rtc_base_approved",
+                "//webrtc/base:rtc_task_queue",
+                "//webrtc/call:call_interfaces",
+                "//webrtc/common_audio:common_audio",
+                "//webrtc/modules/audio_device:audio_device",
+                "//webrtc/modules/audio_processing:audio_processing",
+                "//webrtc/modules/congestion_controller:congestion_controller",
+                "//webrtc/modules/pacing:pacing",
+                "//webrtc/modules/remote_bitrate_estimator:remote_bitrate_estimator",
+                "//webrtc/modules/rtp_rtcp:rtp_rtcp",
+                "//webrtc/system_wrappers:system_wrappers",
+                "//webrtc/voice_engine:voice_engine"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/",
+                "//webrtc/common_audio/resampler/include/",
+                "//webrtc/common_audio/signal_processing/include/",
+                "//webrtc/common_audio/vad/include/",
+                "//webrtc/modules/include/",
+                "//webrtc/modules/audio_device/include/",
+                "//webrtc/modules/audio_device/dummy/",
+                "//webrtc/modules/audio_coding/include/",
+                "//webrtc/modules/include/"
+            ],
+            "libs": [
+                "rt",
+                "m"
+            ],
+            "sources": [
+                "//webrtc/audio/audio_receive_stream.cc",
+                "//webrtc/audio/audio_receive_stream.h",
+                "//webrtc/audio/audio_send_stream.cc",
+                "//webrtc/audio/audio_send_stream.h",
+                "//webrtc/audio/audio_state.cc",
+                "//webrtc/audio/audio_state.h",
+                "//webrtc/audio/audio_transport_proxy.cc",
+                "//webrtc/audio/audio_transport_proxy.h",
+                "//webrtc/audio/conversion.h",
+                "//webrtc/audio/scoped_voe_interface.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/base:gtest_prod": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/base/gtest_prod_util.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/base:rtc_base_approved": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/base/array_view.h",
+                "//webrtc/base/arraysize.h",
+                "//webrtc/base/atomicops.h",
+                "//webrtc/base/base64.cc",
+                "//webrtc/base/base64.h",
+                "//webrtc/base/basictypes.h",
+                "//webrtc/base/bind.h",
+                "//webrtc/base/bitbuffer.cc",
+                "//webrtc/base/bitbuffer.h",
+                "//webrtc/base/buffer.h",
+                "//webrtc/base/bufferqueue.cc",
+                "//webrtc/base/bufferqueue.h",
+                "//webrtc/base/bytebuffer.cc",
+                "//webrtc/base/bytebuffer.h",
+                "//webrtc/base/byteorder.h",
+                "//webrtc/base/checks.cc",
+                "//webrtc/base/checks.h",
+                "//webrtc/base/constructormagic.h",
+                "//webrtc/base/copyonwritebuffer.cc",
+                "//webrtc/base/copyonwritebuffer.h",
+                "//webrtc/base/criticalsection.cc",
+                "//webrtc/base/criticalsection.h",
+                "//webrtc/base/deprecation.h",
+                "//webrtc/base/event.cc",
+                "//webrtc/base/event.h",
+                "//webrtc/base/event_tracer.cc",
+                "//webrtc/base/event_tracer.h",
+                "//webrtc/base/file.cc",
+                "//webrtc/base/file.h",
+                "//webrtc/base/flags.cc",
+                "//webrtc/base/flags.h",
+                "//webrtc/base/format_macros.h",
+                "//webrtc/base/function_view.h",
+                "//webrtc/base/ignore_wundef.h",
+                "//webrtc/base/location.cc",
+                "//webrtc/base/location.h",
+                "//webrtc/base/md5.cc",
+                "//webrtc/base/md5.h",
+                "//webrtc/base/md5digest.cc",
+                "//webrtc/base/md5digest.h",
+                "//webrtc/base/mod_ops.h",
+                "//webrtc/base/onetimeevent.h",
+                "//webrtc/base/optional.cc",
+                "//webrtc/base/optional.h",
+                "//webrtc/base/pathutils.cc",
+                "//webrtc/base/pathutils.h",
+                "//webrtc/base/platform_file.cc",
+                "//webrtc/base/platform_file.h",
+                "//webrtc/base/platform_thread.cc",
+                "//webrtc/base/platform_thread.h",
+                "//webrtc/base/platform_thread_types.h",
+                "//webrtc/base/race_checker.cc",
+                "//webrtc/base/race_checker.h",
+                "//webrtc/base/random.cc",
+                "//webrtc/base/random.h",
+                "//webrtc/base/rate_limiter.cc",
+                "//webrtc/base/rate_limiter.h",
+                "//webrtc/base/rate_statistics.cc",
+                "//webrtc/base/rate_statistics.h",
+                "//webrtc/base/ratetracker.cc",
+                "//webrtc/base/ratetracker.h",
+                "//webrtc/base/refcount.h",
+                "//webrtc/base/refcountedobject.h",
+                "//webrtc/base/safe_compare.h",
+                "//webrtc/base/safe_conversions.h",
+                "//webrtc/base/safe_conversions_impl.h",
+                "//webrtc/base/sanitizer.h",
+                "//webrtc/base/scoped_ref_ptr.h",
+                "//webrtc/base/stringencode.cc",
+                "//webrtc/base/stringencode.h",
+                "//webrtc/base/stringutils.cc",
+                "//webrtc/base/stringutils.h",
+                "//webrtc/base/swap_queue.h",
+                "//webrtc/base/template_util.h",
+                "//webrtc/base/thread_annotations.h",
+                "//webrtc/base/thread_checker.h",
+                "//webrtc/base/thread_checker_impl.cc",
+                "//webrtc/base/thread_checker_impl.h",
+                "//webrtc/base/timestampaligner.cc",
+                "//webrtc/base/timestampaligner.h",
+                "//webrtc/base/timeutils.cc",
+                "//webrtc/base/timeutils.h",
+                "//webrtc/base/trace_event.h",
+                "//webrtc/base/type_traits.h",
+                "//webrtc/base/file_posix.cc",
+                "//webrtc/base/logging.cc",
+                "//webrtc/base/logging.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/base:rtc_numerics": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc/base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/base/numerics/exp_filter.cc",
+                "//webrtc/base/numerics/exp_filter.h",
+                "//webrtc/base/numerics/percentile_filter.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/base:rtc_task_queue": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_BUILD_LIBEVENT",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc/base:rtc_base_approved"
+            ],
+            "include_dirs": [
+                "/ipc/chromium/src/third_party/libevent/include/",
+                "/ipc/chromium/src/third_party/libevent/linux/",
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/base/sequenced_task_checker.h",
+                "//webrtc/base/sequenced_task_checker_impl.cc",
+                "//webrtc/base/sequenced_task_checker_impl.h",
+                "//webrtc/base/weak_ptr.cc",
+                "//webrtc/base/weak_ptr.h",
+                "//webrtc/base/task_queue.h",
+                "//webrtc/base/task_queue_posix.h",
+                "//webrtc/base/task_queue_libevent.cc",
+                "//webrtc/base/task_queue_posix.cc"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/call:call": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_BUILD_LIBEVENT"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/api:call_api",
+                "//webrtc/api:transport_api",
+                "//webrtc/audio:audio",
+                "//webrtc/base:rtc_task_queue",
+                "//webrtc/call:call_interfaces",
+                "//webrtc/logging:rtc_event_log_impl",
+                "//webrtc/modules/congestion_controller:congestion_controller",
+                "//webrtc/modules/rtp_rtcp:rtp_rtcp",
+                "//webrtc/system_wrappers:system_wrappers",
+                "//webrtc/video:video"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [
+                "rt",
+                "m"
+            ],
+            "sources": [
+                "//webrtc/call/bitrate_allocator.cc",
+                "//webrtc/call/call.cc",
+                "//webrtc/call/flexfec_receive_stream_impl.cc",
+                "//webrtc/call/flexfec_receive_stream_impl.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/call:call_interfaces": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/call/audio_receive_stream.h",
+                "//webrtc/call/audio_send_stream.h",
+                "//webrtc/call/audio_state.h",
+                "//webrtc/call/call.h",
+                "//webrtc/call/flexfec_receive_stream.h",
+                "//webrtc/call/audio_send_stream_call.cc"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/common_audio:common_audio": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc/common_audio:common_audio_c",
+                "//webrtc/system_wrappers:system_wrappers"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/",
+                "//webrtc/common_audio/resampler/include/",
+                "//webrtc/common_audio/signal_processing/include/",
+                "//webrtc/common_audio/vad/include/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//webrtc/common_audio/audio_converter.cc",
+                "//webrtc/common_audio/audio_converter.h",
+                "//webrtc/common_audio/audio_ring_buffer.cc",
+                "//webrtc/common_audio/audio_ring_buffer.h",
+                "//webrtc/common_audio/audio_util.cc",
+                "//webrtc/common_audio/blocker.cc",
+                "//webrtc/common_audio/blocker.h",
+                "//webrtc/common_audio/channel_buffer.cc",
+                "//webrtc/common_audio/channel_buffer.h",
+                "//webrtc/common_audio/fir_filter.cc",
+                "//webrtc/common_audio/fir_filter.h",
+                "//webrtc/common_audio/fir_filter_neon.h",
+                "//webrtc/common_audio/fir_filter_sse.h",
+                "//webrtc/common_audio/include/audio_util.h",
+                "//webrtc/common_audio/lapped_transform.cc",
+                "//webrtc/common_audio/lapped_transform.h",
+                "//webrtc/common_audio/real_fourier.cc",
+                "//webrtc/common_audio/real_fourier.h",
+                "//webrtc/common_audio/real_fourier_ooura.cc",
+                "//webrtc/common_audio/real_fourier_ooura.h",
+                "//webrtc/common_audio/resampler/include/push_resampler.h",
+                "//webrtc/common_audio/resampler/include/resampler.h",
+                "//webrtc/common_audio/resampler/push_resampler.cc",
+                "//webrtc/common_audio/resampler/push_sinc_resampler.cc",
+                "//webrtc/common_audio/resampler/push_sinc_resampler.h",
+                "//webrtc/common_audio/resampler/resampler.cc",
+                "//webrtc/common_audio/resampler/sinc_resampler.cc",
+                "//webrtc/common_audio/resampler/sinc_resampler.h",
+                "//webrtc/common_audio/smoothing_filter.cc",
+                "//webrtc/common_audio/smoothing_filter.h",
+                "//webrtc/common_audio/sparse_fir_filter.cc",
+                "//webrtc/common_audio/sparse_fir_filter.h",
+                "//webrtc/common_audio/vad/include/vad.h",
+                "//webrtc/common_audio/vad/vad.cc",
+                "//webrtc/common_audio/wav_file.cc",
+                "//webrtc/common_audio/wav_file.h",
+                "//webrtc/common_audio/wav_header.cc",
+                "//webrtc/common_audio/wav_header.h",
+                "//webrtc/common_audio/window_generator.cc",
+                "//webrtc/common_audio/window_generator.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/common_audio:common_audio_c": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/",
+                "//webrtc/common_audio/resampler/include/",
+                "//webrtc/common_audio/signal_processing/include/",
+                "//webrtc/common_audio/vad/include/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/common_audio/fft4g.c",
+                "//webrtc/common_audio/fft4g.h",
+                "//webrtc/common_audio/ring_buffer.c",
+                "//webrtc/common_audio/ring_buffer.h",
+                "//webrtc/common_audio/signal_processing/auto_corr_to_refl_coef.c",
+                "//webrtc/common_audio/signal_processing/auto_correlation.c",
+                "//webrtc/common_audio/signal_processing/complex_fft_tables.h",
+                "//webrtc/common_audio/signal_processing/copy_set_operations.c",
+                "//webrtc/common_audio/signal_processing/cross_correlation.c",
+                "//webrtc/common_audio/signal_processing/division_operations.c",
+                "//webrtc/common_audio/signal_processing/dot_product_with_scale.c",
+                "//webrtc/common_audio/signal_processing/downsample_fast.c",
+                "//webrtc/common_audio/signal_processing/energy.c",
+                "//webrtc/common_audio/signal_processing/filter_ar.c",
+                "//webrtc/common_audio/signal_processing/filter_ma_fast_q12.c",
+                "//webrtc/common_audio/signal_processing/get_hanning_window.c",
+                "//webrtc/common_audio/signal_processing/get_scaling_square.c",
+                "//webrtc/common_audio/signal_processing/ilbc_specific_functions.c",
+                "//webrtc/common_audio/signal_processing/include/real_fft.h",
+                "//webrtc/common_audio/signal_processing/include/signal_processing_library.h",
+                "//webrtc/common_audio/signal_processing/include/spl_inl.h",
+                "//webrtc/common_audio/signal_processing/levinson_durbin.c",
+                "//webrtc/common_audio/signal_processing/lpc_to_refl_coef.c",
+                "//webrtc/common_audio/signal_processing/min_max_operations.c",
+                "//webrtc/common_audio/signal_processing/randomization_functions.c",
+                "//webrtc/common_audio/signal_processing/real_fft.c",
+                "//webrtc/common_audio/signal_processing/refl_coef_to_lpc.c",
+                "//webrtc/common_audio/signal_processing/resample.c",
+                "//webrtc/common_audio/signal_processing/resample_48khz.c",
+                "//webrtc/common_audio/signal_processing/resample_by_2.c",
+                "//webrtc/common_audio/signal_processing/resample_by_2_internal.c",
+                "//webrtc/common_audio/signal_processing/resample_by_2_internal.h",
+                "//webrtc/common_audio/signal_processing/resample_fractional.c",
+                "//webrtc/common_audio/signal_processing/spl_init.c",
+                "//webrtc/common_audio/signal_processing/spl_inl.c",
+                "//webrtc/common_audio/signal_processing/spl_sqrt.c",
+                "//webrtc/common_audio/signal_processing/splitting_filter.c",
+                "//webrtc/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c",
+                "//webrtc/common_audio/signal_processing/vector_scaling_operations.c",
+                "//webrtc/common_audio/vad/include/webrtc_vad.h",
+                "//webrtc/common_audio/vad/vad_core.c",
+                "//webrtc/common_audio/vad/vad_core.h",
+                "//webrtc/common_audio/vad/vad_filterbank.c",
+                "//webrtc/common_audio/vad/vad_filterbank.h",
+                "//webrtc/common_audio/vad/vad_gmm.c",
+                "//webrtc/common_audio/vad/vad_gmm.h",
+                "//webrtc/common_audio/vad/vad_sp.c",
+                "//webrtc/common_audio/vad/vad_sp.h",
+                "//webrtc/common_audio/vad/webrtc_vad.c",
+                "//webrtc/common_audio/signal_processing/complex_fft.c",
+                "//webrtc/common_audio/signal_processing/complex_bit_reverse.c",
+                "//webrtc/common_audio/signal_processing/filter_ar_fast_q12.c",
+                "//webrtc/common_audio/signal_processing/spl_sqrt_floor.c"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/common_video:common_video": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_BUILD_LIBEVENT"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/api:video_frame_api",
+                "//webrtc/base:rtc_task_queue",
+                "//webrtc/system_wrappers:system_wrappers"
+            ],
+            "include_dirs": [
+                "//webrtc/modules/interface/",
+                "/media/libyuv/libyuv/include/",
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/",
+                "//webrtc/common_video/include/",
+                "//webrtc/common_video/libyuv/include/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//webrtc/common_video/bitrate_adjuster.cc",
+                "//webrtc/common_video/h264/h264_bitstream_parser.cc",
+                "//webrtc/common_video/h264/h264_bitstream_parser.h",
+                "//webrtc/common_video/h264/h264_common.cc",
+                "//webrtc/common_video/h264/h264_common.h",
+                "//webrtc/common_video/h264/pps_parser.cc",
+                "//webrtc/common_video/h264/pps_parser.h",
+                "//webrtc/common_video/h264/profile_level_id.cc",
+                "//webrtc/common_video/h264/profile_level_id.h",
+                "//webrtc/common_video/h264/sps_parser.cc",
+                "//webrtc/common_video/h264/sps_parser.h",
+                "//webrtc/common_video/h264/sps_vui_rewriter.cc",
+                "//webrtc/common_video/h264/sps_vui_rewriter.h",
+                "//webrtc/common_video/i420_buffer_pool.cc",
+                "//webrtc/common_video/include/bitrate_adjuster.h",
+                "//webrtc/common_video/include/frame_callback.h",
+                "//webrtc/common_video/include/i420_buffer_pool.h",
+                "//webrtc/common_video/include/incoming_video_stream.h",
+                "//webrtc/common_video/include/video_bitrate_allocator.h",
+                "//webrtc/common_video/include/video_frame_buffer.h",
+                "//webrtc/common_video/incoming_video_stream.cc",
+                "//webrtc/common_video/libyuv/include/webrtc_libyuv.h",
+                "//webrtc/common_video/libyuv/webrtc_libyuv.cc",
+                "//webrtc/common_video/video_frame.cc",
+                "//webrtc/common_video/video_frame_buffer.cc",
+                "//webrtc/common_video/video_render_frames.cc",
+                "//webrtc/common_video/video_render_frames.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/logging:rtc_event_log_api": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/logging/rtc_event_log/rtc_event_log.h"
+            ],
+            "type": "source_set"
+        },
+        "//webrtc/logging:rtc_event_log_impl": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX",
+                "WEBRTC_BUILD_LIBEVENT"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/call:call_interfaces",
+                "//webrtc/logging:rtc_event_log_api",
+                "//webrtc/modules/rtp_rtcp:rtp_rtcp"
+            ],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [
+                "rt"
+            ],
+            "sources": [
+                "//webrtc/logging/rtc_event_log/ringbuffer.h",
+                "//webrtc/logging/rtc_event_log/rtc_event_log.cc",
+                "//webrtc/logging/rtc_event_log/rtc_event_log_helper_thread.cc",
+                "//webrtc/logging/rtc_event_log/rtc_event_log_helper_thread.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/media:mozilla_rtc_media": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [],
+            "include_dirs": [
+                "//",
+                "/sdb/spectre/src/mozilla-release/obj-powerpc64le-unknown-linux-gnu/media/webrtc/trunk/gn-output/gen/"
+            ],
+            "libs": [],
+            "sources": [
+                "//webrtc/media/base/videoadapter.cc",
+                "//webrtc/media/base/videoadapter.h",
+                "//webrtc/media/base/videobroadcaster.cc",
+                "//webrtc/media/base/videobroadcaster.h",
+                "//webrtc/media/base/videosourcebase.cc",
+                "//webrtc/media/base/videosourcebase.h"
+            ],
+            "type": "static_library"
+        },
+        "//webrtc/modules/audio_coding:audio_coding": {
+            "cflags": [
+                "-fno-strict-aliasing",
+                "--param=ssp-buffer-size=4",
+                "-fstack-protector",
+                "-Wno-builtin-macro-redefined",
+                "-D__DATE__=",
+                "-D__TIME__=",
+                "-D__TIMESTAMP__=",
+                "-funwind-tables",
+                "-fPIC",
+                "-pipe",
+                "-pthread",
+                "-Wall",
+                "-Werror",
+                "-Wno-unused-local-typedefs",
+                "-Wno-maybe-uninitialized",
+                "-Wno-missing-field-initializers",
+                "-Wno-unused-parameter",
+                "-O2",
+                "-fno-ident",
+                "-fdata-sections",
+                "-ffunction-sections",
+                "-fomit-frame-pointer",
+                "-g0",
+                "-fvisibility=hidden",
+                "-Wextra",
+                "-Wno-unused-parameter",
+                "-Wno-missing-field-initializers",
+                "-Wno-strict-overflow"
+            ],
+            "defines": [
+                "WEBRTC_CODEC_OPUS",
+                "WEBRTC_CODEC_G722",
+                "V8_DEPRECATION_WARNINGS",
+                "USE_NSS_CERTS=1",
+                "USE_X11=1",
+                "CHROMIUM_BUILD",
+                "_FILE_OFFSET_BITS=64",
+                "NDEBUG",
+                "NVALGRIND",
+                "DYNAMIC_ANNOTATIONS_ENABLED=0",
+                "WEBRTC_RESTRICT_LOGGING",
+                "EXPAT_RELATIVE_PATH",
+                "WEBRTC_MOZILLA_BUILD",
+                "WEBRTC_POSIX",
+                "WEBRTC_LINUX"
+            ],
+            "deps": [
+                "//webrtc:webrtc_common",
+                "//webrtc/base:rtc_base_approved",
+                "//webrtc/common_audio:common_audio",
+                "//webrtc/logging:rtc_event_log_api",
+                "//webrtc/modules/audio_coding:audio_decoder_factory_interface",
+                "//webrtc/modules/audio_coding:audio_decoder_interface",
+                "//webrtc/modules/audio_coding:builtin_audio_decoder_factory",
+                "//webrtc/modules/audio_coding:cng",
+                "//webrtc/modules/audio_coding:g711",
+                "//webrtc/modules/audio_coding:g722",
+                "//webrtc/modules/audio_coding:isac",