Merge autoland to mozilla-central. a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 15 May 2020 11:29:53 +0200
changeset 530219 5a0a960a8d555795d4d1db432090fec007850716
parent 529897 ac0bb963eab327afea9c7996cb559a954a76400f (current diff)
parent 530218 4266d097e223610178159331d3ffea2fbacf4ec7 (diff)
child 530244 6790c74bbb0c7e8f43dc68d738326fa047e72ece
push id37419
push userarchaeopteryx@coole-files.de
push dateFri, 15 May 2020 09:33:04 +0000
treeherdermozilla-central@5a0a960a8d55 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone78.0a1
first release with
nightly linux32
5a0a960a8d55 / 78.0a1 / 20200515093304 / files
nightly linux64
5a0a960a8d55 / 78.0a1 / 20200515093304 / files
nightly mac
5a0a960a8d55 / 78.0a1 / 20200515093304 / files
nightly win32
5a0a960a8d55 / 78.0a1 / 20200515093304 / files
nightly win64
5a0a960a8d55 / 78.0a1 / 20200515093304 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central. a=merge
browser/actors/PromptChild.jsm
build/autoconf/ios.m4
gfx/docs/DocumentSplitting.rst
layout/reftests/css-animations/print-no-animations-notref.html
layout/reftests/css-animations/print-no-animations-ref.html
layout/reftests/css-animations/print-no-animations.html
layout/reftests/forms/input/selector-read-write-type-change-001-ref.html
layout/reftests/forms/input/selector-read-write-type-change-001.html
layout/reftests/forms/input/selector-read-write-type-change-002-ref.html
layout/reftests/forms/input/selector-read-write-type-change-002.html
services/sync/tests/unit/test_extension_storage_tracker.js
testing/web-platform/meta/PeriodicBackgroundSync/periodicsync.https.window.js.ini
testing/web-platform/meta/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.js.ini
testing/web-platform/meta/css/css-transforms/css-transform-scale-001.html.ini
testing/web-platform/meta/css/selectors/selector-read-write-type-change-002.html.ini
testing/web-platform/meta/dom/events/Event-dispatch-redispatch.html.ini
testing/web-platform/meta/html/semantics/selectors/pseudo-classes/readwrite-readonly.html.ini
testing/web-platform/meta/idle-detection/basics.tentative.https.any.js.ini
testing/web-platform/meta/mathml/relations/css-styling/color-004.html.ini
testing/web-platform/meta/printing/print-microtask-after-navigate.html.ini
testing/web-platform/tests/PeriodicBackgroundSync/periodicsync.https.window.js
testing/web-platform/tests/PeriodicBackgroundSync/service_workers/sw.js
testing/web-platform/tests/css/css-flexbox/flex-direction-column-reverse.html
testing/web-platform/tests/css/css-flexbox/flex-direction-row-reverse.html
testing/web-platform/tests/css/css-flexbox/flex-direction-row.html
testing/web-platform/tests/css/css-flexbox/flex-direction_column-reverse.html
testing/web-platform/tests/css/css-flexbox/flex-direction_column.html
testing/web-platform/tests/css/css-flexbox/flex-direction_row-reverse.html
testing/web-platform/tests/css/css-flexbox/flex-direction_row.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-align-content-center-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-align-content-end-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-align-content-space-around-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-align-content-space-between-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-align-content-start-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-base-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-direction-column-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-direction-column-reverse-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-direction-row-reverse-ref.html
testing/web-platform/tests/css/css-flexbox/reference/ttwf-reftest-flex-inline-ref.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-align-content-center.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-align-content-end.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-align-content-space-around.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-align-content-space-between.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-align-content-start.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-base.html
testing/web-platform/tests/css/css-flexbox/ttwf-reftest-flex-direction-row-reverse.html
testing/web-platform/tests/css/css-fonts/math-script-level-and-math-style/math-script-level-001.tentative.html
testing/web-platform/tests/css/css-fonts/math-script-level-and-math-style/math-script-level-003.tentative.html
testing/web-platform/tests/css/css-fonts/math-script-level-and-math-style/math-script-level-005.tentative.html
testing/web-platform/tests/css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height-ref.html
testing/web-platform/tests/css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height.tentative.html
testing/web-platform/tests/css/css-transforms/css-transform-scale-001.html
testing/web-platform/tests/idle-detection/basics.tentative.https.any.js
testing/web-platform/tests/idle-detection/idlharness.https.any.js
testing/web-platform/tests/lint.whitelist
testing/web-platform/tests/mathml/relations/css-styling/color-004-ref.html
testing/web-platform/tests/mathml/relations/css-styling/color-004.html
testing/web-platform/tests/mathml/relations/css-styling/visibility-004-ref.html
testing/web-platform/tests/mathml/relations/css-styling/visibility-004.html
testing/web-platform/tests/tools/lint/tests/dummy/lint.whitelist
toolkit/components/extensions/test/xpcshell/test_ext_storage.js
toolkit/components/extensions/test/xpcshell/test_ext_storage_content.js
toolkit/components/extensions/test/xpcshell/test_ext_storage_sync_crypto.js
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -896,19 +896,18 @@ module.exports = {
         "toolkit/components/extensions/test/xpcshell/test_ext_background_teardown.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_contentscript_context.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_contentscript_context_isolation.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_contentscript_teardown.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_contexts_gc.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_privacy_disable.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_schemas_interactive.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_shutdown_cleanup.js",
-        "toolkit/components/extensions/test/xpcshell/test_ext_storage.js",
-        "toolkit/components/extensions/test/xpcshell/test_ext_storage_sync.js",
-        "toolkit/components/extensions/test/xpcshell/test_ext_storage_sync_crypto.js",
+        "toolkit/components/extensions/test/xpcshell/test_ext_storage_sync_kinto.js",
+        "toolkit/components/extensions/test/xpcshell/test_ext_storage_sync_kinto_crypto.js",
         "toolkit/components/extensions/test/xpcshell/test_ext_tab_teardown.js",
         "toolkit/components/extensions/test/xpcshell/test_native_manifests.js",
         "toolkit/components/featuregates/test/unit/test_FeatureGate.js",
         "toolkit/components/mozintl/mozIntl.jsm",
         "toolkit/components/normandy/test/browser/browser_actions_ShowHeartbeatAction.js",
         "toolkit/components/osfile/modules/osfile_async_front.jsm",
         "toolkit/components/osfile/modules/osfile_native.jsm",
         "toolkit/components/osfile/tests/xpcshell/test_osfile_kill.js",
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -67,17 +67,17 @@ role HyperTextAccessible::NativeRole() c
   if (frame && frame->IsInlineFrame()) return roles::TEXT;
 
   return roles::TEXT_CONTAINER;
 }
 
 uint64_t HyperTextAccessible::NativeState() const {
   uint64_t states = AccessibleWrap::NativeState();
 
-  if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
+  if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
     states |= states::EDITABLE;
 
   } else if (mContent->IsHTMLElement(nsGkAtoms::article)) {
     // We want <article> to behave like a document in terms of readonly state.
     states |= states::READONLY;
   }
 
   if (HasChildren()) states |= states::SELECTABLE_TEXT;
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -18,17 +18,16 @@ builtin(include, build/autoconf/mozheade
 builtin(include, build/autoconf/compiler-opts.m4)dnl
 builtin(include, build/autoconf/expandlibs.m4)dnl
 builtin(include, build/autoconf/arch.m4)dnl
 builtin(include, build/autoconf/android.m4)dnl
 builtin(include, build/autoconf/zlib.m4)dnl
 builtin(include, build/autoconf/icu.m4)dnl
 builtin(include, build/autoconf/clang-plugin.m4)dnl
 builtin(include, build/autoconf/alloc.m4)dnl
-builtin(include, build/autoconf/ios.m4)dnl
 builtin(include, build/autoconf/sanitize.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
deleted file mode 100644
--- a/browser/actors/PromptChild.jsm
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-var EXPORTED_SYMBOLS = ["PromptChild"];
-
-class PromptChild extends JSWindowActorChild {
-  constructor(dispatcher) {
-    super(dispatcher);
-  }
-
-  handleEvent(aEvent) {
-    if (aEvent.type !== "pagehide") {
-      return;
-    }
-    this.sendAsyncMessage("Prompt:OnPageHide", {});
-  }
-}
--- a/browser/actors/PromptParent.jsm
+++ b/browser/actors/PromptParent.jsm
@@ -34,160 +34,127 @@ ChromeUtils.defineModuleGetter(
  * @type {WeakMap<BrowsingContext, Prompt>}
  */
 let gBrowserPrompts = new WeakMap();
 
 class PromptParent extends JSWindowActorParent {
   didDestroy() {
     // In the event that the subframe or tab crashed, make sure that
     // we close any active Prompts.
-    this.forceClosePrompts(this.browsingContext);
+    this.forceClosePrompts();
   }
 
   /**
    * Registers a new Prompt to be tracked for a particular BrowsingContext.
    * We need to track a Prompt so that we can, for example, force-close the
    * TabModalPrompt if the originating subframe or tab unloads or crashes.
    *
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the Prompt came.
    * @param {Object} tabModalPrompt
    *        The TabModalPrompt that will be shown to the user.
    * @param {string} id
    *        A unique ID to differentiate multiple Prompts coming from the same
    *        BrowsingContext.
    * @return {Promise}
    * @resolves {Object}
    *           Resolves with the arguments returned from the TabModalPrompt when it
    *           is dismissed.
    */
-  registerPrompt(browsingContext, tabModalPrompt, id) {
-    let prompts = gBrowserPrompts.get(browsingContext);
+  registerPrompt(tabModalPrompt, id) {
+    let prompts = gBrowserPrompts.get(this.browsingContext);
     if (!prompts) {
       prompts = new Map();
-      gBrowserPrompts.set(browsingContext, prompts);
+      gBrowserPrompts.set(this.browsingContext, prompts);
     }
 
     let promise = new Promise(resolve => {
       prompts.set(id, {
         tabModalPrompt,
         resolver: resolve,
       });
     });
 
     return promise;
   }
 
   /**
    * Removes a Prompt for a BrowsingContext with a particular ID from the registry.
    * This needs to be done to avoid leaking <xul:browser>'s.
    *
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the Prompt came.
    * @param {string} id
    *        A unique ID to differentiate multiple Prompts coming from the same
    *        BrowsingContext.
    */
-  unregisterPrompt(browsingContext, id) {
-    let prompts = gBrowserPrompts.get(browsingContext);
+  unregisterPrompt(id) {
+    let prompts = gBrowserPrompts.get(this.browsingContext);
     if (prompts) {
       prompts.delete(id);
     }
   }
 
   /**
-   * Programmatically closes a Prompt, without waiting for the TabModalPrompt to
-   * return with any arguments.
-   *
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the Prompt came.
-   * @param {string} id
-   *        A unique ID to differentiate multiple Prompts coming from the same
-   *        BrowsingContext.
+   * Programmatically closes all Prompts for the current BrowsingContext.
    */
-  forceClosePrompt(browsingContext, id) {
-    let prompts = gBrowserPrompts.get(browsingContext);
-    let prompt = prompts.get(id);
-    if (prompt && prompt.tabModalPrompt) {
-      prompt.tabModalPrompt.abortPrompt();
-    }
-  }
-
-  /**
-   * Programmatically closes all Prompts for a BrowsingContext.
-   *
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the Prompts came.
-   */
-  forceClosePrompts(browsingContext) {
-    let prompts = gBrowserPrompts.get(browsingContext) || [];
+  forceClosePrompts() {
+    let prompts = gBrowserPrompts.get(this.browsingContext) || [];
 
     for (let [, prompt] of prompts) {
       prompt.tabModalPrompt && prompt.tabModalPrompt.abortPrompt();
     }
   }
 
   receiveMessage(message) {
     let args = message.data;
-    let browsingContext = args.browsingContext || this.browsingContext;
     let id = args._remoteId;
 
     switch (message.name) {
       case "Prompt:Open": {
-        let topPrincipal =
-          browsingContext.top.currentWindowGlobal.documentPrincipal;
-        args.showAlertOrigin = topPrincipal.equals(args.promptPrincipal);
         if (args.modalType === Ci.nsIPrompt.MODAL_TYPE_WINDOW) {
-          return this.openWindowPrompt(args, browsingContext);
+          return this.openWindowPrompt(args);
         }
-        return this.openTabPrompt(args, browsingContext, id);
-      }
-      case "Prompt:ForceClose": {
-        this.forceClosePrompt(browsingContext, id);
-        break;
-      }
-      case "Prompt:OnPageHide": {
-        // User navigates away, close all non window prompts
-        this.forceClosePrompts(browsingContext);
-        break;
+        return this.openTabPrompt(args, id);
       }
     }
 
     return undefined;
   }
 
   /**
    * Opens a TabModalPrompt for a BrowsingContext, and puts the associated browser
    * in the modal state until the TabModalPrompt is closed.
    *
    * @param {Object} args
    *        The arguments passed up from the BrowsingContext to be passed directly
    *        to the TabModalPrompt.
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the Prompts came.
    * @param {string} id
    *        A unique ID to differentiate multiple Prompts coming from the same
    *        BrowsingContext.
    * @return {Promise}
    *         Resolves when the TabModalPrompt is dismissed.
    * @resolves {Object}
    *           The arguments returned from the TabModalPrompt.
    */
-  openTabPrompt(args, browsingContext = this.browsingContext, id) {
-    let browser = browsingContext.top.embedderElement;
+  openTabPrompt(args, id) {
+    let browser = this.browsingContext.top.embedderElement;
     if (!browser) {
       throw new Error("Cannot tab-prompt without a browser!");
     }
     let window = browser.ownerGlobal;
     let tabPrompt = window.gBrowser.getTabModalPromptBox(browser);
     let newPrompt;
     let needRemove = false;
 
-    let onPromptClose = forceCleanup => {
-      let promptData = gBrowserPrompts.get(browsingContext);
+    // If the page which called the prompt is different from the the top context
+    // where we show the prompt, ask the prompt implementation to display the origin.
+    // For example, this can happen if a cross origin subframe shows a prompt.
+    args.showCallerOrigin =
+      args.promptPrincipal &&
+      !browser.contentPrincipal.equals(args.promptPrincipal);
+
+    let onPromptClose = () => {
+      let promptData = gBrowserPrompts.get(this.browsingContext);
       if (!promptData || !promptData.has(id)) {
         throw new Error(
           "Failed to close a prompt since it wasn't registered for some reason."
         );
       }
 
       let { resolver, tabModalPrompt } = promptData.get(id);
       // It's possible that we removed the prompt during the
@@ -195,17 +162,17 @@ class PromptParent extends JSWindowActor
       // undefined. We set the needRemove flag to remember to remove
       // it right after we've finished adding it.
       if (tabModalPrompt) {
         tabPrompt.removePrompt(tabModalPrompt);
       } else {
         needRemove = true;
       }
 
-      this.unregisterPrompt(browsingContext, id);
+      this.unregisterPrompt(id);
 
       PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser);
       resolver(args);
       browser.maybeLeaveModalState();
     };
 
     try {
       browser.enterModalState();
@@ -219,17 +186,17 @@ class PromptParent extends JSWindowActor
         "DOMWillOpenModalDialog",
         browser,
         eventDetail
       );
 
       args.promptActive = true;
 
       newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
-      let promise = this.registerPrompt(browsingContext, newPrompt, id);
+      let promise = this.registerPrompt(newPrompt, id);
 
       if (needRemove) {
         tabPrompt.removePrompt(newPrompt);
       }
 
       return promise;
     } catch (ex) {
       Cu.reportError(ex);
@@ -241,40 +208,43 @@ class PromptParent extends JSWindowActor
 
   /**
    * Opens a window prompt for a BrowsingContext, and puts the associated
    * browser in the modal state until the prompt is closed.
    *
    * @param {Object} args
    *        The arguments passed up from the BrowsingContext to be passed
    *        directly to the modal window.
-   * @param {BrowsingContext} browsingContext
-   *        The BrowsingContext from which the request to open the window-modal
-   *        prompt came.
    * @return {Promise}
    *         Resolves when the window prompt is dismissed.
    * @resolves {Object}
    *           The arguments returned from the window prompt.
    */
-  async openWindowPrompt(args, browsingContext = this.browsingContext) {
+  async openWindowPrompt(args) {
     const COMMON_DIALOG = "chrome://global/content/commonDialog.xhtml";
     const SELECT_DIALOG = "chrome://global/content/selectDialog.xhtml";
     let uri = args.promptType == "select" ? SELECT_DIALOG : COMMON_DIALOG;
 
-    let browser = browsingContext.top.embedderElement;
-    // If can't get the browser, because the BC does not have an embedder element,
-    // use window associated with the BC.
-    // This happens if we are passed a browsingContext of a chrome window.
-    let win = (browser && browser.ownerGlobal) || browsingContext.top.window;
+    let browsingContext = this.browsingContext.top;
+
+    let browser = browsingContext.embedderElement;
+    let win;
+
+    // If we are a chrome actor we can use the associated chrome win.
+    if (!browsingContext.isContent && browsingContext.window) {
+      win = browsingContext.window;
+    } else {
+      win = browser?.ownerGlobal;
+    }
 
     // There's a requirement for prompts to be blocked if a window is
     // passed and that window is hidden (eg, auth prompts are suppressed if the
     // passed window is the hidden window).
     // See bug 875157 comment 30 for more..
-    if (win && win.winUtils && !win.winUtils.isParentWindowMainWidgetVisible) {
+    if (win?.winUtils && !win.winUtils.isParentWindowMainWidgetVisible) {
       throw new Error("Cannot call openModalWindow on a hidden window");
     }
 
     try {
       if (browser) {
         browser.enterModalState();
         PromptUtils.fireDialogEvent(win, "DOMWillOpenModalDialog", browser);
       }
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -61,17 +61,16 @@ FINAL_TARGET_FILES.actors += [
     'LinkHandlerParent.jsm',
     'NetErrorChild.jsm',
     'NetErrorParent.jsm',
     'PageInfoChild.jsm',
     'PageStyleChild.jsm',
     'PageStyleParent.jsm',
     'PluginChild.jsm',
     'PluginParent.jsm',
-    'PromptChild.jsm',
     'PromptParent.jsm',
     'RFPHelperChild.jsm',
     'RFPHelperParent.jsm',
     'SearchTelemetryChild.jsm',
     'SearchTelemetryParent.jsm',
     'SwitchDocumentDirectionChild.jsm',
     'URIFixupChild.jsm',
     'WebRTCChild.jsm',
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1239,16 +1239,17 @@ pref("services.sync.prefs.sync.privacy.t
 pref("services.sync.prefs.sync.privacy.resistFingerprinting", true);
 pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true);
 pref("services.sync.prefs.sync.security.default_personal_cert", true);
 pref("services.sync.prefs.sync.services.sync.syncedTabs.showRemoteIcons", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
 pref("services.sync.prefs.sync.spellchecker.dictionary", true);
+pref("services.sync.prefs.sync.webextensions.storage.sync.kinto", true);
 
 // A preference which, if false, means sync will only apply incoming preference
 // changes if there's already a local services.sync.prefs.sync.* control pref.
 // If true, all incoming preferences will be applied and the local "control
 // pref" updated accordingly.
 pref("services.sync.prefs.dangerously_allow_arbitrary", false);
 
 // A preference that controls whether we should show the icon for a remote tab.
@@ -1474,18 +1475,16 @@ pref("media.gmp.trial-create.enabled", t
 #ifdef MOZ_WIDEVINE_EME
   pref("media.gmp-widevinecdm.visible", true);
   pref("media.gmp-widevinecdm.enabled", true);
 #endif
 
 pref("media.gmp-gmpopenh264.visible", true);
 pref("media.gmp-gmpopenh264.enabled", true);
 
-// Switch block autoplay logic to v2, and enable UI.
-pref("media.autoplay.enabled.user-gestures-needed", true);
 // Set Firefox to block autoplay, asking for permission by default.
 pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked
 
 #ifdef NIGHTLY_BUILD
   // Block WebAudio from playing automatically.
   pref("media.autoplay.block-webaudio", true);
 #else
   pref("media.autoplay.block-webaudio", false);
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -38,17 +38,16 @@ const whitelist = {
     // Session store
     "resource:///modules/sessionstore/ContentSessionStore.jsm",
 
     // Browser front-end
     "resource:///actors/AboutReaderChild.jsm",
     "resource:///actors/BrowserTabChild.jsm",
     "resource:///actors/LinkHandlerChild.jsm",
     "resource:///actors/SearchTelemetryChild.jsm",
-    "resource:///actors/PromptChild.jsm",
     "resource://gre/actors/AutoCompleteChild.jsm",
     "resource://gre/modules/ActorManagerChild.jsm",
     "resource://gre/modules/E10SUtils.jsm",
     "resource://gre/modules/Readerable.jsm",
 
     // Telemetry
     "resource://gre/modules/TelemetryController.jsm", // bug 1470339
     "resource://gre/modules/TelemetryUtils.jsm", // bug 1470339
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -432,24 +432,16 @@ let ACTORS = {
 
     allFrames: true,
   },
 
   Prompt: {
     parent: {
       moduleURI: "resource:///actors/PromptParent.jsm",
     },
-    child: {
-      moduleURI: "resource:///actors/PromptChild.jsm",
-      events: {
-        pagehide: {
-          capture: true,
-        },
-      },
-    },
     includeChrome: true,
     allFrames: true,
   },
 
   SearchTelemetry: {
     parent: {
       moduleURI: "resource:///actors/SearchTelemetryParent.jsm",
     },
@@ -3058,17 +3050,17 @@ BrowserGlue.prototype = {
       );
     });
   },
 
   // eslint-disable-next-line complexity
   _migrateUI: function BG__migrateUI() {
     // Use an increasing number to keep track of the current migration state.
     // Completely unrelated to the current Firefox release number.
-    const UI_VERSION = 94;
+    const UI_VERSION = 95;
     const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
 
     if (!Services.prefs.prefHasUserValue("browser.migration.version")) {
       // This is a new profile, nothing to migrate.
       Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
       this._isNewProfile = true;
       return;
     }
@@ -3628,16 +3620,24 @@ BrowserGlue.prototype = {
       if (backup == socksProxy) {
         Services.prefs.clearUserPref("network.proxy.backup.socks");
       }
       if (backupPort == socksPort) {
         Services.prefs.clearUserPref("network.proxy.backup.socks_port");
       }
     }
 
+    if (currentUIVersion < 95) {
+      const oldPrefName = "media.autoplay.enabled.user-gestures-needed";
+      const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
+      const newPrefValue = oldPrefValue ? 0 : 1;
+      Services.prefs.setIntPref("media.autoplay.blocking_policy", newPrefValue);
+      Services.prefs.clearUserPref(oldPrefName);
+    }
+
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   _maybeShowDefaultBrowserPrompt() {
     DefaultBrowserCheck.willCheckDefaultBrowser(/* isStartupCheck */ true).then(
       willPrompt => {
         if (!willPrompt) {
--- a/browser/components/extensions/test/browser/browser_ext_autoplayInBackground.js
+++ b/browser/components/extensions/test/browser/browser_ext_autoplayInBackground.js
@@ -1,15 +1,15 @@
 "use strict";
 
 function setup_test_preference(enableScript) {
   return SpecialPowers.pushPrefEnv({
     set: [
       ["media.autoplay.default", 1],
-      ["media.autoplay.enabled.user-gestures-needed", true],
+      ["media.autoplay.blocking_policy", 0],
       ["media.autoplay.allow-extension-background-pages", enableScript],
     ],
   });
 }
 
 async function testAutoplayInBackgroundScript(enableScript) {
   info(`- setup test preference, enableScript=${enableScript} -`);
   await setup_test_preference(enableScript);
--- a/browser/components/urlbar/UrlbarUtils.jsm
+++ b/browser/components/urlbar/UrlbarUtils.jsm
@@ -270,31 +270,34 @@ var UrlbarUtils = {
   /**
    * Returns a list of all the token substring matches in a string.  Matching is
    * case insensitive.  Each match in the returned list is a tuple: [matchIndex,
    * matchLength].  matchIndex is the index in the string of the match, and
    * matchLength is the length of the match.
    *
    * @param {array} tokens The tokens to search for.
    * @param {string} str The string to match against.
-   * @param {boolean} highlightType If HIGHLIGHT.SUGGESTED, return a list of all
-   *   the token string non-matches. Otherwise, return matches.
+   * @param {boolean} highlightType
+   *   One of the HIGHLIGHT values:
+   *     TYPED: match ranges matching the tokens; or
+   *     SUGGESTED: match ranges for words not matching the tokens and the
+   *                endings of words that start with a token.
    * @returns {array} An array: [
    *            [matchIndex_0, matchLength_0],
    *            [matchIndex_1, matchLength_1],
    *            ...
    *            [matchIndex_n, matchLength_n]
    *          ].
    *          The array is sorted by match indexes ascending.
    */
   getTokenMatches(tokens, str, highlightType) {
     str = str.toLocaleLowerCase();
     // To generate non-overlapping ranges, we start from a 0-filled array with
     // the same length of the string, and use it as a collision marker, setting
-    // 1 where a token matches.
+    // 1 where the text should be highlighted.
     let hits = new Array(str.length).fill(
       highlightType == this.HIGHLIGHT.SUGGESTED ? 1 : 0
     );
     let compareIgnoringDiacritics;
     for (let { lowerCaseValue: needle } of tokens) {
       // Ideally we should never hit the empty token case, but just in case
       // the `needle` check protects us from an infinite loop.
       if (!needle) {
@@ -303,16 +306,30 @@ var UrlbarUtils = {
       let index = 0;
       let found = false;
       // First try a diacritic-sensitive search.
       for (;;) {
         index = str.indexOf(needle, index);
         if (index < 0) {
           break;
         }
+
+        if (highlightType == UrlbarUtils.HIGHLIGHT.SUGGESTED) {
+          // We de-emphasize the match only if it's preceded by a space, thus
+          // it's a perfect match or the beginning of a longer word.
+          let previousSpaceIndex = str.lastIndexOf(" ", index) + 1;
+          if (index != previousSpaceIndex) {
+            index += needle.length;
+            // We found the token but we won't de-emphasize it, because it's not
+            // after a word boundary.
+            found = true;
+            continue;
+          }
+        }
+
         hits.fill(
           highlightType == this.HIGHLIGHT.SUGGESTED ? 0 : 1,
           index,
           index + needle.length
         );
         index += needle.length;
         found = true;
       }
@@ -330,16 +347,23 @@ var UrlbarUtils = {
             }).compare;
           }
           compareIgnoringDiacritics = this._compareIgnoringDiacritics;
         }
         index = 0;
         while (index < str.length) {
           let hay = str.substr(index, needle.length);
           if (compareIgnoringDiacritics(needle, hay) === 0) {
+            if (highlightType == UrlbarUtils.HIGHLIGHT.SUGGESTED) {
+              let previousSpaceIndex = str.lastIndexOf(" ", index) + 1;
+              if (index != previousSpaceIndex) {
+                index += needle.length;
+                continue;
+              }
+            }
             hits.fill(
               highlightType == this.HIGHLIGHT.SUGGESTED ? 0 : 1,
               index,
               index + needle.length
             );
             index += needle.length;
           } else {
             index++;
--- a/browser/components/urlbar/tests/browser/browser_autocomplete_a11y_label.js
+++ b/browser/components/urlbar/tests/browser/browser_autocomplete_a11y_label.js
@@ -100,19 +100,19 @@ add_task(async function searchSuggestion
   // by earlier tests.
   Assert.greaterOrEqual(
     length,
     3,
     "Should get at least heuristic result + two search suggestions"
   );
   // The first expected search is the search term itself since the heuristic
   // result will come before the search suggestions.
-  // The extra space is here due to bug 1550644.
+  // The extra spaces are here due to bug 1550644.
   let searchTerm = "foo ";
-  let expectedSearches = [searchTerm, "foofoo ", "foo bar"];
+  let expectedSearches = [searchTerm, "foo foo", "foo bar"];
   for (let i = 0; i < length; i++) {
     let result = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
     if (result.type === UrlbarUtils.RESULT_TYPE.SEARCH) {
       Assert.greaterOrEqual(
         expectedSearches.length,
         0,
         "Should still have expected searches remaining"
       );
--- a/browser/components/urlbar/tests/unit/test_UrlbarUtils_getTokenMatches.js
+++ b/browser/components/urlbar/tests/unit/test_UrlbarUtils_getTokenMatches.js
@@ -206,17 +206,21 @@ add_task(function test() {
     Assert.deepEqual(
       UrlbarUtils.getTokenMatches(tokens, phrase, UrlbarUtils.HIGHLIGHT.TYPED),
       expected,
       `Match "${tokens.map(t => t.value).join(", ")}" on "${phrase}"`
     );
   }
 });
 
-add_task(function testReverse() {
+/**
+ * Tests suggestion highlighting. Note that suggestions are only highlighted if
+ * the matching token is at the beginning of a word in the matched string.
+ */
+add_task(function testSuggestions() {
   const tests = [
     {
       tokens: ["mozilla", "is", "i"],
       phrase: "mozilla is for the Open Web",
       expected: [
         [7, 1],
         [10, 17],
       ],
@@ -227,50 +231,53 @@ add_task(function testReverse() {
       expected: [
         [0, 5],
         [6, 6],
       ],
     },
     {
       tokens: ["mo", "zilla"],
       phrase: "mOzIlLa",
-      expected: [],
+      expected: [[2, 5]],
     },
     {
       tokens: ["MO", "ZILLA"],
       phrase: "mozilla",
-      expected: [],
+      expected: [[2, 5]],
     },
     {
       tokens: [""], // Should never happen in practice.
       phrase: "mozilla",
       expected: [[0, 7]],
     },
     {
-      tokens: ["mo", "om"],
+      tokens: ["mo", "om", "la"],
       phrase: "mozilla mozzarella momo",
       expected: [
         [2, 6],
         [10, 9],
+        [21, 2],
       ],
     },
     {
-      tokens: ["mo", "om"],
+      tokens: ["mo", "om", "la"],
       phrase: "MOZILLA MOZZARELLA MOMO",
       expected: [
         [2, 6],
         [10, 9],
+        [21, 2],
       ],
     },
     {
-      tokens: ["MO", "OM"],
+      tokens: ["MO", "OM", "LA"],
       phrase: "mozilla mozzarella momo",
       expected: [
         [2, 6],
         [10, 9],
+        [21, 2],
       ],
     },
   ];
   for (let { tokens, phrase, expected } of tests) {
     tokens = tokens.map(t => ({
       value: t,
       lowerCaseValue: t.toLocaleLowerCase(),
     }));
deleted file mode 100644
--- a/build/autoconf/ios.m4
+++ /dev/null
@@ -1,107 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-AC_DEFUN([MOZ_IOS_PATH_PROG],
-[
-changequote({,})
-_prog_name=ifelse($2, {}, `echo $1 | tr "[:upper:]" "[:lower:]"`, $2)
-changequote([,])
-AC_CACHE_CHECK([for $_prog_name in iOS SDK],
-ac_cv_ios_path_$1,
-[
-_path=`xcrun --sdk $ios_sdk --find $_prog_name 2>/dev/null`
-_res=$?
-if test $_res -ne 0; then
-   AC_MSG_ERROR([Could not find '$_prog_name' in the iOS SDK])
-fi
-ac_cv_ios_path_$1=$_path
-])
-$1="${ac_cv_ios_path_$1}$3"
-])
-
-AC_DEFUN([MOZ_IOS_SDK],
-[
-
-MOZ_ARG_WITH_STRING(ios-sdk,
-[  --with-ios-sdk=TYPE
-                          Type of iOS SDK to use (iphonesimulator, iphoneos)
-                          and optionally version (like iphoneos8.2)],
-    ios_sdk=$withval)
-
-MOZ_ARG_ENABLE_STRING(ios-target,
-                      [  --enable-ios-target=VER (default=8.0)
-                          Set the minimum iOS version needed at runtime],
-                      [_IOS_TARGET=$enableval])
-_IOS_TARGET_DEFAULT=8.0
-
-case "$target" in
-arm*-apple-darwin*)
-    if test -z "$ios_sdk" -o "$ios_sdk" = "yes"; then
-       ios_sdk=iphoneos
-    fi
-    case "$ios_sdk" in
-         iphoneos*)
-                ios_target_arg="-miphoneos-version-min"
-                ;;
-         *)
-                AC_MSG_ERROR([Only 'iphoneos' SDKs are valid when targeting iOS device, don't know what to do with '$ios_sdk'.])
-                ;;
-    esac
-    ;;
-*-apple-darwin*)
-    ios_target_arg="-mios-simulator-version-min"
-    case "$ios_sdk" in
-         # Empty SDK is okay, this might be an OS X desktop build.
-         ""|iphonesimulator*)
-                ;;
-         # Default to iphonesimulator
-         yes)
-                ios_sdk=iphonesimulator
-                ;;
-         *)
-                AC_MSG_ERROR([Only 'iphonesimulator' SDKs are valid when targeting iOS simulator.])
-                ;;
-    esac
-    ;;
-esac
-
-
-if test -n "$ios_sdk"; then
-   if test -z "$_IOS_TARGET"; then
-      _IOS_TARGET=$_IOS_TARGET_DEFAULT
-      ios_target_arg="${ios_target_arg}=${_IOS_TARGET}"
-   fi
-   # Ensure that xcrun knows where this SDK is.
-   ios_sdk_path=`xcrun --sdk $ios_sdk --show-sdk-path 2>/dev/null`
-   _ret=$?
-   if test $_ret -ne 0; then
-      AC_MSG_ERROR([iOS SDK '$ios_sdk' could not be found.])
-   fi
-   MOZ_IOS=1
-   export HOST_CC=clang
-   export HOST_CXX=clang++
-   # Add isysroot, arch, and ios target arguments
-   case "$target_cpu" in
-        arm*)
-                ARGS="-arch armv7"
-                ;;
-        *)
-                # Unfortunately simulator builds need this.
-                export CROSS_COMPILE=1
-                ;;
-   esac
-   ARGS=" $ARGS -isysroot $ios_sdk_path $ios_target_arg"
-   # Now find our tools
-   MOZ_IOS_PATH_PROG(CC, clang, $ARGS)
-   MOZ_IOS_PATH_PROG(CXX, clang++, $ARGS)
-   export CPP="$CC -E"
-   MOZ_IOS_PATH_PROG(AR)
-   MOZ_IOS_PATH_PROG(AS, as, $ARGS)
-   MOZ_IOS_PATH_PROG(OTOOL)
-   MOZ_IOS_PATH_PROG(STRIP)
-   export PKG_CONFIG_PATH=${ios_sdk_path}/usr/lib/pkgconfig/
-fi
-
-AC_SUBST(MOZ_IOS)
-])
--- a/build/clang-plugin/NoPrincipalGetURI.cpp
+++ b/build/clang-plugin/NoPrincipalGetURI.cpp
@@ -16,12 +16,12 @@ void NoPrincipalGetURI::registerMatchers
           argumentCountIs(1))
           .bind("id"),
       this);
 }
 
 void NoPrincipalGetURI::check(const MatchFinder::MatchResult &Result) {
   const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMemberCallExpr>("id");
   diag(MatchedDecl->getExprLoc(),
-       "nsIPrincipal->GetURI is depricated and will be removed soon. Please "
+       "Principal->GetURI is depricated and will be removed soon. Please "
        "consider using the new helper functions of nsIPrincipal",
-       DiagnosticIDs::Warning);
+       DiagnosticIDs::Error);
 }
--- a/build/clang-plugin/tests/TestNoPrincipalGetUri.cpp
+++ b/build/clang-plugin/tests/TestNoPrincipalGetUri.cpp
@@ -12,20 +12,20 @@ class NullPrincipal : public SomePrincip
 
 class SomeURI {
 public:
   void GetURI(int foo) {}
 };
 
 void f() {
   nsIPrincipal *a = new SomePrincipal();
-  a->GetURI(0); //  expected-warning {{nsIPrincipal->GetURI is depricated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}}
+  a->GetURI(0); //  expected-error {{Principal->GetURI is depricated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}}
 
   nsIPrincipal *b = new NullPrincipal();
-  b->GetURI(0); //  expected-warning {{nsIPrincipal->GetURI is depricated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}}
+  b->GetURI(0); //  expected-error {{Principal->GetURI is depricated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}}
 
   SomeURI *c = new SomeURI();
   c->GetURI(0);
 
   SomePrincipal *d = new SomePrincipal();
   d->GetURI(0);
 
 }
\ No newline at end of file
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -243,17 +243,16 @@ option(env='PYTHON3', nargs=1, help='Pyt
 @imports(_from='__builtin__', _import='Exception')
 @imports('os')
 @imports('sys')
 @imports('subprocess')
 @imports('distutils.sysconfig')
 @imports(_from='mozbuild.configure.util', _import='LineIO')
 @imports(_from='mozbuild.virtualenv', _import='VirtualenvManager')
 @imports(_from='mozbuild.virtualenv', _import='verify_python_version')
-@imports(_from='mozbuild.virtualenv', _import='PY3')
 @imports(_from='mozbuild.pythonutil', _import='find_python3_executable')
 @imports(_from='mozbuild.pythonutil', _import='python_executable_version')
 @imports(_from='six', _import='ensure_text')
 def virtualenv_python3(env_python, build_env, mozconfig, help):
     # Avoid re-executing python when running configure --help.
     if help:
         return
 
@@ -356,40 +355,33 @@ def virtualenv_python3(env_python, build
     if not manager.up_to_date(python):
         log.info('Creating Python 3 environment')
         manager.build(python)
     else:
         log.debug("python3: venv is up to date")
 
     python = normsep(manager.python_path)
 
-    # The currently running interpreter could be Python 2 or Python 3. We make the
-    # part of the code that re-executes everything with the virtualenv's Python
-    # conditional on running the same major version as the current interpreter. If we
-    # don't do this then the configure code for the Py 2 and Py 3 virtualenvs could
-    # activate each other from inside the other's virtualenv.  We can't guarantee
-    # how the virtualenvs would interact if that happens.
-    if PY3:
-        if not normsep(sys.executable).startswith(normsep(virtualenvs_root)):
-            log.debug("python3: executing as %s, should be running as %s" % (
-                sys.executable, manager.python_path))
-            log.info('Re-executing in the virtualenv')
-            if env_python:
-                del os.environ['PYTHON3']
-            # Homebrew on macOS will change Python's sys.executable to a custom
-            # value which messes with mach's virtualenv handling code. Override
-            # Homebrew's changes with the correct sys.executable value.
-            os.environ['PYTHONEXECUTABLE'] = python
-            # One would prefer to use os.execl, but that's completely borked on
-            # Windows.
-            sys.exit(subprocess.call([python] + sys.argv))
+    if not normsep(sys.executable).startswith(normsep(virtualenvs_root)):
+        log.debug("python3: executing as %s, should be running as %s" % (
+            sys.executable, manager.python_path))
+        log.info('Re-executing in the virtualenv')
+        if env_python:
+            del os.environ['PYTHON3']
+        # Homebrew on macOS will change Python's sys.executable to a custom
+        # value which messes with mach's virtualenv handling code. Override
+        # Homebrew's changes with the correct sys.executable value.
+        os.environ['PYTHONEXECUTABLE'] = python
+        # One would prefer to use os.execl, but that's completely borked on
+        # Windows.
+        sys.exit(subprocess.call([python] + sys.argv))
 
-        # We are now in the virtualenv
-        if not distutils.sysconfig.get_python_lib():
-            die('Could not determine python site packages directory')
+    # We are now in the virtualenv
+    if not distutils.sysconfig.get_python_lib():
+        die('Could not determine python site packages directory')
 
     str_version = '.'.join(str(v) for v in version)
 
     return namespace(
         path=python,
         version=version,
         str_version=str_version,
     )
@@ -688,19 +680,16 @@ def split_triplet(triplet, allow_msvc=Fa
         canonical_os = canonical_kernel = 'GNU'
     elif os.startswith('mingw') or (allow_msvc and os == 'windows-msvc'):
         # windows-msvc is only opt-in for the caller of this function until
         # full support in bug 1617793.
         canonical_os = canonical_kernel = 'WINNT'
     elif os.startswith('darwin'):
         canonical_kernel = 'Darwin'
         canonical_os = 'OSX'
-    elif os.startswith('ios'):
-        canonical_kernel = 'Darwin'
-        canonical_os = 'iOS'
     elif os.startswith('dragonfly'):
         canonical_os = canonical_kernel = 'DragonFly'
     elif os.startswith('freebsd'):
         canonical_os = canonical_kernel = 'FreeBSD'
     elif os.startswith('netbsd'):
         canonical_os = canonical_kernel = 'NetBSD'
     elif os.startswith('openbsd'):
         canonical_os = canonical_kernel = 'OpenBSD'
@@ -923,20 +912,16 @@ set_config('HOST_MAJOR_VERSION', host_os
 @depends(host)
 def host_for_sub_configure(host):
     return '--host=%s' % host.alias
 
 
 @depends(target)
 def target_for_sub_configure(target):
     target_alias = target.alias
-    # old-configure does plenty of tests against $target and $target_os
-    # and expects darwin for iOS, so make it happy.
-    if target.os == 'iOS':
-        target_alias = target_alias.replace('-ios', '-darwin')
     return '--target=%s' % target_alias
 
 
 # These variables are for compatibility with the current moz.builds and
 # old-configure. Eventually, we'll want to canonicalize better.
 @depends(target)
 def target_variables(target):
     if target.kernel == 'kFreeBSD':
@@ -1013,25 +998,16 @@ def target_is_darwin(target):
     if target.kernel == 'Darwin':
         return True
 
 
 set_define('XP_DARWIN', target_is_darwin)
 
 
 @depends(target)
-def target_is_ios(target):
-    if target.kernel == 'Darwin' and target.os == 'iOS':
-        return True
-
-
-set_define('XP_IOS', target_is_ios)
-
-
-@depends(target)
 def target_is_osx(target):
     if target.kernel == 'Darwin' and target.os == 'OSX':
         return True
 
 
 set_define('XP_MACOSX', target_is_osx)
 
 
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -205,48 +205,38 @@ def old_configure_options(*options):
         return list(options)
 
     return depends(host_for_sub_configure, target_for_sub_configure, all_options, *options)
 
 
 @old_configure_options(
     '--cache-file',
     '--datadir',
-    '--enable-cookies',
     '--enable-cpp-rtti',
     '--enable-crashreporter',
     '--enable-dbus',
     '--enable-debug-js-modules',
-    '--enable-directshow',
     '--enable-dtrace',
     '--enable-dump-painting',
     '--enable-extensions',
-    '--enable-feeds',
-    '--enable-gconf',
     '--enable-icf',
     '--enable-install-strip',
-    '--enable-ios-target',
-    '--enable-libjpeg-turbo',
     '--enable-libproxy',
-    '--enable-llvm-hacks',
     '--enable-logrefcnt',
     '--enable-mobile-optimize',
     '--enable-necko-wifi',
     '--enable-negotiateauth',
-    '--enable-nfc',
     '--enable-nspr-build',
     '--enable-official-branding',
     '--enable-parental-controls',
     '--enable-pref-extensions',
     '--enable-readline',
     '--enable-sandbox',
-    '--enable-startup-notification',
     '--enable-startupcache',
     '--enable-strip',
-    '--enable-synth-pico',
     '--enable-system-cairo',
     '--enable-system-extension-dirs',
     '--enable-system-pixman',
     '--enable-universalchardet',
     '--enable-updater',
     '--enable-xul',
     '--enable-zipwriter',
     '--includedir',
@@ -256,39 +246,33 @@ def old_configure_options(*options):
     '--with-android-max-sdk',
     '--with-android-min-sdk',
     '--with-app-basename',
     '--with-app-name',
     '--with-branding',
     '--with-cross-lib',
     '--with-debug-label',
     '--with-distribution-id',
-    '--with-doc-include-dirs',
-    '--with-doc-input-dirs',
-    '--with-doc-output-dir',
     '--with-intl-api',
-    '--with-ios-sdk',
     '--with-jitreport-granularity',
     '--with-macbundlename-prefix',
     '--with-nspr-cflags',
     '--with-nspr-exec-prefix',
     '--with-nspr-libs',
     '--with-nspr-prefix',
     '--with-nss-exec-prefix',
     '--with-nss-prefix',
     '--with-qemu-exe',
     '--with-sixgill',
-    '--with-system-bz2',
     '--with-system-icu',
     '--with-system-libevent',
     '--with-system-nspr',
     '--with-system-nss',
     '--with-system-png',
     '--with-system-zlib',
-    '--with-unify-dist',
     '--with-user-appdir',
     '--x-includes',
     '--x-libraries',
 )
 def prepare_configure_options(host, target, all_options, *options):
     # old-configure only supports the options listed in @old_configure_options
     # so we don't need to pass it every single option we've been passed. Only
     # the ones that are not supported by python configure need to.
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -2060,16 +2060,19 @@ def select_linker(linker, c_compiler, de
         # ld64 doesn't have anything to print out a version. It does print out
         # "ld64: For information on command line options please use 'man ld'."
         # but that would require doing two attempts, one with --version, that
         # would fail, and another with --help.
         # Instead, abuse its LD_PRINT_OPTIONS feature to detect a message
         # specific to it on stderr when it fails to process --version.
         env = dict(os.environ)
         env['LD_PRINT_OPTIONS'] = '1'
+        # Some locales might not print out the strings we are looking for, so
+        # ensure consistent output.
+        env['LC_ALL'] = 'C'
         retcode, stdout, stderr = get_cmd_output(*cmd, env=env)
         if retcode == 1 and 'Logging ld64 options' in stderr:
             kind = 'ld64'
 
         elif retcode != 0:
             return None
 
         elif 'GNU ld' in stdout:
--- a/build/sparse-profiles/taskgraph
+++ b/build/sparse-profiles/taskgraph
@@ -46,16 +46,19 @@ glob:**/*.configure
 # are all somewhere in "tooltool-manifests" directories.
 glob:**/tooltool-manifests/**
 
 # For test chunking
 glob:**/*.ini
 glob:**/*.list
 path:testing/mozbase/manifestparser
 path:testing/runtimes
+path:testing/web-platform/tests/
+path:testing/web-platform/mozilla/tests/
+glob:testing/web-platform/*.py
 
 # For scheduling android-gradle-dependencies.
 path:mobile/android/config/
 glob:**/*.gradle
 
 # for action-task building
 path:.taskcluster.yml
 path:.cron.yml
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -610,19 +610,19 @@ nsScriptSecurityManager::CheckLoadURIWit
   }
 
   if (aPrincipal == mSystemPrincipal) {
     // Allow access
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> sourceURI;
-  aPrincipal->GetURI(getter_AddRefs(sourceURI));
+  auto* basePrin = BasePrincipal::Cast(aPrincipal);
+  basePrin->GetURI(getter_AddRefs(sourceURI));
   if (!sourceURI) {
-    auto* basePrin = BasePrincipal::Cast(aPrincipal);
     if (basePrin->Is<ExpandedPrincipal>()) {
       auto expanded = basePrin->As<ExpandedPrincipal>();
       for (auto& prin : expanded->AllowList()) {
         nsresult rv =
             CheckLoadURIWithPrincipal(prin, aTargetURI, aFlags, aInnerWindowID);
         if (NS_SUCCEEDED(rv)) {
           // Allow access if it succeeded with one of the allowlisted principals
           return NS_OK;
--- a/config/external/nspr/pr/moz.build
+++ b/config/external/nspr/pr/moz.build
@@ -46,18 +46,17 @@ elif CONFIG['OS_TARGET'] == 'Darwin':
     DEFINES['DARWIN'] = True
     DEFINES['HAVE_BSD_FLOCK'] = True
     DEFINES['HAVE_SOCKLEN_T'] = True
     DEFINES['HAVE_POINTER_LOCALTIME_R'] = True
     SOURCES += [
         '/nsprpub/pr/src/md/unix/darwin.c',
         '/nsprpub/pr/src/md/unix/os_Darwin.s',
     ]
-    if not CONFIG['MOZ_IOS']:
-        DEFINES['HAVE_CRT_EXTERNS_H'] = True
+    DEFINES['HAVE_CRT_EXTERNS_H'] = True
 elif CONFIG['OS_TARGET'] == 'SunOS':
     DEFINES['HAVE_FCNTL_FILE_LOCKING'] = True
     DEFINES['HAVE_SOCKLEN_T'] = True
     DEFINES['_PR_HAVE_OFF64_T'] = True
     DEFINES['_PR_INET6'] = True
     DEFINES['SOLARIS'] = True
     SOURCES += ['/nsprpub/pr/src/md/unix/solaris.c']
     if CONFIG['CPU_ARCH'] == 'x86_64':
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -302,21 +302,17 @@ HOST_CPP_PROG_LINK	= 1
 endif
 
 #
 # MacOS X specific stuff
 #
 
 ifeq ($(OS_ARCH),Darwin)
 ifdef SHARED_LIBRARY
-ifdef MOZ_IOS
-_LOADER_PATH := @rpath
-else
 _LOADER_PATH := @executable_path
-endif
 EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
 endif
 endif
 
 #
 # GNU doesn't have path length limitation
 #
 
--- a/devtools/client/inspector/compatibility/lib/MDNCompatibility.js
+++ b/devtools/client/inspector/compatibility/lib/MDNCompatibility.js
@@ -354,20 +354,23 @@ class MDNCompatibility {
     if (!supportList) {
       return _SUPPORT_STATE.BROWSER_NOT_FOUND;
     }
 
     supportList = Array.isArray(supportList) ? supportList : [supportList];
     const version = parseFloat(browser.version);
     const terminal = terms[terms.length - 1];
     const match = terminal.match(/^-\w+-/);
-    const prefix = match ? match[0] : null;
+    const prefix = match ? match[0] : undefined;
+    // There are compat data that are defined with prefix like "-moz-binding".
+    // In this case, we don't have to check the prefix.
+    const isPrefixedData = prefix && !this._getAlias(compatNode, ...terms);
 
     for (const support of supportList) {
-      if ((!support.prefix && !prefix) || support.prefix === prefix) {
+      if (isPrefixedData || support.prefix === prefix) {
         const { version_added: added, version_removed: removed } = support;
         const addedVersion = this._asFloatVersion(
           added === null ? true : added
         );
         const removedVersion = this._asFloatVersion(
           removed === null ? false : removed
         );
 
--- a/devtools/client/inspector/compatibility/test/xpcshell/test_mdn-compatibility.js
+++ b/devtools/client/inspector/compatibility/test/xpcshell/test_mdn-compatibility.js
@@ -4,26 +4,31 @@
 
 // Test for the MDN compatibility diagnosis module.
 
 const MDNCompatibility = require("devtools/client/inspector/compatibility/lib/MDNCompatibility");
 const cssPropertiesCompatData = require("devtools/client/inspector/compatibility/lib/dataset/css-properties.json");
 
 const mdnCompatibility = new MDNCompatibility(cssPropertiesCompatData);
 
+const FIREFOX_1 = {
+  id: "firefox",
+  version: "1",
+};
+
+const FIREFOX_60 = {
+  id: "firefox",
+  version: "60",
+};
+
 const FIREFOX_69 = {
   id: "firefox",
   version: "69",
 };
 
-const FIREFOX_1 = {
-  id: "firefox",
-  version: "1",
-};
-
 const SAFARI_13 = {
   id: "safari",
   version: "13",
 };
 
 const TEST_DATA = [
   {
     description: "Test for a supported property",
@@ -109,16 +114,31 @@ const TEST_DATA = [
     description: "Test for aliased properties supported in all browsers",
     declarations: [
       { name: "-moz-user-select" },
       { name: "-webkit-user-select" },
     ],
     browsers: [FIREFOX_69, SAFARI_13],
     expectedIssues: [],
   },
+  {
+    description: "Test for a property defined with prefix",
+    declarations: [{ name: "-moz-binding" }],
+    browsers: [FIREFOX_1, FIREFOX_60, FIREFOX_69],
+    expectedIssues: [
+      {
+        type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY,
+        property: "-moz-binding",
+        url: "https://developer.mozilla.org/docs/Web/CSS/-moz-binding",
+        deprecated: true,
+        experimental: false,
+        unsupportedBrowsers: [FIREFOX_69],
+      },
+    ],
+  },
 ];
 
 add_task(() => {
   for (const {
     description,
     declarations,
     browsers,
     expectedIssues,
--- a/devtools/client/inspector/rules/models/text-property.js
+++ b/devtools/client/inspector/rules/models/text-property.js
@@ -10,17 +10,17 @@ loader.lazyRequireGetter(
   this,
   "escapeCSSComment",
   "devtools/shared/css/parsing-utils",
   true
 );
 
 loader.lazyRequireGetter(
   this,
-  "hasCSSVariable",
+  "getCSSVariables",
   "devtools/client/inspector/rules/utils/utils",
   true
 );
 
 /**
  * TextProperty is responsible for the following:
  *   Manages a single property from the authoredText attribute of the
  *     relevant declaration.
@@ -55,18 +55,21 @@ class TextProperty {
     this.value = value;
     this.priority = priority;
     this.enabled = !!enabled;
     this.invisible = invisible;
     this.elementStyle = this.rule.elementStyle;
     this.cssProperties = this.elementStyle.ruleView.cssProperties;
     this.panelDoc = this.elementStyle.ruleView.inspector.panelDoc;
     this.userProperties = this.elementStyle.store.userProperties;
+    // Names of CSS variables used in the value of this declaration.
+    this.usedVariables = new Set();
 
     this.updateComputed();
+    this.updateUsedVariables();
   }
 
   get computedProperties() {
     return this.computed
       .filter(computed => computed.name !== this.name)
       .map(computed => {
         return {
           isOverridden: computed.overridden,
@@ -135,56 +138,70 @@ class TextProperty {
         name: prop,
         value: dummyStyle.getPropertyValue(prop),
         priority: dummyStyle.getPropertyPriority(prop),
       });
     }
   }
 
   /**
+   * Extract all CSS variable names used in this declaration's value into a Set for
+   * easy querying. Call this method any time the declaration's value changes.
+   */
+  updateUsedVariables() {
+    this.usedVariables.clear();
+
+    for (const variable of getCSSVariables(this.value)) {
+      this.usedVariables.add(variable);
+    }
+  }
+
+  /**
    * Set all the values from another TextProperty instance into
    * this TextProperty instance.
    *
    * @param {TextProperty} prop
    *        The other TextProperty instance.
    */
   set(prop) {
     let changed = false;
     for (const item of ["name", "value", "priority", "enabled"]) {
       if (this[item] !== prop[item]) {
         this[item] = prop[item];
         changed = true;
       }
     }
 
     if (changed) {
+      this.updateUsedVariables();
       this.updateEditor();
     }
   }
 
   setValue(value, priority, force = false) {
     if (value !== this.value || force) {
       this.userProperties.setProperty(this.rule.domRule, this.name, value);
     }
-
-    return this.rule
-      .setPropertyValue(this, value, priority)
-      .then(() => this.updateEditor());
+    return this.rule.setPropertyValue(this, value, priority).then(() => {
+      this.updateUsedVariables();
+      this.updateEditor();
+    });
   }
 
   /**
    * Called when the property's value has been updated externally, and
    * the property and editor should update to reflect that value.
    *
    * @param {String} value
    *        Property value
    */
   updateValue(value) {
     if (value !== this.value) {
       this.value = value;
+      this.updateUsedVariables();
       this.updateEditor();
     }
   }
 
   async setName(name) {
     if (name !== this.name) {
       this.userProperties.setProperty(this.rule.domRule, name, this.value);
     }
@@ -283,13 +300,13 @@ class TextProperty {
    * Returns true if the property value is a CSS variables and contains the given variable
    * name, and false otherwise.
    *
    * @param {String}
    *        CSS variable name (e.g. "--color")
    * @return {Boolean}
    */
   hasCSSVariable(name) {
-    return hasCSSVariable(this.value, name);
+    return this.usedVariables.has(name);
   }
 }
 
 module.exports = TextProperty;
--- a/devtools/client/inspector/rules/utils/utils.js
+++ b/devtools/client/inspector/rules/utils/utils.js
@@ -144,17 +144,17 @@ function getNodeInfo(node, elementStyle)
   } else if (
     declaration &&
     (classList.contains("ruleview-variable") ||
       classList.contains("ruleview-unmatched-variable"))
   ) {
     type = VIEW_NODE_VARIABLE_TYPE;
     value = {
       property: getPropertyNameAndValue(node).name,
-      value: node.textContent,
+      value: node.textContent.trim(),
       enabled: declaration.enabled,
       overridden: declaration.overridden,
       pseudoElement: rule.pseudoElement,
       sheetHref: rule.domRule.href,
       textProperty: declaration,
       variable: node.dataset.variable,
     };
   } else if (
@@ -275,27 +275,60 @@ function getShapePoint(node) {
   });
   if (insetClasses.length > 0) {
     point = insetClasses.join(",");
   }
   return point;
 }
 
 /**
- * Returns true if the given property value is a CSS variables and contains the given
- * variable name, and false otherwise.
+ * Returns an array of CSS variables used in a CSS property value.
+ * If no CSS variables are used, returns an empty array.
+ *
+ * @param {String} propertyValue
+ *        CSS property value (e.g. "1px solid var(--color, blue)")
+ * @return {Array}
+ *         List of variable names (e.g. ["--color"])
+ *
+ */
+function getCSSVariables(propertyValue = "") {
+  const variables = [];
+  const parts = propertyValue.split(/var\(\s*--/);
+
+  if (parts.length) {
+    // Skip first part. It is the substring before the first occurence of "var(--"
+    for (let i = 1; i < parts.length; i++) {
+      // Split the part by any of the following characters expected after a variable name:
+      // comma, closing parenthesis or whitespace.
+      // Take just the first match. Anything else is either:
+      // - the fallback value, ex: ", blue" from "var(--color, blue)"
+      // - the closing parenthesis, ex: ")" from "var(--color)"
+      const variable = parts[i].split(/[,)\s+]/).shift();
+
+      if (variable) {
+        // Add back the double-dash. The initial string was split by "var(--"
+        variables.push(`--${variable}`);
+      }
+    }
+  }
+
+  return variables;
+}
+
+/**
+ * Returns true if the given CSS property value contains the given variable name.
  *
  * @param {String} propertyValue
  *        CSS property value (e.g. "var(--color)")
  * @param {String} variableName
  *        CSS variable name (e.g. "--color")
  * @return {Boolean}
  */
 function hasCSSVariable(propertyValue, variableName) {
-  const regex = new RegExp(`(^|\\W)var\\(${variableName}\\s*[,)]`);
-  return regex.test(propertyValue);
+  return getCSSVariables(propertyValue).includes(variableName);
 }
 
 module.exports = {
+  getCSSVariables,
   getNodeInfo,
   getRuleFromNode,
   hasCSSVariable,
 };
--- a/devtools/client/shared/test/xpcshell/test_hasCSSVariable.js
+++ b/devtools/client/shared/test/xpcshell/test_hasCSSVariable.js
@@ -47,9 +47,15 @@ function run_test() {
     "Did not find --color variable in var(--color1, var(--color2, blue))"
   );
 
   info("Invalid variable");
   ok(
     !hasCSSVariable("--color", "--color"),
     "Did not find --color variable in --color"
   );
+
+  info("Variable with whitespace");
+  ok(
+    hasCSSVariable("var( --color )", "--color"),
+    "Found --color variable in var( --color )"
+  );
 }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7610,17 +7610,17 @@ nsresult nsDocShell::CreateContentViewer
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = BasePrincipal::Cast(thisPrincipal)->GetSiteIdentifier(thisSite);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (!parentSite.Equals(thisSite)) {
 #ifdef MOZ_GECKO_PROFILER
         nsCOMPtr<nsIURI> prinURI;
-        thisPrincipal->GetURI(getter_AddRefs(prinURI));
+        BasePrincipal::Cast(thisPrincipal)->GetURI(getter_AddRefs(prinURI));
         nsPrintfCString marker("Iframe loaded in background: %s",
                                prinURI->GetSpecOrDefault().get());
         TimeStamp now = TimeStamp::Now();
         profiler_add_text_marker("Background Iframe", marker,
                                  JS::ProfilingCategoryPair::DOM, now, now,
                                  Nothing());
 #endif
         SetBackgroundLoadIframe();
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -78,16 +78,47 @@ class MOZ_RAII AutoMutationBatchForAnima
 }  // namespace
 
 // ---------------------------------------------------------------------------
 //
 // Animation interface:
 //
 // ---------------------------------------------------------------------------
 
+/* static */
+already_AddRefed<Animation> Animation::ClonePausedAnimation(
+    nsIGlobalObject* aGlobal, const Animation& aOther, AnimationEffect& aEffect,
+    AnimationTimeline& aTimeline) {
+  RefPtr<Animation> animation = new Animation(aGlobal);
+  // Setup the timing.
+  animation->mTimeline = &aTimeline;
+  const Nullable<TimeDuration> timelineTime =
+      aTimeline.GetCurrentTimeAsDuration();
+  MOZ_ASSERT(!timelineTime.IsNull(), "Timeline not yet set");
+
+  const Nullable<TimeDuration> currentTime = aOther.GetCurrentTimeAsDuration();
+  animation->mHoldTime = currentTime;
+  if (!currentTime.IsNull()) {
+    animation->mPreviousCurrentTime = timelineTime;
+  }
+
+  animation->mPlaybackRate = aOther.mPlaybackRate;
+
+  // Setup the effect's link to this.
+  animation->mEffect = &aEffect;
+  animation->mEffect->SetAnimation(animation);
+
+  // We expect our relevance to be the same as the orginal.
+  animation->mIsRelevant = aOther.mIsRelevant;
+
+  animation->PostUpdate();
+  animation->mTimeline->NotifyAnimationUpdated(*animation);
+  return animation.forget();
+}
+
 NonOwningAnimationTarget Animation::GetTargetForAnimation() const {
   AnimationEffect* effect = GetEffect();
   NonOwningAnimationTarget target;
   if (!effect || !effect->AsKeyframeEffect()) {
     return target;
   }
   return effect->AsKeyframeEffect()->GetAnimationTarget();
 }
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -45,16 +45,24 @@ class Animation : public DOMEventTargetH
                   public LinkedListElement<Animation> {
  protected:
   virtual ~Animation() = default;
 
  public:
   explicit Animation(nsIGlobalObject* aGlobal)
       : DOMEventTargetHelper(aGlobal), mAnimationIndex(sNextAnimationIndex++) {}
 
+  // Constructs a copy of |aOther| with a new effect and timeline.
+  // This is only intended to be used while making a static clone of a document
+  // during printing, and does not assume that |aOther| is in the same document
+  // as any of the other arguments.
+  static already_AddRefed<Animation> ClonePausedAnimation(
+      nsIGlobalObject* aGlobal, const Animation& aOther,
+      AnimationEffect& aEffect, AnimationTimeline& aTimeline);
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Animation, DOMEventTargetHelper)
 
   nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); }
 
   /**
    * Utility function to get the target (pseudo-)element associated with an
    * animation.
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -102,16 +102,22 @@ bool EffectCompositor::AllowCompositorAn
 // GetAnimationsForCompositor and HasAnimationsForCompositor.
 //
 // Takes an optional array to fill with eligible animations.
 //
 // Returns true if there are eligible animations, false otherwise.
 bool FindAnimationsForCompositor(
     const nsIFrame* aFrame, const nsCSSPropertyIDSet& aPropertySet,
     nsTArray<RefPtr<dom::Animation>>* aMatches /*out*/) {
+  // Do not process any animations on the compositor when in print or print
+  // preview.
+  if (aFrame->PresContext()->IsPrintingOrPrintPreview()) {
+    return false;
+  }
+
   MOZ_ASSERT(
       aPropertySet.IsSubsetOf(LayerAnimationInfo::GetCSSPropertiesFor(
           DisplayItemType::TYPE_TRANSFORM)) ||
           aPropertySet.IsSubsetOf(LayerAnimationInfo::GetCSSPropertiesFor(
               DisplayItemType::TYPE_OPACITY)) ||
           aPropertySet.IsSubsetOf(LayerAnimationInfo::GetCSSPropertiesFor(
               DisplayItemType::TYPE_BACKGROUND_COLOR)),
       "Should be the subset of transform-like properties, or opacity, "
@@ -423,18 +429,16 @@ static void ComposeSortedEffects(
     animation->ComposeStyle(*aAnimationValues, propertiesToSkip);
   }
 }
 
 bool EffectCompositor::GetServoAnimationRule(
     const dom::Element* aElement, PseudoStyleType aPseudoType,
     CascadeLevel aCascadeLevel, RawServoAnimationValueMap* aAnimationValues) {
   MOZ_ASSERT(aAnimationValues);
-  MOZ_ASSERT(mPresContext && mPresContext->IsDynamic(),
-             "Should not be in print preview");
   // Gecko_GetAnimationRule should have already checked this
   MOZ_ASSERT(nsContentUtils::GetPresShellForContent(aElement),
              "Should not be trying to run animations on elements in documents"
              " without a pres shell (e.g. XMLHttpRequest documents)");
 
   EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
   if (!effectSet) {
     return false;
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -85,18 +85,32 @@ NS_IMPL_ADDREF_INHERITED(KeyframeEffect,
 NS_IMPL_RELEASE_INHERITED(KeyframeEffect, AnimationEffect)
 
 KeyframeEffect::KeyframeEffect(Document* aDocument,
                                OwningAnimationTarget&& aTarget,
                                TimingParams&& aTiming,
                                const KeyframeEffectParams& aOptions)
     : AnimationEffect(aDocument, std::move(aTiming)),
       mTarget(std::move(aTarget)),
-      mEffectOptions(aOptions),
-      mCumulativeChangeHint(nsChangeHint(0)) {}
+      mEffectOptions(aOptions) {}
+
+KeyframeEffect::KeyframeEffect(Document* aDocument,
+                               OwningAnimationTarget&& aTarget,
+                               const KeyframeEffect& aOther)
+    : AnimationEffect(aDocument, TimingParams{aOther.SpecifiedTiming()}),
+      mTarget(std::move(aTarget)),
+      mEffectOptions{aOther.IterationComposite(), aOther.Composite(),
+                     mTarget.mPseudoType},
+      mKeyframes(aOther.mKeyframes.Clone()),
+      mProperties(aOther.mProperties.Clone()),
+      mBaseValues(aOther.mBaseValues.Count()) {
+  for (auto iter = aOther.mBaseValues.ConstIter(); !iter.Done(); iter.Next()) {
+    mBaseValues.Put(iter.Key(), RefPtr{iter.Data()});
+  }
+}
 
 JSObject* KeyframeEffect::WrapObject(JSContext* aCx,
                                      JS::Handle<JSObject*> aGivenProto) {
   return KeyframeEffect_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 IterationCompositeOperation KeyframeEffect::IterationComposite() const {
   return mEffectOptions.mIterationComposite;
@@ -1028,33 +1042,22 @@ already_AddRefed<KeyframeEffect> Keyfram
   }
 
   // Create a new KeyframeEffect object with aSource's target,
   // iteration composite operation, composite operation, and spacing mode.
   // The constructor creates a new AnimationEffect object by
   // aSource's TimingParams.
   // Note: we don't need to re-throw exceptions since the value specified on
   //       aSource's timing object can be assumed valid.
-  RefPtr<KeyframeEffect> effect = new KeyframeEffect(
-      doc, OwningAnimationTarget(aSource.mTarget),
-      TimingParams(aSource.SpecifiedTiming()), aSource.mEffectOptions);
+  RefPtr<KeyframeEffect> effect =
+      new KeyframeEffect(doc, OwningAnimationTarget{aSource.mTarget}, aSource);
   // Copy cumulative change hint. mCumulativeChangeHint should be the same as
   // the source one because both of targets are the same.
   effect->mCumulativeChangeHint = aSource.mCumulativeChangeHint;
 
-  // Copy aSource's keyframes and animation properties.
-  // Note: We don't call SetKeyframes directly, which might revise the
-  //       computed offsets and rebuild the animation properties.
-  effect->mKeyframes = aSource.mKeyframes.Clone();
-  effect->mProperties = aSource.mProperties.Clone();
-  for (auto iter = aSource.mBaseValues.ConstIter(); !iter.Done(); iter.Next()) {
-    // XXX Should this use non-const Iter() and then pass
-    // std::move(iter.Data())? Otherwise aSource might be a const&...
-    effect->mBaseValues.Put(iter.Key(), RefPtr{iter.Data()});
-  }
   return effect.forget();
 }
 
 void KeyframeEffect::SetPseudoElement(const nsAString& aPseudoElement,
                                       ErrorResult& aRv) {
   PseudoStyleType pseudoType = PseudoStyleType::NotPseudo;
   if (DOMStringIsNull(aPseudoElement)) {
     UpdateTarget(mTarget.mElement, pseudoType);
@@ -1412,27 +1415,32 @@ bool KeyframeEffect::CanThrottle() const
   // value produced on each tick will be the same so we will skip requesting
   // unnecessary restyles in NotifyAnimationTimingUpdated. Any calls we *do* get
   // here will be because of a change in state (e.g. we are newly finished or
   // newly no longer in effect) in which case we shouldn't throttle the sample.
   if (!IsInEffect() || !IsCurrent()) {
     return false;
   }
 
-  nsIFrame* frame = GetStyleFrame();
+  nsIFrame* const frame = GetStyleFrame();
   if (!frame) {
     // There are two possible cases here.
     // a) No target element
     // b) The target element has no frame, e.g. because it is in a display:none
     //    subtree.
     // In either case we can throttle the animation because there is no
     // need to update on the main thread.
     return true;
   }
 
+  // Do not throttle any animations during print preview.
+  if (frame->PresContext()->IsPrintingOrPrintPreview()) {
+    return false;
+  }
+
   if (CanThrottleIfNotVisible(*frame)) {
     return true;
   }
 
   EffectSet* effectSet = nullptr;
   for (const AnimationProperty& property : mProperties) {
     if (!property.mIsRunningOnCompositor) {
       return false;
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -106,16 +106,19 @@ namespace dom {
 class Animation;
 class Document;
 
 class KeyframeEffect : public AnimationEffect {
  public:
   KeyframeEffect(Document* aDocument, OwningAnimationTarget&& aTarget,
                  TimingParams&& aTiming, const KeyframeEffectParams& aOptions);
 
+  KeyframeEffect(Document* aDocument, OwningAnimationTarget&& aTarget,
+                 const KeyframeEffect& aOther);
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffect,
                                                          AnimationEffect)
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   KeyframeEffect* AsKeyframeEffect() override { return this; }
@@ -449,17 +452,17 @@ class KeyframeEffect : public AnimationE
   // The non-animated values for properties in this effect that contain at
   // least one animation value that is composited with the underlying value
   // (i.e. it uses the additive or accumulate composite mode).
   using BaseValuesHashmap =
       nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue>;
   BaseValuesHashmap mBaseValues;
 
  private:
-  nsChangeHint mCumulativeChangeHint;
+  nsChangeHint mCumulativeChangeHint = nsChangeHint{0};
 
   void ComposeStyleRule(RawServoAnimationValueMap& aAnimationValues,
                         const AnimationProperty& aProperty,
                         const AnimationPropertySegment& aSegment,
                         const ComputedTiming& aComputedTiming);
 
   already_AddRefed<ComputedStyle> CreateComputedStyleForAnimationValue(
       nsCSSPropertyID aProperty, const AnimationValue& aValue,
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -3955,31 +3955,31 @@ void Document::OnParsingCompleted() {
   // now we're closing the document.
   OnL10nResourceContainerParsed();
 
   if (mDocumentL10n) {
     mDocumentL10n->TriggerInitialTranslation();
   }
 }
 
-void Document::InitialTranslationCompleted() {
+void Document::InitialTranslationCompleted(bool aL10nCached) {
   if (mDocumentL10n && mDocumentL10n->mBlockingLayout) {
     // This means we blocked the load event in LocalizationLinkAdded.  It's
     // important that the load blocker removal here be async, because our caller
     // will notify the content sink after us, and we want the content sync's
     // work to happen before the load event fires.
     mDocumentL10n->mBlockingLayout = false;
     UnblockOnload(/* aFireSync = */ false);
   }
 
   mL10nProtoElements.Clear();
 
   nsXULPrototypeDocument* proto = GetPrototype();
   if (proto) {
-    proto->SetIsL10nCached();
+    proto->SetIsL10nCached(aL10nCached);
   }
 }
 
 bool Document::AllowsL10n() const {
   bool allowed = false;
   NodePrincipal()->IsL10nAllowed(GetDocumentURI(), &allowed);
   return allowed;
 }
@@ -11045,16 +11045,26 @@ nsresult Document::CloneDocHelper(Docume
     }
     clone->mChannel = channel;
     if (uri) {
       clone->ResetToURI(uri, loadGroup, NodePrincipal(),
                         EffectiveStoragePrincipal());
     }
 
     clone->SetContainer(mDocumentContainer);
+
+    // Setup the navigation time. This will be needed by any animations in the
+    // document, even if they are only paused.
+    MOZ_ASSERT(!clone->GetNavigationTiming(),
+               "Navigation time was already set?");
+    MOZ_ASSERT(mTiming,
+               "Timing should have been setup before making a static clone");
+    RefPtr<nsDOMNavigationTiming> timing =
+        mTiming->CloneNavigationTime(nsDocShell::Cast(clone->GetDocShell()));
+    clone->SetNavigationTiming(timing);
   }
 
   // Now ensure that our clone has the same URI, base URI, and principal as us.
   // We do this after the mCreatingStaticClone block above, because that block
   // can set the base URI to an incorrect value in cases when base URI
   // information came from the channel.  So we override explicitly, and do it
   // for all these properties, in case ResetToURI messes with any of the rest of
   // them.
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3774,18 +3774,21 @@ class Document : public nsINode,
    */
   void OnParsingCompleted();
 
   /**
    * This method is called when the initial translation
    * of the document is completed.
    *
    * It unblocks the load event if translation was blocking it.
-   */
-  void InitialTranslationCompleted();
+   *
+   * If the `aL10nCached` is set to `true`, and the document has
+   * a prototype, it will set the `isL10nCached` flag on it.
+   */
+  void InitialTranslationCompleted(bool aL10nCached);
 
   /**
    * Returns whether the document allows localization.
    */
   bool AllowsL10n() const;
 
  protected:
   RefPtr<DocumentL10n> mDocumentL10n;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -255,18 +255,17 @@ Element::QueryInterface(REFNSIID aIID, v
   if (NS_SUCCEEDED(rv)) {
     return NS_OK;
   }
 
   return NS_NOINTERFACE;
 }
 
 EventStates Element::IntrinsicState() const {
-  return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE
-                      : NS_EVENT_STATE_MOZ_READONLY;
+  return IsEditable() ? NS_EVENT_STATE_READWRITE : NS_EVENT_STATE_READONLY;
 }
 
 void Element::NotifyStateChange(EventStates aStates) {
   Document* doc = GetComposedDoc();
   if (doc) {
     nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, aStates);
   }
@@ -329,21 +328,21 @@ void Element::UpdateEditableState(bool a
   if (aNotify) {
     UpdateState(aNotify);
   } else {
     // Avoid calling UpdateState in this very common case, because
     // this gets called for pretty much every single element on
     // insertion into the document and UpdateState can be slow for
     // some kinds of elements even when not notifying.
     if (IsEditable()) {
-      RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
-      AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
+      RemoveStatesSilently(NS_EVENT_STATE_READONLY);
+      AddStatesSilently(NS_EVENT_STATE_READWRITE);
     } else {
-      RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
-      AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
+      RemoveStatesSilently(NS_EVENT_STATE_READWRITE);
+      AddStatesSilently(NS_EVENT_STATE_READONLY);
     }
   }
 }
 
 Maybe<int32_t> Element::GetTabIndexAttrValue() {
   const nsAttrValue* attrVal = GetParsedAttr(nsGkAtoms::tabindex);
   if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
     return Some(attrVal->GetIntegerValue());
@@ -3395,16 +3394,45 @@ void Element::GetAnimationsUnsorted(Elem
 
     MOZ_ASSERT(animation->IsRelevant(),
                "Only relevant animations should be added to an element's "
                "effect set");
     aAnimations.AppendElement(animation);
   }
 }
 
+void Element::CloneAnimationsFrom(const Element& aOther) {
+  AnimationTimeline* const timeline = OwnerDoc()->Timeline();
+  MOZ_ASSERT(timeline, "Timeline has not been set on the document yet");
+  // Iterate through all pseudo types and copy the effects from each of the
+  // other element's effect sets into this element's effect set.
+  for (PseudoStyleType pseudoType :
+       {PseudoStyleType::NotPseudo, PseudoStyleType::before,
+        PseudoStyleType::after, PseudoStyleType::marker}) {
+    // If the element has an effect set for this pseudo type (or not pseudo)
+    // then copy the effects and animation properties.
+    if (EffectSet* const effects =
+            EffectSet::GetEffectSet(&aOther, pseudoType)) {
+      EffectSet* const clonedEffects =
+          EffectSet::GetOrCreateEffectSet(this, pseudoType);
+      for (KeyframeEffect* const effect : *effects) {
+        // Clone the effect.
+        RefPtr<KeyframeEffect> clonedEffect = new KeyframeEffect(
+            OwnerDoc(), OwningAnimationTarget{this, pseudoType}, *effect);
+
+        // Clone the animation
+        RefPtr<Animation> clonedAnimation = Animation::ClonePausedAnimation(
+            OwnerDoc()->GetParentObject(), *effect->GetAnimation(),
+            *clonedEffect, *timeline);
+        clonedEffects->AddEffect(*clonedEffect);
+      }
+    }
+  }
+}
+
 void Element::GetInnerHTML(nsAString& aInnerHTML, OOMReporter& aError) {
   GetMarkup(false, aInnerHTML);
 }
 
 void Element::SetInnerHTML(const nsAString& aInnerHTML,
                            nsIPrincipal* aSubjectPrincipal,
                            ErrorResult& aError) {
   SetInnerHTMLInternal(aInnerHTML, aError);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -167,17 +167,17 @@ class Grid;
     SetAttr(nsGkAtoms::attr, aValue, aRv);                      \
   }
 
 class Element : public FragmentOrElement {
  public:
 #ifdef MOZILLA_INTERNAL_API
   explicit Element(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
       : FragmentOrElement(std::move(aNodeInfo)),
-        mState(NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_DEFINED) {
+        mState(NS_EVENT_STATE_READONLY | NS_EVENT_STATE_DEFINED) {
     MOZ_ASSERT(mNodeInfo->NodeType() == ELEMENT_NODE,
                "Bad NodeType in aNodeInfo");
     SetIsElement();
   }
 
   ~Element() {
     NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier");
   }
@@ -1379,16 +1379,18 @@ class Element : public FragmentOrElement
 
   void GetAnimationsWithoutFlush(const GetAnimationsOptions& aOptions,
                                  nsTArray<RefPtr<Animation>>& aAnimations);
 
   static void GetAnimationsUnsorted(Element* aElement,
                                     PseudoStyleType aPseudoType,
                                     nsTArray<RefPtr<Animation>>& aAnimations);
 
+  void CloneAnimationsFrom(const Element& aOther);
+
   virtual void GetInnerHTML(nsAString& aInnerHTML, OOMReporter& aError);
   virtual void SetInnerHTML(const nsAString& aInnerHTML,
                             nsIPrincipal* aSubjectPrincipal,
                             ErrorResult& aError);
   void GetOuterHTML(nsAString& aOuterHTML);
   void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
   void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
                           ErrorResult& aError);
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -192,17 +192,17 @@ HTMLSlotElement* nsIContent::GetAssigned
   return slot;
 }
 
 nsIContent::IMEState nsIContent::GetDesiredIMEState() {
   if (!IsEditable()) {
     // Check for the special case where we're dealing with elements which don't
     // have the editable flag set, but are readwrite (such as text controls).
     if (!IsElement() ||
-        !AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
+        !AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
       return IMEState(IMEState::DISABLED);
     }
   }
   // NOTE: The content for independent editors (e.g., input[type=text],
   // textarea) must override this method, so, we don't need to worry about
   // that here.
   nsIContent* editableAncestor = GetEditingHost();
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -518,17 +518,17 @@ bool Navigator::CookieEnabled() {
   }
 
   nsCOMPtr<Document> doc = mWindow->GetExtantDoc();
   if (!doc) {
     return cookieEnabled;
   }
 
   nsCOMPtr<nsIURI> contentURI;
-  doc->NodePrincipal()->GetURI(getter_AddRefs(contentURI));
+  BasePrincipal::Cast(doc->NodePrincipal())->GetURI(getter_AddRefs(contentURI));
 
   if (!contentURI) {
     // Not a content, so technically can't set cookies, but let's
     // just return the default value.
     return cookieEnabled;
   }
 
   uint32_t rejectedReason = 0;
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -356,17 +356,17 @@ static bool IsEditorNode(const nsINode* 
     return false;
   }
 
   if (aNode->IsEditable()) {
     return true;
   }
 
   auto* element = Element::FromNode(aNode);
-  return element && element->State().HasState(NS_EVENT_STATE_MOZ_READWRITE);
+  return element && element->State().HasState(NS_EVENT_STATE_READWRITE);
 }
 
 bool Selection::IsEditorSelection() const {
   return IsEditorNode(GetFocusNode());
 }
 
 Nullable<int16_t> Selection::GetCaretBidiLevel(
     mozilla::ErrorResult& aRv) const {
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -173,16 +173,24 @@ class nsDOMNavigationTiming final : publ
     mozilla::TimeDuration duration = aStamp - mNavigationStart;
     return duration.ToMilliseconds();
   }
 
   // Called by the DocumentLoadListener before sending the timing information
   // to the new content process.
   void Anonymize(nsIURI* aFinalURI);
 
+  inline already_AddRefed<nsDOMNavigationTiming> CloneNavigationTime(
+      nsDocShell* aDocShell) const {
+    RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(aDocShell);
+    timing->mNavigationStartHighRes = mNavigationStartHighRes;
+    timing->mNavigationStart = mNavigationStart;
+    return timing.forget();
+  }
+
  private:
   friend class nsDocShell;
   nsDOMNavigationTiming(nsDocShell* aDocShell, nsDOMNavigationTiming* aOther);
   nsDOMNavigationTiming(const nsDOMNavigationTiming&) = delete;
   ~nsDOMNavigationTiming();
 
   void Clear();
 
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -3268,16 +3268,22 @@ already_AddRefed<nsINode> nsINode::Clone
         return nullptr;
       }
     }
   }
 
   if (aDeep && aNode->IsElement()) {
     if (aClone) {
       if (clone->OwnerDoc()->IsStaticDocument()) {
+        // Clone any animations to the node in the static document, including
+        // the current timing. They will need to be paused later after the new
+        // document's pres shell gets initialized.
+        clone->AsElement()->CloneAnimationsFrom(*aNode->AsElement());
+
+        // Clone the Shadow DOM
         ShadowRoot* originalShadowRoot = aNode->AsElement()->GetShadowRoot();
         if (originalShadowRoot) {
           RefPtr<ShadowRoot> newShadowRoot =
               clone->AsElement()->AttachShadowWithoutNameChecks(
                   originalShadowRoot->Mode());
 
           newShadowRoot->CloneInternalDataFrom(originalShadowRoot);
           for (nsIContent* origChild = originalShadowRoot->GetFirstChild();
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -88,16 +88,17 @@ LOCAL_INCLUDES += [
     '/layout/generic',
     '/layout/style',
     '/layout/xul/tree',
     '/media/mtransport',
     '/media/webrtc/',
     '/media/webrtc/signaling/src/common/time_profiling',
     '/media/webrtc/signaling/src/peerconnection',
     '/media/webrtc/trunk/',
+    '/media/webrtc/trunk/webrtc/',
     '/netwerk/base/'
 ]
 
 LOCAL_INCLUDES += ['/third_party/msgpack/include']
 
 DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True
 DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True
 
--- a/dom/canvas/XRWebGLLayer.cpp
+++ b/dom/canvas/XRWebGLLayer.cpp
@@ -254,12 +254,15 @@ void XRWebGLLayer::EndAnimationFrame() {
     mWebGL->SetFramebufferIsInOpaqueRAF(mFramebuffer.get(), false);
   }
 }
 
 HTMLCanvasElement* XRWebGLLayer::GetCanvas() {
   return mWebGL->GetParentObject();
 }
 
-void XRWebGLLayer::SessionEnded() { DeleteFramebuffer(); }
+void XRWebGLLayer::SessionEnded() {
+  DeleteFramebuffer();
+  mWebGL->ClearVRFrame();
+}
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -92,40 +92,16 @@ DOMEventTargetHelper::~DOMEventTargetHel
     mParentObject->RemoveEventTargetObject(this);
   }
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
   ReleaseWrapper(this);
 }
 
-void DOMEventTargetHelper::BindToOwner(nsPIDOMWindowInner* aOwner) {
-  // Make sure to bind via BindToOwner(nsIGlobalObject*) so
-  // subclasses can override the method to perform additional
-  // actions.
-  nsIGlobalObject* global = aOwner ? aOwner->AsGlobal() : nullptr;
-  BindToOwner(global);
-}
-
-void DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner) {
-  BindToOwnerInternal(aOwner);
-}
-
-void DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther) {
-  // Make sure to bind via BindToOwner(nsIGlobalObject*) so
-  // subclasses can override the method to perform additional
-  // actions.
-  if (!aOther) {
-    BindToOwner(static_cast<nsIGlobalObject*>(nullptr));
-    return;
-  }
-  BindToOwner(aOther->GetParentObject());
-  mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
-}
-
 void DOMEventTargetHelper::DisconnectFromOwner() {
   if (mParentObject) {
     mParentObject->RemoveEventTargetObject(this);
   }
   mOwnerWindow = nullptr;
   mParentObject = nullptr;
   // Event listeners can't be handled anymore, so we can release them here.
   if (mListenerManager) {
@@ -290,25 +266,19 @@ void DOMEventTargetHelper::MaybeUpdateKe
 
 void DOMEventTargetHelper::MaybeDontKeepAlive() {
   if (mIsKeptAlive) {
     mIsKeptAlive = false;
     Release();
   }
 }
 
-void DOMEventTargetHelper::BindToOwnerInternal(nsIGlobalObject* aOwner) {
-  if (mParentObject) {
-    mParentObject->RemoveEventTargetObject(this);
-    if (mOwnerWindow) {
-      mOwnerWindow = nullptr;
-    }
-    mParentObject = nullptr;
-    mHasOrHasHadOwnerWindow = false;
-  }
+void DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner) {
+  MOZ_ASSERT(!mParentObject);
+
   if (aOwner) {
     mParentObject = aOwner;
     aOwner->AddEventTargetObject(this);
     // Let's cache the result of this QI for fast access and off main thread
     // usage
     mOwnerWindow =
         nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
     if (mOwnerWindow) {
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -43,42 +43,36 @@ class DOMEventTargetHelper : public dom:
         mOwnerWindow(nullptr),
         mHasOrHasHadOwnerWindow(false),
         mIsKeptAlive(false) {}
   explicit DOMEventTargetHelper(nsPIDOMWindowInner* aWindow)
       : mParentObject(nullptr),
         mOwnerWindow(nullptr),
         mHasOrHasHadOwnerWindow(false),
         mIsKeptAlive(false) {
-    // Be careful not to call the virtual BindToOwner() in a
-    // constructor.
     nsIGlobalObject* global = aWindow ? aWindow->AsGlobal() : nullptr;
-    BindToOwnerInternal(global);
+    BindToOwner(global);
   }
   explicit DOMEventTargetHelper(nsIGlobalObject* aGlobalObject)
       : mParentObject(nullptr),
         mOwnerWindow(nullptr),
         mHasOrHasHadOwnerWindow(false),
         mIsKeptAlive(false) {
-    // Be careful not to call the virtual BindToOwner() in a
-    // constructor.
-    BindToOwnerInternal(aGlobalObject);
+    BindToOwner(aGlobalObject);
   }
   explicit DOMEventTargetHelper(DOMEventTargetHelper* aOther)
       : mParentObject(nullptr),
         mOwnerWindow(nullptr),
         mHasOrHasHadOwnerWindow(false),
         mIsKeptAlive(false) {
-    // Be careful not to call the virtual BindToOwner() in a
-    // constructor.
     if (!aOther) {
-      BindToOwnerInternal(static_cast<nsIGlobalObject*>(nullptr));
+      BindToOwner(static_cast<nsIGlobalObject*>(nullptr));
       return;
     }
-    BindToOwnerInternal(aOther->GetParentObject());
+    BindToOwner(aOther->GetParentObject());
     mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(DOMEventTargetHelper)
 
   virtual EventListenerManager* GetExistingListenerManager() const override;
   virtual EventListenerManager* GetOrCreateListenerManager() override;
@@ -146,29 +140,16 @@ class DOMEventTargetHelper : public dom:
   nsPIDOMWindowInner* GetOwner() const { return mOwnerWindow; }
   // Like GetOwner, but only returns non-null if the window being returned is
   // current (in the "current document" sense of the HTML spec).
   nsPIDOMWindowInner* GetWindowIfCurrent() const;
   // Returns the document associated with this event target, if that document is
   // the current document of its browsing context.  Will return null otherwise.
   mozilla::dom::Document* GetDocumentIfCurrent() const;
 
-  // DETH subclasses may override the BindToOwner(nsIGlobalObject*) method
-  // to take action when dynamically binding to a new global.  This is only
-  // called on rebind since virtual methods cannot be called from the
-  // constructor.  The other BindToOwner() methods will call into this
-  // method.
-  //
-  // NOTE: Any overrides of BindToOwner() *must* invoke
-  //       DOMEventTargetHelper::BindToOwner(aOwner).
-  virtual void BindToOwner(nsIGlobalObject* aOwner);
-
-  void BindToOwner(nsPIDOMWindowInner* aOwner);
-  void BindToOwner(DOMEventTargetHelper* aOther);
-
   virtual void DisconnectFromOwner();
   using EventTarget::GetParentObject;
   nsIGlobalObject* GetOwnerGlobal() const final { return mParentObject; }
   bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
 
   virtual void EventListenerAdded(nsAtom* aType) override;
 
   virtual void EventListenerRemoved(nsAtom* aType) override;
@@ -196,17 +177,17 @@ class DOMEventTargetHelper : public dom:
   virtual void LastRelease() {}
 
   void KeepAliveIfHasListenersFor(const nsAString& aType);
   void KeepAliveIfHasListenersFor(nsAtom* aType);
 
   void IgnoreKeepAliveIfHasListenersFor(const nsAString& aType);
   void IgnoreKeepAliveIfHasListenersFor(nsAtom* aType);
 
-  void BindToOwnerInternal(nsIGlobalObject* aOwner);
+  void BindToOwner(nsIGlobalObject* aOwner);
 
  private:
   // The parent global object.  The global will clear this when
   // it is destroyed by calling DisconnectFromOwner().
   nsIGlobalObject* MOZ_NON_OWNING_REF mParentObject;
   // mParentObject pre QI-ed and cached (inner window)
   // (it is needed for off main thread access)
   // It is obtained in BindToOwner and reset in DisconnectFromOwner.
--- a/dom/events/EventStates.h
+++ b/dom/events/EventStates.h
@@ -223,21 +223,22 @@ class EventStates {
 // Link hasn't been visited.
 #define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(25)
 // Drag is hovering over content.
 #define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(26)
 // Content value is in-range (and can be out-of-range).
 #define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(27)
 // Content value is out-of-range.
 #define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(28)
-// These two are temporary (see bug 302188)
 // Content is read-only.
-#define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(29)
+// TODO(emilio): This is always the inverse of READWRITE. With some style system
+// work we could remove one of the two bits.
+#define NS_EVENT_STATE_READONLY NS_DEFINE_EVENT_STATE_MACRO(29)
 // Content is editable.
-#define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(30)
+#define NS_EVENT_STATE_READWRITE NS_DEFINE_EVENT_STATE_MACRO(30)
 // Content is the default one (meaning depends of the context).
 #define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(31)
 // Content is a submit control and the form isn't valid.
 #define NS_EVENT_STATE_MOZ_SUBMITINVALID NS_DEFINE_EVENT_STATE_MACRO(32)
 // Content is in the optimum region.
 #define NS_EVENT_STATE_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(33)
 // Content is in the suboptimal region.
 #define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(34)
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -1737,17 +1737,17 @@ nsresult IMEStateManager::NotifyIME(IMEM
 
 // static
 bool IMEStateManager::IsEditable(nsINode* node) {
   if (node->IsEditable()) {
     return true;
   }
   // |node| might be readwrite (for example, a text control)
   if (node->IsElement() &&
-      node->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
+      node->AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
     return true;
   }
   return false;
 }
 
 // static
 nsINode* IMEStateManager::GetRootEditableNode(nsPresContext* aPresContext,
                                               nsIContent* aContent) {
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1972,20 +1972,20 @@ EventStates nsGenericHTMLFormElement::In
   if (mForm && mForm->IsDefaultSubmitElement(this)) {
     NS_ASSERTION(IsSubmitControl(),
                  "Default submit element that isn't a submit control.");
     // We are the default submit element (:default)
     state |= NS_EVENT_STATE_DEFAULT;
   }
 
   // Make the text controls read-write
-  if (!state.HasState(NS_EVENT_STATE_MOZ_READWRITE) && DoesReadOnlyApply()) {
+  if (!state.HasState(NS_EVENT_STATE_READWRITE) && DoesReadOnlyApply()) {
     if (!GetBoolAttr(nsGkAtoms::readonly) && !IsDisabled()) {
-      state |= NS_EVENT_STATE_MOZ_READWRITE;
-      state &= ~NS_EVENT_STATE_MOZ_READONLY;
+      state |= NS_EVENT_STATE_READWRITE;
+      state &= ~NS_EVENT_STATE_READONLY;
     }
   }
 
   return state;
 }
 
 nsGenericHTMLFormElement::FocusTristate nsGenericHTMLFormElement::FocusState() {
   // We can't be focused if we aren't in a (composed) document
--- a/dom/html/test/test_bug1264157.html
+++ b/dom/html/test/test_bug1264157.html
@@ -40,19 +40,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <input type="number" value=11 min=0 max=10 readonly> Read-only out-of-range
 </div>
 <pre id="test">
 <script type="text/javascript">
 
 /** Test for Bug 1264157 **/
 SimpleTest.waitForFocus(function() {
   // Check the initial values.
-  let active = [].slice.call(document.querySelectorAll("input:not(:disabled):not(:-moz-read-only)"));
+  let active = [].slice.call(document.querySelectorAll("input:not(:disabled):not(:read-only)"));
   let disabled = [].slice.call(document.querySelectorAll("input:disabled"));
-  let readonly = [].slice.call(document.querySelectorAll("input:-moz-read-only:not(:disabled)"));
+  let readonly = [].slice.call(document.querySelectorAll("input:read-only:not(:disabled)"));
   ok(active.length == 2, "Test is messed up: missing non-disabled/non-readonly inputs");
   ok(disabled.length == 2, "Test is messed up: missing disabled inputs");
   ok(readonly.length == 2, "Test is messed up: missing readonly inputs");
 
   is(document.querySelectorAll("input:in-range").length, 1,
      "Wrong number of in-range elements selected.");
   is(document.querySelectorAll("input:out-of-range").length, 1,
      "Wrong number of out-of-range elements selected.");
--- a/dom/l10n/DOMLocalization.cpp
+++ b/dom/l10n/DOMLocalization.cpp
@@ -213,18 +213,19 @@ class ElementTranslationHandler : public
           if (!slotPtr->SetValue().Init(aCx, temp)) {
             mReturnValuePromise->MaybeRejectWithUndefined();
             return;
           }
         }
       }
     }
 
-    mDOMLocalization->ApplyTranslations(mElements, l10nData, mProto, rv);
-    if (NS_WARN_IF(rv.Failed())) {
+    bool allTranslated =
+        mDOMLocalization->ApplyTranslations(mElements, l10nData, mProto, rv);
+    if (NS_WARN_IF(rv.Failed()) || !allTranslated) {
       mReturnValuePromise->MaybeRejectWithUndefined();
       return;
     }
 
     mReturnValuePromise->MaybeResolveWithUndefined();
   }
 
   virtual void RejectedCallback(JSContext* aCx,
@@ -314,18 +315,19 @@ already_AddRefed<Promise> DOMLocalizatio
     return nullptr;
   }
 
   if (mIsSync) {
     nsTArray<Nullable<L10nMessage>> l10nMessages;
 
     FormatMessagesSync(cx, l10nKeys, l10nMessages, aRv);
 
-    ApplyTranslations(domElements, l10nMessages, aProto, aRv);
-    if (NS_WARN_IF(aRv.Failed())) {
+    bool allTranslated =
+        ApplyTranslations(domElements, l10nMessages, aProto, aRv);
+    if (NS_WARN_IF(aRv.Failed()) || !allTranslated) {
       promise->MaybeRejectWithUndefined();
       return MaybeWrapPromise(promise);
     }
 
     promise->MaybeResolveWithUndefined();
   } else {
     RefPtr<Promise> callbackResult = FormatMessages(cx, l10nKeys, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
@@ -438,58 +440,63 @@ void DOMLocalization::SetRootInfo(Elemen
 
   uint32_t nameSpace = aElement->GetNameSpaceID();
   nsAtom* dirAtom =
       nameSpace == kNameSpaceID_XUL ? nsGkAtoms::localedir : nsGkAtoms::dir;
 
   aElement->SetAttr(kNameSpaceID_None, dirAtom, dir, true);
 }
 
-void DOMLocalization::ApplyTranslations(
+bool DOMLocalization::ApplyTranslations(
     nsTArray<nsCOMPtr<Element>>& aElements,
     nsTArray<Nullable<L10nMessage>>& aTranslations,
     nsXULPrototypeDocument* aProto, ErrorResult& aRv) {
   if (aElements.Length() != aTranslations.Length()) {
     aRv.Throw(NS_ERROR_FAILURE);
-    return;
+    return false;
   }
 
   PauseObserving(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     aRv.Throw(NS_ERROR_FAILURE);
-    return;
+    return false;
   }
 
+  bool hasMissingTranslation = false;
+
   nsTArray<L10nOverlaysError> errors;
   for (size_t i = 0; i < aTranslations.Length(); ++i) {
     Element* elem = aElements[i];
     if (aTranslations[i].IsNull()) {
+      hasMissingTranslation = true;
       continue;
     }
     L10nOverlays::TranslateElement(*elem, aTranslations[i].Value(), errors,
                                    aRv);
     if (NS_WARN_IF(aRv.Failed())) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
+      hasMissingTranslation = true;
+      continue;
     }
     if (aProto) {
       // We only need to rebuild deep if the translation has a value.
       // Otherwise we'll only rebuild the attributes.
       aProto->RebuildL10nPrototype(elem,
                                    !aTranslations[i].Value().mValue.IsVoid());
     }
   }
 
+  ReportL10nOverlaysErrors(errors);
+
   ResumeObserving(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     aRv.Throw(NS_ERROR_FAILURE);
-    return;
+    return false;
   }
 
-  ReportL10nOverlaysErrors(errors);
+  return !hasMissingTranslation;
 }
 
 /* Protected */
 
 void DOMLocalization::OnChange() {
   Localization::OnChange();
   if (mLocalization) {
     ErrorResult rv;
--- a/dom/l10n/DOMLocalization.h
+++ b/dom/l10n/DOMLocalization.h
@@ -79,18 +79,21 @@ class DOMLocalization : public intl::Loc
    */
   static void SetRootInfo(Element* aElement);
 
   /**
    * Applies l10n translations on translatable elements.
    *
    * If `aProto` gets passed, it'll be used to cache
    * the localized elements.
+   *
+   * Result is `true` if all translations were applied
+   * successfully, and `false` otherwise.
    */
-  void ApplyTranslations(nsTArray<nsCOMPtr<Element>>& aElements,
+  bool ApplyTranslations(nsTArray<nsCOMPtr<Element>>& aElements,
                          nsTArray<Nullable<L10nMessage>>& aTranslations,
                          nsXULPrototypeDocument* aProto, ErrorResult& aRv);
 
   bool SubtreeRootInRoots(nsINode* aSubtreeRoot) {
     for (auto iter = mRoots.Iter(); !iter.Done(); iter.Next()) {
       nsINode* subtreeRoot = iter.Get()->GetKey()->SubtreeRoot();
       if (subtreeRoot == aSubtreeRoot) {
         return true;
--- a/dom/l10n/DocumentL10n.cpp
+++ b/dom/l10n/DocumentL10n.cpp
@@ -88,22 +88,22 @@ class L10nReadyHandler final : public Pr
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(L10nReadyHandler)
 
   explicit L10nReadyHandler(Promise* aPromise, DocumentL10n* aDocumentL10n)
       : mPromise(aPromise), mDocumentL10n(aDocumentL10n) {}
 
   void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
-    mDocumentL10n->InitialTranslationCompleted();
+    mDocumentL10n->InitialTranslationCompleted(true);
     mPromise->MaybeResolveWithUndefined();
   }
 
   void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
-    mDocumentL10n->InitialTranslationCompleted();
+    mDocumentL10n->InitialTranslationCompleted(false);
     mPromise->MaybeRejectWithUndefined();
   }
 
  private:
   ~L10nReadyHandler() = default;
 
   RefPtr<Promise> mPromise;
   RefPtr<DocumentL10n> mDocumentL10n;
@@ -123,42 +123,42 @@ void DocumentL10n::TriggerInitialTransla
     return;
   }
 
   nsTArray<RefPtr<Promise>> promises;
 
   ErrorResult rv;
   promises.AppendElement(TranslateDocument(rv));
   if (NS_WARN_IF(rv.Failed())) {
-    InitialTranslationCompleted();
+    InitialTranslationCompleted(false);
     mReady->MaybeRejectWithUndefined();
     return;
   }
   promises.AppendElement(TranslateRoots(rv));
   Element* documentElement = mDocument->GetDocumentElement();
   if (!documentElement) {
-    InitialTranslationCompleted();
+    InitialTranslationCompleted(false);
     mReady->MaybeRejectWithUndefined();
     return;
   }
 
   DOMLocalization::ConnectRoot(*documentElement, rv);
   if (NS_WARN_IF(rv.Failed())) {
-    InitialTranslationCompleted();
+    InitialTranslationCompleted(false);
     mReady->MaybeRejectWithUndefined();
     return;
   }
 
   AutoEntryScript aes(mGlobal, "DocumentL10n InitialTranslation");
   RefPtr<Promise> promise = Promise::All(aes.cx(), promises, rv);
 
   if (promise->State() == Promise::PromiseState::Resolved) {
     // If the promise is already resolved, we can fast-track
     // to initial translation completed.
-    InitialTranslationCompleted();
+    InitialTranslationCompleted(true);
     mReady->MaybeResolveWithUndefined();
   } else {
     RefPtr<PromiseNativeHandler> l10nReadyHandler =
         new L10nReadyHandler(mReady, this);
     promise->AppendNativeHandler(l10nReadyHandler);
 
     mState = DocumentL10nState::InitialTranslationTriggered;
   }
@@ -253,29 +253,29 @@ already_AddRefed<Promise> DocumentL10n::
   if (NS_WARN_IF(!promise || aRv.Failed())) {
     promise->MaybeRejectWithUndefined();
     return promise.forget();
   }
 
   return promise.forget();
 }
 
-void DocumentL10n::InitialTranslationCompleted() {
+void DocumentL10n::InitialTranslationCompleted(bool aL10nCached) {
   if (mState >= DocumentL10nState::Ready) {
     return;
   }
 
   Element* documentElement = mDocument->GetDocumentElement();
   if (documentElement) {
     SetRootInfo(documentElement);
   }
 
   mState = DocumentL10nState::Ready;
 
-  mDocument->InitialTranslationCompleted();
+  mDocument->InitialTranslationCompleted(aL10nCached);
 
   // In XUL scenario contentSink is nullptr.
   if (mContentSink) {
     mContentSink->InitialTranslationCompleted();
   }
 
   // If sync was true, we want to change the state of
   // mozILocalization to async now.
--- a/dom/l10n/DocumentL10n.h
+++ b/dom/l10n/DocumentL10n.h
@@ -66,17 +66,17 @@ class DocumentL10n final : public DOMLoc
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   Promise* Ready();
 
   void TriggerInitialTranslation();
   already_AddRefed<Promise> TranslateDocument(ErrorResult& aRv);
 
-  void InitialTranslationCompleted();
+  void InitialTranslationCompleted(bool aL10nCached);
 
   Document* GetDocument() { return mDocument; };
   void OnCreatePresShell();
 
   void ConnectRoot(nsINode& aNode, bool aTranslate, ErrorResult& aRv);
 
   DocumentL10nState GetState() { return mState; };
 
--- a/dom/media/AutoplayPolicy.cpp
+++ b/dom/media/AutoplayPolicy.cpp
@@ -28,16 +28,20 @@
 mozilla::LazyLogModule gAutoplayPermissionLog("Autoplay");
 
 #define AUTOPLAY_LOG(msg, ...) \
   MOZ_LOG(gAutoplayPermissionLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
 
 namespace mozilla {
 namespace dom {
 
+static const uint32_t sPOLICY_STICKY_ACTIVATION = 0;
+static const uint32_t sPOLICY_TRANSIENT_ACTIVATION = 1;
+static const uint32_t sPOLICY_USER_INPUT_DEPTH = 2;
+
 static Document* ApproverDocOf(const Document& aDocument) {
   nsCOMPtr<nsIDocShell> ds = aDocument.GetDocShell();
   if (!ds) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   ds->GetInProcessSameTypeRootTreeItem(getter_AddRefs(rootTreeItem));
@@ -156,25 +160,43 @@ static bool IsMediaElementInaudible(cons
 static bool IsAudioContextAllowedToPlay(const AudioContext& aContext) {
   // Offline context won't directly output sound to audio devices.
   return aContext.IsOffline() ||
          IsWindowAllowedToPlay(aContext.GetParentObject());
 }
 
 static bool IsEnableBlockingWebAudioByUserGesturePolicy() {
   return Preferences::GetBool("media.autoplay.block-webaudio", false) &&
-         StaticPrefs::media_autoplay_enabled_user_gestures_needed();
+         StaticPrefs::media_autoplay_blocking_policy() ==
+             sPOLICY_STICKY_ACTIVATION;
 }
 
 static bool IsAllowedToPlayByBlockingModel(const HTMLMediaElement& aElement) {
-  if (!StaticPrefs::media_autoplay_enabled_user_gestures_needed()) {
-    // If element is blessed, it would always be allowed to play().
-    return aElement.IsBlessed() || UserActivation::IsHandlingUserInput();
+  const uint32_t policy = StaticPrefs::media_autoplay_blocking_policy();
+  if (policy == sPOLICY_STICKY_ACTIVATION) {
+    const bool isAllowed =
+        IsWindowAllowedToPlay(aElement.OwnerDoc()->GetInnerWindow());
+    AUTOPLAY_LOG("Use 'sticky-activation', isAllowed=%d", isAllowed);
+    return isAllowed;
   }
-  return IsWindowAllowedToPlay(aElement.OwnerDoc()->GetInnerWindow());
+  // If element is blessed, it would always be allowed to play().
+  const bool isElementBlessed = aElement.IsBlessed();
+  if (policy == sPOLICY_USER_INPUT_DEPTH) {
+    const bool isUserInput = UserActivation::IsHandlingUserInput();
+    AUTOPLAY_LOG("Use 'User-Input-Depth', isBlessed=%d, isUserInput=%d",
+                 isElementBlessed, isUserInput);
+    return isElementBlessed || isUserInput;
+  }
+  const bool hasTransientActivation =
+      aElement.OwnerDoc()->HasValidTransientUserGestureActivation();
+  AUTOPLAY_LOG(
+      "Use 'transient-activation', isBlessed=%d, "
+      "hasValidTransientActivation=%d",
+      isElementBlessed, hasTransientActivation);
+  return isElementBlessed || hasTransientActivation;
 }
 
 // On GeckoView, we don't store any site's permission in permission manager, we
 // would check the GV request status to know if the site can be allowed to play.
 // But on other platforms, we would store the site's permission in permission
 // manager.
 #if defined(MOZ_WIDGET_ANDROID)
 using RType = GVAutoplayRequestType;
--- a/dom/media/FrameStatistics.h
+++ b/dom/media/FrameStatistics.h
@@ -110,26 +110,33 @@ class FrameStatistics {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData.mPresentedFrames;
   }
 
   // Returns the number of presented and dropped frames
   // Can be called on any thread.
   uint64_t GetTotalFrames() const {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    return mFrameStatisticsData.mPresentedFrames + GetDroppedFrames();
+    return GetTotalFrames(mFrameStatisticsData);
+  }
+
+  static uint64_t GetTotalFrames(const FrameStatisticsData& aData) {
+    return aData.mPresentedFrames + GetDroppedFrames(aData);
   }
 
   // Returns the number of frames that have been skipped because they have
   // missed their composition deadline.
   uint64_t GetDroppedFrames() const {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    return mFrameStatisticsData.mDroppedDecodedFrames +
-           mFrameStatisticsData.mDroppedSinkFrames +
-           mFrameStatisticsData.mDroppedCompositorFrames;
+    return GetDroppedFrames(mFrameStatisticsData);
+  }
+
+  static uint64_t GetDroppedFrames(const FrameStatisticsData& aData) {
+    return aData.mDroppedDecodedFrames + aData.mDroppedSinkFrames +
+           aData.mDroppedCompositorFrames;
   }
 
   // Increments the parsed and decoded frame counters by the passed in counts.
   // Can be called on any thread.
   void Accumulate(const FrameStatisticsData& aStats) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     mFrameStatisticsData.Accumulate(aStats);
   }
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -661,33 +661,35 @@ class MediaDecoderStateMachine::Decoding
 
   // At the start of decoding we want to "preroll" the decode until we've
   // got a few frames decoded before we consider whether decode is falling
   // behind. Otherwise our "we're falling behind" logic will trigger
   // unnecessarily if we start playing as soon as the first sample is
   // decoded. These two fields store how many video frames and audio
   // samples we must consume before are considered to be finished prerolling.
   TimeUnit AudioPrerollThreshold() const {
-    return mMaster->mAmpleAudioThreshold / 2;
+    return (mMaster->mAmpleAudioThreshold / 2)
+        .MultDouble(mMaster->mPlaybackRate);
   }
 
   uint32_t VideoPrerollFrames() const {
-    return mMaster->GetAmpleVideoFrames() / 2;
+    return std::min<uint32_t>(
+        (mMaster->GetAmpleVideoFrames() / 2) * mMaster->mPlaybackRate + 1,
+        sVideoQueueDefaultSize);
   }
 
   bool DonePrerollingAudio() {
     return !mMaster->IsAudioDecoding() ||
-           mMaster->GetDecodedAudioDuration() >=
-               AudioPrerollThreshold().MultDouble(mMaster->mPlaybackRate);
+           mMaster->GetDecodedAudioDuration() >= AudioPrerollThreshold();
   }
 
   bool DonePrerollingVideo() {
     return !mMaster->IsVideoDecoding() ||
            static_cast<uint32_t>(mMaster->VideoQueue().GetSize()) >=
-               VideoPrerollFrames() * mMaster->mPlaybackRate + 1;
+               VideoPrerollFrames();
   }
 
   void MaybeStopPrerolling() {
     if (mIsPrerolling &&
         (DonePrerollingAudio() || mMaster->IsWaitingAudioData()) &&
         (DonePrerollingVideo() || mMaster->IsWaitingVideoData())) {
       mIsPrerolling = false;
       // Check if we can start playback.
--- a/dom/media/MediaTrackGraph.cpp
+++ b/dom/media/MediaTrackGraph.cpp
@@ -1724,19 +1724,19 @@ void MediaTrackGraphImpl::RunInStableSta
         MessageBlock* block = mBackMessageQueue.AppendElement();
         block->mMessages.SwapElements(mCurrentTaskMessageQueue);
         EnsureNextIteration();
       }
 
       // If this MediaTrackGraph has entered regular (non-forced) shutdown it
       // is not able to process any more messages. Those messages being added to
       // the graph in the first place is an error.
-      MOZ_DIAGNOSTIC_ASSERT(mForceShutDown ||
-                            LifecycleStateRef() <
-                                LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP);
+      MOZ_DIAGNOSTIC_ASSERT(LifecycleStateRef() <
+                                LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP ||
+                            mForceShutDown);
     }
 
     if (LifecycleStateRef() == LIFECYCLE_THREAD_NOT_STARTED) {
       // Start the driver now. We couldn't start it earlier because the graph
       // might exit immediately on finding it has no tracks. The first message
       // for a new graph must create a track. Ensure that his message runs on
       // the first iteration.
       MOZ_ASSERT(MessagesQueued());
--- a/dom/media/bridge/moz.build
+++ b/dom/media/bridge/moz.build
@@ -19,16 +19,17 @@ LOCAL_INCLUDES += [
     '/media/mtransport',
     '/media/mtransport',
     '/media/webrtc/',
     '/media/webrtc/signaling/src/common/time_profiling',
     '/media/webrtc/signaling/src/media-conduit',
     '/media/webrtc/signaling/src/mediapipeline',
     '/media/webrtc/signaling/src/peerconnection',
     '/media/webrtc/trunk/',
+    '/media/webrtc/trunk/webrtc/',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     XPCOM_MANIFESTS += [
         'components.conf',
     ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/media/mediacapabilities/DecoderBenchmark.cpp
+++ b/dom/media/mediacapabilities/DecoderBenchmark.cpp
@@ -9,18 +9,19 @@
 #include "mozilla/media/MediaUtils.h"
 #include "mozilla/StaticPrefs_media.h"
 
 namespace mozilla {
 
 void DecoderBenchmark::StoreScore(const nsACString& aDecoderName,
                                   const nsACString& aKey,
                                   RefPtr<FrameStatistics> aStats) {
-  uint64_t totalFrames = aStats->GetTotalFrames();
-  uint64_t droppedFrames = aStats->GetDroppedFrames();
+  FrameStatisticsData statsData = aStats->GetFrameStatisticsData();
+  uint64_t totalFrames = FrameStatistics::GetTotalFrames(statsData);
+  uint64_t droppedFrames = FrameStatistics::GetDroppedFrames(statsData);
 
   MOZ_ASSERT(droppedFrames <= totalFrames);
   MOZ_ASSERT(totalFrames >= mLastTotalFrames);
   MOZ_ASSERT(droppedFrames >= mLastDroppedFrames);
 
   uint64_t diffTotalFrames = totalFrames - mLastTotalFrames;
   uint64_t diffDroppedFrames = droppedFrames - mLastDroppedFrames;
 
--- a/dom/media/test/test_autoplay_policy.html
+++ b/dom/media/test/test_autoplay_policy.html
@@ -10,17 +10,17 @@
 <body>
 <pre id="test">
 
 <script>
 
 let manager = new MediaTestManager;
 
 gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-                ["media.autoplay.enabled.user-gestures-needed", true]);
+                ["media.autoplay.blocking_policy", 0]);
 
 window.info = function(msg, token) {
   SimpleTest.info(msg + ", token=" + token);
 }
 
 window.is = function(valA, valB, msg, token) {
   SimpleTest.is(valA, valB, msg + ", token=" + token);
 }
@@ -73,17 +73,17 @@ function createTestArray()
   }
   return tests;
 }
 
 /**
  * Main test function for different autoplay cases without user interaction.
  *
  * When the pref "media.autoplay.default" is 1 and the pref
- * "media.autoplay.enabled.user-gestures-needed" is true, we only allow
+ * "media.autoplay.blocking_policy" is 0, we only allow
  * audible media to autoplay after the website has been activated by specific
  * user gestures. However, inaudible media won't be restricted.
  *
  * Audible means the volume is not zero, or muted is not true for the video with
  * audio track. For media without loading metadata, we can't know whether it has
  * audio track or not, so we would also regard it as audible media.
  *
  * Inaudible means the volume is zero, or the muted is true, or the video without
--- a/dom/media/test/test_autoplay_policy_activation.html
+++ b/dom/media/test/test_autoplay_policy_activation.html
@@ -10,17 +10,17 @@
   <body>
     <pre id="test">
       <script>
 
         // Tests that videos can only play audibly in windows/frames
         // which have been activated by same-origin user gesture.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-                        ["media.autoplay.enabled.user-gestures-needed", true]);
+                        ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({'set': gTestPrefs}, () => {
           runTest();
         });
 
         let test_cases = [
           {
             name: "inaudible playback in unactivated same-origin iframe in activated parent -> allowed",
--- a/dom/media/test/test_autoplay_policy_eventdown_activation.html
+++ b/dom/media/test/test_autoplay_policy_eventdown_activation.html
@@ -11,17 +11,17 @@
 
 <body>
   <pre id="test">
       <script>
 
         // Tests that we gesture activate on mousedown and keydown.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-          ["media.autoplay.enabled.user-gestures-needed", true]);
+          ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
           runTest();
         });
 
         let child_url = "file_autoplay_policy_eventdown_activation.html";
 
         async function runTest() {
--- a/dom/media/test/test_autoplay_policy_key_blacklist.html
+++ b/dom/media/test/test_autoplay_policy_key_blacklist.html
@@ -14,17 +14,17 @@
       <script>
 
         // Tests that keypresses for non-printable characters,
         // and mouse/keyboard interaction with editable elements,
         // don't gesture activate documents, and don't unblock
         // audible autoplay.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-          ["media.autoplay.enabled.user-gestures-needed", true]);
+          ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
           runTest();
         });
 
         let child_url = "file_autoplay_policy_key_blacklist.html";
 
         async function runTest() {
--- a/dom/media/test/test_autoplay_policy_permission.html
+++ b/dom/media/test/test_autoplay_policy_permission.html
@@ -11,17 +11,17 @@
 
 <body>
   <pre id="test">
       <script>
 
         // Tests that origins with "autoplay-media" permission can autoplay.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-          ["media.autoplay.enabled.user-gestures-needed", true]);
+          ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
           runTest();
         });
 
         async function testPlayInOrigin(testCase) {
           // Run test in a new window, to ensure its user gesture
           // activation state isn't tainted by preceeding tests.
--- a/dom/media/test/test_autoplay_policy_play_before_loadedmetadata.html
+++ b/dom/media/test/test_autoplay_policy_play_before_loadedmetadata.html
@@ -15,17 +15,17 @@
 
         window.is = SimpleTest.is;
         window.info = SimpleTest.info;
 
         // Tests that videos which have no audio track will play if play()
         // is called before the video has reached readyState >= HAVE_METADATA.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-          ["media.autoplay.enabled.user-gestures-needed", true]);
+          ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
           runTest();
         });
 
         let testCases = [
           {
             resource: "320x240.ogv", // Only video track.
--- a/dom/media/test/test_autoplay_policy_unmute_pauses.html
+++ b/dom/media/test/test_autoplay_policy_unmute_pauses.html
@@ -15,17 +15,17 @@
 
         window.is = SimpleTest.is;
         window.info = SimpleTest.info;
 
         // Tests that videos can only play audibly in windows/frames
         // which have been activated by same-origin user gesture.
 
         gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-          ["media.autoplay.enabled.user-gestures-needed", true]);
+          ["media.autoplay.blocking_policy", 0]);
 
         SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
           runTest();
         });
 
         let testCases = [
           {
             property: "muted",
--- a/dom/media/test/test_autoplay_policy_web_audio_AudioParamStream.html
+++ b/dom/media/test/test_autoplay_policy_web_audio_AudioParamStream.html
@@ -39,17 +39,17 @@ SimpleTest.waitForExplicitFinish();
 
 /**
  * Test utility functions
  */
 
 function setupTestPreferences() {
   return SpecialPowers.pushPrefEnv({"set": [
     ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-    ["media.autoplay.enabled.user-gestures-needed", true],
+    ["media.autoplay.blocking_policy", 0],
     ["media.autoplay.block-webaudio", true],
     ["media.autoplay.block-event.enabled", true],
   ]});
 }
 
 function createAudioContext() {
   /* global ac */
   window.ac = new AudioContext();
--- a/dom/media/test/test_autoplay_policy_web_audio_createMediaStreamSource.html
+++ b/dom/media/test/test_autoplay_policy_web_audio_createMediaStreamSource.html
@@ -34,17 +34,17 @@ SimpleTest.waitForExplicitFinish();
 
 /**
  * Test utility functions
  */
 
 function setupTestPreferences() {
   return SpecialPowers.pushPrefEnv({"set": [
     ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-    ["media.autoplay.enabled.user-gestures-needed", true],
+    ["media.autoplay.blocking_policy", 0],
     ["media.autoplay.block-webaudio", true],
     ["media.autoplay.block-event.enabled", true],
   ]});
 }
 
 function createAudioContexts() {
   /* global ac1, ac2 */
   window.ac1 = new AudioContext();
--- a/dom/media/test/test_autoplay_policy_web_audio_mediaElementAudioSourceNode.html
+++ b/dom/media/test/test_autoplay_policy_web_audio_mediaElementAudioSourceNode.html
@@ -37,17 +37,17 @@ SimpleTest.waitForExplicitFinish();
 
 /**
  * Test utility functions
  */
 
 function setupTestPreferences() {
   return SpecialPowers.pushPrefEnv({"set": [
     ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-    ["media.autoplay.enabled.user-gestures-needed", true],
+    ["media.autoplay.blocking_policy", 0],
     ["media.autoplay.block-webaudio", true],
     ["media.autoplay.block-event.enabled", true],
   ]});
 }
 
 function createAudioContext() {
   /* global ac */
   window.ac = new AudioContext();
--- a/dom/media/test/test_autoplay_policy_web_audio_notResumePageInvokedSuspendedAudioContext.html
+++ b/dom/media/test/test_autoplay_policy_web_audio_notResumePageInvokedSuspendedAudioContext.html
@@ -37,17 +37,17 @@ SimpleTest.waitForExplicitFinish();
 
 /**
  * Test utility functions
  */
 
 function setupTestPreferences() {
   return SpecialPowers.pushPrefEnv({"set": [
     ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-    ["media.autoplay.enabled.user-gestures-needed", true],
+    ["media.autoplay.blocking_policy", 0],
     ["media.autoplay.block-webaudio", true],
     ["media.autoplay.block-event.enabled", true],
   ]});
 }
 
 async function createAudioContext() {
   /* global ac */
   window.ac = new AudioContext();
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -290,8 +290,9 @@ scheme=http
 [test_peerConnection_nonDefaultRate.html]
 [test_forceSampleRate.html]
 scheme=http
 [test_peerConnection_bug1512281.html]
 fail-if = 1
 [test_setSinkId.html]
 skip-if = os != 'linux' # the only platform with real devices
 [test_peerConnection_telephoneEventFirst.html]
+[test_peerConnection_rtcp_rsize.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_rtcp_rsize.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="pc.js"></script>
+  <script type="application/javascript" src="sdpUtils.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1279153",
+    title: "rtcp-rsize",
+    visible: true
+  });
+
+  // 0) Use webrtc-sdp
+  // 1) ADD RTCP-RISZE to all video m-sections
+  // 2) Check for RTCP-RSIZE in ANSWER
+  // 3) Wait for media to flow
+  // 4) Wait for RTCP stats
+
+  var test;
+  runNetworkTest(async function (options) {
+    // rtcp-rsize is only implemented for webrtc-sdp
+    await SpecialPowers.pushPrefEnv({set: [["media.peerconnection.sdp.parser", "webrtc-sdp"]]});
+
+    test = new PeerConnectionTest(options);
+
+    var mSectionsAltered = 0;
+
+    test.chain.insertAfter("PC_LOCAL_CREATE_OFFER", [
+      function PC_LOCAL_ADD_RTCP_RSIZE(test) {
+        const lines = test.originalOffer.sdp.split("\r\n");
+        info(`SDP before rtcp-rsize: ${lines.join('\n')}`);
+        // Insert an rtcp-rsize for each m section
+        const rsizeAdded = lines.flatMap(line => {
+          if (line.startsWith("m=video")) {
+            mSectionsAltered = mSectionsAltered + 1;
+            return [line, "a=rtcp-rsize"];
+          }
+          return [line];
+        });
+        test.originalOffer.sdp = rsizeAdded.join("\r\n");
+        info(`SDP with rtcp-rsize: ${rsizeAdded.join("\n")}`);
+        is(mSectionsAltered, 1, "We only altered 1 msection")
+    }]);
+
+    // Check that the rtcp-rsize makes into the answer
+    test.chain.insertAfter("PC_LOCAL_SET_REMOTE_DESCRIPTION", [
+      function PC_LOCAL_CHECK_RTCP_RSIZE(test) {
+        const msections = sdputils.getMSections(test.pcLocal._pc.currentRemoteDescription.sdp);
+        var alteredMSectionsFound = 0;
+        for (msection of msections) {
+          if (msection.startsWith("m=video")) {
+            ok(msection.includes("\r\na=rtcp-rsize\r\n"), "video m-section includes RTCP-RSIZE");
+            alteredMSectionsFound = alteredMSectionsFound + 1;
+          } else {
+            ok(!msection.includes("\r\na=rtcp-rsize\r\n"), "audio m-section does not include RTCP-RSIZE");
+          }
+        }
+        is(alteredMSectionsFound, mSectionsAltered, "correct number of msections found");
+      }
+    ]);
+
+    // Make sure that we are still getting RTCP stats
+    test.chain.insertAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW",
+      async function PC_LOCAL_AND_REMOTE_CHECK_FOR_RTCP_STATS(test) {
+        return Promise.all([test.pcLocal.waitForSyncedRtcp(),
+                  test.pcRemote.waitForSyncedRtcp()])
+          .then(async () => {
+            // The work is done by waitForSyncedRtcp which will throw if
+            // RTCP stats are not received.
+            info("RTCP stats received!");
+          })
+        });
+    test.setMediaConstraints([{audio: true}, {video: true}], []);
+    test.run();
+  });
+
+</script>
+</pre>
+</body>
+</html>
\ No newline at end of file
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -740,30 +740,16 @@ nsISerialEventTarget* AudioContext::GetM
 }
 
 void AudioContext::DisconnectFromOwner() {
   mIsDisconnecting = true;
   Shutdown();
   DOMEventTargetHelper::DisconnectFromOwner();
 }
 
-void AudioContext::BindToOwner(nsIGlobalObject* aNew) {
-  auto scopeExit =
-      MakeScopeExit([&] { DOMEventTargetHelper::BindToOwner(aNew); });
-
-  if (GetOwner()) {
-    GetOwner()->RemoveAudioContext(this);
-  }
-
-  nsCOMPtr<nsPIDOMWindowInner> newWindow = do_QueryInterface(aNew);
-  if (newWindow) {
-    newWindow->AddAudioContext(this);
-  }
-}
-
 void AudioContext::Shutdown() {
   // Avoid resend the Telemetry data.
   if (!mIsShutDown) {
     MaybeUpdateAutoplayTelemetryWhenShutdown();
   }
   mIsShutDown = true;
 
   CloseInternal(nullptr, AudioContextOperationFlags::None);
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -145,17 +145,16 @@ class AudioContext final : public DOMEve
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioContext, DOMEventTargetHelper)
   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 
   nsPIDOMWindowInner* GetParentObject() const { return GetOwner(); }
 
   nsISerialEventTarget* GetMainThread() const;
 
   virtual void DisconnectFromOwner() override;
-  virtual void BindToOwner(nsIGlobalObject* aNew) override;
 
   void Shutdown();  // idempotent
 
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
   using DOMEventTargetHelper::DispatchTrustedEvent;
 
--- a/dom/media/webaudio/test/test_notAllowedToStartAudioContextGC.html
+++ b/dom/media/webaudio/test/test_notAllowedToStartAudioContextGC.html
@@ -21,17 +21,17 @@ function observer(subject, topic, data) 
 }
 
 SpecialPowers.addAsyncObserver(observer, "webaudio-node-demise", false);
 SimpleTest.registerCleanupFunction(function() {
   SpecialPowers.removeAsyncObserver(observer, "webaudio-node-demise");
 });
 
 SpecialPowers.pushPrefEnv({"set": [["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
-                                   ["media.autoplay.enabled.user-gestures-needed", true]]},
+                                   ["media.autoplay.blocking_policy", 0]]},
                           startTest);
 
 function startTest() {
   info("- create audio context -");
   let ac = new AudioContext();
 
   info("- get node Id -");
   destId = SpecialPowers.getPrivilegedProps(ac.destination, "id");
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -2865,17 +2865,17 @@ nsresult ScriptLoader::EvaluateScript(Sc
                                  options,
                                  maybeSource.ref<SourceText<Utf8Unit>>());
                 }
               }
             }
 
             if (rv == NS_OK) {
               script = exec.GetScript();
-              if (JS::GetScriptPrivate(script).isUndefined()) {
+              if (script && JS::GetScriptPrivate(script).isUndefined()) {
                 classicScript->AssociateWithScript(script);
               }
               rv = ExecuteCompiledScript(cx, aRequest, exec);
             }
           }
 
           // Queue the current script load request to later save the bytecode.
           if (script && encodeBytecode) {
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -105,17 +105,18 @@ nsresult GetOrigin(nsPIDOMWindowInner* a
     // DOMException whose name is "NotAllowedError", and terminate this
     // algorithm
     MOZ_LOG(gWebAuthnManagerLog, LogLevel::Debug,
             ("Rejecting due to opaque origin"));
     return NS_ERROR_DOM_NOT_ALLOWED_ERR;
   }
 
   nsCOMPtr<nsIURI> originUri;
-  if (NS_FAILED(principal->GetURI(getter_AddRefs(originUri)))) {
+  auto* basePrin = BasePrincipal::Cast(principal);
+  if (NS_FAILED(basePrin->GetURI(getter_AddRefs(originUri)))) {
     return NS_ERROR_FAILURE;
   }
   if (NS_FAILED(originUri->GetAsciiHost(aHost))) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
@@ -123,18 +124,20 @@ nsresult GetOrigin(nsPIDOMWindowInner* a
 nsresult RelaxSameOrigin(nsPIDOMWindowInner* aParent,
                          const nsAString& aInputRpId,
                          /* out */ nsACString& aRelaxedRpId) {
   MOZ_ASSERT(aParent);
   nsCOMPtr<Document> doc = aParent->GetDoc();
   MOZ_ASSERT(doc);
 
   nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+  auto* basePrin = BasePrincipal::Cast(principal);
   nsCOMPtr<nsIURI> uri;
-  if (NS_FAILED(principal->GetURI(getter_AddRefs(uri)))) {
+
+  if (NS_FAILED(basePrin->GetURI(getter_AddRefs(uri)))) {
     return NS_ERROR_FAILURE;
   }
   nsAutoCString originHost;
   if (NS_FAILED(uri->GetAsciiHost(originHost))) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<Document> document = aParent->GetDoc();
   if (!document || !document->IsHTMLDocument()) {
--- a/dom/websocket/WebSocket.cpp
+++ b/dom/websocket/WebSocket.cpp
@@ -892,37 +892,16 @@ WebSocket::WebSocket(nsIGlobalObject* aG
 
 WebSocket::~WebSocket() = default;
 
 JSObject* WebSocket::WrapObject(JSContext* cx,
                                 JS::Handle<JSObject*> aGivenProto) {
   return WebSocket_Binding::Wrap(cx, this, aGivenProto);
 }
 
-void WebSocket::BindToOwner(nsIGlobalObject* aNew) {
-  auto scopeExit =
-      MakeScopeExit([&] { DOMEventTargetHelper::BindToOwner(aNew); });
-
-  // If we're disconnected, then there is no state to update.
-  if (!mImpl || mImpl->mDisconnectingOrDisconnected) {
-    return;
-  }
-
-  // Update state on the old window.
-  if (GetOwner()) {
-    GetOwner()->UpdateWebSocketCount(-1);
-  }
-
-  // Update state on the new window
-  nsCOMPtr<nsPIDOMWindowInner> newWindow = do_QueryInterface(aNew);
-  if (newWindow) {
-    newWindow->UpdateWebSocketCount(1);
-  }
-}
-
 //---------------------------------------------------------------------------
 // WebIDL
 //---------------------------------------------------------------------------
 
 // Constructor:
 already_AddRefed<WebSocket> WebSocket::Constructor(
     const GlobalObject& aGlobal, const nsAString& aUrl,
     const StringOrStringSequence& aProtocols, ErrorResult& aRv) {
--- a/dom/websocket/WebSocket.h
+++ b/dom/websocket/WebSocket.h
@@ -58,19 +58,16 @@ class WebSocket final : public DOMEventT
   GetDebuggerNotificationType() const override {
     return mozilla::Some(EventCallbackDebuggerNotificationType::Websocket);
   }
 
   // nsWrapperCache
   virtual JSObject* WrapObject(JSContext* cx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
-  // DOMEventTargetHelper
-  void BindToOwner(nsIGlobalObject* aNew) override;
-
  public:  // static helpers:
   // Determine if preferences allow WebSocket
   static bool PrefEnabled(JSContext* aCx = nullptr,
                           JSObject* aGlobal = nullptr);
 
  public:  // WebIDL interface:
   // Constructor:
   static already_AddRefed<WebSocket> Constructor(
--- a/dom/xul/nsXULPrototypeDocument.cpp
+++ b/dom/xul/nsXULPrototypeDocument.cpp
@@ -435,17 +435,19 @@ void nsXULPrototypeDocument::TraceProtos
     mGCNumber = currentGCNumber;
   }
 
   if (mRoot) {
     mRoot->TraceAllScripts(aTrc);
   }
 }
 
-void nsXULPrototypeDocument::SetIsL10nCached() { mWasL10nCached = true; }
+void nsXULPrototypeDocument::SetIsL10nCached(bool aIsCached) {
+  mWasL10nCached = aIsCached;
+}
 
 void nsXULPrototypeDocument::RebuildPrototypeFromElement(
     nsXULPrototypeElement* aPrototype, Element* aElement, bool aDeep) {
   aPrototype->mHasIdAttribute = aElement->HasID();
   aPrototype->mHasClassAttribute = aElement->MayHaveClass();
   aPrototype->mHasStyleAttribute = aElement->MayHaveStyle();
   NodeInfo* oldNodeInfo = aElement->NodeInfo();
   RefPtr<NodeInfo> newNodeInfo = mNodeInfoManager->GetNodeInfo(
--- a/dom/xul/nsXULPrototypeDocument.h
+++ b/dom/xul/nsXULPrototypeDocument.h
@@ -92,17 +92,17 @@ class nsXULPrototypeDocument final : pub
   void MarkInCCGeneration(uint32_t aCCGeneration);
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
 
   void TraceProtos(JSTracer* aTrc);
 
   bool WasL10nCached() { return mWasL10nCached; };
 
-  void SetIsL10nCached();
+  void SetIsL10nCached(bool aIsCached);
   void RebuildPrototypeFromElement(nsXULPrototypeElement* aPrototype,
                                    mozilla::dom::Element* aElement, bool aDeep);
   void RebuildL10nPrototype(mozilla::dom::Element* aElement, bool aDeep);
 
  protected:
   nsCOMPtr<nsIURI> mURI;
   RefPtr<nsXULPrototypeElement> mRoot;
   nsTArray<RefPtr<nsXULPrototypePI> > mProcessingInstructions;
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -390,17 +390,17 @@ Element* HTMLEditor::FindSelectionRoot(n
     return GetRoot();
   }
 
   nsIContent* content = aNode->AsContent();
   if (!content->HasFlag(NODE_IS_EDITABLE)) {
     // If the content is in read-write state but is not editable itself,
     // return it as the selection root.
     if (content->IsElement() &&
-        content->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
+        content->AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
       return content->AsElement();
     }
     return nullptr;
   }
 
   // For non-readonly editors we want to find the root of the editable subtree
   // containing aContent.
   return content->GetEditingHost();
--- a/editor/reftests/672709-ref.html
+++ b/editor/reftests/672709-ref.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
   <body>
     <style>
-      :-moz-read-only { color: red; }
-      :-moz-read-write { color: green; }
+      :read-only { color: red; }
+      :read-write { color: green; }
     </style>
     <script>
       onload = function() {
         document.designMode = "on";
         var p = document.createElement("p");
         p.textContent = "test";
         document.getElementById("x").appendChild(p);
         getSelection().removeAllRanges(); // don't need a caret
--- a/editor/reftests/694880-1.html
+++ b/editor/reftests/694880-1.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
   <style>
-    :-moz-read-only { color: green; }
-    :-moz-read-write { color: red; }
+    :read-only { color: green; }
+    :read-write { color: red; }
   </style>
   <body onload="document.designMode='on';document.designMode='off'">
     <div>test</div>
   </body>
 </html>
--- a/editor/reftests/694880-2.html
+++ b/editor/reftests/694880-2.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
   <style>
-    :-moz-read-only { color: green; }
-    :-moz-read-write { color: red; }
+    :read-only { color: green; }
+    :read-write { color: red; }
   </style>
   <body onload="document.designMode='on';document.designMode='off'">
     <div>test</div>
     <div contenteditable></div>
   </body>
 </html>
--- a/editor/reftests/694880-3.html
+++ b/editor/reftests/694880-3.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
   <style>
-    :-moz-read-only { color: red; }
-    :-moz-read-write { color: green; }
+    :read-only { color: red; }
+    :read-write { color: green; }
   </style>
   <body onload="document.designMode='on';document.designMode='off'">
     <div contenteditable>test</div>
   </body>
 </html>
--- a/editor/reftests/readonly-editable.html
+++ b/editor/reftests/readonly-editable.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
   <head>
     <style>
-      :-moz-read-write + span {
+      :read-write + span {
         display: none;
       }
       span {
         color: transparent; /* workaround for bug 617524 */
         outline: 1px solid green;
       }
     </style>
   </head>
--- a/editor/reftests/readonly-non-editable.html
+++ b/editor/reftests/readonly-non-editable.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
   <head>
     <style>
-      :-moz-read-only + span {
+      :read-only + span {
         display: none;
       }
       span {
         color: transparent; /* workaround for bug 617524 */
         outline: 1px solid green;
       }
     </style>
   </head>
--- a/editor/reftests/readwrite-editable.html
+++ b/editor/reftests/readwrite-editable.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
   <head>
     <style>
-      :-moz-read-write + span {
+      :read-write + span {
         display: none;
       }
       span {
         color: transparent; /* workaround for bug 617524 */
         outline: 1px solid green;
       }
     </style>
   </head>
--- a/editor/reftests/readwrite-non-editable.html
+++ b/editor/reftests/readwrite-non-editable.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
   <head>
     <style>
-      :-moz-read-write + span {
+      :read-write + span {
         display: none;
       }
       span {
         color: transparent; /* workaround for bug 617524 */
         outline: 1px solid green;
       }
     </style>
   </head>
deleted file mode 100644
--- a/gfx/docs/DocumentSplitting.rst
+++ /dev/null
@@ -1,332 +0,0 @@
-.. _docsplit:
-
-Document Splitting in WebRender
-===============================
-
-Goals
------
-
-The fundamental goal of document splitting is to fix a specific performance issue.
-The architecture of WebRender is such that any time a content process sends a new
-display list to the compositor, WebRender needs to do a full scene build that
-includes both the content and chrome areas. Likewise if the chrome process sends
-a new display list to the compositor. This means that animations such as the
-tab loading spinner or an animated gif will cause much more WR activity than
-is really needed.
-
-With document splitting, the WR scene is split into two (or more) documents
-based on the visual location of the elements. Everything in the "chrome area"
-of the window (including the tab bar, URL bar, navigation buttons, etc.) are
-considered part of one document, and anything below that (including content,
-devtools, sidebars, etc.) is in another document. Bug 1549976 introduces a
-third "popover" document that encompasses elements that straddle both of these
-visually, but that's a side-effect of the implementation rather than being
-driven by the fundamental problem being addressed.
-
-With the documents split like so, an animation in the UI (such as the tab loading
-spinner) runs independently of the content (by virtue of being in a different
-document) and vice-versa, which results in better user-perceived performance.
-
-Naming
-------
-
-Document splitting is so called because inside the WR code and bindings, a
-"document" is an independent pathway to the compositor that has its own scene,
-render tasks, etc.
-
-In most of the C++ code in gfx/layers and other parts of Firefox/Gecko, the term
-"render root" is used instead. A "render root" is exactly equivalent to a WR
-document; the two terms are used interchangeably. The naming is this way
-because "document" has different pre-existing meanings in Gecko-land. In this
-documentation those other meanings are irrelevant and so "document" always refers
-to the same thing as "render root".
-
-At various points there have been discussions to renaming things so that everything
-is more consistent and less confusing, but that hasn't happened yet.
-
-Fundamental data types
-----------------------
-
-The `wr::RenderRoot
-<https://searchfox.org/mozilla-central/rev/da14c413ef663eb1ba246799e94a240f81c42488/gfx/webrender_bindings/WebRenderTypes.h#65>`_
-data type is an enumeration of all the different documents that are expected
-to be created. As of this writing, the enumeration contains two entries: Default
-and Content. The Default document refers to the one that holds the "chrome" stuff
-and the Content document refers to the one that holds the "content" area stuff.
-
-If document splitting is disabled (gfx.webrender.split-render-roots=false) then
-everything lives in the Default document and the Content document is always empty.
-
-Additional data structures in the same file (e.g. wr::RenderRootArray<T>) facilitate
-converting pre-document-splitting code into document-splitting-aware code, usually
-by turning a single object into an array of objects, one per document.
-
-High-level design
------------------
-
-The notion of having multiple documents has to be introduced at a fairly fundamental
-level in order to be propagated through the entire rendering pipeline. It starts
-in the front-end HTML/XUL code where certain elements are annotated as being the
-transition point between documents. For example, `this code
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/browser/base/content/browser.xhtml#1304>`_
-explicitly identifies an element and its descendants as being in the "content"
-document instead of the "default" (or "chrome") document.
-
-These attributes are `read during display list building
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/layout/xul/nsBoxFrame.cpp#1112>`_
-to create the nsDisplayRenderRoot display item in the Gecko display list.
-
-When the Gecko display list is processed to create a WebRender display list,
-it actually ends up creating multiple WR display lists, one for each document. This
-is necessary because the documents are handled independently inside WR, and so
-each get their own WebRenderAPI object and separate display list. The way the
-implementation manages this is by `creating a "sub builder"
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/layout/painting/nsDisplayList.cpp#7043,7065>`_
-for the render root that is being descended into, and using that instead of the
-main WR display list builder as the display list is recursed into.
-
-Note also that clip chains and stacking contexts are per-document, so when
-recursing past a nsDisplayRenderRoot item, the `ClipManager and StackingContextHelper
-<https://searchfox.org/mozilla-central/rev/da14c413ef663eb1ba246799e94a240f81c42488/gfx/layers/wr/WebRenderCommandBuilder.h#236-237>`_
-being used switches to one specific to the new document. For this to work there are
-certain assumptions that must hold, which are described in the next section.
-Other things that must now be managed on a per-document basis are generally
-encapsulated into the RenderRootStateManager class, and the WebRenderLayerManager
-holds an `array of these
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/gfx/layers/wr/WebRenderLayerManager.h#242>`_.
-
-After the Gecko display list is converted to a set of WebRender display lists
-(one per document), these are sent across IPC along with any associated resources
-as part of the `WebRender transaction
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/gfx/layers/ipc/PWebRenderBridge.ipdl#50>`_.
-Conceptually, the parent side simply demultiplexes the data for different documents,
-and submits the data for each document to the corresponding WebRenderAPI instance.
-
-Limitations/Assumptions
------------------------
-
-One of the fundamental issues with the document splitting implementation is that
-we can have stuff in the UI process that's part of the "content" renderroot (e.g.
-a sidebar that appears to the left of the content area). The expectation for
-front-end authors would be that this would be affected by ancestor elements that
-are also in the UI process. Consider this outline of a Gecko display list:
-
-::
-
-  - Root display item R
-    - ... stuff here (call it Q) ...
-      - display item P
-        - display item A
-        - display item B (flagged as being in the content renderroot)
-        - display item C
-
-If item P was a filter, for example, that would normally apply to all of items
-A, B, and C. This would mean either sharing the filter between the "chrome" renderroot
-and the "content" renderroot, or duplicating it such that it existed in both
-renderroots. The sharing is not possible as it violates the independence of WR
-documents. The duplication is technically possible, but could result in visual
-glitches as the two documents would be processed and composited separately.
-
-In order to avoid this problem, the design of document splitting explicitly assumes
-that such a scenario will not happen. In particular, the only information that
-gets carried across the render root boundary is the positioning offset. Any
-filters, transforms that are not 2D axis-aligned, opacity, or mix blend mode
-properties do NOT get carried across the render root boundary. Similarly, a
-scrollframe may not contain content from multiple render roots, because that
-would lead to a similar problem in APZ where it would have to update the scroll
-position of scrollframes in multiple documents and they might get composited
-at separate times, resulting in visual glitches.
-
-Security Concerns
------------------
-
-On the content side, all of the document splitting work happens in the UI process.
-In other words, content processes don't generally know what document they are part
-of, and don't ever split their display lists into multiple documents. Only the UI
-process ever sends multiple display lists to the compositor side.
-
-There are a number of APIs on PWebRenderBridge where a wr::RenderRoot is passed
-across from the content side to the compositor side. And since PWebRenderBridge
-is a unified protocol that is used by both the UI process and content processes
-to communicate with the compositor, the content processes must provide *some*
-value for the wr::RenderRoot. But since it doesn't (or shouldn't) be aware of
-what document it's in, it must always pass wr::RenderRoot::Default.
-
-Compositor-side code in WebRenderBridgeParent is responsible for checking that
-any wr::RenderRoot values provided from a content process are in fact wr::RenderRoot::Default.
-If this is not the case, it is either a programmer error or a hijacked content
-process, and appropriate handling should be used. In particular, the compositor
-side code should *never* blindly use the wr::RenderRoot value provided over the IPC
-channel as hijacked content processes could force the compositor into leaking
-information or otherwise violate the security and integrity of the browser. Instead,
-the compositor is responsible for determining where the content is attached in
-the display list of the UI process, and determine the appropriate document for that
-content process. This information is stored in the `WebRenderBridgeParent::mRenderRoot
-<https://searchfox.org/mozilla-central/rev/8ed8474757695cdae047150a0eaf94a5f1c96dbe/gfx/layers/wr/WebRenderBridgeParent.h#495>`_
-field.
-
-Implementation details
-----------------------
-
-This section describes various knots of complexity in the document splitting
-implementation. That is, these pieces are thought to introduce higher-than-normal
-levels of complexity into the feature, and should be handled with care.
-
-APZ interaction
-~~~~~~~~~~~~~~~
-
-When a display list transaction is sent from the content side to the compositor,
-APZ is also notified of the update, so that it can internally update its own
-data structures. One of these data structures is a tree representation of the
-scrollable frames on the page. With document splitting, the scrollable frames
-may now be split across multiple documents. APZ needs to record which document
-each scrollable frame belongs to, so that when providing the async scroll offset
-to WebRender, it can send the scroll offset for a given a scrollable frame to the
-correct WebRender document. As one might expect, this is stored in the `mRenderRoot
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/layers/apz/src/AsyncPanZoomController.h#916>`_
-field in the AsyncPanZoomController (there is one instance of this per scrollable
-frame).
-
-Additionally, when new display list transactions and other messages are received
-in WebRenderBridgeParent, APZ cannot process these updates right away. Doing so
-would cause APZ to respond to user input based on the new display list, while
-the WebRender internal state still corresponds to the old display list. To ensure
-that APZ and WR's internal state remain in sync, APZ puts these update messages
-into an `"updater queue"
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/layers/apz/src/APZUpdater.cpp#340>`_
-which is processed synchronously with the WebRender scene swap. This ensures that
-APZ's internal state is updated at the same time that WebRender swaps in the new
-scene, and everything stays in sync.  Conceptually this is relatively simple,
-until we add document splitting to the mix.
-
-Now instead of one scene swap, we have multiple scene swaps happening, one for
-each of the documents. In other words, even though WebRenderBridgeParent gets a
-single "display list transaction", the display lists for the different documents
-modify WR's internal state at different times. Consequently, to keep APZ in sync,
-we must apply a similar "splitting" to the APZ updater queue, so that messages
-pertaining to a particular document are applied synchronously with that
-document's scene swap.
-
-(As a relevant aside: there other messages that APZ receives over other IPC
-channels (e.g. PAPZCTreeManager) that have ordering requirements with the
-PWebRenderBridge messages, and so those also normally end up in the updater queue.
-Consequently, these other messages are also now subjected to the splitting of
-the updater queue.)
-
-Again, conceptually this is relatively simple - we just need to keep a separate
-queue for each document, and when an update message comes in, we decide which
-document a given update message is associated with, and put the message into the
-corresponding queue. The catch is that often these messages deal with a specific
-element or scrollframe on the page, and so when the message is sent from the
-UI process, we need to do a DOM or frame tree walk to determine which render root
-that element is associated with. There are some `GetRenderRootForXXX
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/thebes/gfxUtils.h#317-322>`_
-helpers in gfxUtils that assist with this task.
-
-The other catch is that an APZ message may be associated with multiple documents.
-A concrete example is if a user on a touch device does a multitouch action with
-different fingers landing on different documents, which would trigger a call to
-`RecvSetTargetAPZC
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/layers/ipc/APZCTreeManagerParent.cpp#76>`_
-with multiple targets, each potentially belonging to a different render root.
-In this case, we need to ensure that the message only gets processed after
-the corresponding scene swaps for all the related documents. This is currently
-implemented by having each message in the queue associated with a set of documents
-rather than a single document, and only processing the message once all the
-documents have done their scene swap. In the example above, this is indicated by
-building the set of render roots `here
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/layers/ipc/APZCTreeManagerParent.cpp#83>`_
-and passing that to the updater queue when queueing the message. This interaction
-is a source of some complexity and may have latent bugs.
-
-Deferred updates
-~~~~~~~~~~~~~~~~
-
-Bug 1547351 provided a new and tricky problem where a content process is rendering
-stuff that needs to go into the "default" document because it's actually an
-out-of-process addon content that renders in the chrome area. Prior to this bug,
-the WebRenderBridgeParent instances that corresponded to content processes
-(hereafter referred to as "sub-WRBPs", in contrast to the "root WRBP" that
-corresponds to the UI process) simply assumed they were in the "Content" document,
-but this bug proved that this simplistic assumption does not always hold.
-
-The solution chosen to this problem was to have the root WebRenderLayerManager
-(that lives in the trusted UI process) to annotate each out-of-process subpipeline
-with the render root it belongs in, and send that information over to the
-root WRBP as part of the display list transaction. The sub-WRBPs know their own
-pipeline ids, and therefore can find their render root by querying the root WRBP.
-The catch is that sub-WRBPs may receive display list transactions *before* the
-root WRBP receives the display list update that contains the render root mapping
-information. This happens in cases like during tab switch preload, where the
-user mouses over a background tab, and we pre-render it (i.e. compute and send
-the display list for that tab to the compositor) so that the tab switch is faster.
-In this scenario, that display list/subpipeline is not actually rendered, is not
-tied in to the display list of the UI process, and therefore doesn't get associated
-with a render root.
-
-When the sub-WRBP receives a transaction in a scenario like this, it cannot
-actually process it (by sending it to WebRender) because it doesn't know which
-WR document it associated with. So it has to hold on to it in a "deferred update"
-queue until some later point where it does find out which WR document it is
-associated with, and at that point it can process the deferred update queue.
-
-Again, conceptually this is straightforward, but the implementation produces a
-bunch of complexity because it needs to handle both orderings - the case where
-the sub-WRBP knows its render root, and the case where it doesn't yet. And the
-root WRBP, upon receiving a new transaction, would need to notify the sub-WRBPs
-of their render roots and trigger processing of the deferred updates.
-
-Further complicating matters is Fission, because with Fission there can be
-pipelines nested to arbitrary depths. This results in a tree of sub-WRBPs, with
-each WRBP knowing what its direct children are, and only the root WRBP knowing
-which documents its immediate children are in. So there could be a chain of
-sub-WRBPs with a "missing link" (i.e. one that doesn't yet know what its children
-are, because it hasn't received a display list transaction yet) and upon filling
-in that missing link, all the descendant WRBPs from that point suddenly also
-know which WR document they are associated with and can process their deferred
-updates.
-
-Managing all this deferred state, ensuring it is processed as soon as possible,
-and clearing it out when the content side is torn down (which may happen without
-it ever being rendered) is a source of complexity and may have latent bugs.
-
-Transaction completion
-~~~~~~~~~~~~~~~~~~~~~~
-
-Transactions between the content and compositor side are throttled such that
-the content side doesn't go nuts pushing over display lists to the compositor
-when the compositor has a backlog of pending display lists. The way the throttling
-works is that each transaction sent has a transaction id, and after the compositor
-is done processing a transaction, it reports the completed transaction id back
-to the content side. The content side can use this information to track how many
-transactions are inflight at any given time and apply throttling as necessary.
-
-With document splitting, a transaction sent from the content side gets split up
-and sent to multiple WR documents, each of which are operating independently of
-each other. If we propagate the transaction id to each of those WR documents,
-then the first document to complete its work would trigger the "transaction complete"
-message back to the content, which would unthrottle the next transaction. In this
-scenario, other documents may still be backlogged, so the unthrottling is
-undesirable.
-
-Instead, what we want is for all documents processing a particular transaction
-id to finish their work and render before we send the completion message back
-to content. In fact, there's a bunch of work that falls into the same category
-as this completion message - stuff that should happen after all the WR documents
-are done processing their pieces of the split transaction.
-
-The way this is managed is via a conditional in `HandleFrame
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/webrender_bindings/RenderThread.cpp#988>`_.
-This code is invoked once for each document as it advances to the rendering step,
-and the code in `RenderThread::IncRenderingFrameCount
-<https://searchfox.org/mozilla-central/rev/06bd14ced96f25ff1dbd5352cb985fc0fa12a64e/gfx/webrender_bindings/RenderThread.cpp#552-553>`_
-acts as a barrier to ensure that the call chain only gets propagated once all
-the documents have done their processing work.
-
-I'm listing this piece as a potential source of complexity for document splitting
-because it seems like a fairly important piece but the relevant code is
-"buried" away in a place where one might not easily stumble upon it. It's also not
-clear to me that the implications of this problem and solution have been fully
-explored. In particular, I assume that there are latent bugs here because other
-pieces of code were assuming a certain behaviour from the pre-document-splitting
-code that the post-document-splitting code may not satisfy exactly.
--- a/gfx/docs/index.rst
+++ b/gfx/docs/index.rst
@@ -11,9 +11,8 @@ information about graphics and the graph
    :maxdepth: 1
 
    GraphicsOverview
    LayersHistory
    OffMainThreadPainting
    AsyncPanZoom
    AdvancedLayers
    Silk
-   DocumentSplitting
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -195,16 +195,22 @@ SharedSurface_SurfaceTexture::SharedSurf
     const GLFormats& formats, java::GeckoSurface::Param surface,
     EGLSurface eglSurface)
     : SharedSurface(SharedSurfaceType::AndroidSurfaceTexture,
                     AttachmentType::Screen, gl, size, hasAlpha, true),
       mSurface(surface),
       mEglSurface(eglSurface) {}
 
 SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
+  if (mOrigEglSurface) {
+    // We are about to destroy mEglSurface.
+    // Make sure gl->SetEGLSurfaceOverride() doesn't keep a reference
+    // to the surface.
+    UnlockProd();
+  }
   GLContextProviderEGL::DestroyEGLSurface(mEglSurface);
   java::SurfaceAllocator::DisposeSurface(mSurface);
 }
 
 void SharedSurface_SurfaceTexture::LockProdImpl() {
   MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
 
   GLContextEGL* gl = GLContextEGL::Cast(mGL);
--- a/gfx/layers/ShareableCanvasRenderer.cpp
+++ b/gfx/layers/ShareableCanvasRenderer.cpp
@@ -182,18 +182,17 @@ CanvasClient::CanvasClientType Shareable
 
   if (mOOPRenderer) {
     return CanvasClient::CanvasClientTypeOOP;
   }
 
   return CanvasClient::CanvasClientSurface;
 }
 
-void ShareableCanvasRenderer::UpdateCompositableClient(
-    wr::RenderRoot aRenderRoot) {
+void ShareableCanvasRenderer::UpdateCompositableClient() {
   if (!CreateCompositable()) {
     return;
   }
 
   if (mCanvasClient && mAsyncRenderer) {
     mCanvasClient->UpdateAsync(mAsyncRenderer);
   }
 
@@ -203,22 +202,20 @@ void ShareableCanvasRenderer::UpdateComp
   ResetDirty();
 
   FirePreTransactionCallback();
   if (mBufferProvider && mBufferProvider->GetTextureClient()) {
     if (!mBufferProvider->SetKnowsCompositor(GetForwarder())) {
       gfxCriticalNote << "BufferProvider::SetForwarder failed";
       return;
     }
-    mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient(),
-                                     aRenderRoot);
+    mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
   } else {
-    mCanvasClient->Update(gfx::IntSize(mSize.width, mSize.height), this,
-                          aRenderRoot);
+    mCanvasClient->Update(gfx::IntSize(mSize.width, mSize.height), this);
   }
 
   FireDidTransactionCallback();
 
-  mCanvasClient->Updated(aRenderRoot);
+  mCanvasClient->Updated();
 }
 
 }  // namespace layers
 }  // namespace mozilla
--- a/gfx/layers/ShareableCanvasRenderer.h
+++ b/gfx/layers/ShareableCanvasRenderer.h
@@ -34,18 +34,17 @@ class ShareableCanvasRenderer : public C
 
   virtual CompositableForwarder* GetForwarder() = 0;
 
   virtual bool CreateCompositable() = 0;
 
   void ClearCachedResources() override;
   void Destroy() override;
 
-  void UpdateCompositableClient(
-      wr::RenderRoot aRenderRoot = wr::RenderRoot::Default);
+  void UpdateCompositableClient();
 
   const TextureFlags& Flags() const { return mFlags; }
 
   CanvasClient* GetCanvasClient() { return mCanvasClient; }
 
  protected:
   bool UpdateTarget(gfx::DrawTarget* aDestTarget);
 
--- a/gfx/layers/UpdateImageHelper.h
+++ b/gfx/layers/UpdateImageHelper.h
@@ -47,31 +47,30 @@ class UpdateImageHelper {
   already_AddRefed<gfx::DrawTarget> GetDrawTarget() {
     RefPtr<gfx::DrawTarget> target;
     if (mTexture) {
       target = mTexture->BorrowDrawTarget();
     }
     return target.forget();
   }
 
-  bool UpdateImage(wr::RenderRoot aRenderRoot) {
+  bool UpdateImage() {
     if (!mTexture) {
       return false;
     }
 
     if (mIsLocked) {
       mTexture->Unlock();
       mIsLocked = false;
     }
 
     RefPtr<TextureWrapperImage> image = new TextureWrapperImage(
         mTexture, gfx::IntRect(gfx::IntPoint(0, 0), mImageSize));
     mImageContainer->SetCurrentImageInTransaction(image);
-    return mImageClient->UpdateImage(mImageContainer, /* unused */ 0,
-                                     Some(aRenderRoot));
+    return mImageClient->UpdateImage(mImageContainer, /* unused */ 0);
   }
 
  private:
   RefPtr<ImageContainer> mImageContainer;
   RefPtr<ImageClient> mImageClient;
   gfx::IntSize mImageSize;
   RefPtr<TextureClient> mTexture;
   bool mIsLocked;
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -63,18 +63,17 @@ void CanvasClientBridge::UpdateAsync(Asy
     return;
   }
 
   static_cast<ShadowLayerForwarder*>(GetForwarder())
       ->AttachAsyncCompositable(asyncID, mLayer);
   mAsyncHandle = asyncID;
 }
 
-void CanvasClient2D::UpdateFromTexture(TextureClient* aTexture,
-                                       wr::RenderRoot aRenderRoot) {
+void CanvasClient2D::UpdateFromTexture(TextureClient* aTexture) {
   MOZ_ASSERT(aTexture);
 
   if (!aTexture->IsSharedWithCompositor()) {
     if (!AddTextureClient(aTexture)) {
       return;
     }
   }
 
@@ -88,18 +87,17 @@ void CanvasClient2D::UpdateFromTexture(T
   t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
   t->mFrameID = mFrameID;
 
   GetForwarder()->UseTextures(this, textures);
   aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
 }
 
 void CanvasClient2D::Update(gfx::IntSize aSize,
-                            ShareableCanvasRenderer* aCanvasRenderer,
-                            wr::RenderRoot aRenderRoot) {
+                            ShareableCanvasRenderer* aCanvasRenderer) {
   mBufferProviderTexture = nullptr;
 
   AutoRemoveTexture autoRemove(this);
   if (mBackBuffer &&
       (mBackBuffer->IsReadLocked() || mBackBuffer->GetSize() != aSize)) {
     autoRemove.mTexture = mBackBuffer;
     mBackBuffer = nullptr;
   }
@@ -374,19 +372,18 @@ static already_AddRefed<SharedSurfaceTex
 
   if (!ret) {
     return nullptr;
   }
 
   return dest.forget();
 }
 
-void CanvasClientSharedSurface::Update(gfx::IntSize aSize,
-                                       ShareableCanvasRenderer* aCanvasRenderer,
-                                       wr::RenderRoot aRenderRoot) {
+void CanvasClientSharedSurface::Update(
+    gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) {
   Renderer renderer;
   renderer.construct<ShareableCanvasRenderer*>(aCanvasRenderer);
   UpdateRenderer(aSize, renderer);
 }
 
 void CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer) {
   Renderer renderer;
   renderer.construct<AsyncCanvasRenderer*>(aRenderer);
@@ -495,17 +492,17 @@ void CanvasClientSharedSurface::UpdateRe
         << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: "
         << aSize;
     return;
   }
 
   mNewFront = newFront;
 }
 
-void CanvasClientSharedSurface::Updated(wr::RenderRoot aRenderRoot) {
+void CanvasClientSharedSurface::Updated() {
   if (!mNewFront) {
     return;
   }
 
   auto forwarder = GetForwarder();
 
   mFront = mNewFront;
   mNewFront = nullptr;
@@ -545,19 +542,17 @@ void CanvasClientOOP::SetLayer(Shadowabl
   mLayer = aLayer;
   mCanvasContext = aRenderer->mContext;
   MOZ_ASSERT(mCanvasContext);
   Connect();
   aRenderer->mCanvasClient = this;
 }
 
 void CanvasClientOOP::Update(gfx::IntSize aSize,
-                             ShareableCanvasRenderer* aRenderer,
-                             wr::RenderRoot aRenderRoot) {
-  // DLP: TODO: aRenderRoot?
+                             ShareableCanvasRenderer* aRenderer) {
   if (!GetForwarder() || !mLayer || !mCanvasContext || !aRenderer) {
     return;
   }
 
   // Make sure the host is using the right Compositable.
   CompositableHandle handle = GetIPCHandle();
   if (!handle || mHandle == handle) {
     return;
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -62,30 +62,28 @@ class CanvasClient : public Compositable
     mTextureFlags = aFlags;
   }
 
   virtual ~CanvasClient() = default;
 
   virtual void Clear(){};
 
   virtual void Update(gfx::IntSize aSize,
-                      ShareableCanvasRenderer* aCanvasRenderer,
-                      wr::RenderRoot aRenderRoot) = 0;
+                      ShareableCanvasRenderer* aCanvasRenderer) = 0;
 
   bool AddTextureClient(TextureClient* aTexture) override {
     ++mFrameID;
     return CompositableClient::AddTextureClient(aTexture);
   }
 
   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
 
-  virtual void UpdateFromTexture(TextureClient* aTexture,
-                                 wr::RenderRoot aRenderRoot) {}
+  virtual void UpdateFromTexture(TextureClient* aTexture) {}
 
-  virtual void Updated(wr::RenderRoot aRenderRoot) {}
+  virtual void Updated() {}
 
  protected:
   int32_t mFrameID;
 };
 
 // Used for 2D canvases and WebGL canvas on non-GL systems where readback is
 // requried.
 class CanvasClient2D : public CanvasClient {
@@ -96,21 +94,20 @@ class CanvasClient2D : public CanvasClie
   TextureInfo GetTextureInfo() const override {
     return TextureInfo(CompositableType::IMAGE, mTextureFlags);
   }
 
   void Clear() override {
     mBackBuffer = mFrontBuffer = mBufferProviderTexture = nullptr;
   }
 
-  void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer,
-              wr::RenderRoot aRenderRoot) override;
+  void Update(gfx::IntSize aSize,
+              ShareableCanvasRenderer* aCanvasRenderer) override;
 
-  void UpdateFromTexture(TextureClient* aBuffer,
-                         wr::RenderRoot aRenderRoot) override;
+  void UpdateFromTexture(TextureClient* aBuffer) override;
 
   bool AddTextureClient(TextureClient* aTexture) override {
     return CanvasClient::AddTextureClient(aTexture);
   }
 
   void OnDetach() override { mBackBuffer = mFrontBuffer = nullptr; }
 
  private:
@@ -146,23 +143,23 @@ class CanvasClientSharedSurface : public
   ~CanvasClientSharedSurface();
 
   TextureInfo GetTextureInfo() const override {
     return TextureInfo(CompositableType::IMAGE);
   }
 
   void Clear() override { ClearSurfaces(); }
 
-  void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer,
-              wr::RenderRoot aRenderRoot) override;
+  void Update(gfx::IntSize aSize,
+              ShareableCanvasRenderer* aCanvasRenderer) override;
   void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
 
   void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
 
-  void Updated(wr::RenderRoot aRenderRoot) override;
+  void Updated() override;
 
   void OnDetach() override;
 };
 
 /**
  * Used for OMT<canvas> uploads using the image bridge protocol.
  * Actual CanvasClient is on the ImageBridgeChild thread, so we
  * only forward its AsyncID here
@@ -174,18 +171,18 @@ class CanvasClientBridge final : public 
       : CanvasClient(aLayerForwarder, aFlags), mLayer(nullptr) {
     mIsAsync = true;
   }
 
   TextureInfo GetTextureInfo() const override {
     return TextureInfo(CompositableType::IMAGE);
   }
 
-  void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer,
-              wr::RenderRoot aRenderRoot) override {}
+  void Update(gfx::IntSize aSize,
+              ShareableCanvasRenderer* aCanvasRenderer) override {}
 
   void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
 
   void SetLayer(ShadowableLayer* aLayer) { mLayer = aLayer; }
 
  protected:
   CompositableHandle mAsyncHandle;
   ShadowableLayer* mLayer;
@@ -199,18 +196,17 @@ class CanvasClientOOP final : public Can
   CanvasClientOOP(CompositableForwarder* aLayerForwarder, TextureFlags aFlags);
   ~CanvasClientOOP();
 
   TextureInfo GetTextureInfo() const override {
     return TextureInfo(CompositableType::IMAGE);
   }
 
   virtual void Update(gfx::IntSize aSize,
-                      ShareableCanvasRenderer* aCanvasRenderer,
-                      wr::RenderRoot aRenderRoot) override;
+                      ShareableCanvasRenderer* aCanvasRenderer) override;
 
   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override {
     MOZ_ASSERT_UNREACHABLE("Illegal to call UpdateAsync on CanvasClientOOP");
   }
 
   void SetLayer(ShadowableLayer* aLayer, OOPCanvasRenderer* aRenderer);
 
  protected:
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -113,33 +113,33 @@ class ClientImageLayer : public ImageLay
 void ClientImageLayer::RenderLayer() {
   RenderMaskLayers(this);
 
   if (!mContainer) {
     return;
   }
 
   if (!mImageClient ||
-      !mImageClient->UpdateImage(mContainer, GetContentFlags(), Nothing())) {
+      !mImageClient->UpdateImage(mContainer, GetContentFlags())) {
     CompositableType type = GetImageClientType();
     if (type == CompositableType::UNKNOWN) {
       return;
     }
     TextureFlags flags = TextureFlags::DEFAULT;
     mImageClient = ImageClient::CreateImageClient(
         type, ClientManager()->AsShadowForwarder(), flags);
     if (!mImageClient) {
       return;
     }
     mImageClient->SetLayer(this);
     if (HasShadow() && !mContainer->IsAsync()) {
       mImageClient->Connect();
       ClientManager()->AsShadowForwarder()->Attach(mImageClient, this);
     }
-    if (!mImageClient->UpdateImage(mContainer, GetContentFlags(), Nothing())) {
+    if (!mImageClient->UpdateImage(mContainer, GetContentFlags())) {
       return;
     }
   }
   ClientManager()->Hold(this);
 }
 
 already_AddRefed<ImageLayer> ClientLayerManager::CreateImageLayer() {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -156,18 +156,17 @@ already_AddRefed<TextureClient> ImageCli
     }
 
     texture->Unlock();
   }
   return texture.forget();
 }
 
 bool ImageClientSingle::UpdateImage(ImageContainer* aContainer,
-                                    uint32_t aContentFlags,
-                                    const Maybe<wr::RenderRoot>& aRenderRoot) {
+                                    uint32_t aContentFlags) {
   AutoTArray<ImageContainer::OwningImage, 4> images;
   uint32_t generationCounter;
   aContainer->GetCurrentImages(&images, &generationCounter);
 
   if (mLastUpdateGenerationCounter == generationCounter) {
     return true;
   }
   mLastUpdateGenerationCounter = generationCounter;
@@ -281,18 +280,17 @@ ImageClient::ImageClient(CompositableFor
       mType(aType),
       mLastUpdateGenerationCounter(0) {}
 
 ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
                                      TextureFlags aFlags)
     : ImageClient(aFwd, aFlags, CompositableType::IMAGE_BRIDGE) {}
 
 bool ImageClientBridge::UpdateImage(ImageContainer* aContainer,
-                                    uint32_t aContentFlags,
-                                    const Maybe<wr::RenderRoot>& aRenderRoot) {
+                                    uint32_t aContentFlags) {
   if (!GetForwarder() || !mLayer) {
     return false;
   }
   if (mAsyncContainerHandle == aContainer->GetAsyncContainerHandle()) {
     return true;
   }
 
   mAsyncContainerHandle = aContainer->GetAsyncContainerHandle();
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -48,18 +48,18 @@ class ImageClient : public CompositableC
 
   virtual ~ImageClient() = default;
 
   /**
    * Update this ImageClient from aContainer in aLayer
    * returns false if this is the wrong kind of ImageClient for aContainer.
    * Note that returning true does not necessarily imply success
    */
-  virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags,
-                           const Maybe<wr::RenderRoot>& aRenderRoot) = 0;
+  virtual bool UpdateImage(ImageContainer* aContainer,
+                           uint32_t aContentFlags) = 0;
 
   void SetLayer(ClientLayer* aLayer) { mLayer = aLayer; }
   ClientLayer* GetLayer() const { return mLayer; }
 
   /**
    * asynchronously remove all the textures used by the image client.
    *
    */
@@ -90,18 +90,17 @@ class ImageClient : public CompositableC
 /**
  * An image client which uses a single texture client.
  */
 class ImageClientSingle : public ImageClient {
  public:
   ImageClientSingle(CompositableForwarder* aFwd, TextureFlags aFlags,
                     CompositableType aType);
 
-  bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag,
-                   const Maybe<wr::RenderRoot>& aRenderRoot) override;
+  bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag) override;
 
   void OnDetach() override;
 
   bool AddTextureClient(TextureClient* aTexture) override;
 
   TextureInfo GetTextureInfo() const override;
 
   void FlushAllImages() override;
@@ -124,18 +123,17 @@ class ImageClientSingle : public ImageCl
  * Image class to be used for async image uploads using the image bridge
  * protocol.
  * We store the ImageBridge id in the TextureClientIdentifier.
  */
 class ImageClientBridge : public ImageClient {
  public:
   ImageClientBridge(CompositableForwarder* aFwd, TextureFlags aFlags);
 
-  bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags,
-                   const Maybe<wr::RenderRoot>& aRenderRoot) override;
+  bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags) override;
   bool Connect(ImageContainer* aImageContainer) override { return false; }
 
   TextureInfo GetTextureInfo() const override { return TextureInfo(mType); }
 
  protected:
   CompositableHandle mAsyncContainerHandle;
 };
 
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/AsyncCompositionManager.h"
 #include <stdint.h>                 // for uint32_t
 #include "LayerManagerComposite.h"  // for LayerManagerComposite, etc
 #include "Layers.h"                 // for Layer, ContainerLayer, etc
 #include "gfxPoint.h"               // for gfxPoint, gfxSize
 #include "mozilla/ServoBindings.h"  // for Servo_AnimationValue_GetOpacity, etc
+#include "mozilla/ScopeExit.h"      // for MakeScopeExit
 #include "mozilla/StaticPrefs_apz.h"
 #include "mozilla/StaticPrefs_gfx.h"
 #include "mozilla/WidgetUtils.h"      // for ComputeTransformForRotation
 #include "mozilla/gfx/BaseRect.h"     // for BaseRect
 #include "mozilla/gfx/Point.h"        // for RoundedToInt, PointTyped
 #include "mozilla/gfx/Rect.h"         // for RoundedToInt, RectTyped
 #include "mozilla/gfx/ScaleFactor.h"  // for ScaleFactor
 #include "mozilla/layers/AnimationHelper.h"
@@ -636,63 +637,70 @@ static void ApplyAnimatedValue(
       layerCompositor->SetShadowOpacitySetByAnimation(false);
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
   }
 }
 
-static bool SampleAnimations(Layer* aLayer,
-                             CompositorAnimationStorage* aStorage,
-                             TimeStamp aPreviousFrameTime,
-                             TimeStamp aCurrentFrameTime) {
+bool AsyncCompositionManager::SampleAnimations(Layer* aLayer,
+                                               TimeStamp aCurrentFrameTime) {
   bool isAnimating = false;
+  CompositorAnimationStorage* storage =
+      mCompositorBridge->GetAnimationStorage();
+
+  auto autoClearAnimationStorage = MakeScopeExit([&] {
+    if (!isAnimating) {
+      // Clean up the CompositorAnimationStorage because
+      // there are no active animations running
+      storage->Clear();
+    }
+  });
 
   ForEachNode<ForwardIterator>(aLayer, [&](Layer* layer) {
     auto& propertyAnimationGroups = layer->GetPropertyAnimationGroups();
     if (propertyAnimationGroups.IsEmpty()) {
       return;
     }
 
     isAnimating = true;
     AnimatedValue* previousValue =
-        aStorage->GetAnimatedValue(layer->GetCompositorAnimationsId());
+        storage->GetAnimatedValue(layer->GetCompositorAnimationsId());
 
     nsTArray<RefPtr<RawServoAnimationValue>> animationValues;
     AnimationHelper::SampleResult sampleResult =
         AnimationHelper::SampleAnimationForEachNode(
-            aPreviousFrameTime, aCurrentFrameTime, previousValue,
+            mPreviousFrameTimeStamp, aCurrentFrameTime, previousValue,
             propertyAnimationGroups, animationValues);
 
     const PropertyAnimationGroup& lastPropertyAnimationGroup =
         propertyAnimationGroups.LastElement();
 
     switch (sampleResult) {
       case AnimationHelper::SampleResult::Sampled:
         // We assume all transform like properties (on the same frame) live in
         // a single same layer, so using the transform data of the last element
         // should be fine.
-        ApplyAnimatedValue(layer, aStorage,
-                           lastPropertyAnimationGroup.mProperty,
+        ApplyAnimatedValue(layer, storage, lastPropertyAnimationGroup.mProperty,
                            animationValues);
         break;
       case AnimationHelper::SampleResult::Skipped:
         switch (lastPropertyAnimationGroup.mProperty) {
           case eCSSProperty_background_color:
           case eCSSProperty_opacity: {
             if (lastPropertyAnimationGroup.mProperty == eCSSProperty_opacity) {
               MOZ_ASSERT(
                   layer->AsHostLayer()->GetShadowOpacitySetByAnimation());
 #ifdef DEBUG
               // Disable this assertion until the root cause is fixed in bug
               // 1459775.
               // MOZ_ASSERT(FuzzyEqualsMultiplicative(
               //   Servo_AnimationValue_GetOpacity(animationValue),
-              //   *(aStorage->GetAnimationOpacity(layer->GetCompositorAnimationsId()))));
+              //   *(storage->GetAnimationOpacity(layer->GetCompositorAnimationsId()))));
 #endif
             }
             // Even if opacity or background-color  animation value has
             // unchanged, we have to set the shadow base transform value
             // here since the value might have been changed by APZC.
             HostLayer* layerCompositor = layer->AsHostLayer();
             layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
             layerCompositor->SetShadowTransformSetByAnimation(false);
@@ -1420,29 +1428,20 @@ bool AsyncCompositionManager::TransformS
     CompositorBridgeParentBase::TransformsToSkip aSkip) {
   AUTO_PROFILER_LABEL("AsyncCompositionManager::TransformShadowTree", GRAPHICS);
 
   Layer* root = mLayerManager->GetRoot();
   if (!root) {
     return false;
   }
 
-  CompositorAnimationStorage* storage =
-      mCompositorBridge->GetAnimationStorage();
   // First, compute and set the shadow transforms from OMT animations.
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
-  bool wantNextFrame =
-      SampleAnimations(root, storage, mPreviousFrameTimeStamp, aCurrentFrame);
-
-  if (!wantNextFrame) {
-    // Clean up the CompositorAnimationStorage because
-    // there are no active animations running
-    storage->Clear();
-  }
+  bool wantNextFrame = SampleAnimations(root, aCurrentFrame);
 
   // Advance animations to the next expected vsync timestamp, if we can
   // get it.
   TimeStamp nextFrame = aCurrentFrame;
 
   MOZ_ASSERT(aVsyncRate != TimeDuration::Forever());
   if (aVsyncRate != TimeDuration::Forever()) {
     nextFrame += aVsyncRate;
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -215,16 +215,18 @@ class AsyncCompositionManager final {
    * since ResolveRefLayers was called.
    */
   void DetachRefLayers();
 
   // Records the shadow transforms for the tree of layers rooted at the given
   // layer
   void RecordShadowTransforms(Layer* aLayer);
 
+  bool SampleAnimations(Layer* aLayer, TimeStamp aCurrentFrameTime);
+
   TargetConfig mTargetConfig;
   CSSRect mContentRect;
 
   RefPtr<HostLayerManager> mLayerManager;
   // When this flag is set, the next composition will be the first for a
   // particular document (i.e. the document displayed on the screen will
   // change). This happens when loading a new page or switching tabs. We notify
   // the front-end (e.g. Java on Android) about this so that it take the new
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -2257,25 +2257,24 @@ void CompositorBridgeParent::DidComposit
     mTxnStartTime = TimeStamp();
     mFwdTime = TimeStamp();
 #endif
     mPendingTransaction = TransactionId{0};
   }
 }
 
 void CompositorBridgeParent::NotifyDidSceneBuild(
-    const nsTArray<wr::RenderRoot>& aRenderRoots,
     RefPtr<const wr::WebRenderPipelineInfo> aInfo) {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   if (mPaused) {
     return;
   }
 
   if (mWrBridge) {
-    mWrBridge->NotifyDidSceneBuild(aRenderRoots, aInfo);
+    mWrBridge->NotifyDidSceneBuild(aInfo);
   } else {
     mCompositorScheduler->ScheduleComposition();
   }
 }
 
 void CompositorBridgeParent::NotifyPipelineRendered(
     const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
     const VsyncId& aCompositeStartId, TimeStamp& aCompositeStart,
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -443,18 +443,17 @@ class CompositorBridgeParent final : pub
   void NotifyWebRenderDisableNativeCompositor();
 
   void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
                               const wr::Epoch& aEpoch,
                               const VsyncId& aCompositeStartId,
                               TimeStamp& aCompositeStart,
                               TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
                               wr::RendererStats* aStats = nullptr);
-  void NotifyDidSceneBuild(const nsTArray<wr::RenderRoot>& aRenderRoots,
-                           RefPtr<const wr::WebRenderPipelineInfo> aInfo);
+  void NotifyDidSceneBuild(RefPtr<const wr::WebRenderPipelineInfo> aInfo);
   RefPtr<AsyncImagePipelineManager> GetAsyncImagePipelineManager() const;
 
   PCompositorWidgetParent* AllocPCompositorWidgetParent(
       const CompositorWidgetInitData& aInitData) override;
   bool DeallocPCompositorWidgetParent(PCompositorWidgetParent* aActor) override;
 
   void ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch,
                            bool aActive) override {}
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -324,17 +324,17 @@ void ImageBridgeChild::UpdateImageClient
 
   // If the client has become disconnected before this event was dispatched,
   // early return now.
   if (!client->IsConnected()) {
     return;
   }
 
   BeginTransaction();
-  client->UpdateImage(aContainer, Layer::CONTENT_OPAQUE, Nothing());
+  client->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
   EndTransaction();
 }
 
 void ImageBridgeChild::UpdateAsyncCanvasRendererSync(
     SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper) {
   AutoCompleteTask complete(aTask);
 
   UpdateAsyncCanvasRendererNow(aWrapper);
@@ -363,18 +363,17 @@ void ImageBridgeChild::UpdateAsyncCanvas
     AsyncCanvasRenderer* aWrapper) {
   MOZ_ASSERT(aWrapper);
 
   if (!CanSend()) {
     return;
   }
 
   BeginTransaction();
-  // TODO wr::RenderRoot::Unknown
-  aWrapper->GetCanvasClient()->Updated(wr::RenderRoot::Default);
+  aWrapper->GetCanvasClient()->Updated();
   EndTransaction();
 }
 
 void ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
                                           ImageClient* aClient,
                                           ImageContainer* aContainer) {
   AutoCompleteTask complete(aTask);
 
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -19,17 +19,16 @@ using mozilla::layers::ScrollableLayerGu
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositionPayload from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::wr::BuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::MaybeIdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ExternalImageKeyPair from "mozilla/webrender/WebRenderTypes.h";
-using mozilla::wr::RenderRoot from "mozilla/webrender/WebRenderTypes.h";
 using moveonly mozilla::layers::RenderRootDisplayListData from "mozilla/layers/RenderRootTypes.h";
 using moveonly mozilla::layers::RenderRootUpdates from "mozilla/layers/RenderRootTypes.h";
 using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
 using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
 
 namespace mozilla {
@@ -57,18 +56,17 @@ parent:
                          RenderRootUpdates[] renderRootUpdates,
                          OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
                          VsyncId vsyncId, TimeStamp vsyncStartTime,
                          TimeStamp refreshStartTime, TimeStamp txnStartTime,
                          nsCString txnURL, TimeStamp fwdTime,
                          CompositionPayload[] payloads);
   async SetFocusTarget(FocusTarget focusTarget);
   async UpdateResources(OpUpdateResource[] aResourceUpdates,
-                        RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
-                        RenderRoot aRenderRoot);
+                        RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync GetSnapshot(PTexture texture);
   async SetLayersObserverEpoch(LayersObserverEpoch childEpoch);
   async ClearCachedResources();
   // Invalidate rendered frame
   async InvalidateRenderedFrame();
   // Schedule a composite if one isn't already scheduled.
   async ScheduleComposite();
--- a/gfx/layers/wr/RenderRootStateManager.cpp
+++ b/gfx/layers/wr/RenderRootStateManager.cpp
@@ -31,17 +31,16 @@ WebRenderCommandBuilder& RenderRootState
 
 RenderRootStateManager::WebRenderUserDataRefTable*
 RenderRootStateManager::GetWebRenderUserDataTable() {
   return mLayerManager->GetWebRenderUserDataTable();
 }
 
 wr::IpcResourceUpdateQueue& RenderRootStateManager::AsyncResourceUpdates() {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(XRE_IsParentProcess() || mRenderRoot == wr::RenderRoot::Default);
 
   if (!mAsyncResourceUpdates) {
     mAsyncResourceUpdates.emplace(WrBridge());
 
     RefPtr<Runnable> task = NewRunnableMethod(
         "RenderRootStateManager::FlushAsyncResourceUpdates", this,
         &RenderRootStateManager::FlushAsyncResourceUpdates);
     NS_DispatchToMainThread(task.forget());
@@ -68,17 +67,17 @@ void RenderRootStateManager::Destroy() {
 void RenderRootStateManager::FlushAsyncResourceUpdates() {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mAsyncResourceUpdates) {
     return;
   }
 
   if (!IsDestroyed() && WrBridge()) {
-    WrBridge()->UpdateResources(mAsyncResourceUpdates.ref(), mRenderRoot);
+    WrBridge()->UpdateResources(mAsyncResourceUpdates.ref());
   }
 
   mAsyncResourceUpdates.reset();
 }
 
 void RenderRootStateManager::AddImageKeyForDiscard(wr::ImageKey key) {
   mImageKeysToDelete.AppendElement(key);
 }
@@ -175,17 +174,17 @@ void RenderRootStateManager::WrReleasedI
 }
 
 void RenderRootStateManager::AddWebRenderParentCommand(
     const WebRenderParentCommand& aCmd) {
   WrBridge()->AddWebRenderParentCommand(aCmd);
 }
 void RenderRootStateManager::UpdateResources(
     wr::IpcResourceUpdateQueue& aResources) {
-  WrBridge()->UpdateResources(aResources, mRenderRoot);
+  WrBridge()->UpdateResources(aResources);
 }
 void RenderRootStateManager::AddPipelineIdForAsyncCompositable(
     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
   WrBridge()->AddPipelineIdForAsyncCompositable(aPipelineId, aHandle);
 }
 void RenderRootStateManager::AddPipelineIdForCompositable(
     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
   WrBridge()->AddPipelineIdForCompositable(aPipelineId, aHandle);
@@ -197,20 +196,18 @@ void RenderRootStateManager::RemovePipel
 /// Release TextureClient that is bounded to ImageKey.
 /// It is used for recycling TextureClient.
 void RenderRootStateManager::ReleaseTextureOfImage(const wr::ImageKey& aKey) {
   WrBridge()->ReleaseTextureOfImage(aKey);
 }
 
 Maybe<wr::FontInstanceKey> RenderRootStateManager::GetFontKeyForScaledFont(
     gfx::ScaledFont* aScaledFont, wr::IpcResourceUpdateQueue* aResources) {
-  return WrBridge()->GetFontKeyForScaledFont(aScaledFont, mRenderRoot,
-                                             aResources);
+  return WrBridge()->GetFontKeyForScaledFont(aScaledFont, aResources);
 }
 
 Maybe<wr::FontKey> RenderRootStateManager::GetFontKeyForUnscaledFont(
     gfx::UnscaledFont* aUnscaledFont, wr::IpcResourceUpdateQueue* aResources) {
-  return WrBridge()->GetFontKeyForUnscaledFont(aUnscaledFont, mRenderRoot,
-                                               aResources);
+  return WrBridge()->GetFontKeyForUnscaledFont(aUnscaledFont, aResources);
 }
 
 }  // namespace layers
 }  // namespace mozilla
--- a/gfx/layers/wr/RenderRootStateManager.h
+++ b/gfx/layers/wr/RenderRootStateManager.h
@@ -22,22 +22,20 @@ class RenderRootStateManager {
       WebRenderUserDataRefTable;
 
  public:
   void AddRef();
   void Release();
 
   RenderRootStateManager()
       : mLayerManager(nullptr),
-        mRenderRoot(wr::RenderRoot::Default),
         mDestroyed(false) {}
 
   void Destroy();
   bool IsDestroyed() { return mDestroyed; }
-  wr::RenderRoot GetRenderRoot() { return mRenderRoot; }
   wr::IpcResourceUpdateQueue& AsyncResourceUpdates();
   WebRenderBridgeChild* WrBridge() const;
   WebRenderCommandBuilder& CommandBuilder();
   WebRenderUserDataRefTable* GetWebRenderUserDataTable();
   WebRenderLayerManager* LayerManager() { return mLayerManager; }
 
   void AddImageKeyForDiscard(wr::ImageKey key);
   void AddBlobImageKeyForDiscard(wr::BlobImageKey key);
@@ -88,17 +86,16 @@ class RenderRootStateManager {
 
   // Set of compositor animation ids for which there are active animations (as
   // of the last transaction) on the compositor side.
   std::unordered_set<uint64_t> mActiveCompositorAnimationIds;
   // Compositor animation ids for animations that are done now and that we want
   // the compositor to discard information for.
   nsTArray<uint64_t> mDiscardedCompositorAnimationsIds;
 
-  wr::RenderRoot mRenderRoot;
   bool mDestroyed;
 
   friend class WebRenderLayerManager;
 };
 
 }  // namespace layers
 }  // namespace mozilla
 
--- a/gfx/layers/wr/RenderRootTypes.cpp
+++ b/gfx/layers/wr/RenderRootTypes.cpp
@@ -8,35 +8,33 @@
 #include "mozilla/layers/WebRenderMessageUtils.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 
 namespace mozilla {
 namespace ipc {
 
 void IPDLParamTraits<mozilla::layers::RenderRootDisplayListData>::Write(
     IPC::Message* aMsg, IProtocol* aActor, paramType&& aParam) {
-  WriteIPDLParam(aMsg, aActor, aParam.mRenderRoot);
   WriteIPDLParam(aMsg, aActor, aParam.mIdNamespace);
   WriteIPDLParam(aMsg, aActor, aParam.mRect);
   WriteIPDLParam(aMsg, aActor, aParam.mCommands);
   WriteIPDLParam(aMsg, aActor, aParam.mContentSize);
   WriteIPDLParam(aMsg, aActor, std::move(aParam.mDL));
   WriteIPDLParam(aMsg, aActor, aParam.mDLDesc);
   WriteIPDLParam(aMsg, aActor, aParam.mRemotePipelineIds);
   WriteIPDLParam(aMsg, aActor, aParam.mResourceUpdates);
   WriteIPDLParam(aMsg, aActor, aParam.mSmallShmems);
   WriteIPDLParam(aMsg, aActor, std::move(aParam.mLargeShmems));
   WriteIPDLParam(aMsg, aActor, aParam.mScrollData);
 }
 
 bool IPDLParamTraits<mozilla::layers::RenderRootDisplayListData>::Read(
     const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
     paramType* aResult) {
-  if (ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRenderRoot) &&
-      ReadIPDLParam(aMsg, aIter, aActor, &aResult->mIdNamespace) &&
+  if (ReadIPDLParam(aMsg, aIter, aActor, &aResult->mIdNamespace) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRect) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCommands) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mContentSize) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDL) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLDesc) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRemotePipelineIds) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResourceUpdates) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSmallShmems) &&
@@ -79,30 +77,28 @@ bool ReadScrollUpdates(const IPC::Messag
 
   MOZ_RELEASE_ASSERT(map.Count() == count);
   *aResult = std::move(map);
   return true;
 }
 
 void IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Write(
     IPC::Message* aMsg, IProtocol* aActor, paramType&& aParam) {
-  WriteIPDLParam(aMsg, aActor, aParam.mRenderRoot);
   WriteIPDLParam(aMsg, aActor, aParam.mCommands);
   WriteIPDLParam(aMsg, aActor, aParam.mResourceUpdates);
   WriteIPDLParam(aMsg, aActor, aParam.mSmallShmems);
   WriteIPDLParam(aMsg, aActor, std::move(aParam.mLargeShmems));
   WriteScrollUpdates(aMsg, aActor, aParam.mScrollUpdates);
   WriteIPDLParam(aMsg, aActor, aParam.mPaintSequenceNumber);
 }
 
 bool IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Read(
     const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
     paramType* aResult) {
-  if (ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRenderRoot) &&
-      ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCommands) &&
+  if (ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCommands) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResourceUpdates) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSmallShmems) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLargeShmems) &&
       ReadScrollUpdates(aMsg, aIter, aActor, &aResult->mScrollUpdates) &&
       ReadIPDLParam(aMsg, aIter, aActor, &aResult->mPaintSequenceNumber)) {
     return true;
   }
   return false;
--- a/gfx/layers/wr/RenderRootTypes.h
+++ b/gfx/layers/wr/RenderRootTypes.h
@@ -13,54 +13,38 @@
 #include "mozilla/layers/WebRenderScrollData.h"
 #include "mozilla/Variant.h"
 
 namespace mozilla {
 
 namespace layers {
 
 struct RenderRootDisplayListData {
-  wr::RenderRoot mRenderRoot;
   wr::IdNamespace mIdNamespace;
   LayoutDeviceRect mRect;
   nsTArray<WebRenderParentCommand> mCommands;
   wr::LayoutSize mContentSize;
   Maybe<mozilla::ipc::ByteBuf> mDL;
   wr::BuiltDisplayListDescriptor mDLDesc;
   nsTArray<wr::PipelineId> mRemotePipelineIds;
   nsTArray<OpUpdateResource> mResourceUpdates;
   nsTArray<RefCountedShmem> mSmallShmems;
   nsTArray<mozilla::ipc::Shmem> mLargeShmems;
   Maybe<WebRenderScrollData> mScrollData;
 };
 
 struct RenderRootUpdates {
-  wr::RenderRoot mRenderRoot;
   nsTArray<WebRenderParentCommand> mCommands;
   nsTArray<OpUpdateResource> mResourceUpdates;
   nsTArray<RefCountedShmem> mSmallShmems;
   nsTArray<mozilla::ipc::Shmem> mLargeShmems;
   ScrollUpdatesMap mScrollUpdates;
   uint32_t mPaintSequenceNumber;
 };
 
-struct ResourceUpdates {
-  nsTArray<OpUpdateResource> mResourceUpdates;
-  nsTArray<RefCountedShmem> mSmallShmems;
-  nsTArray<mozilla::ipc::Shmem> mLargeShmems;
-};
-
-struct ParentCommands {
-  nsTArray<WebRenderParentCommand> mCommands;
-};
-
-typedef Variant<RenderRootDisplayListData, RenderRootUpdates, ResourceUpdates,
-                ParentCommands, FocusTarget>
-    RenderRootDeferredData;
-
 }  // namespace layers
 
 namespace ipc {
 
 template <>
 struct IPDLParamTraits<mozilla::layers::RenderRootDisplayListData> {
   typedef mozilla::layers::RenderRootDisplayListData paramType;
 
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -79,48 +79,47 @@ void WebRenderBridgeChild::AddWebRenderP
 void WebRenderBridgeChild::BeginTransaction() {
   MOZ_ASSERT(!mDestroyed);
 
   UpdateFwdTransactionId();
   mIsInTransaction = true;
 }
 
 void WebRenderBridgeChild::UpdateResources(
-    wr::IpcResourceUpdateQueue& aResources, wr::RenderRoot aRenderRoot) {
+    wr::IpcResourceUpdateQueue& aResources) {
   if (!IPCOpen()) {
     aResources.Clear();
     return;
   }
 
   if (aResources.IsEmpty()) {
     return;
   }
 
   nsTArray<OpUpdateResource> resourceUpdates;
   nsTArray<RefCountedShmem> smallShmems;
   nsTArray<ipc::Shmem> largeShmems;
   aResources.Flush(resourceUpdates, smallShmems, largeShmems);
 
   this->SendUpdateResources(resourceUpdates, smallShmems,
-                            std::move(largeShmems), aRenderRoot);
+                            std::move(largeShmems));
 }
 
 bool WebRenderBridgeChild::EndTransaction(
     nsTArray<RenderRootDisplayListData>& aRenderRoots,
     TransactionId aTransactionId, bool aContainsSVGGroup,
     const mozilla::VsyncId& aVsyncId, const mozilla::TimeStamp& aVsyncStartTime,
     const mozilla::TimeStamp& aRefreshStartTime,
     const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   TimeStamp fwdTime = TimeStamp::Now();
 
   for (auto& renderRoot : aRenderRoots) {
-    MOZ_ASSERT(renderRoot.mRenderRoot == wr::RenderRoot::Default);
     renderRoot.mCommands = std::move(mParentCommands);
     renderRoot.mIdNamespace = mIdNamespace;
   }
 
   nsTArray<CompositionPayload> payloads;
   if (mManager) {
     mManager->TakeCompositionPayloads(payloads);
   }
@@ -149,17 +148,16 @@ void WebRenderBridgeChild::EndEmptyTrans
     const mozilla::TimeStamp& aRefreshStartTime,
     const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   TimeStamp fwdTime = TimeStamp::Now();
 
   for (auto& update : aRenderRootUpdates) {
-    MOZ_ASSERT(update.mRenderRoot == wr::RenderRoot::Default);
     update.mCommands = std::move(mParentCommands);
   }
 
   nsTArray<CompositionPayload> payloads;
   if (mManager) {
     mManager->TakeCompositionPayloads(payloads);
   }
 
@@ -244,44 +242,42 @@ static void WriteFontDescriptor(const ui
 void WebRenderBridgeChild::PushGlyphs(
     wr::DisplayListBuilder& aBuilder, Range<const wr::GlyphInstance> aGlyphs,
     gfx::ScaledFont* aFont, const wr::ColorF& aColor,
     const StackingContextHelper& aSc, const wr::LayoutRect& aBounds,
     const wr::LayoutRect& aClip, bool aBackfaceVisible,
     const wr::GlyphOptions* aGlyphOptions) {
   MOZ_ASSERT(aFont);
 
-  Maybe<wr::WrFontInstanceKey> key =
-      GetFontKeyForScaledFont(aFont, aBuilder.GetRenderRoot());
+  Maybe<wr::WrFontInstanceKey> key = GetFontKeyForScaledFont(aFont);
   MOZ_ASSERT(key.isSome());
 
   if (key.isSome()) {
     aBuilder.PushText(aBounds, aClip, aBackfaceVisible, aColor, key.value(),
                       aGlyphs, aGlyphOptions);
   }
 }
 
 Maybe<wr::FontInstanceKey> WebRenderBridgeChild::GetFontKeyForScaledFont(
-    gfx::ScaledFont* aScaledFont, wr::RenderRoot aRenderRoot,
-    wr::IpcResourceUpdateQueue* aResources) {
+    gfx::ScaledFont* aScaledFont, wr::IpcResourceUpdateQueue* aResources) {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(aScaledFont);
   MOZ_ASSERT(aScaledFont->CanSerialize());
 
   wr::FontInstanceKey instanceKey = {wr::IdNamespace{0}, 0};
   if (mFontInstanceKeys.Get(aScaledFont, &instanceKey)) {
     return Some(instanceKey);
   }
 
   Maybe<wr::IpcResourceUpdateQueue> resources =
       aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
   aResources = resources.ptrOr(aResources);
 
-  Maybe<wr::FontKey> fontKey = GetFontKeyForUnscaledFont(
-      aScaledFont->GetUnscaledFont(), aRenderRoot, aResources);
+  Maybe<wr::FontKey> fontKey =
+      GetFontKeyForUnscaledFont(aScaledFont->GetUnscaledFont(), aResources);
   if (fontKey.isNothing()) {
     return Nothing();
   }
 
   instanceKey = GetNextFontInstanceKey();
 
   Maybe<wr::FontInstanceOptions> options;
   Maybe<wr::FontInstancePlatformOptions> platformOptions;
@@ -289,27 +285,26 @@ Maybe<wr::FontInstanceKey> WebRenderBrid
   aScaledFont->GetWRFontInstanceOptions(&options, &platformOptions,
                                         &variations);
 
   aResources->AddFontInstance(
       instanceKey, fontKey.value(), aScaledFont->GetSize(),
       options.ptrOr(nullptr), platformOptions.ptrOr(nullptr),
       Range<const FontVariation>(variations.data(), variations.size()));
   if (resources.isSome()) {
-    UpdateResources(resources.ref(), aRenderRoot);
+    UpdateResources(resources.ref());
   }
 
   mFontInstanceKeys.Put(aScaledFont, instanceKey);
 
   return Some(instanceKey);
 }
 
 Maybe<wr::FontKey> WebRenderBridgeChild::GetFontKeyForUnscaledFont(
-    gfx::UnscaledFont* aUnscaled, wr::RenderRoot aRenderRoot,
-    wr::IpcResourceUpdateQueue* aResources) {
+    gfx::UnscaledFont* aUnscaled, wr::IpcResourceUpdateQueue* aResources) {
   MOZ_ASSERT(!mDestroyed);
 
   wr::FontKey fontKey = {wr::IdNamespace{0}, 0};
   if (!mFontKeys.Get(aUnscaled, &fontKey)) {
     Maybe<wr::IpcResourceUpdateQueue> resources =
         aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
 
     FontFileDataSink sink = {&fontKey, this, resources.ptrOr(aResources)};
@@ -319,17 +314,17 @@ Maybe<wr::FontKey> WebRenderBridgeChild:
     // fails, then the only thing left to do is signal failure by returning a
     // null font key.
     if (!aUnscaled->GetFontDescriptor(WriteFontDescriptor, &sink) &&
         !aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
       return Nothing();
     }
 
     if (resources.isSome()) {
-      UpdateResources(resources.ref(), aRenderRoot);
+      UpdateResources(resources.ref());
     }
 
     mFontKeys.Put(aUnscaled, fontKey);
   }
 
   return Some(fontKey);
 }
 
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -62,18 +62,17 @@ class WebRenderBridgeChild final : publi
   friend class PWebRenderBridgeChild;
 
  public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
   bool HasWebRenderParentCommands() { return !mParentCommands.IsEmpty(); }
 
-  void UpdateResources(wr::IpcResourceUpdateQueue& aResources,
-                       wr::RenderRoot aRenderRoot);
+  void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
   void BeginTransaction();
   bool EndTransaction(nsTArray<RenderRootDisplayListData>& aRenderRoots,
                       TransactionId aTransactionId, bool aContainsSVGroup,
                       const mozilla::VsyncId& aVsyncId,
                       const mozilla::TimeStamp& aVsyncStartTime,
                       const mozilla::TimeStamp& aRefreshStartTime,
                       const mozilla::TimeStamp& aTxnStartTime,
                       const nsCString& aTxtURL);
@@ -140,20 +139,20 @@ class WebRenderBridgeChild final : publi
                   Range<const wr::GlyphInstance> aGlyphs,
                   gfx::ScaledFont* aFont, const wr::ColorF& aColor,
                   const StackingContextHelper& aSc,
                   const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
                   bool aBackfaceVisible,
                   const wr::GlyphOptions* aGlyphOptions = nullptr);
 
   Maybe<wr::FontInstanceKey> GetFontKeyForScaledFont(
-      gfx::ScaledFont* aScaledFont, wr::RenderRoot aRenderRoot,
+      gfx::ScaledFont* aScaledFont,
       wr::IpcResourceUpdateQueue* aResources = nullptr);
   Maybe<wr::FontKey> GetFontKeyForUnscaledFont(
-      gfx::UnscaledFont* aUnscaledFont, wr::RenderRoot aRenderRoot,
+      gfx::UnscaledFont* aUnscaledFont,
       wr::IpcResourceUpdateQueue* aResources = nullptr);
   void RemoveExpiredFontKeys(wr::IpcResourceUpdateQueue& aResources);
 
   void BeginClearCachedResources();
   void EndClearCachedResources();
 
   void SetWebRenderLayerManager(WebRenderLayerManager* aManager);
 
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -356,18 +356,16 @@ WebRenderBridgeParent::WebRenderBridgePa
   MOZ_ASSERT(mAsyncImageManager);
   MOZ_ASSERT(mAnimStorage);
   mAsyncImageManager->AddPipeline(mPipelineId, this);
   if (IsRootWebRenderBridgeParent()) {
     MOZ_ASSERT(!mCompositorScheduler);
     mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
   }
 
-  mRenderRoot = Some(wr::RenderRoot::Default);
-
   UpdateDebugFlags();
   UpdateQualitySettings();
 }
 
 WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId)
     : mCompositorBridge(nullptr),
       mPipelineId(aPipelineId),
       mChildLayersObserverEpoch{0},
@@ -378,212 +376,38 @@ WebRenderBridgeParent::WebRenderBridgePa
       mDestroyed(true),
       mReceivedDisplayList(false),
       mIsFirstPaint(false),
       mSkippedComposite(false),
       mDisablingNativeCompositor(false),
       mPendingScrollPayloads("WebRenderBridgeParent::mPendingScrollPayloads") {}
 
 WebRenderBridgeParent::~WebRenderBridgeParent() {
-  if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
-    root->RemoveDeferredPipeline(mPipelineId);
-  }
-}
-
-bool WebRenderBridgeParent::RenderRootIsValid(wr::RenderRoot aRenderRoot) {
-  return aRenderRoot == wr::RenderRoot::Default;
-}
-
-void WebRenderBridgeParent::RemoveDeferredPipeline(wr::PipelineId aPipelineId) {
-  MOZ_ASSERT(IsRootWebRenderBridgeParent());
-  mPipelineRenderRoots.Remove(wr::AsUint64(aPipelineId));
-  if (auto entry = mPipelineDeferredUpdates.Lookup(wr::AsUint64(aPipelineId))) {
-    RefPtr<WebRenderBridgeParent> self = this;
-    for (auto& variant : entry.Data()) {
-      variant.match(
-          [=](RenderRootDisplayListData& x) {
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
-          },
-          [=](RenderRootUpdates& x) {
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
-          },
-          [=](ResourceUpdates& x) {
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
-            wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
-          },
-          [=](ParentCommands& x) {}, [=](FocusTarget& x) {});
-    }
-    entry.Remove();
-  }
 }
 
 /* static */
 WebRenderBridgeParent* WebRenderBridgeParent::CreateDestroyed(
     const wr::PipelineId& aPipelineId) {
   return new WebRenderBridgeParent(aPipelineId);
 }
 
-void WebRenderBridgeParent::PushDeferredPipelineData(
-    RenderRootDeferredData&& aDeferredData) {
-  MOZ_ASSERT(!IsRootWebRenderBridgeParent());
-  if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
-    uint64_t key = wr::AsUint64(mPipelineId);
-    root->mPipelineDeferredUpdates.LookupForAdd(key)
-        .OrInsert([]() { return nsTArray<RenderRootDeferredData>(); })
-        .AppendElement(std::move(aDeferredData));
-  }
-}
-
-bool WebRenderBridgeParent::HandleDeferredPipelineData(
-    nsTArray<RenderRootDeferredData>& aDeferredData,
-    const TimeStamp& aTxnStartTime) {
-  MOZ_ASSERT(!IsRootWebRenderBridgeParent());
-  for (auto& entry : aDeferredData) {
-    bool success = entry.match(
-        [&](RenderRootDisplayListData& data) {
-          // We ensure this with RenderRootIsValid before calling
-          // PushDeferredPipelineData:
-          MOZ_ASSERT(data.mRenderRoot == wr::RenderRoot::Default);
-          wr::Epoch wrEpoch = GetNextWrEpoch();
-          bool validTransaction = data.mIdNamespace == mIdNamespace;
-
-          if (!ProcessRenderRootDisplayListData(data, wrEpoch, aTxnStartTime,
-                                                validTransaction, false)) {
-            return false;
-          }
-
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
-          return true;
-        },
-        [&](RenderRootUpdates& data) {
-          // We ensure this with RenderRootIsValid before calling
-          // PushDeferredPipelineData:
-          MOZ_ASSERT(data.mRenderRoot == wr::RenderRoot::Default);
-          bool scheduleComposite;
-          if (!ProcessEmptyTransactionUpdates(data, &scheduleComposite)) {
-            return false;
-          }
-          if (scheduleComposite) {
-            ScheduleGenerateFrame();
-          }
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
-          return true;
-        },
-        [&](ResourceUpdates& data) {
-          wr::TransactionBuilder txn;
-          txn.SetLowPriority(!IsRootWebRenderBridgeParent());
-
-          if (!UpdateResources(data.mResourceUpdates, data.mSmallShmems,
-                               data.mLargeShmems, txn)) {
-            return false;
-          }
-
-          mApi->SendTransaction(txn);
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
-          wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
-          return true;
-        },
-        [&](ParentCommands& data) {
-          wr::TransactionBuilder txn;
-          txn.SetLowPriority(!IsRootWebRenderBridgeParent());
-          if (!ProcessWebRenderParentCommands(data.mCommands, txn)) {
-            return false;
-          }
-
-          mApi->SendTransaction(txn);
-          return true;
-        },
-        [&](FocusTarget& data) {
-          UpdateAPZFocusState(data);
-          return true;
-        });
-
-    if (!success) {
-      return false;
-    }
-  }
-  aDeferredData.Clear();
-  return true;
-}
-
-bool WebRenderBridgeParent::MaybeHandleDeferredPipelineDataForPipeline(
-    wr::RenderRoot aRenderRoot, wr::PipelineId aPipelineId,
-    const TimeStamp& aTxnStartTime) {
-  MOZ_ASSERT(IsRootWebRenderBridgeParent());
-
-  uint64_t key = wr::AsUint64(aPipelineId);
-  auto entry = mPipelineRenderRoots.LookupForAdd(key);
-  if (!entry) {
-    entry.OrInsert([=]() { return aRenderRoot; });
-
-    CompositorBridgeParent::LayerTreeState* lts =
-        CompositorBridgeParent::GetIndirectShadowTree(
-            wr::AsLayersId(aPipelineId));
-    if (!lts) {
-      return true;
-    }
-    RefPtr<WebRenderBridgeParent> wrbp = lts->mWrBridge;
-    if (!wrbp) {
-      return true;
-    }
-    MOZ_ASSERT(wrbp->mRenderRoot.refOr(aRenderRoot) == aRenderRoot);
-    wrbp->mRenderRoot = Some(aRenderRoot);
-
-    if (auto entry = mPipelineDeferredUpdates.Lookup(key)) {
-      wrbp->HandleDeferredPipelineData(entry.Data(), aTxnStartTime);
-      entry.Remove();
-
-      for (auto it = wrbp->mChildPipelines.Iter(); !it.Done(); it.Next()) {
-        if (!MaybeHandleDeferredPipelineDataForPipeline(
-                aRenderRoot, wr::AsPipelineId(it.Get()->GetKey()),
-                aTxnStartTime)) {
-          return false;
-        }
-      }
-    }
-  }
-
-  return true;
-}
-
-bool WebRenderBridgeParent::MaybeHandleDeferredPipelineData(
-    wr::RenderRoot aRenderRoot, const nsTArray<wr::PipelineId>& aPipelineIds,
-    const TimeStamp& aTxnStartTime) {
-  MOZ_ASSERT(IsRootWebRenderBridgeParent());
-  return true;
-}
-
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEnsureConnected(
     TextureFactoryIdentifier* aTextureFactoryIdentifier,
     MaybeIdNamespace* aMaybeIdNamespace) {
   if (mDestroyed) {
     *aTextureFactoryIdentifier =
         TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
     *aMaybeIdNamespace = Nothing();
     return IPC_OK();
   }
 
   MOZ_ASSERT(mIdNamespace.mHandle != 0);
   *aTextureFactoryIdentifier = GetTextureFactoryIdentifier();
   *aMaybeIdNamespace = Some(mIdNamespace);
 
-  if (!mRenderRoot) {
-    RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent();
-    if (!root) {
-      return IPC_FAIL(this, "Root WRBP is missing (shutting down?)");
-    }
-    if (auto p = root->mPipelineRenderRoots.Lookup(wr::AsUint64(mPipelineId))) {
-      mRenderRoot.emplace(p.Data());
-    }
-  }
-
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvShutdown() {
   return HandleShutdown();
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvShutdownSync() {
@@ -953,36 +777,23 @@ void WebRenderBridgeParent::ObserveShare
   for (const auto& pair : aPairs) {
     SharedSurfacesParent::Release(pair.id);
   }
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources(
     nsTArray<OpUpdateResource>&& aResourceUpdates,
     nsTArray<RefCountedShmem>&& aSmallShmems,
-    nsTArray<ipc::Shmem>&& aLargeShmems, const wr::RenderRoot& aRenderRoot) {
+    nsTArray<ipc::Shmem>&& aLargeShmems) {
   if (mDestroyed) {
     wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
     wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
     return IPC_OK();
   }
 
-  if (!RenderRootIsValid(aRenderRoot)) {
-    return IPC_FAIL(this, "Received an invalid renderRoot");
-  }
-
-  if (!mRenderRoot) {
-    PushDeferredPipelineData(AsVariant(ResourceUpdates{
-        std::move(aResourceUpdates),
-        std::move(aSmallShmems),
-        std::move(aLargeShmems),
-    }));
-    return IPC_OK();
-  }
-
   wr::TransactionBuilder txn;
   txn.SetLowPriority(!IsRootWebRenderBridgeParent());
 
   bool success =
       UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems, txn);
   wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
   wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
 
@@ -1099,48 +910,41 @@ WebRenderBridgeParent::GetRootWebRenderB
   if (!cbp) {
     return nullptr;
   }
 
   return cbp->GetWebRenderBridgeParent();
 }
 
 void WebRenderBridgeParent::UpdateAPZFocusState(const FocusTarget& aFocus) {
-  if (!mRenderRoot) {
-    PushDeferredPipelineData(AsVariant(aFocus));
-    return;
-  }
-
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
   if (!cbp) {
     return;
   }
   LayersId rootLayersId = cbp->RootLayerTreeId();
   if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
     apz->UpdateFocusState(rootLayersId, GetLayersId(), aFocus);
   }
 }
 
 void WebRenderBridgeParent::UpdateAPZScrollData(const wr::Epoch& aEpoch,
-                                                WebRenderScrollData&& aData,
-                                                wr::RenderRoot aRenderRoot) {
+                                                WebRenderScrollData&& aData) {
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
   if (!cbp) {
     return;
   }
   LayersId rootLayersId = cbp->RootLayerTreeId();
   if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
     apz->UpdateScrollDataAndTreeState(rootLayersId, GetLayersId(), aEpoch,
                                       std::move(aData));
   }
 }
 
 void WebRenderBridgeParent::UpdateAPZScrollOffsets(
-    ScrollUpdatesMap&& aUpdates, uint32_t aPaintSequenceNumber,
-    wr::RenderRoot aRenderRoot) {
+    ScrollUpdatesMap&& aUpdates, uint32_t aPaintSequenceNumber) {
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
   if (!cbp) {
     return;
   }
   LayersId rootLayersId = cbp->RootLayerTreeId();
   if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
     apz->UpdateScrollOffsets(rootLayersId, GetLayersId(), std::move(aUpdates),
                              aPaintSequenceNumber);
@@ -1161,19 +965,18 @@ void WebRenderBridgeParent::SetAPZSample
     if (frameInterval != TimeDuration::Forever()) {
       animationTime += frameInterval;
     }
     apz->SetSampleTime(animationTime);
   }
 }
 
 bool WebRenderBridgeParent::SetDisplayList(
-    wr::RenderRoot aRenderRoot, const LayoutDeviceRect& aRect,
-    const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL,
-    const wr::BuiltDisplayListDescriptor& aDLDesc,
+    const LayoutDeviceRect& aRect, const wr::LayoutSize& aContentSize,
+    ipc::ByteBuf&& aDL, const wr::BuiltDisplayListDescriptor& aDLDesc,
     const nsTArray<OpUpdateResource>& aResourceUpdates,
     const nsTArray<RefCountedShmem>& aSmallShmems,
     const nsTArray<ipc::Shmem>& aLargeShmems, const TimeStamp& aTxnStartTime,
     wr::TransactionBuilder& aTxn, wr::Epoch aWrEpoch, bool aValidTransaction,
     bool aObserveLayersUpdate) {
   if (NS_WARN_IF(!UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems,
                                   aTxn))) {
     return false;
@@ -1221,37 +1024,32 @@ bool WebRenderBridgeParent::ProcessRende
     bool aObserveLayersUpdate) {
   wr::TransactionBuilder txn;
   Maybe<wr::AutoTransactionSender> sender;
 
   // Note that this needs to happen before the display list transaction is
   // sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to
   // be in the updater queue at the time that the scene swap completes.
   if (aDisplayList.mScrollData) {
-    UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()),
-                        aDisplayList.mRenderRoot);
+    UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()));
   }
 
-  MOZ_ASSERT(aDisplayList.mRenderRoot == wr::RenderRoot::Default ||
-             IsRootWebRenderBridgeParent());
-  auto renderRoot = aDisplayList.mRenderRoot;
-
   txn.SetLowPriority(!IsRootWebRenderBridgeParent());
   if (aValidTransaction) {
     MOZ_ASSERT(aDisplayList.mIdNamespace == mIdNamespace);
     sender.emplace(mApi, &txn);
   }
 
   if (NS_WARN_IF(
           !ProcessWebRenderParentCommands(aDisplayList.mCommands, txn))) {
     return false;
   }
 
   if (aDisplayList.mDL &&
-      !SetDisplayList(renderRoot, aDisplayList.mRect, aDisplayList.mContentSize,
+      !SetDisplayList(aDisplayList.mRect, aDisplayList.mContentSize,
                       std::move(aDisplayList.mDL.ref()), aDisplayList.mDLDesc,
                       aDisplayList.mResourceUpdates, aDisplayList.mSmallShmems,
                       aDisplayList.mLargeShmems, aTxnStartTime, txn, aWrEpoch,
                       aValidTransaction, aObserveLayersUpdate)) {
     return false;
   }
   return true;
 }
@@ -1270,21 +1068,16 @@ mozilla::ipc::IPCResult WebRenderBridgeP
     }
     return IPC_OK();
   }
 
   // Guard against malicious content processes
   if (aDisplayLists.Length() == 0) {
     return IPC_FAIL(this, "Must send at least one RenderRootDisplayListData.");
   }
-  for (auto& displayList : aDisplayLists) {
-    if (!RenderRootIsValid(displayList.mRenderRoot)) {
-      return IPC_FAIL(this, "Received an invalid renderRoot");
-    }
-  }
 
   if (!IsRootWebRenderBridgeParent()) {
     CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
   }
 
   AUTO_PROFILER_TRACING_MARKER("Paint", "SetDisplayList", GRAPHICS);
   UpdateFwdTransactionId(aFwdTransactionId);
 
@@ -1316,49 +1109,16 @@ mozilla::ipc::IPCResult WebRenderBridgeP
         auto& firstNonEmpty = aDisplayLists[*firstScrollDataIndex].mScrollData;
         // Ensure the flag is the same on all of them.
         MOZ_RELEASE_ASSERT(scrollData->IsFirstPaint() ==
                            firstNonEmpty->IsFirstPaint());
       }
     }
   }
 
-  if (!mRenderRoot) {
-    // Only non-root WRBPs will ever have an unresolved mRenderRoot
-    MOZ_ASSERT(!IsRootWebRenderBridgeParent());
-    if (aDisplayLists.Length() != 1) {
-      return IPC_FAIL(this,
-                      "Well-behaved content processes must only send a DL for "
-                      "a single renderRoot");
-    }
-    PushDeferredPipelineData(AsVariant(std::move(aDisplayLists[0])));
-    aDisplayLists.Clear();
-  }
-
-  for (auto& displayList : aDisplayLists) {
-    if (IsRootWebRenderBridgeParent()) {
-      if (!MaybeHandleDeferredPipelineData(displayList.mRenderRoot,
-                                           displayList.mRemotePipelineIds,
-                                           aTxnStartTime)) {
-        return IPC_FAIL(this, "Failed processing deferred pipeline data");
-      }
-    } else {
-      RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent();
-      if (!root) {
-        return IPC_FAIL(this, "Root WRBP is missing (shutting down?)");
-      }
-
-      for (auto pipelineId : displayList.mRemotePipelineIds) {
-        auto id = wr::AsUint64(pipelineId);
-        root->mPipelineRenderRoots.Put(id, *mRenderRoot);
-        mChildPipelines.PutEntry(id);
-      }
-    }
-  }
-
   bool validTransaction = aDisplayLists.Length() > 0 &&
                           aDisplayLists[0].mIdNamespace == mIdNamespace;
   bool observeLayersUpdate = ShouldParentObserveEpoch();
 
   for (auto& displayList : aDisplayLists) {
     if (!ProcessRenderRootDisplayListData(displayList, wrEpoch, aTxnStartTime,
                                           validTransaction,
                                           observeLayersUpdate)) {
@@ -1401,22 +1161,19 @@ mozilla::ipc::IPCResult WebRenderBridgeP
 }
 
 bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
     RenderRootUpdates& aUpdates, bool* aScheduleComposite) {
   *aScheduleComposite = false;
   wr::TransactionBuilder txn;
   txn.SetLowPriority(!IsRootWebRenderBridgeParent());
 
-  MOZ_ASSERT(aUpdates.mRenderRoot == wr::RenderRoot::Default ||
-             IsRootWebRenderBridgeParent());
-
   if (!aUpdates.mScrollUpdates.IsEmpty()) {
     UpdateAPZScrollOffsets(std::move(aUpdates.mScrollUpdates),
-                           aUpdates.mPaintSequenceNumber, aUpdates.mRenderRoot);
+                           aUpdates.mPaintSequenceNumber);
   }
 
   // Update WrEpoch for UpdateResources() and ProcessWebRenderParentCommands().
   // WrEpoch is used to manage ExternalImages lifetimes in
   // AsyncImagePipelineManager.
   Unused << GetNextWrEpoch();
 
   if (!UpdateResources(aUpdates.mResourceUpdates, aUpdates.mSmallShmems,
@@ -1474,55 +1231,33 @@ mozilla::ipc::IPCResult WebRenderBridgeP
     const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads) {
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
     }
     return IPC_OK();
   }
 
-  // Guard against malicious content processes
-  for (auto& update : aRenderRootUpdates) {
-    if (!RenderRootIsValid(update.mRenderRoot)) {
-      return IPC_FAIL(this, "Received an invalid renderRoot");
-    }
-  }
-
   if (!IsRootWebRenderBridgeParent()) {
     CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
   }
 
   AUTO_PROFILER_TRACING_MARKER("Paint", "EmptyTransaction", GRAPHICS);
   UpdateFwdTransactionId(aFwdTransactionId);
 
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(
       this, &aToDestroy);
 
-  if (!mRenderRoot && aRenderRootUpdates.Length() > 0) {
-    // Only non-root WRBPs will ever have an unresolved mRenderRoot
-    MOZ_ASSERT(!IsRootWebRenderBridgeParent());
-    if (aRenderRootUpdates.Length() != 1) {
-      return IPC_FAIL(this,
-                      "Well-behaved content processes must only send a DL for "
-                      "a single renderRoot");
-    }
-    PushDeferredPipelineData(AsVariant(std::move(aRenderRootUpdates[0])));
-    aRenderRootUpdates.Clear();
-  }
-
   UpdateAPZFocusState(aFocusTarget);
 
   bool scheduleAnyComposite = false;
 
   for (auto& update : aRenderRootUpdates) {
-    MOZ_ASSERT(update.mRenderRoot == wr::RenderRoot::Default ||
-               IsRootWebRenderBridgeParent());
-
     bool scheduleComposite = false;
     if (!ProcessEmptyTransactionUpdates(update, &scheduleComposite)) {
       return IPC_FAIL(this, "Failed to process empty transaction update.");
     }
     scheduleAnyComposite = scheduleAnyComposite || scheduleComposite;
   }
 
   // If we are going to kick off a new composite as a result of this
@@ -1570,23 +1305,16 @@ mozilla::ipc::IPCResult WebRenderBridgeP
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvParentCommands(
     nsTArray<WebRenderParentCommand>&& aCommands) {
   if (mDestroyed) {
     return IPC_OK();
   }
 
-  if (!mRenderRoot) {
-    PushDeferredPipelineData(AsVariant(ParentCommands{
-        std::move(aCommands),
-    }));
-    return IPC_OK();
-  }
-
   wr::TransactionBuilder txn;
   txn.SetLowPriority(!IsRootWebRenderBridgeParent());
   if (!ProcessWebRenderParentCommands(aCommands, txn)) {
     return IPC_FAIL(this, "Invalid parent command found");
   }
 
   mApi->SendTransaction(txn);
   return IPC_OK();
@@ -1970,31 +1698,25 @@ mozilla::ipc::IPCResult WebRenderBridgeP
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
   if (mDestroyed) {
     return IPC_OK();
   }
 
-  if (mRenderRoot) {
-    // Clear resources
-    wr::TransactionBuilder txn;
-    txn.SetLowPriority(true);
-    txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
-    txn.Notify(wr::Checkpoint::SceneBuilt,
-               MakeUnique<ScheduleObserveLayersUpdate>(
-                   mCompositorBridge, GetLayersId(), mChildLayersObserverEpoch,
-                   false));
-    mApi->SendTransaction(txn);
-  } else {
-    if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
-      root->RemoveDeferredPipeline(mPipelineId);
-    }
-  }
+  // Clear resources
+  wr::TransactionBuilder txn;
+  txn.SetLowPriority(true);
+  txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
+  txn.Notify(
+      wr::Checkpoint::SceneBuilt,
+      MakeUnique<ScheduleObserveLayersUpdate>(
+          mCompositorBridge, GetLayersId(), mChildLayersObserverEpoch, false));
+  mApi->SendTransaction(txn);
 
   // Schedule generate frame to clean up Pipeline
   ScheduleGenerateFrame();
 
   // Remove animations.
   for (const auto& id : mActiveAnimations) {
     mAnimStorage->ClearById(id.first);
   }
@@ -2431,17 +2153,16 @@ void WebRenderBridgeParent::NotifySceneB
     if (id.mEpoch.mHandle == aEpoch.mHandle) {
       id.mSceneBuiltTime = aEndTime;
       break;
     }
   }
 }
 
 void WebRenderBridgeParent::NotifyDidSceneBuild(
-    const nsTArray<wr::RenderRoot>& aRenderRoots,
     RefPtr<const wr::WebRenderPipelineInfo> aInfo) {
   MOZ_ASSERT(IsRootWebRenderBridgeParent());
   if (!mCompositorScheduler) {
     return;
   }
 
   mAsyncImageManager->SetWillGenerateFrame();
 
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -136,18 +136,17 @@ class WebRenderBridgeParent final
 
   mozilla::ipc::IPCResult RecvShutdown() override;
   mozilla::ipc::IPCResult RecvShutdownSync() override;
   mozilla::ipc::IPCResult RecvDeleteCompositorAnimations(
       nsTArray<uint64_t>&& aIds) override;
   mozilla::ipc::IPCResult RecvUpdateResources(
       nsTArray<OpUpdateResource>&& aUpdates,
       nsTArray<RefCountedShmem>&& aSmallShmems,
-      nsTArray<ipc::Shmem>&& aLargeShmems,
-      const wr::RenderRoot& aRenderRoot) override;
+      nsTArray<ipc::Shmem>&& aLargeShmems) override;
   mozilla::ipc::IPCResult RecvSetDisplayList(
       nsTArray<RenderRootDisplayListData>&& aDisplayLists,
       nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
       const TransactionId& aTransactionId, const bool& aContainsSVGGroup,
       const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime,
       const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
       const nsCString& aTxnURL, const TimeStamp& aFwdTime,
       nsTArray<CompositionPayload>&& aPayloads) override;
@@ -273,50 +272,26 @@ class WebRenderBridgeParent final
   /**
    * Schedule forced frame rendering at next composite timing.
    *
    * WebRender could skip frame rendering if there is no update.
    * This function is used to force rendering even when there is no update.
    */
   void ScheduleForcedGenerateFrame();
 
-  void NotifyDidSceneBuild(const nsTArray<wr::RenderRoot>& aRenderRoots,
-                           RefPtr<const wr::WebRenderPipelineInfo> aInfo);
+  void NotifyDidSceneBuild(RefPtr<const wr::WebRenderPipelineInfo> aInfo);
 
   wr::Epoch UpdateWebRender(
       CompositorVsyncScheduler* aScheduler, RefPtr<wr::WebRenderAPI>&& aApi,
       AsyncImagePipelineManager* aImageMgr,
       CompositorAnimationStorage* aAnimStorage,
       const TextureFactoryIdentifier& aTextureFactoryIdentifier);
 
   void RemoveEpochDataPriorTo(const wr::Epoch& aRenderedEpoch);
 
-  void PushDeferredPipelineData(RenderRootDeferredData&& aDeferredData);
-
-  /**
-   * If we attempt to process information for a particular pipeline before we
-   * can determine what RenderRoot it belongs to, then we defer that data until
-   * we can. This handles processing that deferred data.
-   */
-  bool MaybeHandleDeferredPipelineData(
-      wr::RenderRoot aRenderRoot, const nsTArray<wr::PipelineId>& aPipelineIds,
-      const TimeStamp& aTxnStartTime);
-
-  /**
-   * See MaybeHandleDeferredPipelineData - this is the implementation of that
-   * for a single pipeline.
-   */
-  bool MaybeHandleDeferredPipelineDataForPipeline(
-      wr::RenderRoot aRenderRoot, wr::PipelineId aPipelineId,
-      const TimeStamp& aTxnStartTime);
-
-  bool HandleDeferredPipelineData(
-      nsTArray<RenderRootDeferredData>& aDeferredData,
-      const TimeStamp& aTxnStartTime);
-
   bool IsRootWebRenderBridgeParent() const;
   LayersId GetLayersId() const;
 
   void SetCompositionRecorder(
       UniquePtr<layers::WebRenderCompositionRecorder> aRecorder);
 
   /**
    * Write the frames collected by the |WebRenderCompositionRecorder| to disk.
@@ -353,62 +328,40 @@ class WebRenderBridgeParent final
       const std::pair<wr::PipelineId, wr::Epoch>& aKey);
 
  private:
   class ScheduleSharedSurfaceRelease;
 
   explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
   virtual ~WebRenderBridgeParent();
 
-  // Within WebRenderBridgeParent, we can use wr::RenderRoot::Default to
-  // refer to DefaultApi(), which can be the content API if this
-  // WebRenderBridgeParent is for a content WebRenderBridgeChild. However,
-  // different WebRenderBridgeParents use the same AsyncImagePipelineManager,
-  // for example, which doesn't have this distinction, so we need to
-  // convert out our RenderRoot.
-  wr::RenderRoot RenderRootForExternal(wr::RenderRoot aRenderRoot) {
-    if (IsRootWebRenderBridgeParent()) {
-      return aRenderRoot;
-    } else {
-      MOZ_ASSERT(aRenderRoot == wr::RenderRoot::Default);
-      return *mRenderRoot;
-    }
-  }
-
-  // Returns whether a given render root is valid for this WRBP to receive as
-  // input from the WRBC.
-  bool RenderRootIsValid(wr::RenderRoot aRenderRoot);
-
-  void RemoveDeferredPipeline(wr::PipelineId aPipelineId);
-
   bool ProcessEmptyTransactionUpdates(RenderRootUpdates& aUpdates,
                                       bool* aScheduleComposite);
 
   bool ProcessRenderRootDisplayListData(RenderRootDisplayListData& aDisplayList,
                                         wr::Epoch aWrEpoch,
                                         const TimeStamp& aTxnStartTime,
                                         bool aValidTransaction,
                                         bool aObserveLayersUpdate);
 
-  bool SetDisplayList(wr::RenderRoot aRenderRoot, const LayoutDeviceRect& aRect,
+  bool SetDisplayList(const LayoutDeviceRect& aRect,
                       const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL,
                       const wr::BuiltDisplayListDescriptor& aDLDesc,
                       const nsTArray<OpUpdateResource>& aResourceUpdates,
                       const nsTArray<RefCountedShmem>& aSmallShmems,
                       const nsTArray<ipc::Shmem>& aLargeShmems,
                       const TimeStamp& aTxnStartTime,
                       wr::TransactionBuilder& aTxn, wr::Epoch aWrEpoch,
                       bool aValidTransaction, bool aObserveLayersUpdate);
 
   void UpdateAPZFocusState(const FocusTarget& aFocus);
-  void UpdateAPZScrollData(const wr::Epoch& aEpoch, WebRenderScrollData&& aData,
-                           wr::RenderRoot aRenderRoot);
+  void UpdateAPZScrollData(const wr::Epoch& aEpoch,
+                           WebRenderScrollData&& aData);
   void UpdateAPZScrollOffsets(ScrollUpdatesMap&& aUpdates,
-                              uint32_t aPaintSequenceNumber,
-                              wr::RenderRoot aRenderRoot);
+                              uint32_t aPaintSequenceNumber);
 
   bool UpdateResources(const nsTArray<OpUpdateResource>& aResourceUpdates,
                        const nsTArray<RefCountedShmem>& aSmallShmems,
                        const nsTArray<ipc::Shmem>& aLargeShmems,
                        wr::TransactionBuilder& aUpdates);
   bool AddPrivateExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey,
                                wr::ImageDescriptor aDesc,
                                wr::TransactionBuilder& aResources);
@@ -536,35 +489,16 @@ class WebRenderBridgeParent final
     wr::Epoch mEpoch;
     nsTArray<uint64_t> mIds;
   };
 
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
   RefPtr<wr::WebRenderAPI> mApi;
-  // This is a map from pipeline id to render root, that tracks the render
-  // roots of all subpipelines (including nested subpipelines, e.g. in the
-  // Fission case) attached to this WebRenderBridgeParent. This is only
-  // populated on the root WRBP. It is used to resolve the render root for the
-  // subpipelines, since they may not know where they are attached in the
-  // parent display list and therefore may not know their render root.
-  nsDataHashtable<nsUint64HashKey, wr::RenderRoot> mPipelineRenderRoots;
-  // This is a hashset of child pipelines for this WRBP. This allows us to
-  // iterate through all the children of a non-root WRBP and add them to
-  // the root's mPipelineRenderRoots, and potentially resolve any of their
-  // deferred updates.
-  nsTHashtable<nsUint64HashKey> mChildPipelines;
-  // This is a map from pipeline id to a list of deferred data. This is only
-  // populated on the root WRBP. The data contained within is deferred because
-  // the sub-WRBP that received it did not know which renderroot it belonged
-  // to. Once that is resolved by the root WRBP getting the right display list
-  // update, the deferred data is processed.
-  nsDataHashtable<nsUint64HashKey, nsTArray<RenderRootDeferredData>>
-      mPipelineDeferredUpdates;
   RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
   RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
   RefPtr<CompositorAnimationStorage> mAnimStorage;
   // mActiveAnimations is used to avoid leaking animations when
   // WebRenderBridgeParent is destroyed abnormally and Tab move between
   // different windows.
   std::unordered_map<uint64_t, wr::Epoch> mActiveAnimations;
   std::unordered_map<uint64_t, RefPtr<WebRenderImageHost>> mAsyncCompositables;
@@ -583,17 +517,16 @@ class WebRenderBridgeParent final
   std::deque<PendingTransactionId> mPendingTransactionIds;
   std::queue<CompositorAnimationIdsForEpoch> mCompositorAnimationsToDelete;
   wr::Epoch mWrEpoch;
   wr::IdNamespace mIdNamespace;
 
   VsyncId mSkippedCompositeId;
   TimeStamp mMostRecentComposite;
 
-  Maybe<wr::RenderRoot> mRenderRoot;
 #if defined(MOZ_WIDGET_ANDROID)
   UiCompositorControllerParent* mScreenPixelsTarget;
 #endif
   bool mPaused;
   bool mDestroyed;
   bool mReceivedDisplayList;
   bool mIsFirstPaint;
   bool mSkippedComposite;
--- a/gfx/layers/wr/WebRenderCanvasRenderer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasRenderer.cpp
@@ -80,17 +80,17 @@ void WebRenderCanvasRendererAsync::Destr
     mManager->RemovePipelineIdForCompositable(mPipelineId.ref());
     mPipelineId.reset();
   }
 }
 
 void WebRenderCanvasRendererAsync::
     UpdateCompositableClientForEmptyTransaction() {
   bool wasDirty = IsDirty();
-  UpdateCompositableClient(mManager->GetRenderRoot());
+  UpdateCompositableClient();
   if (wasDirty && mPipelineId.isSome()) {
     // Notify an update of async image pipeline during empty transaction.
     // During non empty transaction, WebRenderBridgeParent receives
     // OpUpdateAsyncImagePipeline message, but during empty transaction, the
     // message is not sent to WebRenderBridgeParent. Then
     // OpUpdatedAsyncImagePipeline is used to notify the update.
     mManager->AddWebRenderParentCommand(
         OpUpdatedAsyncImagePipeline(mPipelineId.ref()));
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -304,17 +304,17 @@ struct DIGroup {
   ScrollableLayerGuid::ViewID mScrollId;
   CompositorHitTestInfo mHitInfo;
   LayerPoint mResidualOffset;
   LayerIntRect mLayerBounds;  // mGroupBounds converted to Layer space
   // mLayerBounds clipped to the container/parent of the
   // current item being processed.
   IntRect mClippedImageBounds;  // mLayerBounds with the clipping of any
                                 // containers applied
-  Maybe<std::pair<wr::RenderRoot, wr::BlobImageKey>> mKey;
+  Maybe<wr::BlobImageKey> mKey;
   std::vector<RefPtr<ScaledFont>> mFonts;
 
   DIGroup()
       : mAppUnitsPerDevPixel(0),
         mScrollId(ScrollableLayerGuid::NULL_SCROLL_ID),
         mHitInfo(CompositorHitTestInvisibleToHit) {}
 
   void InvalidateRect(const IntRect& aRect) {
@@ -338,17 +338,17 @@ struct DIGroup {
       iter.Remove();
       delete data;
     }
   }
 
   void ClearImageKey(RenderRootStateManager* aManager, bool aForce = false) {
     if (mKey) {
       MOZ_RELEASE_ASSERT(aForce || mInvalidRect.IsEmpty());
-      aManager->AddBlobImageKeyForDiscard(mKey.value().second);
+      aManager->AddBlobImageKeyForDiscard(*mKey);
       mKey = Nothing();
     }
     mFonts.clear();
   }
 
   static IntRect ToDeviceSpace(nsRect aBounds, Matrix& aMatrix,
                                int32_t aAppUnitsPerDevPixel) {
     // RoundedOut can convert empty rectangles to non-empty ones
@@ -610,17 +610,17 @@ struct DIGroup {
     if (mInvalidRect.IsEmpty() && mVisibleRect.IsEqualEdges(mLastVisibleRect)) {
       GP("Not repainting group because it's empty\n");
       GP("End EndGroup\n");
       if (mKey) {
         // Although the contents haven't changed, the visible area *may* have,
         // so request it be updated unconditionally (wr should be able to easily
         // detect if this is a no-op on its side, if that matters)
         aResources.SetBlobImageVisibleArea(
-            mKey.value().second,
+            *mKey,
             ViewAs<ImagePixel>(mVisibleRect,
                                PixelCastJustification::LayerIsImage));
         mLastVisibleRect = mVisibleRect;
         PushImage(aBuilder, itemBounds);
       }
       return;
     }
 
@@ -631,17 +631,17 @@ struct DIGroup {
         MakeAndAddRef<WebRenderDrawEventRecorder>(
             [&](MemStream& aStream,
                 std::vector<RefPtr<ScaledFont>>& aScaledFonts) {
               size_t count = aScaledFonts.size();
               aStream.write((const char*)&count, sizeof(count));
               for (auto& scaled : aScaledFonts) {
                 Maybe<wr::FontInstanceKey> key =
                     aWrManager->WrBridge()->GetFontKeyForScaledFont(
-                        scaled, aBuilder.GetRenderRoot(), &aResources);
+                        scaled, &aResources);
                 if (key.isNothing()) {
                   validFonts = false;
                   break;
                 }
                 BlobFont font = {key.value(), scaled};
                 aStream.write((const char*)&font, sizeof(font));
               }
               fonts = std::move(aScaledFonts);
@@ -701,40 +701,40 @@ struct DIGroup {
       wr::ImageDescriptor descriptor(dtSize, 0, dt->GetFormat(), opacity);
       MOZ_RELEASE_ASSERT(bytes.length() > sizeof(size_t));
       if (!aResources.AddBlobImage(
               key, descriptor, bytes,
               ViewAs<ImagePixel>(mVisibleRect,
                                  PixelCastJustification::LayerIsImage))) {
         return;
       }
-      mKey = Some(std::make_pair(aBuilder.GetRenderRoot(), key));
+      mKey = Some(key);
     } else {
       wr::ImageDescriptor descriptor(dtSize, 0, dt->GetFormat(), opacity);
 
       // Convert mInvalidRect to image space by subtracting the corner of the
       // image bounds
       auto dirtyRect = ViewAs<ImagePixel>(mInvalidRect);
 
       auto bottomRight = dirtyRect.BottomRight();
       GP("check invalid %d %d - %d %d\n", bottomRight.x, bottomRight.y,
          dtSize.width, dtSize.height);
       GP("Update Blob %d %d %d %d\n", mInvalidRect.x, mInvalidRect.y,
          mInvalidRect.width, mInvalidRect.height);
       if (!aResources.UpdateBlobImage(
-              mKey.value().second, descriptor, bytes,
+              *mKey, descriptor, bytes,
               ViewAs<ImagePixel>(mVisibleRect,
                                  PixelCastJustification::LayerIsImage),
               dirtyRect)) {
         return;
       }
     }
     mFonts = std::move(fonts);
     aResources.SetBlobImageVisibleArea(
-        mKey.value().second,
+        *mKey,
         ViewAs<ImagePixel>(mVisibleRect, PixelCastJustification::LayerIsImage));
     mLastVisibleRect = mVisibleRect;
     PushImage(aBuilder, itemBounds);
     GP("End EndGroup\n\n");
   }
 
   void PushImage(wr::DisplayListBuilder& aBuilder,
                  const LayoutDeviceRect& bounds) {
@@ -755,17 +755,17 @@ struct DIGroup {
 
     // XXX - clipping the item against the paint rect breaks some content.
     // cf. Bug 1455422.
     // wr::LayoutRect clip = wr::ToLayoutRect(bounds.Intersect(mVisibleRect));
 
     aBuilder.SetHitTestInfo(mScrollId, hitInfo, SideBits::eNone);
     aBuilder.PushImage(dest, dest, !backfaceHidden,
                        wr::ToImageRendering(sampleFilter),
-                       wr::AsImageKey(mKey.value().second));
+                       wr::AsImageKey(*mKey));
     aBuilder.ClearHitTestInfo();
   }
 
   void PaintItemRange(Grouper* aGrouper, nsDisplayItem* aStartItem,
                       nsDisplayItem* aEndItem, gfxContext* aContext,
                       WebRenderDrawEventRecorder* aRecorder,
                       RenderRootStateManager* aRootManager,
                       wr::IpcResourceUpdateQueue& aResources) {
@@ -1137,17 +1137,17 @@ void Grouper::ConstructGroups(nsDisplayL
 
   nsDisplayItem* item = aList->GetBottom();
   nsDisplayItem* startOfCurrentGroup = item;
   while (item) {
     if (IsItemProbablyActive(item, mDisplayListBuilder)) {
       // We're going to be starting a new group.
       RefPtr<WebRenderGroupData> groupData =
           aCommandBuilder->CreateOrRecycleWebRenderUserData<WebRenderGroupData>(
-              item, aBuilder.GetRenderRoot());
+              item);
 
       groupData->mFollowingGroup.mInvalidRect.SetEmpty();
 
       // Initialize groupData->mFollowingGroup with data from currentGroup.
       // We want to copy out this information before calling EndGroup because
       // EndGroup will set mLastVisibleRect depending on whether
       // we send something to WebRender.
 
@@ -1381,18 +1381,17 @@ void WebRenderCommandBuilder::DoGrouping
   mClipManager.BeginList(aSc);
   Grouper g(mClipManager);
 
   int32_t appUnitsPerDevPixel =
       aWrappingItem->Frame()->PresContext()->AppUnitsPerDevPixel();
 
   g.mDisplayListBuilder = aDisplayListBuilder;
   RefPtr<WebRenderGroupData> groupData =
-      CreateOrRecycleWebRenderUserData<WebRenderGroupData>(
-          aWrappingItem, aBuilder.GetRenderRoot());
+      CreateOrRecycleWebRenderUserData<WebRenderGroupData>(aWrappingItem);
 
   bool snapped;
   nsRect groupBounds =
       aWrappingItem->GetUntransformedBounds(aDisplayListBuilder, &snapped);
   DIGroup& group = groupData->mSubGroup;
 
   gfx::Size scale = aSc.GetInheritedScale();
   GP("Inherrited scale %f %f\n", scale.width, scale.height);
@@ -1823,18 +1822,17 @@ void WebRenderCommandBuilder::PopOverrid
 
 Maybe<wr::ImageKey> WebRenderCommandBuilder::CreateImageKey(
     nsDisplayItem* aItem, ImageContainer* aContainer,
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     mozilla::wr::ImageRendering aRendering, const StackingContextHelper& aSc,
     gfx::IntSize& aSize, const Maybe<LayoutDeviceRect>& aAsyncImageBounds) {
   RefPtr<WebRenderImageData> imageData =
-      CreateOrRecycleWebRenderUserData<WebRenderImageData>(
-          aItem, aBuilder.GetRenderRoot());
+      CreateOrRecycleWebRenderUserData<WebRenderImageData>(aItem);
   MOZ_ASSERT(imageData);
 
   if (aContainer->IsAsync()) {
     MOZ_ASSERT(aAsyncImageBounds);
 
     LayoutDeviceRect rect = aAsyncImageBounds.value();
     LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), rect.Size());
     gfx::MaybeIntSize scaleToSize;
@@ -2086,18 +2084,17 @@ WebRenderCommandBuilder::GenerateFallbac
       StaticPrefs::gfx_webrender_blob_images() && !paintOnContentSide;
   Maybe<gfx::DeviceColor> highlight = Nothing();
   if (StaticPrefs::gfx_webrender_highlight_painted_layers()) {
     highlight = Some(useBlobImage ? gfx::DeviceColor(1.0, 0.0, 0.0, 0.5)
                                   : gfx::DeviceColor(1.0, 1.0, 0.0, 0.5));
   }
 
   RefPtr<WebRenderFallbackData> fallbackData =
-      CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(
-          aItem, aBuilder.GetRenderRoot());
+      CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
 
   bool snap;
   nsRect itemBounds = aItem->GetBounds(aDisplayListBuilder, &snap);
 
   // Blob images will only draw the visible area of the blob so we don't need to
   // clip them here and can just rely on the webrender clipping.
   // TODO We also don't clip native themed widget to avoid over-invalidation
   // during scrolling. It would be better to support a sort of streaming/tiling
@@ -2241,17 +2238,17 @@ WebRenderCommandBuilder::GenerateFallbac
           MakeAndAddRef<WebRenderDrawEventRecorder>(
               [&](MemStream& aStream,
                   std::vector<RefPtr<ScaledFont>>& aScaledFonts) {
                 size_t count = aScaledFonts.size();
                 aStream.write((const char*)&count, sizeof(count));
                 for (auto& scaled : aScaledFonts) {
                   Maybe<wr::FontInstanceKey> key =
                       mManager->WrBridge()->GetFontKeyForScaledFont(
-                          scaled, aBuilder.GetRenderRoot(), &aResources);
+                          scaled, &aResources);
                   if (key.isNothing()) {
                     validFonts = false;
                     break;
                   }
                   BlobFont font = {key.value(), scaled};
                   aStream.write((const char*)&font, sizeof(font));
                 }
                 fonts = std::move(aScaledFonts);
@@ -2336,17 +2333,17 @@ WebRenderCommandBuilder::GenerateFallbac
               aItem, dt,
               /*aOffset: */ aImageRect.TopLeft(),
               /*aVisibleRect: */ dt->GetRect(), aDisplayListBuilder,
               fallbackData->mBasicLayerManager, scale, highlight);
         }
 
         if (isInvalidated) {
           // Update image if there it's invalidated.
-          if (!helper.UpdateImage(aBuilder.GetRenderRoot())) {
+          if (!helper.UpdateImage()) {
             return nullptr;
           }
         } else {
           // If there is no invalidation region and we don't have a image key,
           // it means we don't need to push image for the item.
           if (!imageData->GetImageKey().isSome()) {
             return nullptr;
           }
@@ -2417,18 +2414,17 @@ class WebRenderMaskData : public WebRend
 };
 
 Maybe<wr::ImageMask> WebRenderCommandBuilder::BuildWrMaskImage(
     nsDisplayMasksAndClipPaths* aMaskItem, wr::DisplayListBuilder& aBuilder,
     wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc,
     nsDisplayListBuilder* aDisplayListBuilder,
     const LayoutDeviceRect& aBounds) {
   RefPtr<WebRenderMaskData> maskData =
-      CreateOrRecycleWebRenderUserData<WebRenderMaskData>(
-          aMaskItem, aBuilder.GetRenderRoot());
+      CreateOrRecycleWebRenderUserData<WebRenderMaskData>(aMaskItem);
 
   if (!maskData) {
     return Nothing();
   }
 
   bool snap;
   nsRect bounds = aMaskItem->GetBounds(aDisplayListBuilder, &snap);
 
@@ -2473,18 +2469,18 @@ Maybe<wr::ImageMask> WebRenderCommandBui
         MakeAndAddRef<WebRenderDrawEventRecorder>(
             [&](MemStream& aStream,
                 std::vector<RefPtr<ScaledFont>>& aScaledFonts) {
               size_t count = aScaledFonts.size();
               aStream.write((const char*)&count, sizeof(count));
 
               for (auto& scaled : aScaledFonts) {
                 Maybe<wr::FontInstanceKey> key =
-                    mManager->WrBridge()->GetFontKeyForScaledFont(
-                        scaled, aBuilder.GetRenderRoot(), &aResources);
+                    mManager->WrBridge()->GetFontKeyForScaledFont(scaled,
+                                                                  &aResources);
                 if (key.isNothing()) {
                   validFonts = false;
                   break;
                 }
                 BlobFont font = {key.value(), scaled};
                 aStream.write((const char*)&font, sizeof(font));
               }
 
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -114,18 +114,17 @@ class WebRenderCommandBuilder final {
   bool GetContainsSVGGroup() { return mContainsSVGGroup; }
 
   // Those are data that we kept between transactions. We used to cache some
   // data in the layer. But in layers free mode, we don't have layer which
   // means we need some other place to cached the data between transaction.
   // We store the data in frame's property.
   template <class T>
   already_AddRefed<T> CreateOrRecycleWebRenderUserData(
-      nsDisplayItem* aItem, wr::RenderRoot aRenderRoot,
-      bool* aOutIsRecycled = nullptr) {
+      nsDisplayItem* aItem, bool* aOutIsRecycled = nullptr) {
     MOZ_ASSERT(aItem);
     nsIFrame* frame = aItem->Frame();
     if (aOutIsRecycled) {
       *aOutIsRecycled = true;
     }
 
     WebRenderUserDataTable* userDataTable =
         frame->GetProperty(WebRenderUserDataProperty::Key());
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -37,17 +37,16 @@ WebRenderLayerManager::WebRenderLayerMan
       mLatestTransactionId{0},
       mNeedsComposite(false),
       mIsFirstPaint(false),
       mTarget(nullptr),
       mPaintSequenceNumber(0),
       mWebRenderCommandBuilder(this),
       mLastDisplayListSize(0) {
   MOZ_COUNT_CTOR(WebRenderLayerManager);
-  mStateManager.mRenderRoot = wr::RenderRoot::Default;
   mStateManager.mLayerManager = this;
 
   if (XRE_IsContentProcess() &&
       StaticPrefs::gfx_webrender_enable_item_cache_AtStartup()) {
     static const size_t kInitialCacheSize = 1024;
     static const size_t kMaximumCacheSize = 10240;
 
     mDisplayItemCache.SetCapacity(kInitialCacheSize, kMaximumCacheSize);
@@ -240,21 +239,20 @@ bool WebRenderLayerManager::EndEmptyTran
     if (WrBridge()->GetSyncObject() &&
         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
       WrBridge()->GetSyncObject()->Synchronize();
     }
   }
 
   GetCompositorBridgeChild()->EndCanvasTransaction();
 
-  AutoTArray<RenderRootUpdates, wr::kRenderRootCount> renderRootUpdates;
+  AutoTArray<RenderRootUpdates, 1> renderRootUpdates;
   if (mStateManager.mAsyncResourceUpdates || !mPendingScrollUpdates.IsEmpty() ||
       WrBridge()->HasWebRenderParentCommands()) {
     auto updates = renderRootUpdates.AppendElement();
-    updates->mRenderRoot = wr::RenderRoot::Default;
     updates->mPaintSequenceNumber = mPaintSequenceNumber;
     if (mStateManager.mAsyncResourceUpdates) {
       mStateManager.mAsyncResourceUpdates->Flush(updates->mResourceUpdates,
                                                  updates->mSmallShmems,
                                                  updates->mLargeShmems);
     }
     updates->mScrollUpdates = std::move(mPendingScrollUpdates);
     for (auto it = updates->mScrollUpdates.Iter(); !it.Done(); it.Next()) {
@@ -373,18 +371,17 @@ void WebRenderLayerManager::EndTransacti
     refreshStart = mTransactionStart;
   }
 
   if (mStateManager.mAsyncResourceUpdates) {
     if (resourceUpdates.IsEmpty()) {
       resourceUpdates.ReplaceResources(
           std::move(mStateManager.mAsyncResourceUpdates.ref()));
     } else {
-      WrBridge()->UpdateResources(mStateManager.mAsyncResourceUpdates.ref(),
-                                  mStateManager.GetRenderRoot());
+      WrBridge()->UpdateResources(mStateManager.mAsyncResourceUpdates.ref());
     }
     mStateManager.mAsyncResourceUpdates.reset();
   }
   mStateManager.DiscardImagesInTransaction(resourceUpdates);
 
   WrBridge()->RemoveExpiredFontKeys(resourceUpdates);
 
   // Skip the synchronization for buffer since we also skip the painting during
@@ -397,17 +394,16 @@ void WebRenderLayerManager::EndTransacti
   }
 
   GetCompositorBridgeChild()->EndCanvasTransaction();
 
   {
     AUTO_PROFILER_TRACING_MARKER("Paint", "ForwardDPTransaction", GRAPHICS);
     nsTArray<RenderRootDisplayListData> renderRootDLs;
     auto renderRootDL = renderRootDLs.AppendElement();
-    renderRootDL->mRenderRoot = wr::RenderRoot::Default;
     builder.Finalize(*renderRootDL);
     mLastDisplayListSize = renderRootDL->mDL->mCapacity;
     resourceUpdates.Flush(renderRootDL->mResourceUpdates,
                           renderRootDL->mSmallShmems,
                           renderRootDL->mLargeShmems);
     renderRootDL->mRect =
         LayoutDeviceRect(LayoutDevicePoint(), LayoutDeviceSize(size));
     renderRootDL->mScrollData.emplace(std::move(mScrollData));
@@ -517,17 +513,17 @@ void WebRenderLayerManager::MakeSnapshot
   dt->FillRect(dst, pattern);
 
   mTarget = nullptr;
 }
 
 void WebRenderLayerManager::DiscardImages() {
   wr::IpcResourceUpdateQueue resources(WrBridge());
   mStateManager.DiscardImagesInTransaction(resources);
-  WrBridge()->UpdateResources(resources, wr::RenderRoot::Default);
+  WrBridge()->UpdateResources(resources);
 }
 
 void WebRenderLayerManager::DiscardLocalImages() {
   mStateManager.DiscardLocalImages();
 }
 
 void WebRenderLayerManager::SetLayersObserverEpoch(LayersObserverEpoch aEpoch) {
   if (WrBridge()->IPCOpen()) {
--- a/gfx/layers/wr/WebRenderMessageUtils.h
+++ b/gfx/layers/wr/WebRenderMessageUtils.h
@@ -105,22 +105,16 @@ template <>
 struct ParamTraits<mozilla::wr::LayoutRect>
     : public PlainOldDataSerializer<mozilla::wr::LayoutRect> {};
 
 template <>
 struct ParamTraits<mozilla::wr::LayoutPoint>
     : public PlainOldDataSerializer<mozilla::wr::LayoutPoint> {};
 
 template <>
-struct ParamTraits<mozilla::wr::RenderRoot>
-    : public ContiguousEnumSerializerInclusive<
-          mozilla::wr::RenderRoot, mozilla::wr::RenderRoot::Default,
-          mozilla::wr::kHighestRenderRoot> {};
-
-template <>
 struct ParamTraits<mozilla::wr::ImageRendering>
     : public ContiguousEnumSerializer<mozilla::wr::ImageRendering,
                                       mozilla::wr::ImageRendering::Auto,
                                       mozilla::wr::ImageRendering::Sentinel> {};
 
 template <>
 struct ParamTraits<mozilla::wr::MixBlendMode>
     : public ContiguousEnumSerializer<mozilla::wr::MixBlendMode,
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -176,18 +176,17 @@ Maybe<wr::ImageKey> WebRenderImageData::
     return Nothing();
   }
 
   MOZ_ASSERT(mImageClient->AsImageClientSingle());
 
   ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
   uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();
 
-  bool ret = imageClient->UpdateImage(aContainer, /* unused */ 0,
-                                      Some(mManager->GetRenderRoot()));
+  bool ret = imageClient->UpdateImage(aContainer, /* unused */ 0);
   RefPtr<TextureClient> currentTexture = imageClient->GetForwardedTexture();
   if (!ret || !currentTexture) {
     // Delete old key
     ClearImageKey();
     return Nothing();
   }
 
   // Reuse old key if generation is not updated.
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -1084,34 +1084,25 @@ void wr_schedule_render(mozilla::wr::WrW
   RefPtr<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
       CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
   if (cbp) {
     cbp->ScheduleRenderOnCompositorThread();
   }
 }
 
 static void NotifyDidSceneBuild(RefPtr<layers::CompositorBridgeParent> aBridge,
-                                const nsTArray<wr::RenderRoot>& aRenderRoots,
                                 RefPtr<const wr::WebRenderPipelineInfo> aInfo) {
-  aBridge->NotifyDidSceneBuild(aRenderRoots, aInfo);
+  aBridge->NotifyDidSceneBuild(aInfo);
 }
 
 void wr_finished_scene_build(mozilla::wr::WrWindowId aWindowId,
-                             const mozilla::wr::WrDocumentId* aDocumentIds,
-                             size_t aDocumentIdsCount,
                              mozilla::wr::WrPipelineInfo* aInfo) {
   RefPtr<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
       CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
   RefPtr<wr::WebRenderPipelineInfo> info = new wr::WebRenderPipelineInfo();
   info->Raw() = std::move(*aInfo);
   if (cbp) {
-    nsTArray<wr::RenderRoot> renderRoots;
-    renderRoots.SetLength(aDocumentIdsCount);
-    for (size_t i = 0; i < aDocumentIdsCount; ++i) {
-      renderRoots[i] = wr::RenderRootFromId(aDocumentIds[i]);
-    }
-    layers::CompositorThread()->Dispatch(
-        NewRunnableFunction("NotifyDidSceneBuild", &NotifyDidSceneBuild, cbp,
-                            std::move(renderRoots), info));
+    layers::CompositorThread()->Dispatch(NewRunnableFunction(
+        "NotifyDidSceneBuild", &NotifyDidSceneBuild, cbp, info));
   }
 }
 
 }  // extern C
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -107,17 +107,17 @@ class NewRenderer : public RendererEvent
             aRenderThread.GetProgramCache()
                 ? aRenderThread.GetProgramCache()->Raw()
                 : nullptr,
             aRenderThread.GetShaders()
                 ? aRenderThread.GetShaders()->RawShaders()
                 : nullptr,
             aRenderThread.ThreadPool().Raw(),
             aRenderThread.ThreadPoolLP().Raw(), &WebRenderMallocSizeOf,
-            &WebRenderMallocEnclosingSizeOf, (uint32_t)wr::RenderRoot::Default,
+            &WebRenderMallocEnclosingSizeOf, 0,
             compositor->ShouldUseNativeCompositor() ? compositor.get()
                                                     : nullptr,
             compositor->GetMaxUpdateRects(),
             compositor->GetMaxPartialPresentRects(), mDocHandle, &wrRenderer,
             mMaxTextureSize,
             StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(),
             panic_on_gl_error)) {
       // wr_window_new puts a message into gfxCriticalNote if it returns false
@@ -320,69 +320,49 @@ already_AddRefed<WebRenderAPI> WebRender
   task.Wait();
 
   if (!docHandle) {
     return nullptr;
   }
 
   return RefPtr<WebRenderAPI>(
              new WebRenderAPI(docHandle, aWindowId, maxTextureSize, useANGLE,
-                              useDComp, useTripleBuffering, syncHandle,
-                              wr::RenderRoot::Default))
+                              useDComp, useTripleBuffering, syncHandle))
       .forget();
 }
 
 already_AddRefed<WebRenderAPI> WebRenderAPI::Clone() {
   wr::DocumentHandle* docHandle = nullptr;
   wr_api_clone(mDocHandle, &docHandle);
 
   RefPtr<WebRenderAPI> renderApi =
       new WebRenderAPI(docHandle, mId, mMaxTextureSize, mUseANGLE, mUseDComp,
-                       mUseTripleBuffering, mSyncHandle, mRenderRoot);
+                       mUseTripleBuffering, mSyncHandle);
   renderApi->mRootApi = this;  // Hold root api
   renderApi->mRootDocumentApi = this;
 
   return renderApi.forget();
 }
 
-already_AddRefed<WebRenderAPI> WebRenderAPI::CreateDocument(
-    LayoutDeviceIntSize aSize, int8_t aLayerIndex, wr::RenderRoot aRenderRoot) {
-  wr::DeviceIntSize wrSize;
-  wrSize.width = aSize.width;
-  wrSize.height = aSize.height;
-  wr::DocumentHandle* newDoc;
-
-  wr_api_create_document(mDocHandle, &newDoc, wrSize, aLayerIndex,
-                         (uint32_t)aRenderRoot);
-
-  RefPtr<WebRenderAPI> api(
-      new WebRenderAPI(newDoc, mId, mMaxTextureSize, mUseANGLE, mUseDComp,
-                       mUseTripleBuffering, mSyncHandle, aRenderRoot));
-  api->mRootApi = this;
-  return api.forget();
-}
-
 wr::WrIdNamespace WebRenderAPI::GetNamespace() {
   return wr_api_get_namespace(mDocHandle);
 }
 
 WebRenderAPI::WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId,
                            uint32_t aMaxTextureSize, bool aUseANGLE,
                            bool aUseDComp, bool aUseTripleBuffering,
-                           layers::SyncHandle aSyncHandle,
-                           wr::RenderRoot aRenderRoot)
+                           layers::SyncHandle aSyncHandle)
     : mDocHandle(aHandle),
       mId(aId),
       mMaxTextureSize(aMaxTextureSize),
       mUseANGLE(aUseANGLE),
       mUseDComp(aUseDComp),
       mUseTripleBuffering(aUseTripleBuffering),
       mCaptureSequence(false),
-      mSyncHandle(aSyncHandle),
-      mRenderRoot(aRenderRoot) {}
+      mSyncHandle(aSyncHandle) {}
 
 WebRenderAPI::~WebRenderAPI() {
   if (!mRootDocumentApi) {
     wr_api_delete_document(mDocHandle);
   }
 
   if (!mRootApi) {
     RenderThread::Get()->SetDestroyed(GetId());
@@ -877,23 +857,21 @@ void WebRenderAPI::SetFrameStartTime(con
 void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mDocHandle, event);
 }
 
 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
                                        const wr::LayoutSize& aContentSize,
                                        size_t aCapacity,
-                                       layers::DisplayItemCache* aCache,
-                                       RenderRoot aRenderRoot)
+                                       layers::DisplayItemCache* aCache)
     : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
       mActiveFixedPosTracker(nullptr),
       mPipelineId(aId),
       mContentSize(aContentSize),
-      mRenderRoot(aRenderRoot),
       mDisplayItemCache(aCache) {
   MOZ_COUNT_CTOR(DisplayListBuilder);
   mWrState = wr_state_new(aId, aContentSize, aCapacity);
 
   if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
     mDisplayItemCache->SetPipelineId(aId);
   }
 }
@@ -920,18 +898,16 @@ void DisplayListBuilder::DumpSerializedD
 void DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
                                   BuiltDisplayList& aOutDisplayList) {
   wr_api_finalize_builder(mWrState, &aOutContentSize, &aOutDisplayList.dl_desc,
                           &aOutDisplayList.dl.inner);
 }
 
 void DisplayListBuilder::Finalize(
     layers::RenderRootDisplayListData& aOutTransaction) {
-  MOZ_ASSERT(mRenderRoot == wr::RenderRoot::Default);
-
   if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
     wr_dp_set_cache_size(mWrState, mDisplayItemCache->CurrentSize());
   }
 
   wr::VecU8 dl;
   wr_api_finalize_builder(mWrState, &aOutTransaction.mContentSize,
                           &aOutTransaction.mDLDesc, &dl.inner);
   aOutTransaction.mDL.emplace(dl.inner.data, dl.inner.length,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -225,20 +225,16 @@ class WebRenderAPI final {
 
  public:
   /// This can be called on the compositor thread only.
   static already_AddRefed<WebRenderAPI> Create(
       layers::CompositorBridgeParent* aBridge,
       RefPtr<widget::CompositorWidget>&& aWidget,
       const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize);
 
-  already_AddRefed<WebRenderAPI> CreateDocument(LayoutDeviceIntSize aSize,
-                                                int8_t aLayerIndex,
-                                                wr::RenderRoot aRenderRoot);
-
   already_AddRefed<WebRenderAPI> Clone();
 
   wr::WindowId GetId() const { return mId; }
 
   /// Do a non-blocking hit-testing query on a shared version of the hit
   /// testing information.
   std::vector<WrHitResult> HitTest(const wr::WorldPoint& aPoint);
 
@@ -262,17 +258,16 @@ class WebRenderAPI final {
 
   void WakeSceneBuilder();
   void FlushSceneBuilder();
 
   void NotifyMemoryPressure();
   void AccumulateMemoryReport(wr::MemoryReport*);
 
   wr::WrIdNamespace GetNamespace();
-  wr::RenderRoot GetRenderRoot() const { return mRenderRoot; }
   uint32_t GetMaxTextureSize() const { return mMaxTextureSize; }
   bool GetUseANGLE() const { return mUseANGLE; }
   bool GetUseDComp() const { return mUseDComp; }
   bool GetUseTripleBuffering() const { return mUseTripleBuffering; }
   layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
 
   void Capture();
 
@@ -301,34 +296,32 @@ class WebRenderAPI final {
    * If there is not currently a recorder, this is a no-op and the promise will
    * be rejected.
    */
   RefPtr<GetCollectedFramesPromise> GetCollectedFrames();
 
  protected:
   WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId,
                uint32_t aMaxTextureSize, bool aUseANGLE, bool aUseDComp,
-               bool aUseTripleBuffering, layers::SyncHandle aSyncHandle,
-               wr::RenderRoot aRenderRoot);
+               bool aUseTripleBuffering, layers::SyncHandle aSyncHandle);
 
   ~WebRenderAPI();
   // Should be used only for shutdown handling
   void WaitFlushed();
 
   void UpdateDebugFlags(uint32_t aFlags);
 
   wr::DocumentHandle* mDocHandle;
   wr::WindowId mId;
   int32_t mMaxTextureSize;
   bool mUseANGLE;
   bool mUseDComp;
   bool mUseTripleBuffering;
   bool mCaptureSequence;
   layers::SyncHandle mSyncHandle;
-  wr::RenderRoot mRenderRoot;
 
   // We maintain alive the root api to know when to shut the render backend
   // down, and the root api for the document to know when to delete the
   // document. mRootApi is null for the api object that owns the channel (and is
   // responsible for shutting it down), and mRootDocumentApi is null for the api
   // object owning (and responsible for destroying) a given document. All api
   // objects in the same window use the same channel, and some api objects write
   // to the same document (but there is only one owner for each channel and for
@@ -398,36 +391,33 @@ struct MOZ_STACK_CLASS StackingContextPa
 
 /// This is a simple C++ wrapper around WrState defined in the rust bindings.
 /// We may want to turn this into a direct wrapper on top of
 /// WebRenderFrameBuilder instead, so the interface may change a bit.
 class DisplayListBuilder final {
  public:
   DisplayListBuilder(wr::PipelineId aId, const wr::LayoutSize& aContentSize,
                      size_t aCapacity = 0,
-                     layers::DisplayItemCache* aCache = nullptr,
-                     RenderRoot aRenderRoot = RenderRoot::Default);
+                     layers::DisplayItemCache* aCache = nullptr);
   DisplayListBuilder(DisplayListBuilder&&) = default;
 
   ~DisplayListBuilder();
 
   void Save();
   void Restore();
   void ClearSave();
 
   usize Dump(usize aIndent, const Maybe<usize>& aStart,
              const Maybe<usize>& aEnd);
   void DumpSerializedDisplayList();
 
   void Finalize(wr::LayoutSize& aOutContentSizes,
                 wr::BuiltDisplayList& aOutDisplayList);
   void Finalize(layers::RenderRootDisplayListData& aOutTransaction);
 
-  RenderRoot GetRenderRoot() const { return mRenderRoot; }
-
   Maybe<wr::WrSpatialId> PushStackingContext(
       const StackingContextParams& aParams, const wr::LayoutRect& aBounds,
       const wr::RasterSpace& aRasterSpace);
   void PopStackingContext(bool aIsReferenceFrame);
 
   wr::WrClipChainId DefineClipChain(const nsTArray<wr::WrClipId>& aClips,
                                     bool aParentWithCurrentChain = false);
 
@@ -722,17 +712,16 @@ class DisplayListBuilder final {
   RefPtr<gfxContext> mCachedContext;
 
   FixedPosScrollTargetTracker* mActiveFixedPosTracker;
 
   wr::PipelineId mPipelineId;
   wr::LayoutSize mContentSize;
 
   nsTArray<wr::PipelineId> mRemotePipelineIds;
-  RenderRoot mRenderRoot;
 
   layers::DisplayItemCache* mDisplayItemCache;
   Maybe<uint16_t> mCurrentCacheSlot;
 
   friend class WebRenderAPI;
   friend class SpaceAndClipChainHelper;
 };
 
--- a/gfx/webrender_bindings/WebRenderTypes.cpp
+++ b/gfx/webrender_bindings/WebRenderTypes.cpp
@@ -83,15 +83,10 @@ WrSpaceAndClip RootScrollNode() {
 
 WrSpaceAndClipChain RootScrollNodeWithChain() {
   WrSpaceAndClipChain sacc;
   sacc.clip_chain = wr::ROOT_CLIP_CHAIN;
   sacc.space = wr_root_scroll_node_id();
   return sacc;
 }
 
-RenderRoot RenderRootFromId(DocumentId id) {
-  MOZ_ASSERT(id.mHandle < kRenderRootCount);
-  return (RenderRoot)id.mHandle;
-}
-
 }  // namespace wr
 }  // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -60,31 +60,16 @@ typedef Maybe<FontInstancePlatformOption
 struct ExternalImageKeyPair {
   ImageKey key;
   ExternalImageId id;
 };
 
 /* Generate a brand new window id and return it. */
 WindowId NewWindowId();
 
-MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
-    RenderRoot, uint8_t,
-    (
-        // The default render root - within the parent process, this refers
-        // to everything within the top chrome area (urlbar, tab strip, etc.).
-        // Within the content process, this refers to the content area. Any
-        // system that multiplexes data streams from different processes is
-        // responsible for converting RenderRoot::Default into
-        // whatever value is appropriate
-        Default));
-
-typedef EnumSet<RenderRoot, uint8_t> RenderRootSet;
-
-RenderRoot RenderRootFromId(DocumentId id);
-
 inline DebugFlags NewDebugFlags(uint32_t aFlags) { return {aFlags}; }
 
 inline Maybe<wr::ImageFormat> SurfaceFormatToImageFormat(
     gfx::SurfaceFormat aFormat) {
   switch (aFormat) {
     case gfx::SurfaceFormat::R8G8B8X8:
       // WebRender not support RGBX8. Assert here.
       MOZ_ASSERT(false);
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -523,18 +523,16 @@ extern "C" {
     fn wr_notifier_wake_up(window_id: WrWindowId);
     fn wr_notifier_new_frame_ready(window_id: WrWindowId);
     fn wr_notifier_nop_frame_done(window_id: WrWindowId);
     fn wr_notifier_external_event(window_id: WrWindowId, raw_event: usize);
     fn wr_schedule_render(window_id: WrWindowId);
     // NOTE: This moves away from pipeline_info.
     fn wr_finished_scene_build(
         window_id: WrWindowId,
-        document_id_array: *const WrDocumentId,
-        document_id_count: usize,
         pipeline_info: &mut WrPipelineInfo,
     );
 
     fn wr_transaction_notification_notified(handler: usize, when: Checkpoint);
 }
 
 impl RenderNotifier for CppNotifier {
     fn clone(&self) -> Box<dyn RenderNotifier> {
@@ -917,27 +915,27 @@ impl SceneBuilderHooks for APZCallbacks 
 
     fn pre_scene_swap(&self, scenebuild_time: u64) {
         unsafe {
             record_telemetry_time(TelemetryProbe::SceneBuildTime, scenebuild_time);
             apz_pre_scene_swap(self.window_id);
         }
     }
 
-    fn post_scene_swap(&self, document_ids: &Vec<DocumentId>, info: PipelineInfo, sceneswap_time: u64) {
+    fn post_scene_swap(&self, _document_ids: &Vec<DocumentId>, info: PipelineInfo, sceneswap_time: u64) {
         let mut info = WrPipelineInfo::new(&info);
         unsafe {
             record_telemetry_time(TelemetryProbe::SceneSwapTime, sceneswap_time);
             apz_post_scene_swap(self.window_id, &info);
         }
 
         // After a scene swap we should schedule a render for the next vsync,
         // otherwise there's no guarantee that the new scene will get rendered
         // anytime soon
-        unsafe { wr_finished_scene_build(self.window_id, document_ids.as_ptr(), document_ids.len(), &mut info) }
+        unsafe { wr_finished_scene_build(self.window_id, &mut info) }
         unsafe {
             gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char);
         }
     }
 
     fn post_resource_update(&self, _document_ids: &Vec<DocumentId>) {
         unsafe { wr_schedule_render(self.window_id) }
         unsafe {
--- a/gfx/wr/tileview/src/main.rs
+++ b/gfx/wr/tileview/src/main.rs
@@ -266,39 +266,47 @@ fn tile_to_svg(key: TileOffset,
             },
             reason => {
                 invalidation_report.push_str(&format!("{:?}", reason));
             },
         }
         invalidation_report.push_str("</div>\n");
     }
 
-    svg = format!(r#"{}<rect x="{}" y="{}" width="{}" height="{}" style="{}" ></rect>"#,
-            svg,
+    svg += &format!(r#"<rect x="{}" y="{}" width="{}" height="{}" style="{}" ></rect>"#,
             tile.rect.origin.x    * svg_settings.scale + svg_settings.x,
             tile.rect.origin.y    * svg_settings.scale + svg_settings.y,
             tile.rect.size.width  * svg_settings.scale,
             tile.rect.size.height * svg_settings.scale,
             tile_style);
 
-    svg = format!("{}\n\n<g class=\"svg_quadtree\">\n{}</g>\n",
-                   svg,
+    svg += &format!("\n\n<g class=\"svg_quadtree\">\n{}</g>\n",
                    tile_node_to_svg(&tile.root, &slice.transform, svg_settings));
 
     let right  = (tile.rect.origin.x + tile.rect.size.width) as i32;
     let bottom = (tile.rect.origin.y + tile.rect.size.height) as i32;
 
     *svg_width  = if right  > *svg_width  { right  } else { *svg_width  };
     *svg_height = if bottom > *svg_height { bottom } else { *svg_height };
 
     svg += "\n<!-- primitives -->\n";
 
-    svg = format!("{}<g id=\"{}\">\n\t",
-                  svg,
-                  prim_class);
+    svg += &format!("<g id=\"{}\">\n\t", prim_class);
+
+
+    let rect_visual_id = Rect {
+        origin: tile.rect.origin,
+        size: PictureSize::new(1.0, 1.0)
+    };
+    let rect_visual_id_world = slice.transform.transform_rect(&rect_visual_id).unwrap();
+    svg += &format!("\n<text class=\"svg_tile_visual_id\" x=\"{}\" y=\"{}\">{},{} ({})</text>",
+            rect_visual_id_world.origin.x           * svg_settings.scale + svg_settings.x,
+            (rect_visual_id_world.origin.y + 110.0) * svg_settings.scale + svg_settings.y,
+            key.x, key.y, slice.tile_cache.slice);
+
 
     for prim in &tile.current_descriptor.prims {
         let rect = prim.prim_clip_box;
 
         // the transform could also be part of the CSS, let the browser do it;
         // might be a bit faster and also enable actual 3D transforms.
         let rect_pixel = Rect {
             origin: PicturePoint::new(rect.min.x, rect.min.y),
@@ -355,23 +363,25 @@ fn slices_to_svg(slices: &[Slice], prev_
 
     let mut svg = String::new();
     let mut invalidation_report = "<div class=\"header\">Invalidation</div>\n".to_string();
 
     for slice in slices {
         let tile_cache = &slice.tile_cache;
         *max_slice_index = if tile_cache.slice > *max_slice_index { tile_cache.slice } else { *max_slice_index };
 
+        invalidation_report.push_str(&format!("<div id=\"invalidation_slice{}\">\n", tile_cache.slice));
+
         let prim_class = format!("tile_slice{}", tile_cache.slice);
 
-        svg.push_str(&format!("\n<g id=\"tile_slice{}_everything\">", tile_cache.slice));
+        svg += &format!("\n<g id=\"tile_slice{}_everything\">", tile_cache.slice);
 
         //println!("slice {}", tile_cache.slice);
-        svg.push_str(&format!("\n<!-- tile_cache slice {} -->\n",
-                              tile_cache.slice));
+        svg += &format!("\n<!-- tile_cache slice {} -->\n",
+                              tile_cache.slice);
 
         //let tile_stroke = "stroke:grey;stroke-width:1;".to_string();
         let tile_stroke = "stroke:none;".to_string();
 
         let mut prev_slice = None;
         if let Some(prev) = &prev_slices {
             for prev_search in prev {
                 if prev_search.tile_cache.slice == tile_cache.slice {
@@ -382,24 +392,26 @@ fn slices_to_svg(slices: &[Slice], prev_
         }
 
         for (key, tile) in &tile_cache.tiles {
             let mut prev_tile = None;
             if let Some(prev) = prev_slice {
                 prev_tile = prev.tile_cache.tiles.get(key);
             }
 
-            svg.push_str(&tile_to_svg(*key, &tile, &slice, prev_tile,
+            svg += &tile_to_svg(*key, &tile, &slice, prev_tile,
                                       itemuid_to_string,
                                       &tile_stroke, &prim_class,
                                       &mut invalidation_report,
-                                      svg_width, svg_height, svg_settings));
+                                      svg_width, svg_height, svg_settings);
         }
 
-        svg.push_str("\n</g>");
+        svg += "\n</g>";
+
+        invalidation_report.push_str("</div>\n");
     }
 
     (
         format!("{}<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\" \
                 width=\"{}\" height=\"{}\" >",
                     svg_begin,
                     svg_width,
                     svg_height)
@@ -521,16 +533,22 @@ fn write_css(output_dir: &Path, max_slic
                         }}\n\n",
                         prim_class,
                         //rgb,
                         "none",
                         0.8 * svg_settings.scale,
                         rgb);
     }
 
+    css += &format!(".svg_tile_visual_id {{\n\
+                         font: {}px sans-serif;\n\
+                         fill: rgb(50,50,50);\n\
+                     }}\n\n",
+                     150.0 * svg_settings.scale);
+
     let output_file = output_dir.join("tilecache.css");
     let mut css_output = File::create(output_file).unwrap();
     css_output.write_all(css.as_bytes()).unwrap();
 }
 
 macro_rules! updatelist_to_html_macro {
     ( $( $name:ident: $ty:ty, )+ ) => {
         fn updatelist_to_html(update_lists: &TileCacheLoggerUpdateLists,
@@ -633,19 +651,28 @@ fn main() {
     let y     = if args.len() >= 6 { args[5].parse::<f32>().unwrap() } else { 0.0 };
     let svg_settings = SvgSettings { scale, x, y };
 
     let mut svg_width = 100i32;
     let mut svg_height = 100i32;
     let mut max_slice_index = 0;
 
     let mut entries: Vec<_> = std::fs::read_dir(input_dir).unwrap()
-                                                          //.map(|r| r.unwrap())
                                                           .filter_map(|r| r.ok())
                                                           .collect();
+    // auto-fix a missing 'tile_cache' postfix on the input path -- easy to do when copy-pasting a
+    // path to a wr-capture; there should at least be a frame00000.ron...
+    let frame00000 = entries.iter().find(|&entry| entry.path().ends_with("frame00000.ron"));
+    // ... and if not, try again with 'tile_cache' appended to the input folder
+    if frame00000.is_none() {
+        let new_path = input_dir.join("tile_cache");
+        entries = std::fs::read_dir(new_path).unwrap()
+                                             .filter_map(|r| r.ok())
+                                             .collect();
+    }
     entries.sort_by_key(|dir| dir.path());
 
     let mut svg_files: Vec::<String> = Vec::new();
     let mut intern_files: Vec::<String> = Vec::new();
     let mut prev_slices = None;
 
     let mut itemuid_to_string = HashMap::default();
 
--- a/gfx/wr/tileview/src/tilecache.js
+++ b/gfx/wr/tileview/src/tilecache.js
@@ -44,33 +44,44 @@ function toggle_quadtree() {
 
 function update_slice_visibility(max_slice) {
 	let content = frontbuffer.contentDocument;
 	update_slice_visibility_for_content(content, max_slice);
 }
 
 function update_slice_visibility_for_content(content, max_slice) {
 
-	if( !content ) // might happen due to cross-scripting -- use SimpleHTTPServer
-		return;
+	intern = document.getElementById('intern').contentDocument;
 
 	for (let slice = 0; slice != max_slice; ++slice) {
 		var cbox_name = "slice_toggle" + slice;
 		let cbox = document.getElementById(cbox_name);
 		if( !cbox )
 			continue;
 		let checked = cbox.checked;
-		var id = "tile_slice" + slice + "_everything";
-		var group = content.getElementById(id);
-		if( !group )
-			continue;
-		if( checked )
-			group.style.display = "block";
-		else
-			group.style.display = "none";
+		if (content) { // might fail due to cross scripting -- use SimpleHTTPServer
+			var id = "tile_slice" + slice + "_everything";
+			var group = content.getElementById(id);
+			if (group) {
+				if (checked)
+					group.style.display = "block";
+				else
+					group.style.display = "none";
+			}
+		}
+		if (intern) {
+			var id = "invalidation_slice" + slice;
+			var div = intern.getElementById(id);
+			if (div) {
+				if (checked)
+					div.style.display = "block";
+				else
+					div.style.display = "none";
+			}
+		}
 	}
 }
 
 // try to block repeated keypressed from causing flickering
 // when they land between go_to_svg returning and onload
 // firing.
 var is_loading = false;
 
@@ -99,18 +110,18 @@ function go_to_svg(index) {
     backbuffer.style.display = '';
     frontbuffer.style.display = 'none';
 
     var t = frontbuffer;
     frontbuffer = backbuffer;
     backbuffer = t;
     is_loading = false;
   }
+  document.getElementById('intern').src = intern_files[svg_index];
   backbuffer.setAttribute('data', svg_files[svg_index]);
-  document.getElementById('intern').src = intern_files[svg_index];
 
   // also see https://stackoverflow.com/a/29915275
 }
 
 function load() {
   window.addEventListener('keypress', handle_keyboard_shortcut);
   window.addEventListener('keydown',  handle_keydown);
 
--- a/gfx/wr/webrender/res/brush_image.glsl
+++ b/gfx/wr/webrender/res/brush_image.glsl
@@ -98,47 +98,51 @@ void image_brush_vs(
             vec2 uv_size = res.uv_rect.p1 - res.uv_rect.p0;
             uv0 = res.uv_rect.p0 + segment_data.xy * uv_size;
             uv1 = res.uv_rect.p0 + segment_data.zw * uv_size;
 
             // Size of the uv rect of the segment we are considering when computing
             // the repetitions. In most case it is the current segment, but for the
             // middle area we look at the border size instead.
             vec2 segment_uv_size = uv1 - uv0;
-
             #ifdef WR_FEATURE_REPETITION
+            // Value of the stretch size with repetition. We have to compute it for
+            // both axis even if we only repeat on one axis because the value for
+            // each axis depends on what the repeated value would have been for the
+            // other axis.
+            vec2 repeated_stretch_size = stretch_size;
             // The repetition parameters for the middle area of a nine-patch are based
             // on the size of the border segments rather than the middle segment itself,
             // taking top and left by default, falling back to bottom and right when a
             // size is empty.
             // TODO(bug 1609893): Move this logic to the CPU as well as other sources of
             // branchiness in this shader.
             if ((brush_flags & BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE) != 0) {
                 segment_uv_size = uv0 - res.uv_rect.p0;
-                stretch_size.x = segment_rect.p0.x - prim_rect.p0.x;
-                stretch_size.y = segment_rect.p0.y - prim_rect.p0.y;
+                repeated_stretch_size = segment_rect.p0 - prim_rect.p0;
                 float epsilon = 0.001;
-                if (segment_uv_size.x < epsilon || stretch_size.x < epsilon) {
+
+                if (segment_uv_size.x < epsilon || repeated_stretch_size.x < epsilon) {
                     segment_uv_size.x = res.uv_rect.p1.x - uv1.x;
-                    stretch_size.x = prim_rect.p0.x + prim_rect.size.x
+                    repeated_stretch_size.x = prim_rect.p0.x + prim_rect.size.x
                         - segment_rect.p0.x - segment_rect.size.x;
                 }
-                if (segment_uv_size.y < epsilon || stretch_size.y < epsilon) {
+
+                if (segment_uv_size.y < epsilon || repeated_stretch_size.y < epsilon) {
                     segment_uv_size.y = res.uv_rect.p1.y - uv1.y;
-                    stretch_size.y = prim_rect.p0.y + prim_rect.size.y
+                    repeated_stretch_size.y = prim_rect.p0.y + prim_rect.size.y
                         - segment_rect.p0.y - segment_rect.size.y;
                 }
             }
 
-            vec2 original_stretch_size = stretch_size;
             if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
-              stretch_size.x = original_stretch_size.y / segment_uv_size.y * segment_uv_size.x;
+              stretch_size.x = repeated_stretch_size.y / segment_uv_size.y * segment_uv_size.x;
             }
             if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
-              stretch_size.y = original_stretch_size.x / segment_uv_size.x * segment_uv_size.y;
+              stretch_size.y = repeated_stretch_size.x / segment_uv_size.x * segment_uv_size.y;
             }
             #endif
 
         } else {
             #ifdef WR_FEATURE_REPETITION
             if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
                 stretch_size.x = segment_data.z - segment_data.x;
             }
--- a/gfx/wr/webrender/src/scene_building.rs
+++ b/gfx/wr/webrender/src/scene_building.rs
@@ -1959,16 +1959,18 @@ impl<'a> SceneBuilder<'a> {
             stacking_context.composite_ops.filter_primitives,
             stacking_context.composite_ops.filter_datas,
             stacking_context.prim_flags,
             stacking_context.requested_raster_space,
             stacking_context.spatial_node_index,
             true,
         );
 
+        let has_filters = current_pic_index != filtered_pic_index;
+
         current_pic_index = filtered_pic_index;
         cur_instance = filtered_instance;
 
         // Same for mix-blend-mode, except we can skip if this primitive is the first in the parent
         // stacking context.
         // From https://drafts.fxtf.org/compositing-1/#generalformula, the formula for blending is:
         // Cs = (1 - ab) x Cs + ab x Blend(Cb, Cs)
         // where
@@ -2029,17 +2031,17 @@ impl<'a> SceneBuilder<'a> {
         // Set the stacking context clip on the outermost picture in the chain,
         // unless we already set it on the leaf picture.
         cur_instance.clip_chain_id = stacking_context.clip_chain_id;
 
         // The primitive instance for the remainder of flat children of this SC
         // if it's a part of 3D hierarchy but not the root of it.
         let trailing_children_instance = match self.sc_stack.last_mut() {
             // Preserve3D path (only relevant if there are no filters/mix-blend modes)
-            Some(ref parent_sc) if parent_sc.is_3d() => {
+            Some(ref parent_sc) if !has_filters && parent_sc.is_3d() => {
                 Some(cur_instance)
             }
             // Regular parenting path
             Some(ref mut parent_sc) => {
                 parent_sc.prim_list.add_prim(
                     cur_instance,
                     LayoutRect::zero(),
                     stacking_context.spatial_node_index,
index 3dcd4aaf3bcef9b23aa1423c99855423a441a0f4..41627d9455727fb6d3f3b22197092ebb354c8926
GIT binary patch
literal 28383
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
--- a/gfx/wr/wrench/reftests/border/border-image-fill.yaml
+++ b/gfx/wr/wrench/reftests/border/border-image-fill.yaml
@@ -11,8 +11,44 @@ root:
           image-source: "border-image-src.png"
           image-width: 96
           image-height: 96
           slice: [ 32 ]
           outset: 0
           repeat-vertical: repeat
           repeat-horizontal: repeat
           fill: true
+        - type: border
+          bounds: [ 300, 100, 192, 192 ]
+          width: 32
+          border-type: image
+          image-source: "border-image-src.png"
+          image-width: 96
+          image-height: 96
+          slice: [ 32 ]
+          outset: 0
+          repeat-vertical: stretch
+          repeat-horizontal: repeat
+          fill: true
+        - type: border
+          bounds: [ 100, 300, 192, 192 ]
+          width: 32
+          border-type: image
+          image-source: "border-image-src.png"
+          image-width: 96
+          image-height: 96
+          slice: [ 32 ]
+          outset: 0
+          repeat-vertical: repeat
+          repeat-horizontal: stretch
+          fill: true
+        - type: border
+          bounds: [ 300, 300, 192, 192 ]
+          width: 32
+          border-type: image
+          image-source: "border-image-src.png"
+          image-width: 96
+          image-height: 96
+          slice: [ 32 ]
+          outset: 0
+          repeat-vertical: stretch
+          repeat-horizontal: stretch
+          fill: true
--- a/gfx/wr/wrench/reftests/border/reftest.list
+++ b/gfx/wr/wrench/reftests/border/reftest.list
@@ -14,17 +14,17 @@ platform(linux,mac) == border-suite-3.ya
 skip_on(android,device) == border-double-simple.yaml border-double-simple-ref.yaml  # Fails on Pixel2
 == border-double-simple-2.yaml border-double-simple-2-ref.yaml
 skip_on(android,device) fuzzy(64,24) == border-groove-simple.yaml border-groove-simple-ref.yaml  # Fails on Pixel2
 skip_on(android,device) fuzzy(64,24) == border-ridge-simple.yaml border-ridge-simple-ref.yaml  # Fails on Pixel2
 platform(linux,mac) fuzzy(1,3) == degenerate-curve.yaml degenerate-curve.png
 platform(linux,mac) == border-image.yaml border-image-ref.png
 platform(linux,mac) == border-image-round.yaml border-image-round-ref.png
 == border-image-crash.yaml border-image-crash-ref.yaml
-== border-image-fill.yaml border-image-fill-ref.png
+fuzzy(1,5000) == border-image-fill.yaml border-image-fill-ref.png
 == border-no-bogus-line.yaml border-no-bogus-line-ref.png
 platform(linux,mac) == dotted-corner-small-radius.yaml dotted-corner-small-radius.png
 == overlapping.yaml overlapping.png
 == zero-width.yaml blank.yaml
 platform(linux,mac) == small-dotted-border.yaml small-dotted-border.png
 == discontinued-dash.yaml discontinued-dash.png
 platform(linux,mac) == border-dashed-dotted-caching.yaml border-dashed-dotted-caching.png
 != small-inset-outset.yaml small-inset-outset-notref.yaml
--- a/gfx/wr/wrench/reftests/filters/reftest.list
+++ b/gfx/wr/wrench/reftests/filters/reftest.list
@@ -1,14 +1,14 @@
 == filter-grayscale.yaml filter-grayscale-ref.yaml
 platform(linux,mac) == draw_calls(7) color_targets(7) alpha_targets(0) filter-blur.yaml filter-blur.png
 == isolated.yaml isolated-ref.yaml
 == invisible.yaml invisible-ref.yaml
-color_targets(2) alpha_targets(0) == opacity.yaml opacity-ref.yaml
-color_targets(2) alpha_targets(0) == opacity-combined.yaml opacity-combined-ref.yaml
+== opacity.yaml opacity-ref.yaml
+fuzzy-range(<=1,*10000) == opacity-combined.yaml opacity-combined-ref.yaml
 == opacity-overlap.yaml opacity-overlap-ref.yaml
 == filter-brightness.yaml filter-brightness-ref.yaml
 == filter-brightness-2.yaml filter-brightness-2-ref.yaml
 == filter-brightness-3.yaml filter-brightness-3-ref.yaml
 == filter-brightness-4.yaml filter-brightness-4-ref.yaml
 == filter-component-transfer.yaml filter-component-transfer-ref.yaml
 skip_on(android,device) == filter-color-matrix.yaml filter-color-matrix-ref.yaml  # fails on Pixel2
 == filter-contrast-gray-alpha-1.yaml filter-contrast-gray-alpha-1-ref.yaml
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -18,17 +18,16 @@ builtin(include, ../../build/autoconf/co
 builtin(include, ../../build/autoconf/expandlibs.m4)dnl
 builtin(include, ../../build/autoconf/arch.m4)dnl
 builtin(include, ../../build/autoconf/android.m4)dnl
 builtin(include, ../../build/autoconf/zlib.m4)dnl
 builtin(include, ../../build/autoconf/icu.m4)dnl
 builtin(include, ../../build/autoconf/clang-plugin.m4)dnl
 builtin(include, ../../build/autoconf/alloc.m4)dnl
 builtin(include, ../../build/autoconf/sanitize.m4)dnl
-builtin(include, ../../build/autoconf/ios.m4)dnl
 
 define([__MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE]))
 define([AC_INIT_PREPARE],
 [if test -z "$srcdir"; then
   srcdir=`dirname "[$]0"`
 fi
 srcdir="$srcdir/../.."
 __MOZ_AC_INIT_PREPARE($1)
--- a/js/src/devtools/automation/arm64-jstests-slow.txt
+++ b/js/src/devtools/automation/arm64-jstests-slow.txt
@@ -41,9 +41,9 @@ non262/object/15.2.3.6-redefinition-2-of
 non262/object/15.2.3.6-redefinition-3-of-4.js
 non262/object/15.2.3.6-redefinition-4-of-4.js
 non262/extensions/clone-complex-object.js
 non262/reflect-parse/classes.js
 non262/reflect-parse/destructuring-variable-declarations.js
 test262/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
 test262/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
 test262/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
-
+test262/built-ins/RegExp/property-escapes/generated/
--- a/js/src/new-regexp/regexp-shim.h
+++ b/js/src/new-regexp/regexp-shim.h
@@ -24,16 +24,18 @@
 
 #include "jit/Label.h"
 #include "jit/shared/Assembler-shared.h"
 #include "js/Value.h"
 #include "new-regexp/RegExpTypes.h"
 #include "new-regexp/util/flags.h"
 #include "new-regexp/util/vector.h"
 #include "new-regexp/util/zone.h"
+#include "threading/ExclusiveData.h"
+#include "vm/MutexIDs.h"
 #include "vm/NativeObject.h"
 
 // Forward declaration of classes
 namespace v8 {
 namespace internal {
 
 class Heap;
 class Isolate;
@@ -169,27 +171,32 @@ inline constexpr bool IsInRange(T value,
   using unsigned_T = typename std::make_unsigned<T>::type;
   // Use static_cast to support enum classes.
   return static_cast<unsigned_T>(static_cast<unsigned_T>(value) -
                                  static_cast<unsigned_T>(lower_limit)) <=
          static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
                                  static_cast<unsigned_T>(lower_limit));
 }
 
-#define LAZY_INSTANCE_INITIALIZER { mozilla::Nothing() }
+#define LAZY_INSTANCE_INITIALIZER { }
 
 template <typename T>
-struct LazyInstanceImpl {
-  mozilla::Maybe<T> value_;
-  T* Pointer() {
-    if (value_.isNothing()) {
-      value_.emplace();
+class LazyInstanceImpl {
+ public:
+  LazyInstanceImpl() : value_(js::mutexid::IrregexpLazyStatic) {}
+
+  const T* Pointer() {
+    auto val = value_.lock();
+    if (val->isNothing()) {
+      val->emplace();
     }
-    return value_.ptr();
+    return val->ptr();
   }
+ private:
+  js::ExclusiveData<mozilla::Maybe<T>> value_;
 };
 
 template <typename T>
 class LazyInstance {
 public:
   using type = LazyInstanceImpl<T>;
 };
 
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -72,22 +72,16 @@ AC_SUBST(autoconfmk)
 if test -n "$JS_STANDALONE"; then
   jsconfdefs=$_objdir/js/src/js-confdefs.h
 else
   jsconfdefs=$_objdir/js-confdefs.h
 fi
 
 MOZ_ANDROID_NDK
 
-case "$target" in
-*-apple-darwin*)
-    MOZ_IOS_SDK
-    ;;
-esac
-
 dnl ========================================================
 dnl Checks for compilers.
 dnl ========================================================
 
 if test "$COMPILE_ENVIRONMENT"; then
 
 # Note:
 #   In Mozilla, we use the names $target, $host and $build incorrectly, but are
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -488,17 +488,16 @@ struct ShellCompartmentPrivate {
 struct MOZ_STACK_CLASS EnvironmentPreparer
     : public js::ScriptEnvironmentPreparer {
   explicit EnvironmentPreparer(JSContext* cx) {
     js::SetScriptEnvironmentPreparer(cx, this);
   }
   void invoke(JS::HandleObject global, Closure& closure) override;
 };
 
-bool shell::enableDeferredMode = true;
 bool shell::enableCodeCoverage = false;
 bool shell::enableDisassemblyDumps = false;
 bool shell::offthreadCompilation = false;
 bool shell::enableAsmJS = false;
 bool shell::enableWasm = false;
 bool shell::enableSharedMemory = SHARED_MEMORY_DEFAULT;
 bool shell::enableWasmBaseline = false;
 bool shell::enableWasmIon = false;
@@ -11710,19 +11709,16 @@ int main(int argc, char** argv, char** e
     js::DisableExtraThreads();
   }
 
   enableCodeCoverage = op.getBoolOption("code-coverage");
   if (enableCodeCoverage) {
     coverage::EnableLCov();
   }
 
-  enableDeferredMode = !op.getBoolOption("disable-parser-deferred-alloc") &&
-                       getenv("DISABLE_PARSER_DEFERRED_ALLOC") == nullptr;
-
 #ifdef JS_WITHOUT_NSPR
   if (!op.getMultiStringOption("dll").empty()) {
     fprintf(stderr, "Error: --dll requires NSPR support!\n");
     return EXIT_FAILURE;
   }
 #else
   AutoLibraryLoader loader;
   MultiStringRange dllPaths = op.getMultiStringOption("dll");
--- a/js/src/shell/jsshell.h
+++ b/js/src/shell/jsshell.h
@@ -92,17 +92,16 @@ struct RCFile {
   bool release();
 };
 
 // Shell command-line arguments and count.
 extern int sArgc;
 extern char** sArgv;
 
 // Shell state set once at startup.
-extern bool enableDeferredMode;
 extern bool enableCodeCoverage;
 extern bool enableDisassemblyDumps;
 extern bool offthreadCompilation;
 extern bool enableAsmJS;
 extern bool enableWasm;
 extern bool enableSharedMemory;
 extern bool enableWasmBaseline;
 extern bool enableWasmIon;
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -373,16 +373,17 @@ skip script test262/annexB/language/func
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1508683
 # All of these tests pass except with --more-compartments.
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/multiline/cross-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/global/cross-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/sticky/cross-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/ignoreCase/cross-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/unicode/cross-realm.js
+ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/dotAll/cross-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/RegExp/prototype/source/cross-realm.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1545038
 # All of these tests pass except with --more-compartments.
 ignore-flag(--more-compartments) script test262/built-ins/String/prototype/valueOf/non-generic-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/String/prototype/valueOf/non-generic-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/String/prototype/toString/non-generic-realm.js
 ignore-flag(--more-compartments) script test262/built-ins/String/prototype/toString/non-generic-realm.js
--- a/js/src/tests/test262-update.py
+++ b/js/src/tests/test262-update.py
@@ -20,21 +20,18 @@ from operator import itemgetter
 
 # Skip all tests which use features not supported in SpiderMonkey.
 UNSUPPORTED_FEATURES = set([
     "tail-call-optimization",
     "class-fields-private",
     "class-static-fields-private",
     "class-methods-private",
     "class-static-methods-private",
-    "regexp-dotall",
-    "regexp-lookbehind",
     "regexp-match-indices",
     "regexp-named-groups",
-    "regexp-unicode-property-escapes",
     "export-star-as-namespace-from-module",
     "Intl.DateTimeFormat-quarter",
     "Intl.DateTimeFormat-datetimestyle",
     "Intl.DateTimeFormat-formatRange",
     "Intl.DisplayNames",
     "Intl.Segmenter",
     "top-level-await",
 ])
--- a/js/src/tests/test262/annexB/built-ins/RegExp/named-groups/non-unicode-malformed-lookbehind.js
+++ b/js/src/tests/test262/annexB/built-ins/RegExp/named-groups/non-unicode-malformed-lookbehind.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- regexp-named-groups,regexp-lookbehind is not supported
+// |reftest| skip -- regexp-named-groups is not supported
 // Copyright 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: prod-GroupSpecifier
 description: >
   \k is parsed as IdentityEscape as look-behind assertion is not a GroupName.
 features: [regexp-named-groups, regexp-lookbehind]
--- a/js/src/tests/test262/annexB/built-ins/RegExp/prototype/flags/order-after-compile.js
+++ b/js/src/tests/test262/annexB/built-ins/RegExp/prototype/flags/order-after-compile.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-dotall is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-get-regexp.prototype.flags
 description: >
   The flags come in the same order in a new instance produced by RegExp.prototype.compile
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/dotall/with-dotall-unicode.js
+++ b/js/src/tests/test262/built-ins/RegExp/dotall/with-dotall-unicode.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-dotall is not supported
 // Copyright 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Test the characters included by . in dotAll and unicode mode
 info: |
   21.2.2.8 Atom
   The production Atom::. evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/dotall/with-dotall.js
+++ b/js/src/tests/test262/built-ins/RegExp/dotall/with-dotall.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-dotall is not supported
 // Copyright 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Test the characters included by . in dotAll and non-unicode mode
 info: |
   21.2.2.8 Atom
   The production Atom::. evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/duplicate-flags.js
+++ b/js/src/tests/test262/built-ins/RegExp/duplicate-flags.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-dotall is not supported
 // Copyright 2017 the V8 project authors.  All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 info: |
     RegExpInitialize ( obj, pattern, flags )
       5. If F contains any code unit other than "g", "i", "m", "s", "u", or "y" or if it contains the same code unit more than once, throw a SyntaxError exception.
 esid: sec-regexpinitialize
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/alternations.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/alternations.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Alternations are tried left to right, and we do not backtrack into a lookbehind.
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/back-references-to-captures.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/back-references-to-captures.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Back references to captures inside the lookbehind.
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/back-references.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/back-references.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Back references
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/captures-negative.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/captures-negative.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: >
   Captures inside negative lookbehind. (They never capture.)
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/captures.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/captures.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: >
   Capturing matches
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/do-not-backtrack.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/do-not-backtrack.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Do not backtrack into a lookbehind.
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/greedy-loop.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/greedy-loop.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Greedy loop
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/misc.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/misc.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Misc RegExp lookbehind tests
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/mutual-recursive.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/mutual-recursive.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Mutual recursive capture/back references
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/negative.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/negative.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: RegExp negative lookbehind
 info: |
   The production Assertion :: (?<!Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/nested-lookaround.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/nested-lookaround.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Nested lookaround
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/simple-fixed-length.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/simple-fixed-length.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Simple fixed-length matches
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/sliced-strings.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/sliced-strings.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Sliced strings
 info: |
   Rationale from https://github.com/tc39/test262/pull/999#discussion_r113807747
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/start-of-line.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/start-of-line.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Start of line matches
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/sticky.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/sticky.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Sticky
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/variable-length.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/variable-length.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Variable-length matches
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/lookBehind/word-boundary.js
+++ b/js/src/tests/test262/built-ins/RegExp/lookBehind/word-boundary.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-lookbehind is not supported
 // Copyright (C) 2017 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-assertion
 description: Word boundary
 info: |
   The production Assertion :: (?<=Disjunction) evaluates as follows:
--- a/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js
+++ b/js/src/tests/test262/built-ins/RegExp/named-groups/lookbehind.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- regexp-named-groups,regexp-lookbehind is not supported
+// |reftest| skip -- regexp-named-groups is not supported
 // Copyright 2018 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Named groups can be used in conjunction with lookbehind
 esid: prod-GroupSpecifier
 features: [regexp-named-groups, regexp-lookbehind]
 includes: [compareArray.js]
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Invalid.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_N-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_N-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_N.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_N.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_No-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_No-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_No.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_No.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_T-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_T-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_T.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_T.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Y-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Y-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Y.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Y.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Yes-negated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Yes-negated.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Yes.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_Yes.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Binary properties with an explicit value must throw in Unicode property
   escapes (even if the value is valid).
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-end.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-end.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   NonemptyClassRanges :: ClassAtom - ClassAtom ClassRanges
 
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-no-dash-end.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-no-dash-end.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassRanges
 
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-no-dash-start.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-no-dash-start.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassRanges
 
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-start.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class-range-start.js
@@ -1,9 +1,9 @@
-// |reftest| skip error:SyntaxError -- regexp-unicode-property-escapes is not supported
+// |reftest| error:SyntaxError
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   NonemptyClassRanges :: ClassAtom - ClassAtom ClassRanges
 
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/character-class.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2018 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes must be supported in character classes.
 esid: sec-static-semantics-unicodematchproperty-p
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `ASCII`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ASCII_Hex_Digit.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `ASCII_Hex_Digit`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Alphabetic.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Alphabetic`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Any.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Any`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Assigned.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Assigned`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Control.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Bidi_Control`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Bidi_Mirrored.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Bidi_Mirrored`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Case_Ignorable.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Case_Ignorable`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Cased.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Cased`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casefolded.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_Casefolded`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Casemapped.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_Casemapped`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Lowercased.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_Lowercased`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_NFKC_Casefolded.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_NFKC_Casefolded`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Titlecased.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_Titlecased`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Changes_When_Uppercased.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Changes_When_Uppercased`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Dash.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Dash`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Default_Ignorable_Code_Point.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Default_Ignorable_Code_Point`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Deprecated.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Deprecated`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Diacritic.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Diacritic`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Emoji`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Component.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Emoji_Component`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Emoji_Modifier`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Modifier_Base.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Emoji_Modifier_Base`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Emoji_Presentation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Emoji_Presentation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extended_Pictographic.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Extended_Pictographic`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Extender.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Extender`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Cased_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Cased_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Close_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Close_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Connector_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Connector_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Control.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Control`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Currency_Symbol.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Currency_Symbol`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Dash_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Dash_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Decimal_Number`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Enclosing_Mark.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Enclosing_Mark`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Final_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Final_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Format.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Format`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Initial_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Initial_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Letter_Number.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Letter_Number`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Line_Separator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Line_Separator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Lowercase_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Lowercase_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Mark.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Mark`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Math_Symbol.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Math_Symbol`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Modifier_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Modifier_Symbol.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Modifier_Symbol`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Nonspacing_Mark.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Nonspacing_Mark`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Number.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Number`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Open_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Open_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Other`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Other_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Number.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Other_Number`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Other_Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Other_Symbol.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Other_Symbol`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Paragraph_Separator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Paragraph_Separator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Private_Use.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Private_Use`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Punctuation.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Punctuation`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Separator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Separator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Space_Separator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Space_Separator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Spacing_Mark.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Spacing_Mark`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Surrogate.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Surrogate`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Symbol.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Symbol`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Titlecase_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Titlecase_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Unassigned.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Unassigned`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/General_Category_-_Uppercase_Letter.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `General_Category=Uppercase_Letter`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Base.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Grapheme_Base`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Grapheme_Extend.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Grapheme_Extend`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Hex_Digit.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Hex_Digit`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Binary_Operator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `IDS_Binary_Operator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/IDS_Trinary_Operator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `IDS_Trinary_Operator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Continue.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `ID_Continue`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/ID_Start.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `ID_Start`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Ideographic.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Ideographic`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Join_Control.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Join_Control`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Logical_Order_Exception.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Logical_Order_Exception`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Lowercase.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Lowercase`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Math.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Math`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Noncharacter_Code_Point.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Noncharacter_Code_Point`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_Syntax.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Pattern_Syntax`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Pattern_White_Space.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Pattern_White_Space`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Quotation_Mark.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Quotation_Mark`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Radical.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Radical`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Regional_Indicator.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Regional_Indicator`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Adlam.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Adlam`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Ahom.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Ahom`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Anatolian_Hieroglyphs.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Anatolian_Hieroglyphs`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Arabic.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Arabic`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Armenian.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Armenian`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Avestan.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Avestan`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Balinese.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Balinese`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bamum.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Bamum`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bassa_Vah.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Bassa_Vah`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Batak.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Batak`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bengali.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Bengali`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bhaiksuki.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Bhaiksuki`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Bopomofo.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 author: Mathias Bynens
 description: >
   Unicode property escapes for `Script=Bopomofo`
 info: |
--- a/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js
+++ b/js/src/tests/test262/built-ins/RegExp/property-escapes/generated/Script_-_Brahmi.js
@@ -1,9 +1,8 @@
-// |reftest| skip -- regexp-unicode-property-escapes is not supported
 // Copyright 2020 Mathias Bynens. All rights reserved.