Merge autoland to mozilla-central. a=merge
authorMihai Alexandru Michis <malexandru@mozilla.com>
Wed, 06 Jan 2021 17:49:56 +0200
changeset 562140 dd21b22c480175ca00f0834dbd4d9c1684aa85d2
parent 562108 855ec176a3c2239fe2f166431c96ee7710204b30 (current diff)
parent 562139 90a0c52c92ba4d8f857d02f82df3b5dccbd182eb (diff)
child 562156 c191ede3431c3af139a688e755329a514e08920b
push id38082
push usermalexandru@mozilla.com
push dateWed, 06 Jan 2021 15:51:27 +0000
treeherdermozilla-central@dd21b22c4801 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone86.0a1
first release with
nightly linux32
dd21b22c4801 / 86.0a1 / 20210106155127 / files
nightly linux64
dd21b22c4801 / 86.0a1 / 20210106155127 / files
nightly mac
dd21b22c4801 / 86.0a1 / 20210106155127 / files
nightly win32
dd21b22c4801 / 86.0a1 / 20210106155127 / files
nightly win64
dd21b22c4801 / 86.0a1 / 20210106155127 / 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
mobile/android/themes/core/aboutAccounts.css
mobile/android/themes/core/aboutAddons.css
mobile/android/themes/core/aboutBase.css
mobile/android/themes/core/aboutDownloads.css
mobile/android/themes/core/aboutExperiments.css
mobile/android/themes/core/aboutLogins.css
mobile/android/themes/core/aboutPage.css
mobile/android/themes/core/aboutPrivateBrowsing.css
mobile/android/themes/core/aboutReader.css
mobile/android/themes/core/defines.css
mobile/android/themes/core/images/about-btn-darkgrey.png
mobile/android/themes/core/images/amo-logo.png
mobile/android/themes/core/images/blocked-warning.png
mobile/android/themes/core/images/certerror-warning.png
mobile/android/themes/core/images/checkbox_checked.png
mobile/android/themes/core/images/checkbox_checked_disabled.png
mobile/android/themes/core/images/checkbox_checked_pressed.png
mobile/android/themes/core/images/checkbox_unchecked.png
mobile/android/themes/core/images/checkbox_unchecked_disabled.png
mobile/android/themes/core/images/checkbox_unchecked_pressed.png
mobile/android/themes/core/images/chevron-rtl.png
mobile/android/themes/core/images/chevron.png
mobile/android/themes/core/images/errorpage-warning.png
mobile/android/themes/core/images/extension-update.svg
mobile/android/themes/core/images/grey-caution.svg
mobile/android/themes/core/images/icon_key_emptypage.svg
mobile/android/themes/core/images/logo-hdpi.png
mobile/android/themes/core/images/placeholder_image.svg
mobile/android/themes/core/images/privatebrowsing-mask-and-shield.svg
mobile/android/themes/core/images/privatebrowsing-mask.png
mobile/android/themes/core/images/reader-minus-hdpi.png
mobile/android/themes/core/images/reader-minus-xhdpi.png
mobile/android/themes/core/images/reader-minus-xxhdpi.png
mobile/android/themes/core/images/reader-plus-hdpi.png
mobile/android/themes/core/images/reader-plus-xhdpi.png
mobile/android/themes/core/images/reader-plus-xxhdpi.png
mobile/android/themes/core/images/reader-style-icon-hdpi.png
mobile/android/themes/core/images/reader-style-icon-xhdpi.png
mobile/android/themes/core/images/reader-style-icon-xxhdpi.png
mobile/android/themes/core/images/wordmark-hdpi.png
mobile/android/themes/core/jar.mn
mobile/android/themes/core/moz.build
mobile/android/themes/core/spinner.css
testing/web-platform/meta/custom-elements/parser/parser-sets-attributes-and-children.html.ini
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -329,34 +329,31 @@ dependencies = [
 ]
 
 [[package]]
 name = "bits_client"
 version = "0.2.0"
 dependencies = [
  "bits",
  "comedy",
- "failure",
- "failure_derive",
  "guid_win",
  "lazy_static",
  "rand",
  "regex",
  "tempfile",
+ "thiserror",
 ]
 
 [[package]]
 name = "bitsdownload"
 version = "0.1.0"
 dependencies = [
  "bits_client",
  "comedy",
  "crossbeam-utils 0.6.5",
- "failure",
- "failure_derive",
  "libc",
  "log",
  "moz_task",
  "nserror",
  "nsstring",
  "xpcom",
 ]
 
--- a/browser/config/mozconfigs/win32/mingwclang
+++ b/browser/config/mozconfigs/win32/mingwclang
@@ -1,17 +1,14 @@
 # Sets:
 #    MOZ_AUTOMATION flags
 #    SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE - shouldn't be used?
 #    TOOLTOOL_DIR
-#    DUMP_SYMS - isn't used.
 . "$topsrcdir/build/mozconfig.win-common"
 
-unset DUMP_SYMS
-
 # Sets:
 #  build/mozconfig.common
 #    AUTOCLOBBER=1
 #    --enable-crashreporter
 #    --enable-release
 #    MOZ_ADDON_SIGNING
 #    MOZ_REQUIRE_SIGNING
 #    --enable-js-shell
@@ -25,17 +22,16 @@ unset DUMP_SYMS
 
 export MOZ_PACKAGE_JSSHELL=1
 
 # MinGW Stuff
 ac_add_options --target=i686-w64-mingw32
 ac_add_options --with-toolchain-prefix=i686-w64-mingw32-
 
 ac_add_options --disable-warnings-as-errors
-MOZ_COPY_PDBS=1
 mk_add_options "export WIDL_TIME_OVERRIDE=0"
 
 # This replicates Tor's configuration
 ac_add_options --enable-proxy-bypass-protection
 
 # These aren't supported on mingw at this time
 ac_add_options --disable-webrtc # Bug 1393901
 ac_add_options --disable-geckodriver # Bug 1489320
--- a/browser/config/mozconfigs/win64/mingwclang
+++ b/browser/config/mozconfigs/win64/mingwclang
@@ -1,17 +1,14 @@
 # Sets:
 #    MOZ_AUTOMATION flags
 #    SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE - shouldn't be used?
 #    TOOLTOOL_DIR
-#    DUMP_SYMS - isn't used.
 . "$topsrcdir/build/mozconfig.win-common"
 
-unset DUMP_SYMS
-
 # Sets:
 #  build/mozconfig.common
 #    AUTOCLOBBER=1
 #    --enable-crashreporter
 #    --enable-release
 #    MOZ_ADDON_SIGNING
 #    MOZ_REQUIRE_SIGNING
 #    --enable-js-shell
@@ -25,17 +22,16 @@ unset DUMP_SYMS
 
 export MOZ_PACKAGE_JSSHELL=1
 
 # MinGW Stuff
 ac_add_options --target=x86_64-w64-mingw32
 ac_add_options --with-toolchain-prefix=x86_64-w64-mingw32-
 
 ac_add_options --disable-warnings-as-errors
-MOZ_COPY_PDBS=1
 mk_add_options "export WIDL_TIME_OVERRIDE=0"
 
 # This replicates Tor's configuration
 ac_add_options --enable-proxy-bypass-protection
 
 # These aren't supported on mingw at this time
 ac_add_options --disable-webrtc # Bug 1393901
 ac_add_options --disable-geckodriver # Bug 1489320
--- a/devtools/client/shared/unicode-url.js
+++ b/devtools/client/shared/unicode-url.js
@@ -83,17 +83,23 @@ function getUnicodeUrlPath(urlPath) {
 function getUnicodeUrl(url) {
   try {
     const { protocol, hostname } = new URL(url);
     if (protocol === "data:") {
       // Never convert a data: URI.
       return url;
     }
     const readableHostname = getUnicodeHostname(hostname);
-    url = decodeURI(url);
+
+    /* We use `decodeURIComponent` instead of decodeURI as the
+     * later does not decode some characters, it only can decode characters
+     * previously encoded by the encodeURI. See
+     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#Description
+     */
+    url = decodeURIComponent(url);
     return url.replace(hostname, readableHostname);
   } catch (err) {}
   return url;
 }
 
 module.exports = {
   getUnicodeHostname,
   getUnicodeUrlPath,
--- a/devtools/client/webconsole/actions/input.js
+++ b/devtools/client/webconsole/actions/input.js
@@ -162,19 +162,28 @@ function onExpressionEvaluated(response)
       return;
     }
 
     await dispatch(handleHelperResult(response));
   };
 }
 
 function handleHelperResult(response) {
+  // eslint-disable-next-line complexity
   return async ({ dispatch, hud, toolbox, webConsoleUI }) => {
     const { result, helperResult } = response;
     const helperHasRawOutput = !!helperResult?.rawOutput;
+    const hasNetworkResourceWatcherSupport = hud.resourceWatcher.hasResourceWatcherSupport(
+      hud.resourceWatcher.TYPES.NETWORK_EVENT
+    );
+    let networkFront = null;
+    // @backward-compat { version 86 } default network events watcher support
+    if (hasNetworkResourceWatcherSupport) {
+      networkFront = await hud.resourceWatcher.watcherFront.getNetworkParentActor();
+    }
 
     if (helperResult?.type) {
       switch (helperResult.type) {
         case "clearOutput":
           dispatch(messagesActions.messagesClear());
           break;
         case "clearHistory":
           dispatch(historyActions.clearHistory());
@@ -207,17 +216,24 @@ function handleHelperResult(response) {
                 message,
                 resourceType: ResourceWatcher.TYPES.PLATFORM_MESSAGE,
               }))
             )
           );
           break;
         case "blockURL":
           const blockURL = helperResult.args.url;
-
+          // The console actor isn't able to block the request as the console actor runs in the content
+          // process, while the request has to be blocked from the parent process.
+          // Then, calling the Netmonitor action will only update the visual state of the Netmonitor,
+          // but we also have to block the request via the NetworkParentActor.
+          // @backward-compat { version 86 } default network events watcher support
+          if (hasNetworkResourceWatcherSupport && networkFront) {
+            await networkFront.blockRequest({ url: blockURL });
+          }
           toolbox
             .getPanel("netmonitor")
             ?.panelWin.store.dispatch(
               netmonitorBlockingActions.addBlockedUrl(blockURL)
             );
 
           dispatch(
             messagesActions.messagesAdd([
@@ -228,16 +244,20 @@ function handleHelperResult(response) {
                   [blockURL]
                 ),
               },
             ])
           );
           break;
         case "unblockURL":
           const unblockURL = helperResult.args.url;
+          // @backward-compat { version 86 } see related comments in block url above
+          if (hasNetworkResourceWatcherSupport && networkFront) {
+            await networkFront.unblockRequest({ url: unblockURL });
+          }
           toolbox
             .getPanel("netmonitor")
             ?.panelWin.store.dispatch(
               netmonitorBlockingActions.removeBlockedUrl(unblockURL)
             );
 
           dispatch(
             messagesActions.messagesAdd([
--- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js
+++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js
@@ -183,16 +183,27 @@ function getCommands() {
   function foo() {
     testStacktraceWithLog()
   }
 
   foo()
   `,
     },
     {
+      keys: ['console.trace("%cHello%c|%cWorld")'],
+      code: `
+    console.trace(
+      "%cHello%c|%cWorld",
+      "color:red",
+      "",
+      "color: blue"
+    );
+  `,
+    },
+    {
       keys: [
         "console.time('bar')",
         "timerAlreadyExists",
         "console.timeLog('bar') - 1",
         "console.timeLog('bar') - 2",
         "console.timeEnd('bar')",
         "timeEnd.timerDoesntExist",
         "timeLog.timerDoesntExist",
--- a/devtools/client/webconsole/test/node/fixtures/stubs/consoleApi.js
+++ b/devtools/client/webconsole/test/node/fixtures/stubs/consoleApi.js
@@ -14,16 +14,17 @@ const {
 const { prepareMessage } = require("devtools/client/webconsole/utils/messages");
 const {
   ConsoleMessage,
   NetworkEventMessage,
 } = require("devtools/client/webconsole/types");
 
 const rawPackets = new Map();
 rawPackets.set(`console.log('foobar', 'test')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "foobar",
       "test"
     ],
     "chromeContext": false,
     "columnNumber": 35,
@@ -37,21 +38,21 @@ rawPackets.set(`console.log('foobar', 't
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log(undefined)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "type": "undefined"
       }
     ],
     "chromeContext": false,
@@ -66,21 +67,21 @@ rawPackets.set(`console.log(undefined)`,
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.warn('danger, will robinson!')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "danger, will robinson!"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -93,21 +94,21 @@ rawPackets.set(`console.warn('danger, wi
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log(NaN)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "type": "NaN"
       }
     ],
     "chromeContext": false,
@@ -122,21 +123,21 @@ rawPackets.set(`console.log(NaN)`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log(null)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "type": "null"
       }
     ],
     "chromeContext": false,
@@ -151,21 +152,21 @@ rawPackets.set(`console.log(null)`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('鼬')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "鼬"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -178,21 +179,21 @@ rawPackets.set(`console.log('鼬')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.clear()`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -203,21 +204,21 @@ rawPackets.set(`console.clear()`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": {
@@ -233,21 +234,21 @@ rawPackets.set(`console.count('bar')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.assert(false, {message: 'foobar'})`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj31",
           "class": "Object",
@@ -296,21 +297,21 @@ rawPackets.set(`console.assert(false, {m
         "functionName": "triggerPacket",
         "lineNumber": 1,
         "sourceId": "server0.conn0.child1/source30"
       }
     ],
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('úṇĩçödê țĕșť')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "úṇĩçödê țĕșť"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -323,21 +324,21 @@ rawPackets.set(`console.log('úṇĩçödê țĕșť')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.dirxml(window)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj34",
           "class": "Window",
@@ -366,21 +367,21 @@ rawPackets.set(`console.dirxml(window)`,
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('myarray', ['red', 'green', 'blue'])`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "myarray",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj36",
@@ -415,21 +416,21 @@ rawPackets.set(`console.log('myarray', [
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('myregex', /a.b.c/)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "myregex",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj38",
@@ -456,21 +457,21 @@ rawPackets.set(`console.log('myregex', /
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.table(['red', 'green', 'blue']);`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj40",
           "class": "Array",
@@ -516,21 +517,21 @@ rawPackets.set(`console.table(['red', 'g
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('myobject', {red: 'redValue', green: 'greenValue', blue: 'blueValue'});`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "myobject",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj42",
@@ -583,21 +584,21 @@ rawPackets.set(`console.log('myobject', 
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.debug('debug message');`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "debug message"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -610,21 +611,21 @@ rawPackets.set(`console.debug('debug mes
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.info('info message');`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "info message"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -637,21 +638,21 @@ rawPackets.set(`console.info('info messa
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.error('error message');`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "error message"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -673,21 +674,21 @@ rawPackets.set(`console.error('error mes
         "functionName": "triggerPacket",
         "lineNumber": 1,
         "sourceId": "server0.conn0.child1/source30"
       }
     ],
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('mymap')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "mymap",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj47",
@@ -727,21 +728,21 @@ rawPackets.set(`console.log('mymap')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source46",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log('myset')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "myset",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj49",
@@ -775,35 +776,36 @@ rawPackets.set(`console.log('myset')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.trace()`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 13,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "testStacktraceFiltering",
     "groupName": "",
     "level": "trace",
     "lineNumber": 3,
     "prefix": "",
     "private": false,
     "sourceId": "server0.conn0.child1/source50",
+    "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "stacktrace": [
       {
         "columnNumber": 13,
         "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
         "functionName": "testStacktraceFiltering",
         "lineNumber": 3,
@@ -820,24 +822,23 @@ rawPackets.set(`console.trace()`, {
         "columnNumber": 3,
         "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
         "functionName": "triggerPacket",
         "lineNumber": 9,
         "sourceId": "server0.conn0.child1/source50"
       }
     ],
     "workerType": "none",
-    "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.trace('bar', {'foo': 'bar'}, [1,2,3])`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar",
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj52",
@@ -894,16 +895,17 @@ rawPackets.set(`console.trace('bar', {'f
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "testStacktraceWithLog",
     "groupName": "",
     "level": "trace",
     "lineNumber": 3,
     "prefix": "",
     "private": false,
     "sourceId": "server0.conn0.child1/source51",
+    "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "stacktrace": [
       {
         "columnNumber": 13,
         "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
         "functionName": "testStacktraceWithLog",
         "lineNumber": 3,
@@ -920,24 +922,65 @@ rawPackets.set(`console.trace('bar', {'f
         "columnNumber": 3,
         "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
         "functionName": "triggerPacket",
         "lineNumber": 9,
         "sourceId": "server0.conn0.child1/source50"
       }
     ],
     "workerType": "none",
-    "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
+});
+
+rawPackets.set(`console.trace("%cHello%c|%cWorld")`, {
+  "resourceType": "console-message",
+  "message": {
+    "addonId": "",
+    "arguments": [
+      "Hello",
+      "|",
+      "World"
+    ],
+    "chromeContext": false,
+    "columnNumber": 13,
+    "counter": null,
+    "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
+    "functionName": "triggerPacket",
+    "groupName": "",
+    "level": "trace",
+    "lineNumber": 2,
+    "prefix": "",
+    "private": false,
+    "sourceId": "server0.conn0.child3/source57",
+    "styles": [
+      "color:red",
+      "",
+      "color: blue"
+    ],
+    "timeStamp": 1572867483805,
+    "timer": null,
+    "stacktrace": [
+      {
+        "columnNumber": 13,
+        "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
+        "functionName": "triggerPacket",
+        "lineNumber": 2,
+        "sourceId": "server0.conn0.child3/source57"
+      }
+    ],
+    "workerType": "none",
+    "category": "webdev",
+    "innerWindowID": 10737418241
+  }
 });
 
 rawPackets.set(`console.time('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -952,21 +995,21 @@ rawPackets.set(`console.time('bar')`, {
     "timeStamp": 1572867483805,
     "timer": {
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`timerAlreadyExists`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -982,21 +1025,21 @@ rawPackets.set(`timerAlreadyExists`, {
     "timer": {
       "error": "timerAlreadyExists",
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.timeLog('bar') - 1`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1012,21 +1055,21 @@ rawPackets.set(`console.timeLog('bar') -
     "timer": {
       "duration": 4,
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.timeLog('bar') - 2`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar",
       "second call",
       {
         "_grip": {
           "type": "object",
@@ -1071,21 +1114,21 @@ rawPackets.set(`console.timeLog('bar') -
     "timer": {
       "duration": 5,
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.timeEnd('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1101,21 +1144,21 @@ rawPackets.set(`console.timeEnd('bar')`,
     "timer": {
       "duration": 9,
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`timeEnd.timerDoesntExist`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1131,21 +1174,21 @@ rawPackets.set(`timeEnd.timerDoesntExist
     "timer": {
       "error": "timerDoesntExist",
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`timeLog.timerDoesntExist`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1161,21 +1204,21 @@ rawPackets.set(`timeLog.timerDoesntExist
     "timer": {
       "error": "timerDoesntExist",
       "name": "bar"
     },
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.table('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1188,21 +1231,21 @@ rawPackets.set(`console.table('bar')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.table(['a', 'b', 'c'])`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj58",
           "class": "Array",
@@ -1248,21 +1291,21 @@ rawPackets.set(`console.table(['a', 'b',
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.group('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1275,21 +1318,21 @@ rawPackets.set(`console.group('bar')`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupEnd('bar')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1300,21 +1343,21 @@ rawPackets.set(`console.groupEnd('bar')`
     "private": false,
     "sourceId": "server0.conn0.child1/source54",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupCollapsed('foo')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "foo"
     ],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
@@ -1327,21 +1370,21 @@ rawPackets.set(`console.groupCollapsed('
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupEnd('foo')`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1352,21 +1395,21 @@ rawPackets.set(`console.groupEnd('foo')`
     "private": false,
     "sourceId": "server0.conn0.child1/source54",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.group()`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1377,21 +1420,21 @@ rawPackets.set(`console.group()`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source48",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupEnd()`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1402,21 +1445,21 @@ rawPackets.set(`console.groupEnd()`, {
     "private": false,
     "sourceId": "server0.conn0.child1/source54",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log(%cfoobar)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "foo",
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
@@ -1433,21 +1476,21 @@ rawPackets.set(`console.log(%cfoobar)`, 
       "color:blue; font-size:1.3em; background:url('http://example.com/test'); position:absolute; top:10px; ",
       "color:red; line-height: 1.5; background:url('http://example.com/test')"
     ],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log("%cHello%c|%cWorld")`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "Hello",
       "|",
       "World"
     ],
     "chromeContext": false,
@@ -1466,21 +1509,21 @@ rawPackets.set(`console.log("%cHello%c|%
       "",
       "color: blue"
     ],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.group(%cfoo%cbar)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "foo",
       "bar"
     ],
     "chromeContext": false,
     "columnNumber": 11,
@@ -1497,21 +1540,21 @@ rawPackets.set(`console.group(%cfoo%cbar
       "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
       "color:red;background:url('http://example.com/test')"
     ],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupEnd(%cfoo%cbar)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1522,21 +1565,21 @@ rawPackets.set(`console.groupEnd(%cfoo%c
     "private": false,
     "sourceId": "server0.conn0.child1/source54",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupCollapsed(%cfoo%cbaz)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "foo",
       "baz"
     ],
     "chromeContext": false,
     "columnNumber": 11,
@@ -1553,21 +1596,21 @@ rawPackets.set(`console.groupCollapsed(%
       "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
       "color:red;background:url('http://example.com/test')"
     ],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.groupEnd(%cfoo%cbaz)`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 11,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1578,21 +1621,21 @@ rawPackets.set(`console.groupEnd(%cfoo%c
     "private": false,
     "sourceId": "server0.conn0.child1/source54",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.dir({C, M, Y, K})`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       {
         "_grip": {
           "type": "object",
           "actor": "server0.conn0.child1/obj67",
           "class": "Object",
@@ -1650,21 +1693,21 @@ rawPackets.set(`console.dir({C, M, Y, K}
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | default: 1`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "default"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1680,21 +1723,21 @@ rawPackets.set(`console.count | default:
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | default: 2`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "default"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1710,21 +1753,21 @@ rawPackets.set(`console.count | default:
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | test counter: 1`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "test counter"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1740,21 +1783,21 @@ rawPackets.set(`console.count | test cou
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | test counter: 2`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "test counter"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1770,21 +1813,21 @@ rawPackets.set(`console.count | test cou
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | default: 3`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "default"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1800,21 +1843,21 @@ rawPackets.set(`console.count | default:
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | clear`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": null,
     "filename": "http://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html",
     "functionName": "triggerPacket",
@@ -1825,21 +1868,21 @@ rawPackets.set(`console.count | clear`, 
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | default: 4`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "default"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1855,21 +1898,21 @@ rawPackets.set(`console.count | default:
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.count | test counter: 3`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "test counter"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1885,21 +1928,21 @@ rawPackets.set(`console.count | test cou
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.countReset | test counter: 0`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "test counter"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1915,21 +1958,21 @@ rawPackets.set(`console.countReset | tes
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.countReset | counterDoesntExist`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "test counter"
     ],
     "chromeContext": false,
     "columnNumber": 15,
     "counter": {
@@ -1945,21 +1988,21 @@ rawPackets.set(`console.countReset | cou
     "private": false,
     "sourceId": "server0.conn0.child1/source68",
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "styles": [],
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 rawPackets.set(`console.log escaped characters`, {
+  "resourceType": "console-message",
   "message": {
     "addonId": "",
     "arguments": [
       "hello \nfrom \rthe \"string world!"
     ],
     "chromeContext": false,
     "columnNumber": 35,
     "counter": null,
@@ -1972,18 +2015,17 @@ rawPackets.set(`console.log escaped char
     "private": false,
     "sourceId": "server0.conn0.child1/source22",
     "styles": [],
     "timeStamp": 1572867483805,
     "timer": null,
     "workerType": "none",
     "category": "webdev",
     "innerWindowID": 8589934593
-  },
-  "resourceType": "console-message"
+  }
 });
 
 
 const stubPackets = parsePacketsWithFronts(rawPackets);
 
 const stubPreparedMessages = new Map();
 for (const [key, packet] of Array.from(stubPackets.entries())) {
   const transformedPacket = prepareMessage(packet, {
--- a/devtools/server/actors/network-monitor/network-parent.js
+++ b/devtools/server/actors/network-monitor/network-parent.js
@@ -114,11 +114,33 @@ const NetworkParentActor = ActorClassWit
    * Returns the urls that are block
    */
   getBlockedUrls() {
     if (!this.networkEventWatcher) {
       throw new Error("Not listening for network events");
     }
     return this.networkEventWatcher.getBlockedUrls();
   },
+
+  /**
+   * Blocks the requests based on the filters
+   * @param {Object} filters
+   */
+  blockRequest(filters) {
+    if (!this.networkEventWatcher) {
+      throw new Error("Not listening for network events");
+    }
+    this.networkEventWatcher.blockRequest(filters);
+  },
+
+  /**
+   * Unblocks requests based on the filters
+   * @param {Object} filters
+   */
+  unblockRequest(filters) {
+    if (!this.networkEventWatcher) {
+      throw new Error("Not listening for network events");
+    }
+    this.networkEventWatcher.unblockRequest(filters);
+  },
 });
 
 exports.NetworkParentActor = NetworkParentActor;
--- a/devtools/server/actors/resources/network-events.js
+++ b/devtools/server/actors/resources/network-events.js
@@ -63,16 +63,32 @@ class NetworkEventWatcher {
    * @param {*} data
    *
    */
   setThrottleData(data) {
     this.listener.throttleData = data;
   }
 
   /**
+   * Block requests based on the filters
+   * @param {Object} filters
+   */
+  blockRequest(filters) {
+    this.listener.blockRequest(filters);
+  }
+
+  /**
+   * Unblock requests based on the fitlers
+   * @param {Object} filters
+   */
+  unblockRequest(filters) {
+    this.listener.unblockRequest(filters);
+  }
+
+  /**
    * Calls the listener to set blocked urls
    *
    * @param {Array} urls
    *        The urls to block
    */
 
   setBlockedUrls(urls) {
     this.listener.setBlockedUrls(urls);
--- a/devtools/shared/specs/network-parent.js
+++ b/devtools/shared/specs/network-parent.js
@@ -32,12 +32,24 @@ const networkParentSpec = generateActorS
       },
     },
     getBlockedUrls: {
       request: {},
       response: {
         urls: RetVal("array:string"),
       },
     },
+    blockRequest: {
+      request: {
+        filters: Arg(0, "json"),
+      },
+      response: {},
+    },
+    unblockRequest: {
+      request: {
+        filters: Arg(0, "json"),
+      },
+      response: {},
+    },
   },
 });
 
 exports.networkParentSpec = networkParentSpec;
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -300,16 +300,23 @@ class CustomElementReactionsStack {
     mRecursionDepth--;
     // Restore the is-element-queue-pushed flag cached in AutoCEReaction when
     // leaving the recursion level.
     mIsElementQueuePushedForCurrentRecursionDepth = aWasElementQueuePushed;
 
     MOZ_ASSERT_IF(!mRecursionDepth, mReactionsStack.IsEmpty());
   }
 
+  bool IsElementQueuePushedForCurrentRecursionDepth() {
+    MOZ_ASSERT_IF(mIsElementQueuePushedForCurrentRecursionDepth,
+                  !mReactionsStack.IsEmpty() &&
+                      !mReactionsStack.LastElement()->IsEmpty());
+    return mIsElementQueuePushedForCurrentRecursionDepth;
+  }
+
  private:
   ~CustomElementReactionsStack() = default;
   ;
 
   /**
    * Push a new element queue onto the custom element reactions stack.
    */
   void CreateAndPushElementQueue();
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -1640,16 +1640,17 @@ bool Console::PopulateConsoleNotificatio
     case MethodInfo:
     case MethodWarn:
     case MethodError:
     case MethodException:
     case MethodDebug:
     case MethodAssert:
     case MethodGroup:
     case MethodGroupCollapsed:
+    case MethodTrace:
       event.mArguments.Construct();
       event.mStyles.Construct();
       if (NS_WARN_IF(!ProcessArguments(aCx, aArguments,
                                        event.mArguments.Value(),
                                        event.mStyles.Value()))) {
         return false;
       }
 
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddatabasemanager_h__
 #define mozilla_dom_indexeddatabasemanager_h__
 
 #include "js/TypeDecls.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/dom/quota/PersistenceType.h"
+#include "mozilla/Logging.h"
 #include "mozilla/Mutex.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "SafeRefPtr.h"
 
 namespace mozilla {
 
 class EventChainPostVisitor;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1318,17 +1318,16 @@ void ContentChild::InitXPCOM(
   // The stylesheet cache is not ready yet. Store this URL for future use.
   nsCOMPtr<nsIURI> ucsURL = std::move(aXPCOMInit.userContentSheetURL());
   GlobalStyleSheetCache::SetUserContentCSSURL(ucsURL);
 
   GfxInfoBase::SetFeatureStatus(std::move(aXPCOMInit.gfxFeatureStatus()));
 
   DataStorage::SetCachedStorageEntries(aXPCOMInit.dataStorage());
 
-  PDMFactory::SetSupported(aXPCOMInit.codecsSupported());
   // Initialize the RemoteDecoderManager thread and its associated PBackground
   // channel.
   RemoteDecoderManagerChild::Init();
 
   // Set the dynamic scalar definitions for this process.
   TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
 }
 
@@ -4448,16 +4447,24 @@ JSActorManager* ContentChild::AsJSActorM
 
 IPCResult ContentChild::RecvFlushFOGData(FlushFOGDataResolver&& aResolver) {
 #ifdef MOZ_GLEAN
   glean::FlushFOGData(std::move(aResolver));
 #endif
   return IPC_OK();
 }
 
+IPCResult ContentChild::RecvUpdateMediaCodecsSupported(
+    RemoteDecodeIn aLocation,
+    const PDMFactory::MediaCodecsSupported& aSupported) {
+  RemoteDecoderManagerChild::SetSupported(aLocation, aSupported);
+
+  return IPC_OK();
+}
+
 }  // namespace dom
 
 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
 
 static LazyLogModule sPledgeLog("OpenBSDSandbox");
 
 NS_IMETHODIMP
 OpenBSDFindPledgeUnveilFilePath(const char* file, nsACString& result) {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -832,16 +832,20 @@ class ContentChild final : public PConte
  public:
   static void DispatchBeforeUnloadToSubtree(
       BrowsingContext* aStartingAt,
       const DispatchBeforeUnloadToSubtreeResolver& aResolver);
 
  private:
   mozilla::ipc::IPCResult RecvFlushFOGData(FlushFOGDataResolver&& aResolver);
 
+  mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported(
+      RemoteDecodeIn aLocation,
+      const PDMFactory::MediaCodecsSupported& aSupported);
+
 #ifdef NIGHTLY_BUILD
   virtual PContentChild::Result OnMessageReceived(const Message& aMsg) override;
 #else
   using PContentChild::OnMessageReceived;
 #endif
 
   virtual PContentChild::Result OnMessageReceived(const Message& aMsg,
                                                   Message*& aReply) override;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -25,24 +25,24 @@
 #include "GeckoProfiler.h"
 #include "GMPServiceParent.h"
 #include "HandlerServiceParent.h"
 #include "IHistory.h"
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
 #  include "mozilla/a11y/AccessibleWrap.h"
 #  include "mozilla/a11y/Compatibility.h"
 #endif
+#include <map>
 #include <utility>
 
 #include "BrowserParent.h"
 #include "ContentProcessManager.h"
 #include "Geolocation.h"
 #include "GfxInfoBase.h"
 #include "MMPrinter.h"
-#include "PDMFactory.h"
 #include "PreallocatedProcessManager.h"
 #include "ProcessPriorityManager.h"
 #include "SandboxHal.h"
 #include "SourceSurfaceRawData.h"
 #include "URIUtils.h"
 #include "gfxPlatform.h"
 #include "gfxPlatformFontList.h"
 #include "mozilla/AutoRestore.h"
@@ -362,16 +362,19 @@ namespace mozilla {
 namespace CubebUtils {
 extern FileDescriptor CreateAudioIPCConnection();
 }
 
 namespace dom {
 
 LazyLogModule gProcessLog("Process");
 
+static std::map<RemoteDecodeIn, PDMFactory::MediaCodecsSupported>
+    sCodecsSupported;
+
 /* static */
 LogModule* ContentParent::GetLog() { return gProcessLog; }
 
 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
 #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
 
 // IPC receiver for remote GC/CC logging.
 class CycleCollectWithLogsParent final : public PCycleCollectWithLogsParent {
@@ -1496,16 +1499,26 @@ static LookAndFeelData GetLookAndFeelDat
 void ContentParent::BroadcastThemeUpdate(widget::ThemeChangeKind aKind) {
   LookAndFeelData lnfData = GetLookAndFeelData();
 
   for (auto* cp : AllProcesses(eLive)) {
     Unused << cp->SendThemeChanged(lnfData, aKind);
   }
 }
 
+/*static */
+void ContentParent::BroadcastMediaCodecsSupportedUpdate(
+    RemoteDecodeIn aLocation,
+    const PDMFactory::MediaCodecsSupported& aSupported) {
+  sCodecsSupported[aLocation] = aSupported;
+  for (auto* cp : AllProcesses(eAll)) {
+    Unused << cp->SendUpdateMediaCodecsSupported(aLocation, aSupported);
+  }
+}
+
 const nsACString& ContentParent::GetRemoteType() const { return mRemoteType; }
 
 void ContentParent::Init() {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     size_t length = ArrayLength(sObserverTopics);
     for (size_t i = 0; i < length; ++i) {
       obs->AddObserver(this, sObserverTopics[i], false);
@@ -2783,19 +2796,19 @@ bool ContentParent::InitInternal(Process
       widget::WinContentSystemParameters::GetSingleton()->GetParentValues();
 #endif
 
   DataStorage::GetAllChildProcessData(xpcomInit.dataStorage());
 
   // Send the dynamic scalar definitions to the new process.
   TelemetryIPC::GetDynamicScalarDefinitions(xpcomInit.dynamicScalarDefs());
 
-  // Pre-calculate the various PlatformDecoderModule (PDM) supported on this
-  // machine.
-  xpcomInit.codecsSupported() = PDMFactory::Supported();
+  for (auto const& [location, supported] : sCodecsSupported) {
+    Unused << SendUpdateMediaCodecsSupported(location, supported);
+  }
 
   // Must send screen info before send initialData
   ScreenManager& screenManager = ScreenManager::GetSingleton();
   screenManager.CopyScreensToRemote(this);
 
   // Send the UA sheet shared memory buffer and the address it is mapped at.
   Maybe<SharedMemoryHandle> sharedUASheetHandle;
   uintptr_t sharedUASheetAddress = sheetCache->GetSharedMemoryAddress();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -252,16 +252,20 @@ class ContentParent final
   static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
   static void BroadcastStringBundle(const StringBundleDescriptor&);
 
   static void BroadcastFontListChanged();
 
   static void BroadcastThemeUpdate(widget::ThemeChangeKind);
 
+  static void BroadcastMediaCodecsSupportedUpdate(
+      RemoteDecodeIn aLocation,
+      const PDMFactory::MediaCodecsSupported& aSupported);
+
   const nsACString& GetRemoteType() const override;
 
   virtual void DoGetRemoteType(nsACString& aRemoteType,
                                ErrorResult& aError) const override {
     aRemoteType = GetRemoteType();
   }
 
   enum CPIteratorPolicy { eLive, eAll };
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -141,16 +141,17 @@ using mozilla::ContentBlocking::StorageA
 using JSActorMessageKind from "mozilla/dom/JSActor.h";
 using JSActorMessageMeta from "mozilla/dom/PWindowGlobal.h";
 using mozilla::PermissionDelegateHandler::DelegatedPermissionList from "mozilla/PermissionDelegateHandler.h";
 using refcounted class nsILayoutHistoryState from "nsILayoutHistoryState.h";
 using class mozilla::dom::SessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
 using struct nsPoint from "nsPoint.h";
 using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
 using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
+using mozilla::RemoteDecodeIn from "mozilla/RemoteDecoderManagerChild.h";
 using mozilla::dom::PerformanceTimingData from "mozilla/dom/PerformanceTiming.h";
 
 union ChromeRegistryItem
 {
     ChromePackage;
     OverrideMapping;
     SubstitutionMapping;
 };
@@ -322,17 +323,16 @@ struct XPCOMInitData
     GfxVarUpdate[] gfxNonDefaultVarUpdates;
     ContentDeviceData contentDeviceData;
     GfxInfoFeatureStatus[] gfxFeatureStatus;
     DataStorageEntry[] dataStorage;
     nsCString[] appLocales;
     nsCString[] requestedLocales;
     DynamicScalarDefinition[] dynamicScalarDefs;
     SystemParameterKVPair[] systemParameters;
-    MediaCodecsSupported codecsSupported;
 };
 
 struct VisitedQueryResult
 {
     nsIURI uri;
     bool visited;
 };
 
@@ -942,16 +942,19 @@ child:
    async DispatchLocationChangeEvent(MaybeDiscardedBrowsingContext aContext);
 
   // Dispatches a "beforeunload" event to each in-process content window in the
   // subtree beginning at `aStartingAt`, and returns the result as documented in
   // the `PermitUnloadResult` enum.
   async DispatchBeforeUnloadToSubtree(MaybeDiscardedBrowsingContext aStartingAt)
       returns (PermitUnloadResult result);
 
+  // Update the cached list of codec supported in the given process.
+  async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported);
+
 parent:
     /**
      * This is a temporary way to pass index and length through parent process.
      * Used for testing.
      */
     async SessionHistoryUpdate(MaybeDiscardedBrowsingContext aTopContext,
                                int32_t aIndex, int32_t aLength, nsID aChangeID);
 
--- a/dom/l10n/tests/mochitest/l10n_mutations/test_disconnectedRoot_webcomponent.html
+++ b/dom/l10n/tests/mochitest/l10n_mutations/test_disconnectedRoot_webcomponent.html
@@ -129,18 +129,18 @@ key4 = Key 4
         document.domLoc.setAttributes(shadowLabel, "key4");
         document.domLoc.setAttributes(lightLabel, "key4");
       }
     }
     customElements.define("fluent-widget", FluentWidget);
   </script>
 </head>
 <body>
+  <p id="lightLabel"></p>
+
   <template id="fluent-widget-template">
     <div id="shadowDiv">
       <p id="shadowLabel"></p>
     </div>
   </template>
   <fluent-widget id="widget1"></fluent-widget>
-
-  <p id="lightLabel"></p>
 </body>
 </html>
--- a/dom/media/ipc/PRDD.ipdl
+++ b/dom/media/ipc/PRDD.ipdl
@@ -10,16 +10,17 @@ include PrefsTypes;
 include protocol PProfiler;
 include protocol PRemoteDecoderManager;
 include protocol PVideoBridge;
 
 using mozilla::dom::NativeThreadId from "mozilla/dom/NativeThreadId.h";
 using moveonly mozilla::UntrustedModulesData from "mozilla/UntrustedModulesData.h";
 using moveonly mozilla::ModulePaths from "mozilla/UntrustedModulesData.h";
 using moveonly mozilla::ModulesMapResult from "mozilla/UntrustedModulesData.h";
+using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
 
 namespace mozilla {
 
 // This protocol allows the UI process to talk to the RDD
 // (RemoteDataDecoder) process. There is one instance of this protocol,
 // with the RDDParent living on the main thread of the RDD process and
 // the RDDChild living on the main thread of the UI process.
 protocol PRDD
@@ -53,11 +54,15 @@ parent:
 child:
 
   async InitCrashReporter(NativeThreadId threadId);
 
   async AddMemoryReport(MemoryReport aReport);
 
   async GetModulesTrust(ModulePaths aModPaths, bool aRunAtNormalPriority)
       returns (ModulesMapResult? modMapResult);
+
+  // Update the cached list of codec supported following a check in the
+  // RDD parent.
+  async UpdateMediaCodecsSupported(MediaCodecsSupported aSupported);
 };
 
 } // namespace mozilla
--- a/dom/media/ipc/RDDChild.cpp
+++ b/dom/media/ipc/RDDChild.cpp
@@ -1,21 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "RDDChild.h"
 
 #include "mozilla/RDDProcessManager.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/gfx/GPUProcessManager.h"
+#include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/CrashReporterHost.h"
 #include "mozilla/ipc/Endpoint.h"
-#include "mozilla/gfx/gfxVars.h"
-#include "mozilla/gfx/GPUProcessManager.h"
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
 #  include "mozilla/SandboxBroker.h"
 #  include "mozilla/SandboxBrokerPolicyFactory.h"
 #endif
 
 #include "mozilla/Telemetry.h"
 
@@ -133,16 +134,23 @@ mozilla::ipc::IPCResult RDDChild::RecvGe
           },
           [aResolver](nsresult aRv) { aResolver(Nothing()); });
   return IPC_OK();
 #else
   return IPC_FAIL(this, "Unsupported on this platform");
 #endif  // defined(XP_WIN)
 }
 
+mozilla::ipc::IPCResult RDDChild::RecvUpdateMediaCodecsSupported(
+    const PDMFactory::MediaCodecsSupported& aSupported) {
+  dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(
+      RemoteDecodeIn::RddProcess, aSupported);
+  return IPC_OK();
+}
+
 void RDDChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (aWhy == AbnormalShutdown) {
     GenerateCrashReport(OtherPid());
   }
 
   auto* gpm = gfx::GPUProcessManager::Get();
   if (gpm) {
     // Note: the manager could have shutdown already.
--- a/dom/media/ipc/RDDChild.h
+++ b/dom/media/ipc/RDDChild.h
@@ -1,21 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _include_dom_media_ipc_RDDChild_h_
 #define _include_dom_media_ipc_RDDChild_h_
 #include "mozilla/PRDDChild.h"
-
+#include "mozilla/UniquePtr.h"
+#include "mozilla/gfx/GPUProcessListener.h"
+#include "mozilla/gfx/gfxVarReceiver.h"
 #include "mozilla/ipc/CrashReporterHelper.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/gfx/gfxVarReceiver.h"
-#include "mozilla/gfx/GPUProcessListener.h"
 
 namespace mozilla {
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
 class SandboxBroker;
 #endif
 
 namespace dom {
@@ -40,16 +39,18 @@ class RDDChild final : public PRDDChild,
   void OnVarChanged(const GfxVarUpdate& aVar) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvGetModulesTrust(
       ModulePaths&& aModPaths, bool aRunAtNormalPriority,
       GetModulesTrustResolver&& aResolver);
+  mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported(
+      const PDMFactory::MediaCodecsSupported& aSupported);
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const Maybe<ipc::FileDescriptor>& aDMDFile);
 
   static void Destroy(UniquePtr<RDDChild>&& aChild);
 
--- a/dom/media/ipc/RDDParent.cpp
+++ b/dom/media/ipc/RDDParent.cpp
@@ -1,55 +1,59 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "RDDParent.h"
 
 #if defined(XP_WIN)
-#  include "mozilla/gfx/DeviceManagerDx.h"
-#  include "WMF.h"
+#  include <dwrite.h>
 #  include <process.h>
-#  include <dwrite.h>
+
+#  include "WMF.h"
+#  include "WMFDecoderModule.h"
 #  include "mozilla/WinDllServices.h"
+#  include "mozilla/gfx/DeviceManagerDx.h"
 #else
 #  include <unistd.h>
 #endif
 
+#include "PDMFactory.h"
 #include "chrome/common/ipc_channel.h"
+#include "gfxConfig.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/HangDetails.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/RemoteDecoderManagerChild.h"
 #include "mozilla/RemoteDecoderManagerParent.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/ipc/ProcessChild.h"
-#include "mozilla/gfx/gfxVars.h"
-#include "gfxConfig.h"
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
 #  include "mozilla/Sandbox.h"
 #endif
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ChildProfilerController.h"
 #endif
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
+#  include "RDDProcessHost.h"
 #  include "mozilla/Sandbox.h"
 #  include "nsMacUtilsImpl.h"
-#  include "RDDProcessHost.h"
 #endif
 
+#include "ProcessUtils.h"
 #include "nsDebugImpl.h"
 #include "nsThreadManager.h"
-#include "ProcessUtils.h"
 
 namespace mozilla {
 
 using namespace ipc;
 using namespace gfx;
 
 static RDDParent* sRDDParent;
 
@@ -115,16 +119,19 @@ void CGSShutdownServerConnections();
 
 mozilla::ipc::IPCResult RDDParent::RecvInit(
     nsTArray<GfxVarUpdate>&& vars, const Maybe<FileDescriptor>& aBrokerFd,
     const bool& aCanRecordReleaseTelemetry) {
   for (const auto& var : vars) {
     gfxVars::ApplyUpdate(var);
   }
 
+  auto supported = PDMFactory::Supported();
+  Unused << SendUpdateMediaCodecsSupported(supported);
+
 #if defined(MOZ_SANDBOX)
 #  if defined(XP_MACOSX)
   // Close all current connections to the WindowServer. This ensures that the
   // Activity Monitor will not label the content process as "Not responding"
   // because it's not running a native event loop. See bug 1384336.
   CGSShutdownServerConnections();
 
 #  elif defined(XP_LINUX)
@@ -141,16 +148,28 @@ mozilla::ipc::IPCResult RDDParent::RecvI
     RefPtr<DllServices> dllSvc(DllServices::Get());
     dllSvc->StartUntrustedModulesProcessor();
   }
 #endif  // defined(XP_WIN)
   return IPC_OK();
 }
 
 IPCResult RDDParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
+#if defined(XP_WIN)
+  auto scopeExit = MakeScopeExit(
+      [couldUseHWDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding()] {
+        if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) {
+          // The capabilities of the system may have changed, force a refresh by
+          // re-initializing the WMF PDM.
+          WMFDecoderModule::Init();
+          Unused << RDDParent::GetSingleton()->SendUpdateMediaCodecsSupported(
+              PDMFactory::Supported(true /* force refresh */));
+        }
+      });
+#endif
   gfxVars::ApplyUpdate(aUpdate);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult RDDParent::RecvInitProfiler(
     Endpoint<PProfilerChild>&& aEndpoint) {
 #ifdef MOZ_GECKO_PROFILER
   mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
--- a/dom/media/ipc/RDDProcessManager.cpp
+++ b/dom/media/ipc/RDDProcessManager.cpp
@@ -95,95 +95,114 @@ void RDDProcessManager::OnPreferenceChan
   if (!!mRDDChild) {
     MOZ_ASSERT(mQueuedPrefs.IsEmpty());
     mRDDChild->SendPreferenceUpdate(pref);
   } else if (IsRDDProcessLaunching()) {
     mQueuedPrefs.AppendElement(pref);
   }
 }
 
+RefPtr<GenericNonExclusivePromise> RDDProcessManager::LaunchRDDProcess() {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!Get()) {
+    // Shutdown?
+    return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
+                                                       __func__);
+  }
+
+  if (mNumProcessAttempts && !StaticPrefs::media_rdd_retryonfailure_enabled()) {
+    // We failed to start the RDD process earlier, abort now.
+    return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
+                                                       __func__);
+  }
+
+  if (mLaunchRDDPromise && mProcess) {
+    return mLaunchRDDPromise;
+  }
+
+  std::vector<std::string> extraArgs;
+  nsCString parentBuildID(mozilla::PlatformBuildID());
+  extraArgs.push_back("-parentBuildID");
+  extraArgs.push_back(parentBuildID.get());
+
+  // The subprocess is launched asynchronously, so we
+  // wait for the promise to be resolved to acquire the IPDL actor.
+  mProcess = new RDDProcessHost(this);
+  if (!mProcess->Launch(extraArgs)) {
+    mNumProcessAttempts++;
+    DestroyProcess();
+    return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
+                                                       __func__);
+  }
+
+  mLaunchRDDPromise = mProcess->LaunchPromise()->Then(
+      GetMainThreadSerialEventTarget(), __func__,
+      [this](bool) {
+        if (!Get()) {
+          // Shutdown?
+          return GenericNonExclusivePromise::CreateAndReject(
+              NS_ERROR_NOT_AVAILABLE, __func__);
+        }
+
+        mRDDChild = mProcess->GetActor();
+        mProcessToken = mProcess->GetProcessToken();
+
+        // Flush any pref updates that happened during
+        // launch and weren't included in the blobs set
+        // up in LaunchRDDProcess.
+        for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
+          Unused << NS_WARN_IF(!mRDDChild->SendPreferenceUpdate(pref));
+        }
+        mQueuedPrefs.Clear();
+
+        CrashReporter::AnnotateCrashReport(
+            CrashReporter::Annotation::RDDProcessStatus, "Running"_ns);
+
+        if (!CreateVideoBridge()) {
+          mNumProcessAttempts++;
+          DestroyProcess();
+          return GenericNonExclusivePromise::CreateAndReject(
+              NS_ERROR_NOT_AVAILABLE, __func__);
+        }
+        return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
+      },
+      [this](nsresult aError) {
+        if (Get()) {
+          mNumProcessAttempts++;
+          DestroyProcess();
+        }
+        return GenericNonExclusivePromise::CreateAndReject(aError, __func__);
+      });
+  return mLaunchRDDPromise;
+}
+
 auto RDDProcessManager::EnsureRDDProcessAndCreateBridge(
     base::ProcessId aOtherProcess) -> RefPtr<EnsureRDDPromise> {
   return InvokeAsync(
       GetMainThreadSerialEventTarget(), __func__,
       [aOtherProcess, this]() -> RefPtr<EnsureRDDPromise> {
-        if (!Get()) {
-          // Shutdown?
-          return EnsureRDDPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
-                                                   __func__);
-        }
-        if (mProcess) {
-          return mProcess->LaunchPromise()->Then(
-              GetMainThreadSerialEventTarget(), __func__,
-              [aOtherProcess, this](bool) {
-                ipc::Endpoint<PRemoteDecoderManagerChild> endpoint;
-                if (!CreateContentBridge(aOtherProcess, &endpoint)) {
-                  return EnsureRDDPromise::CreateAndReject(
-                      NS_ERROR_NOT_AVAILABLE, __func__);
-                }
-                return EnsureRDDPromise::CreateAndResolve(std::move(endpoint),
-                                                          __func__);
-              },
-              [](nsresult aError) {
-                return EnsureRDDPromise::CreateAndReject(aError, __func__);
-              });
-        }
-
-        if (mNumProcessAttempts &&
-            !StaticPrefs::media_rdd_retryonfailure_enabled()) {
-          // We failed to start the RDD process earlier, abort now.
-          return EnsureRDDPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
-                                                   __func__);
-        }
-        // Launch the RDD process.
-        std::vector<std::string> extraArgs;
-        nsCString parentBuildID(mozilla::PlatformBuildID());
-        extraArgs.push_back("-parentBuildID");
-        extraArgs.push_back(parentBuildID.get());
-
-        // The subprocess is launched asynchronously, so we
-        // wait for the promise to be resolved to acquire the IPDL actor.
-        mProcess = new RDDProcessHost(this);
-        if (!mProcess->Launch(extraArgs)) {
-          DestroyProcess();
-          return EnsureRDDPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
-                                                   __func__);
-        }
-        return mProcess->LaunchPromise()->Then(
+        return LaunchRDDProcess()->Then(
             GetMainThreadSerialEventTarget(), __func__,
-            [aOtherProcess, this](bool) {
-              mRDDChild = mProcess->GetActor();
-              mProcessToken = mProcess->GetProcessToken();
-
-              // Flush any pref updates that happened during
-              // launch and weren't included in the blobs set
-              // up in LaunchRDDProcess.
-              for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
-                Unused << NS_WARN_IF(!mRDDChild->SendPreferenceUpdate(pref));
+            [aOtherProcess, this]() {
+              if (!Get()) {
+                // Shutdown?
+                return EnsureRDDPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
+                                                         __func__);
               }
-              mQueuedPrefs.Clear();
-
-              CrashReporter::AnnotateCrashReport(
-                  CrashReporter::Annotation::RDDProcessStatus, "Running"_ns);
-
               ipc::Endpoint<PRemoteDecoderManagerChild> endpoint;
-
-              if (!CreateVideoBridge() ||
-                  !CreateContentBridge(aOtherProcess, &endpoint)) {
-                mNumProcessAttempts++;
+              if (!CreateContentBridge(aOtherProcess, &endpoint)) {
                 return EnsureRDDPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
                                                          __func__);
               }
               mNumProcessAttempts = 0;
               return EnsureRDDPromise::CreateAndResolve(std::move(endpoint),
                                                         __func__);
             },
-            [this](nsresult aError) {
-              mNumProcessAttempts++;
-              DestroyProcess();
+            [](nsresult aError) {
               return EnsureRDDPromise::CreateAndReject(aError, __func__);
             });
       });
 }
 
 bool RDDProcessManager::IsRDDProcessLaunching() {
   MOZ_ASSERT(NS_IsMainThread());
   return !!mProcess && !mRDDChild;
@@ -262,34 +281,35 @@ bool RDDProcessManager::CreateContentBri
 bool RDDProcessManager::CreateVideoBridge() {
   MOZ_ASSERT(NS_IsMainThread());
   ipc::Endpoint<PVideoBridgeParent> parentPipe;
   ipc::Endpoint<PVideoBridgeChild> childPipe;
 
   GPUProcessManager* gpuManager = GPUProcessManager::Get();
   base::ProcessId gpuProcessPid = gpuManager ? gpuManager->GPUProcessPid() : -1;
 
+  // Build content device data first; this ensure that the GPU process is fully
+  // ready.
+  ContentDeviceData contentDeviceData;
+  gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData);
+
   // The child end is the producer of video frames; the parent end is the
   // consumer.
   base::ProcessId childPid = RDDProcessPid();
   base::ProcessId parentPid =
       gpuProcessPid != -1 ? gpuProcessPid : base::GetCurrentProcId();
 
   nsresult rv = PVideoBridge::CreateEndpoints(parentPid, childPid, &parentPipe,
                                               &childPipe);
   if (NS_FAILED(rv)) {
     MOZ_LOG(sPDMLog, LogLevel::Debug,
             ("Could not create video bridge: %d", int(rv)));
-    DestroyProcess();
     return false;
   }
 
-  ContentDeviceData contentDeviceData;
-  gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData);
-
   mRDDChild->SendInitVideoBridge(std::move(childPipe),
                                  mNumUnexpectedCrashes == 0, contentDeviceData);
   if (gpuProcessPid != -1) {
     gpuManager->InitVideoBridge(std::move(parentPipe));
   } else {
     VideoBridgeParent::Open(std::move(parentPipe),
                             VideoBridgeSource::RddProcess);
   }
--- a/dom/media/ipc/RDDProcessManager.h
+++ b/dom/media/ipc/RDDProcessManager.h
@@ -26,16 +26,18 @@ class RDDProcessManager final : public R
   static void Initialize();
   static void Shutdown();
   static RDDProcessManager* Get();
 
   ~RDDProcessManager();
 
   using EnsureRDDPromise =
       MozPromise<ipc::Endpoint<PRemoteDecoderManagerChild>, nsresult, true>;
+  // Launch a new RDD process asynchronously
+  RefPtr<GenericNonExclusivePromise> LaunchRDDProcess();
   // If not using a RDD process, launch a new RDD process asynchronously and
   // create a RemoteDecoderManager bridge
   RefPtr<EnsureRDDPromise> EnsureRDDProcessAndCreateBridge(
       base::ProcessId aOtherProcess);
 
   void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) override;
 
   // Notify the RDDProcessManager that a top-level PRDD protocol has been
@@ -99,13 +101,16 @@ class RDDProcessManager final : public R
   // Fields that are associated with the current RDD process.
   RDDProcessHost* mProcess = nullptr;
   uint64_t mProcessToken = 0;
   RDDChild* mRDDChild = nullptr;
   // Collects any pref changes that occur during process launch (after
   // the initial map is passed in command-line arguments) to be sent
   // when the process can receive IPC messages.
   nsTArray<dom::Pref> mQueuedPrefs;
+  // Promise will be resolved when the RDD process has been fully started and
+  // VideoBridge configured. Only accessed on the main thread.
+  RefPtr<GenericNonExclusivePromise> mLaunchRDDPromise;
 };
 
 }  // namespace mozilla
 
 #endif  // _include_dom_media_ipc_RDDProcessManager_h_
--- a/dom/media/ipc/RemoteDecoderManagerChild.cpp
+++ b/dom/media/ipc/RemoteDecoderManagerChild.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "RemoteDecoderManagerChild.h"
 
+#include "PDMFactory.h"
 #include "RemoteAudioDecoder.h"
 #include "RemoteMediaDataDecoder.h"
 #include "RemoteVideoDecoder.h"
 #include "VideoUtils.h"
 #include "mozilla/DataMutex.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/dom/ContentChild.h"  // for launching RDD w/ ContentChild
 #include "mozilla/gfx/2D.h"
@@ -40,16 +41,21 @@ static StaticDataMutex<StaticRefPtr<nsIT
 // Only accessed from sRemoteDecoderManagerChildThread
 static StaticRefPtr<RemoteDecoderManagerChild>
     sRemoteDecoderManagerChildForRDDProcess;
 
 static StaticRefPtr<RemoteDecoderManagerChild>
     sRemoteDecoderManagerChildForGPUProcess;
 static UniquePtr<nsTArray<RefPtr<Runnable>>> sRecreateTasks;
 
+static StaticDataMutex<Maybe<PDMFactory::MediaCodecsSupported>> sGPUSupported(
+    "RDMC::sGPUSupported");
+static StaticDataMutex<Maybe<PDMFactory::MediaCodecsSupported>> sRDDSupported(
+    "RDMC::sRDDSupported");
+
 class ShutdownObserver final : public nsIObserver {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
  protected:
   ~ShutdownObserver() = default;
 };
@@ -185,28 +191,45 @@ nsISerialEventTarget* RemoteDecoderManag
   auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock();
   return *remoteDecoderManagerThread;
 }
 
 /* static */
 bool RemoteDecoderManagerChild::Supports(
     RemoteDecodeIn aLocation, const SupportDecoderParams& aParams,
     DecoderDoctorDiagnostics* aDiagnostics) {
-  RefPtr<PDMFactory> pdm;
+  Maybe<PDMFactory::MediaCodecsSupported> supported;
   switch (aLocation) {
-    case RemoteDecodeIn::RddProcess:
-      pdm = PDMFactory::PDMFactoryForRdd();
+    case RemoteDecodeIn::RddProcess: {
+      auto supportedRDD = sRDDSupported.Lock();
+      supported = *supportedRDD;
       break;
-    case RemoteDecodeIn::GpuProcess:
-      pdm = PDMFactory::PDMFactoryForGpu();
+    }
+    case RemoteDecodeIn::GpuProcess: {
+      auto supportedGPU = sGPUSupported.Lock();
+      supported = *supportedGPU;
       break;
+    }
     default:
       return false;
   }
-  return pdm->Supports(aParams, aDiagnostics);
+  if (!supported) {
+    // We haven't received the correct information yet from either the GPU or
+    // the RDD process; assume it is supported to prevent false negative.
+    if (aLocation == RemoteDecodeIn::RddProcess) {
+      // Ensure the RDD process got started.
+      // TODO: This can be removed once bug 1684991 is fixed.
+      LaunchRDDProcessIfNeeded();
+    }
+    return true;
+  }
+
+  // We can ignore the SupportDecoderParams argument for now as creation of the
+  // decoder will actually fail later and fallback PDMs will be tested on later.
+  return PDMFactory::SupportsMimeType(aParams.MimeType(), *supported);
 }
 
 /* static */
 RefPtr<PlatformDecoderModule::CreateDecoderPromise>
 RemoteDecoderManagerChild::CreateAudioDecoder(
     const CreateDecoderParams& aParams) {
   nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
   if (!managerThread) {
@@ -569,9 +592,28 @@ void RemoteDecoderManagerChild::Dealloca
         }
       })));
 }
 
 void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const {
   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
 }
 
+void RemoteDecoderManagerChild::SetSupported(
+    RemoteDecodeIn aLocation,
+    const PDMFactory::MediaCodecsSupported& aSupported) {
+  switch (aLocation) {
+    case RemoteDecodeIn::GpuProcess: {
+      auto supported = sGPUSupported.Lock();
+      *supported = Some(aSupported);
+      break;
+    }
+    case RemoteDecodeIn::RddProcess: {
+      auto supported = sRDDSupported.Lock();
+      *supported = Some(aSupported);
+      break;
+    }
+    default:
+      MOZ_CRASH("Not to be used for any other process");
+  }
+}
+
 }  // namespace mozilla
--- a/dom/media/ipc/RemoteDecoderManagerChild.h
+++ b/dom/media/ipc/RemoteDecoderManagerChild.h
@@ -1,42 +1,49 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
 #define include_dom_media_ipc_RemoteDecoderManagerChild_h
+
 #include "GPUVideoImage.h"
+#include "ipc/EnumSerializer.h"
+#include "mozilla/EnumTypeTraits.h"
 #include "mozilla/PRemoteDecoderManagerChild.h"
 #include "mozilla/layers/VideoBridgeUtils.h"
 
 namespace mozilla {
 
 class RemoteDecoderChild;
 
 enum class RemoteDecodeIn {
   Unspecified,
   RddProcess,
   GpuProcess,
+
+  SENTINEL,
 };
 
 class RemoteDecoderManagerChild final
     : public PRemoteDecoderManagerChild,
       public mozilla::ipc::IShmemAllocator,
       public mozilla::layers::IGPUVideoSurfaceManager {
   friend class PRemoteDecoderManagerChild;
 
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild, override)
 
   // Can only be called from the manager thread
   static RemoteDecoderManagerChild* GetSingleton(RemoteDecodeIn aLocation);
 
   static void Init();
+  static void SetSupported(RemoteDecodeIn aLocation,
+                           const PDMFactory::MediaCodecsSupported& aSupported);
 
   // Can be called from any thread.
   static bool Supports(RemoteDecodeIn aLocation,
                        const SupportDecoderParams& aParams,
                        DecoderDoctorDiagnostics* aDiagnostics);
   static RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateAudioDecoder(
       const CreateDecoderParams& aParams);
   static RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateVideoDecoder(
@@ -109,9 +116,17 @@ class RemoteDecoderManagerChild final
 
   RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
   // The location for decoding, Rdd or Gpu process.
   const RemoteDecodeIn mLocation;
 };
 
 }  // namespace mozilla
 
+namespace IPC {
+template <>
+struct ParamTraits<mozilla::RemoteDecodeIn>
+    : public ContiguousEnumSerializer<mozilla::RemoteDecodeIn,
+                                      mozilla::RemoteDecodeIn::Unspecified,
+                                      mozilla::RemoteDecodeIn::SENTINEL> {};
+}  // namespace IPC
+
 #endif  // include_dom_media_ipc_RemoteDecoderManagerChild_h
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -1,28 +1,35 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PDMFactory.h"
 
+#ifdef MOZ_AV1
+#  include "AOMDecoder.h"
+#endif
 #include "AgnosticDecoderModule.h"
 #include "AudioTrimmer.h"
 #include "BlankDecoderModule.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "EMEDecoderModule.h"
 #include "GMPDecoderModule.h"
 #include "H264.h"
 #include "MP4Decoder.h"
 #include "MediaChangeMonitor.h"
 #include "MediaInfo.h"
+#include "OpusDecoder.h"
+#include "TheoraDecoder.h"
+#include "VPXDecoder.h"
 #include "VideoUtils.h"
-#include "VPXDecoder.h"
+#include "VorbisDecoder.h"
+#include "WAVDecoder.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/RemoteDecoderManagerChild.h"
 #include "mozilla/RemoteDecoderModule.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/StaticPrefs_media.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/TaskQueue.h"
@@ -49,32 +56,26 @@
 #ifdef MOZ_OMX
 #  include "OmxDecoderModule.h"
 #endif
 
 #include <functional>
 
 namespace mozilla {
 
-// Set on the main thread, in content processes before any PDMFactory will ever
-// be created; never modified after.
-static Maybe<PDMFactory::MediaCodecsSupported> sSupported;
-
 extern already_AddRefed<PlatformDecoderModule> CreateNullDecoderModule();
 
 class PDMFactoryImpl final {
  public:
   PDMFactoryImpl() {
     if (XRE_IsGPUProcess()) {
       InitGpuPDMs();
     } else if (XRE_IsRDDProcess()) {
       InitRddPDMs();
     } else if (XRE_IsContentProcess()) {
-      MOZ_DIAGNOSTIC_ASSERT(sSupported.isSome(),
-                            "PDMFactory accessed while not initialized");
       InitContentPDMs();
     } else {
       MOZ_DIAGNOSTIC_ASSERT(
           XRE_IsParentProcess(),
           "PDMFactory is only usable in the Parent/GPU/RDD/Content process");
       InitDefaultPDMs();
     }
   }
@@ -226,41 +227,16 @@ class SupportChecker {
 PDMFactory::PDMFactory() {
   EnsureInit();
   CreatePDMs();
   CreateNullPDM();
 }
 
 PDMFactory::~PDMFactory() = default;
 
-PDMFactory::PDMFactory(const RemoteDecodeIn& aProcess) {
-  switch (aProcess) {
-    case RemoteDecodeIn::RddProcess:
-      CreateRddPDMs();
-      break;
-    case RemoteDecodeIn::GpuProcess:
-      CreateGpuPDMs();
-      break;
-    default:
-      MOZ_CRASH("Not to be used for any other process");
-  }
-}
-
-/* static */
-already_AddRefed<PDMFactory> PDMFactory::PDMFactoryForRdd() {
-  RefPtr<PDMFactory> pdm = new PDMFactory(RemoteDecodeIn::RddProcess);
-  return pdm.forget();
-}
-
-/* static */
-already_AddRefed<PDMFactory> PDMFactory::PDMFactoryForGpu() {
-  RefPtr<PDMFactory> pdm = new PDMFactory(RemoteDecodeIn::GpuProcess);
-  return pdm.forget();
-}
-
 /* static */
 void PDMFactory::EnsureInit() {
   {
     StaticMutexAutoLock mon(sMonitor);
     if (sInstance) {
       // Quick exit if we already have an instance.
       return;
     }
@@ -409,25 +385,16 @@ bool PDMFactory::SupportsMimeType(
   return Supports(SupportDecoderParams(*trackInfo), aDiagnostics);
 }
 
 bool PDMFactory::Supports(const SupportDecoderParams& aParams,
                           DecoderDoctorDiagnostics* aDiagnostics) const {
   if (mEMEPDM) {
     return mEMEPDM->Supports(aParams, aDiagnostics);
   }
-  if (VPXDecoder::IsVPX(aParams.MimeType(),
-                        VPXDecoder::VP8 | VPXDecoder::VP9) &&
-      !aParams.mConfig.GetAsVideoInfo()->HasAlpha()) {
-    // Work around bug 1521370, where trying to instantiate an external decoder
-    // could cause a crash.
-    // We always ship a VP8/VP9 decoder (libvpx) and optionally we have ffvpx.
-    // So we can speed up the test by assuming that this codec is supported.
-    return true;
-  }
 
   RefPtr<PlatformDecoderModule> current =
       GetDecoderModule(aParams, aDiagnostics);
   return !!current;
 }
 
 void PDMFactory::CreatePDMs() {
   if (StaticPrefs::media_use_blank_decoder()) {
@@ -637,60 +604,105 @@ void PDMFactory::SetCDMProxy(CDMProxy* a
     return;
   }
 #endif
   auto m = MakeRefPtr<PDMFactory>();
   mEMEPDM = MakeRefPtr<EMEDecoderModule>(aProxy, m);
 }
 
 /* static */
-PDMFactory::MediaCodecsSupported PDMFactory::Supported() {
-  if (XRE_IsContentProcess()) {
-    return *sSupported;
-  }
-  MOZ_ASSERT(XRE_IsParentProcess());
+PDMFactory::MediaCodecsSupported PDMFactory::Supported(bool aForceRefresh) {
+  MOZ_ASSERT(NS_IsMainThread());
 
-  static MediaCodecsSupported supported = []() {
+  static auto calculate = []() {
     auto pdm = MakeRefPtr<PDMFactory>();
     MediaCodecsSupported supported;
     // H264 and AAC depends on external framework that must be dynamically
     // loaded.
     // We currently only ship a single PDM per platform able to decode AAC or
     // H264. As such we can assert that being able to create a H264 or AAC
     // decoder indicates that with WMF on Windows or FFmpeg on Unixes is
     // available.
     // This logic will have to be revisited if a PDM supporting either codec
     // will be added in addition to the WMF and FFmpeg PDM (such as OpenH264)
     if (pdm->SupportsMimeType("video/avc"_ns, nullptr)) {
       supported += MediaCodecs::H264;
     }
+    if (pdm->SupportsMimeType("video/vp9"_ns, nullptr)) {
+      supported += MediaCodecs::VP9;
+    }
+    if (pdm->SupportsMimeType("video/vp8"_ns, nullptr)) {
+      supported += MediaCodecs::VP8;
+    }
+    if (pdm->SupportsMimeType("video/av1"_ns, nullptr)) {
+      supported += MediaCodecs::AV1;
+    }
+    if (pdm->SupportsMimeType("video/theora"_ns, nullptr)) {
+      supported += MediaCodecs::Theora;
+    }
     if (pdm->SupportsMimeType("audio/mp4a-latm"_ns, nullptr)) {
       supported += MediaCodecs::AAC;
     }
     // MP3 can be either decoded by ffvpx or WMF/FFmpeg
     if (pdm->SupportsMimeType("audio/mpeg"_ns, nullptr)) {
       supported += MediaCodecs::MP3;
     }
-    // The codecs below are potentially always supported as we ship native
-    // support for them. If they are disabled through pref, it will be handled
-    // in MediaDecoder class that could use those.
-    supported += MediaCodecs::VP9;
-    supported += MediaCodecs::VP8;
-    supported += MediaCodecs::AV1;
-    supported += MediaCodecs::Theora;
-    supported += MediaCodecs::Opus;
-    supported += MediaCodecs::Vorbis;
-    supported += MediaCodecs::Flac;
-    supported += MediaCodecs::Wave;
-
+    if (pdm->SupportsMimeType("audio/opus"_ns, nullptr)) {
+      supported += MediaCodecs::Opus;
+    }
+    if (pdm->SupportsMimeType("audio/vorbis"_ns, nullptr)) {
+      supported += MediaCodecs::Vorbis;
+    }
+    if (pdm->SupportsMimeType("audio/flac"_ns, nullptr)) {
+      supported += MediaCodecs::Flac;
+    }
+    if (pdm->SupportsMimeType("audio/x-wav"_ns, nullptr)) {
+      supported += MediaCodecs::Wave;
+    }
     return supported;
-  }();
+  };
+  static MediaCodecsSupported supported = calculate();
+  if (aForceRefresh) {
+    supported = calculate();
+  }
   return supported;
 }
 
 /* static */
-void PDMFactory::SetSupported(const MediaCodecsSupported& aSupported) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  sSupported = Some(aSupported);
+bool PDMFactory::SupportsMimeType(const nsACString& aMimeType,
+                                  const MediaCodecsSupported& aSupported) {
+  if (MP4Decoder::IsH264(aMimeType)) {
+    return aSupported.contains(MediaCodecs::H264);
+  }
+  if (VPXDecoder::IsVP9(aMimeType)) {
+    return aSupported.contains(MediaCodecs::VP9);
+  }
+  if (VPXDecoder::IsVP8(aMimeType)) {
+    return aSupported.contains(MediaCodecs::VP8);
+  }
+  if (AOMDecoder::IsAV1(aMimeType)) {
+    return aSupported.contains(MediaCodecs::AV1);
+  }
+  if (TheoraDecoder::IsTheora(aMimeType)) {
+    return aSupported.contains(MediaCodecs::Theora);
+  }
+  if (MP4Decoder::IsAAC(aMimeType)) {
+    return aSupported.contains(MediaCodecs::AAC);
+  }
+  if (aMimeType.EqualsLiteral("audio/mpeg")) {
+    return aSupported.contains(MediaCodecs::MP3);
+  }
+  if (OpusDataDecoder::IsOpus(aMimeType)) {
+    return aSupported.contains(MediaCodecs::Opus);
+  }
+  if (VorbisDataDecoder::IsVorbis(aMimeType)) {
+    return aSupported.contains(MediaCodecs::Vorbis);
+  }
+  if (aMimeType.EqualsLiteral("audio/flac")) {
+    return aSupported.contains(MediaCodecs::Flac);
+  }
+  if (WaveDataDecoder::IsWave(aMimeType)) {
+    return aSupported.contains(MediaCodecs::Wave);
+  }
+  return false;
 }
 
 }  // namespace mozilla
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -39,21 +39,16 @@ using PDMCreateDecoderPromise =
                /* IsExclusive = */ true>;
 
 class PDMFactory final {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDMFactory)
 
   PDMFactory();
 
-  // To be called in the content process only, used to determine which PDMs are
-  // usable in their respective process.
-  static already_AddRefed<PDMFactory> PDMFactoryForRdd();
-  static already_AddRefed<PDMFactory> PDMFactoryForGpu();
-
   // Factory method that creates the appropriate PlatformDecoderModule for
   // the platform we're running on.
   RefPtr<PDMCreateDecoderPromise> CreateDecoder(
       const CreateDecoderParams& aParams);
 
   bool SupportsMimeType(const nsACString& aMimeType,
                         DecoderDoctorDiagnostics* aDiagnostics) const;
   bool Supports(const SupportDecoderParams& aParams,
@@ -87,25 +82,22 @@ class PDMFactory final {
     Flac,
     Wave,
 
     SENTINEL,
   };
 
   using MediaCodecsSupported = EnumSet<MediaCodecs>;
 
-  static MediaCodecsSupported Supported();
-  static void SetSupported(const MediaCodecsSupported& aSupported);
+  static MediaCodecsSupported Supported(bool aForceRefresh = false);
+  static bool SupportsMimeType(const nsACString& aMimeType,
+                               const MediaCodecsSupported& aSupported);
 
  private:
   virtual ~PDMFactory();
-  // Will set PDM list for the required process.
-  // This is used to determine which PDMs are available on the given process
-  // from the content process.
-  explicit PDMFactory(const RemoteDecodeIn& aProcess);
 
   void CreatePDMs();
   void CreateNullPDM();
   void CreateGpuPDMs();
   void CreateRddPDMs();
   void CreateContentPDMs();
   void CreateDefaultPDMs();
 
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -310,16 +310,18 @@ class PlatformDecoderModule {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule)
 
   // Perform any per-instance initialization.
   // This is called on the decode task queue.
   virtual nsresult Startup() { return NS_OK; }
 
   // Indicates if the PlatformDecoderModule supports decoding of aMimeType.
+  // The answer to both SupportsMimeType and Supports doesn't guarantee that
+  // creation of a decoder will actually succeed.
   virtual bool SupportsMimeType(
       const nsACString& aMimeType,
       DecoderDoctorDiagnostics* aDiagnostics) const = 0;
 
   virtual bool Supports(const SupportDecoderParams& aParams,
                         DecoderDoctorDiagnostics* aDiagnostics) const {
     const TrackInfo& trackInfo = aParams.mConfig;
     if (!SupportsMimeType(trackInfo.mMimeType, aDiagnostics)) {
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -10,40 +10,36 @@
 
 #include "AppleATDecoder.h"
 #include "AppleVTDecoder.h"
 #include "MP4Decoder.h"
 #include "VPXDecoder.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Logging.h"
 #include "mozilla/StaticPrefs_media.h"
-#include "mozilla/gfx/gfxVars.h"
 
 extern "C" {
 // Only exists from MacOS 11
 extern void VTRegisterSupplementalVideoDecoderIfAvailable(
     CMVideoCodecType codecType) __attribute__((weak_import));
 extern Boolean VTIsHardwareDecodeSupported(CMVideoCodecType codecType)
     __attribute__((weak_import));
 }
 
 namespace mozilla {
 
 bool AppleDecoderModule::sInitialized = false;
-bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
 bool AppleDecoderModule::sCanUseVP9Decoder = false;
 
 /* static */
 void AppleDecoderModule::Init() {
   if (sInitialized) {
     return;
   }
 
-  sCanUseHardwareVideoDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding();
-
   sInitialized = true;
   if (RegisterSupplementalVP9Decoder()) {
     sCanUseVP9Decoder = CanCreateVP9Decoder();
   }
 }
 
 nsresult AppleDecoderModule::Startup() {
   if (!sInitialized) {
@@ -129,17 +125,17 @@ bool AppleDecoderModule::IsVideoSupporte
 }
 
 /* static */
 bool AppleDecoderModule::CanCreateVP9Decoder() {
   // We must wrap the code within __builtin_available to avoid compilation
   // warning as VTIsHardwareDecodeSupported is only available from macOS 10.13.
   if (__builtin_available(macOS 10.13, *)) {
     // Only use VP9 decoder if it's hardware accelerated.
-    if (!sCanUseHardwareVideoDecoder || !VTIsHardwareDecodeSupported ||
+    if (!VTIsHardwareDecodeSupported ||
         !VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9)) {
       return false;
     }
 
     // Check that we can instantiate a VP9 decoder.
     VideoInfo info(1920, 1080);
     info.mMimeType = "video/vp9";
     VPXDecoder::GetVPCCBox(info.mExtraData, VPXDecoder::VPXStreamInfo());
--- a/dom/media/platforms/apple/AppleDecoderModule.h
+++ b/dom/media/platforms/apple/AppleDecoderModule.h
@@ -31,17 +31,16 @@ class AppleDecoderModule : public Platfo
   bool SupportsMimeType(const nsACString& aMimeType,
                         DecoderDoctorDiagnostics* aDiagnostics) const override;
 
   bool Supports(const SupportDecoderParams& aParams,
                 DecoderDoctorDiagnostics* aDiagnostics) const override;
 
   static void Init();
 
-  static bool sCanUseHardwareVideoDecoder;
   static bool sCanUseVP9Decoder;
 
   static constexpr int kCMVideoCodecType_VP9{'vp09'};
 
  private:
   AppleDecoderModule() = default;
   virtual ~AppleDecoderModule() = default;
 
--- a/dom/media/platforms/apple/AppleVTDecoder.cpp
+++ b/dom/media/platforms/apple/AppleVTDecoder.cpp
@@ -16,16 +16,17 @@
 #include "MacIOSurfaceImage.h"
 #include "MediaData.h"
 #include "VPXDecoder.h"
 #include "VideoUtils.h"
 #include "gfxPlatform.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Logging.h"
 #include "mozilla/TaskQueue.h"
+#include "mozilla/gfx/gfxVars.h"
 #include "nsThreadUtils.h"
 
 #define LOG(...) DDMOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, __VA_ARGS__)
 #define LOGEX(_this, ...) \
   DDMOZ_LOGEX(_this, sPDMLog, mozilla::LogLevel::Debug, __VA_ARGS__)
 
 namespace mozilla {
 
@@ -576,17 +577,17 @@ CFDictionaryRef AppleVTDecoder::CreateDe
                             &kCFTypeDictionaryKeyCallBacks,
                             &kCFTypeDictionaryValueCallBacks);
 }
 
 CFDictionaryRef AppleVTDecoder::CreateDecoderSpecification() {
   const void* specKeys[] = {
       kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder};
   const void* specValues[1];
-  if (AppleDecoderModule::sCanUseHardwareVideoDecoder) {
+  if (gfx::gfxVars::CanUseHardwareVideoDecoding()) {
     specValues[0] = kCFBooleanTrue;
   } else {
     // This GPU is blacklisted for hardware decoding.
     specValues[0] = kCFBooleanFalse;
   }
   static_assert(ArrayLength(specKeys) == ArrayLength(specValues),
                 "Non matching keys/values array size");
 
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -63,25 +63,26 @@ already_AddRefed<PlatformDecoderModule> 
 
 WMFDecoderModule::~WMFDecoderModule() {
   if (mWMFInitialized) {
     DebugOnly<HRESULT> hr = wmf::MFShutdown();
     NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
   }
 }
 
-static bool IsRemoteAcceleratedCompositor(const SupportDecoderParams& aParams) {
-  if (!aParams.mKnowsCompositor) {
+static bool IsRemoteAcceleratedCompositor(
+    layers::KnowsCompositor* aKnowsCompositor) {
+  if (!aKnowsCompositor) {
     return false;
   }
 
   TextureFactoryIdentifier ident =
-      aParams.mKnowsCompositor->GetTextureFactoryIdentifier();
+      aKnowsCompositor->GetTextureFactoryIdentifier();
   return ident.mParentBackend != LayersBackend::LAYERS_BASIC &&
-         !aParams.mKnowsCompositor->UsingSoftwareWebRender() &&
+         !aKnowsCompositor->UsingSoftwareWebRender() &&
          ident.mParentProcessType == GeckoProcessType_GPU;
 }
 
 static bool CanCreateMFTDecoder(const GUID& aGuid) {
   // The IMFTransform interface used by MFTDecoder is documented to require to
   // run on an MTA thread.
   // https://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85).aspx#components
   // Note: our normal SharedThreadPool task queues are initialized to MTA, but
@@ -167,16 +168,23 @@ int WMFDecoderModule::GetNumDecoderThrea
 
 nsresult WMFDecoderModule::Startup() {
   mWMFInitialized = SUCCEEDED(wmf::MFStartup());
   return mWMFInitialized ? NS_OK : NS_ERROR_FAILURE;
 }
 
 already_AddRefed<MediaDataDecoder> WMFDecoderModule::CreateVideoDecoder(
     const CreateDecoderParams& aParams) {
+  // In GPU process, only support decoding if an accelerated compositor is
+  // known.
+  if (XRE_IsGPUProcess() &&
+      !IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor)) {
+    return nullptr;
+  }
+
   UniquePtr<WMFVideoMFTManager> manager(new WMFVideoMFTManager(
       aParams.VideoConfig(), aParams.mKnowsCompositor, aParams.mImageContainer,
       aParams.mRate.mValue, aParams.mOptions, sDXVAEnabled));
 
   MediaResult result = manager->Init();
   if (NS_FAILED(result)) {
     if (aParams.mError) {
       *aParams.mError = result;
@@ -196,16 +204,21 @@ already_AddRefed<MediaDataDecoder> WMFDe
       manager->GetDescriptionName().get());
 
   RefPtr<MediaDataDecoder> decoder = new WMFMediaDataDecoder(manager.release());
   return decoder.forget();
 }
 
 already_AddRefed<MediaDataDecoder> WMFDecoderModule::CreateAudioDecoder(
     const CreateDecoderParams& aParams) {
+  if (XRE_IsGPUProcess()) {
+    // Only allow video in the GPU process.
+    return nullptr;
+  }
+
   UniquePtr<WMFAudioMFTManager> manager(
       new WMFAudioMFTManager(aParams.AudioConfig()));
 
   if (!manager->Init()) {
     WmfDecoderModuleMarkerAndLog(
         "WMFADecoderCreation Failure",
         "WMFDecoderModule::CreateAudioDecoder failed for manager with "
         "description %s",
@@ -231,72 +244,58 @@ static bool CanCreateWMFDecoder() {
   if (result.isNothing()) {
     result.emplace(CanCreateMFTDecoder(aGuid));
   }
   return result.value();
 }
 
 /* static */
 bool WMFDecoderModule::HasH264() {
-  if (XRE_IsContentProcess()) {
-    return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::H264);
-  }
   return CanCreateWMFDecoder<CLSID_CMSH264DecoderMFT>();
 }
 
 /* static */
 bool WMFDecoderModule::HasVP8() {
-  if (XRE_IsContentProcess()) {
-    return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::VP8);
-  }
   return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
 }
 
 /* static */
 bool WMFDecoderModule::HasVP9() {
-  if (XRE_IsContentProcess()) {
-    return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::VP9);
-  }
   return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
 }
 
 /* static */
 bool WMFDecoderModule::HasAAC() {
-  if (XRE_IsContentProcess()) {
-    return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::AAC);
-  }
   return CanCreateWMFDecoder<CLSID_CMSAACDecMFT>();
 }
 
 /* static */
 bool WMFDecoderModule::HasMP3() {
-  if (XRE_IsContentProcess()) {
-    return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::MP3);
-  }
   return CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>();
 }
 
 bool WMFDecoderModule::SupportsMimeType(
     const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
   UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType);
   if (!trackInfo) {
     return false;
   }
   return Supports(SupportDecoderParams(*trackInfo), aDiagnostics);
 }
 
 bool WMFDecoderModule::Supports(const SupportDecoderParams& aParams,
                                 DecoderDoctorDiagnostics* aDiagnostics) const {
-  // In GPU process, only support decoding if an accelerated compositor is
-  // known.
-  if (XRE_IsGPUProcess() && !IsRemoteAcceleratedCompositor(aParams)) {
+  // In GPU process, only support decoding if video. This only gives a hint of
+  // what the GPU decoder *may* support. The actual check will occur in
+  // CreateVideoDecoder.
+  const auto& trackInfo = aParams.mConfig;
+  if (XRE_IsGPUProcess() && !trackInfo.GetAsVideoInfo()) {
     return false;
   }
 
-  const auto& trackInfo = aParams.mConfig;
   const auto* videoInfo = trackInfo.GetAsVideoInfo();
   // Temporary - forces use of VPXDecoder when alpha is present.
   // Bug 1263836 will handle alpha scenario once implemented. It will shift
   // the check for alpha to PDMFactory but not itself remove the need for a
   // check.
   if (videoInfo && (!SupportsColorDepth(videoInfo->mColorDepth, aDiagnostics) ||
                     videoInfo->HasAlpha())) {
     return false;
--- a/dom/svg/SVGFECompositeElement.cpp
+++ b/dom/svg/SVGFECompositeElement.cpp
@@ -27,16 +27,17 @@ SVGElement::NumberInfo SVGFECompositeEle
 
 SVGEnumMapping SVGFECompositeElement::sOperatorMap[] = {
     {nsGkAtoms::over, SVG_FECOMPOSITE_OPERATOR_OVER},
     {nsGkAtoms::in, SVG_FECOMPOSITE_OPERATOR_IN},
     {nsGkAtoms::out, SVG_FECOMPOSITE_OPERATOR_OUT},
     {nsGkAtoms::atop, SVG_FECOMPOSITE_OPERATOR_ATOP},
     {nsGkAtoms::xor_, SVG_FECOMPOSITE_OPERATOR_XOR},
     {nsGkAtoms::arithmetic, SVG_FECOMPOSITE_OPERATOR_ARITHMETIC},
+    {nsGkAtoms::lighter, SVG_FECOMPOSITE_OPERATOR_LIGHTER},
     {nullptr, 0}};
 
 SVGElement::EnumInfo SVGFECompositeElement::sEnumInfo[1] = {
     {nsGkAtoms::_operator, sOperatorMap, SVG_FECOMPOSITE_OPERATOR_OVER}};
 
 SVGElement::StringInfo SVGFECompositeElement::sStringInfo[3] = {
     {nsGkAtoms::result, kNameSpaceID_None, true},
     {nsGkAtoms::in, kNameSpaceID_None, true},
--- a/dom/webidl/SVGFECompositeElement.webidl
+++ b/dom/webidl/SVGFECompositeElement.webidl
@@ -16,16 +16,17 @@ interface SVGFECompositeElement : SVGEle
   // Composite Operators
   const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_IN = 2;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_OUT = 3;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_ATOP = 4;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5;
   const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
+  const unsigned short SVG_FECOMPOSITE_OPERATOR_LIGHTER = 7;
 
   [Constant]
   readonly attribute SVGAnimatedString in1;
   [Constant]
   readonly attribute SVGAnimatedString in2;
   [Constant]
   readonly attribute SVGAnimatedEnumeration operator;
   [Constant]
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -115,16 +115,18 @@ D2D1_COMPOSITE_MODE D2DFilterComposition
     case COMPOSITE_OPERATOR_IN:
       return D2D1_COMPOSITE_MODE_SOURCE_IN;
     case COMPOSITE_OPERATOR_OUT:
       return D2D1_COMPOSITE_MODE_SOURCE_OUT;
     case COMPOSITE_OPERATOR_ATOP:
       return D2D1_COMPOSITE_MODE_SOURCE_ATOP;
     case COMPOSITE_OPERATOR_XOR:
       return D2D1_COMPOSITE_MODE_XOR;
+    case COMPOSITE_OPERATOR_LIGHTER:
+      return D2D1_COMPOSITE_MODE_PLUS;
   }
 
   MOZ_CRASH("GFX: Unknown enum value D2DFilterCompositionMode!");
   return D2D1_COMPOSITE_MODE_SOURCE_OVER;
 }
 
 D2D1_CHANNEL_SELECTOR D2DChannelSelector(uint32_t aMode) {
   switch (aMode) {
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -2932,16 +2932,17 @@ already_AddRefed<DataSourceSurface> Filt
       FilterProcessing::ApplyComposition(input, dest, mOperator);
     } else {
       // We need to treat input as transparent. Depending on the composite
       // operator, different things happen to dest.
       switch (mOperator) {
         case COMPOSITE_OPERATOR_OVER:
         case COMPOSITE_OPERATOR_ATOP:
         case COMPOSITE_OPERATOR_XOR:
+        case COMPOSITE_OPERATOR_LIGHTER:
           // dest is unchanged.
           break;
         case COMPOSITE_OPERATOR_OUT:
           // dest is now transparent, but it can become non-transparent again
           // when compositing additional inputs.
           ClearDataSourceSurface(dest);
           break;
         case COMPOSITE_OPERATOR_IN:
--- a/gfx/2d/FilterProcessingSIMD-inl.h
+++ b/gfx/2d/FilterProcessingSIMD-inl.h
@@ -774,16 +774,32 @@ static inline u16x8_t CompositeTwoPixels
                                                   twoFiftyFiveMinusDestAlpha);
       i32x4_t result2 =
           simd::MulAdd16x8x2To32x4(destSourceInterleaved2, rightFactor2);
 
       return simd::PackAndSaturate32ToU16(simd::FastDivideBy255(result1),
                                           simd::FastDivideBy255(result2));
     }
 
+    case COMPOSITE_OPERATOR_LIGHTER: {
+      // val = dest * sourceAlpha + source * destAlpha;
+      u16x8_t destSourceInterleaved1 = simd::InterleaveLo16(dest, source);
+      u16x8_t rightFactor1 = simd::InterleaveLo16(sourceAlpha, destAlpha);
+      i32x4_t result1 =
+          simd::MulAdd16x8x2To32x4(destSourceInterleaved1, rightFactor1);
+
+      u16x8_t destSourceInterleaved2 = simd::InterleaveHi16(dest, source);
+      u16x8_t rightFactor2 = simd::InterleaveHi16(sourceAlpha, destAlpha);
+      i32x4_t result2 =
+          simd::MulAdd16x8x2To32x4(destSourceInterleaved2, rightFactor2);
+
+      return simd::PackAndSaturate32ToU16(simd::FastDivideBy255(result1),
+                                          simd::FastDivideBy255(result2));
+    }
+
     default:
       return simd::FromU16<u16x8_t>(0);
   }
 }
 
 template <typename i32x4_t, typename u16x8_t, typename u8x16_t, uint32_t op>
 static void ApplyComposition(DataSourceSurface* aSource,
                              DataSourceSurface* aDest) {
@@ -845,16 +861,20 @@ static void ApplyComposition_SIMD(DataSo
     case COMPOSITE_OPERATOR_ATOP:
       ApplyComposition<i32x4_t, i16x8_t, u8x16_t, COMPOSITE_OPERATOR_ATOP>(
           aSource, aDest);
       break;
     case COMPOSITE_OPERATOR_XOR:
       ApplyComposition<i32x4_t, i16x8_t, u8x16_t, COMPOSITE_OPERATOR_XOR>(
           aSource, aDest);
       break;
+    case COMPOSITE_OPERATOR_LIGHTER:
+      ApplyComposition<i32x4_t, i16x8_t, u8x16_t, COMPOSITE_OPERATOR_LIGHTER>(
+          aSource, aDest);
+      break;
     default:
       MOZ_CRASH("GFX: Incomplete switch");
   }
 }
 
 template <typename u8x16_t>
 static void SeparateColorChannels_SIMD(
     const IntSize& size, uint8_t* sourceData, int32_t sourceStride,
--- a/gfx/2d/Filters.h
+++ b/gfx/2d/Filters.h
@@ -228,17 +228,18 @@ enum CompositeAtts {
   ATT_COMPOSITE_OPERATOR = 0  // CompositeOperator
 };
 
 enum CompositeOperator {
   COMPOSITE_OPERATOR_OVER = 0,
   COMPOSITE_OPERATOR_IN,
   COMPOSITE_OPERATOR_OUT,
   COMPOSITE_OPERATOR_ATOP,
-  COMPOSITE_OPERATOR_XOR
+  COMPOSITE_OPERATOR_XOR,
+  COMPOSITE_OPERATOR_LIGHTER
 };
 
 enum CompositeInputs {
   // arbitrary number of inputs
   IN_COMPOSITE_IN_START = 0
 };
 
 enum GaussianBlurAtts {
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -1,36 +1,39 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "GPUChild.h"
-#include "gfxConfig.h"
-#include "GfxInfoBase.h"
-#include "gfxPlatform.h"
+
 #include "GPUProcessHost.h"
 #include "GPUProcessManager.h"
+#include "GfxInfoBase.h"
 #include "VRProcessManager.h"
-#include "mozilla/gfx/Logging.h"
+#include "gfxConfig.h"
+#include "gfxPlatform.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/dom/CheckerboardReportService.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/gfx/Logging.h"
 #include "mozilla/gfx/gfxVars.h"
 #if defined(XP_WIN)
 #  include "mozilla/gfx/DeviceManagerDx.h"
 #endif
+#include "mozilla/HangDetails.h"
+#include "mozilla/RemoteDecoderManagerChild.h"  // For RemoteDecodeIn
+#include "mozilla/Unused.h"
 #include "mozilla/ipc/Endpoint.h"
 #include "mozilla/layers/APZInputBridgeChild.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
-#include "mozilla/Unused.h"
-#include "mozilla/HangDetails.h"
 #include "nsIGfxInfo.h"
 #include "nsIObserverService.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #  include "ProfilerParent.h"
 #endif
 
 namespace mozilla {
@@ -294,16 +297,23 @@ mozilla::ipc::IPCResult GPUChild::RecvBH
     // moving our deserialized argument.
     nsCOMPtr<nsIHangDetails> hangDetails =
         new nsHangDetails(HangDetails(aDetails), PersistedToDisk::No);
     obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
   }
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult GPUChild::RecvUpdateMediaCodecsSupported(
+    const PDMFactory::MediaCodecsSupported& aSupported) {
+  dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(
+      RemoteDecodeIn::GpuProcess, aSupported);
+  return IPC_OK();
+}
+
 class DeferredDeleteGPUChild : public Runnable {
  public:
   explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
       : Runnable("gfx::DeferredDeleteGPUChild"), mChild(std::move(aChild)) {}
 
   NS_IMETHODIMP Run() override { return NS_OK; }
 
  private:
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -63,16 +63,18 @@ class GPUChild final : public ipc::Crash
   mozilla::ipc::IPCResult RecvNotifyUiObservers(const nsCString& aTopic);
   mozilla::ipc::IPCResult RecvNotifyDeviceReset(const GPUDeviceData& aData);
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvUpdateFeature(const Feature& aFeature,
                                             const FeatureFailure& aChange);
   mozilla::ipc::IPCResult RecvUsedFallback(const Fallback& aFallback,
                                            const nsCString& aMessage);
   mozilla::ipc::IPCResult RecvBHRThreadHang(const HangDetails& aDetails);
+  mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported(
+      const PDMFactory::MediaCodecsSupported& aSupported);
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const Maybe<ipc::FileDescriptor>& aDMDFile);
 
   static void Destroy(UniquePtr<GPUChild>&& aChild);
 
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -1,76 +1,80 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef XP_WIN
 #  include "WMF.h"
+#  include "WMFDecoderModule.h"
 #endif
+#include "GLContextProvider.h"
 #include "GPUParent.h"
+#include "GPUProcessHost.h"
+#include "GPUProcessManager.h"
+#include "GfxInfoBase.h"
+#include "ProcessUtils.h"
+#include "VRGPUChild.h"
+#include "VRManager.h"
+#include "VRManagerParent.h"
+#include "VsyncBridgeParent.h"
+#include "cairo.h"
 #include "gfxConfig.h"
 #include "gfxCrashReporterUtils.h"
-#include "GfxInfoBase.h"
 #include "gfxPlatform.h"
-#include "GLContextProvider.h"
-#include "GPUProcessHost.h"
-#include "GPUProcessManager.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/HangDetails.h"
 #include "mozilla/PerfStats.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/RemoteDecoderManagerChild.h"
+#include "mozilla/RemoteDecoderManagerParent.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
-#include "mozilla/RemoteDecoderManagerChild.h"
-#include "mozilla/RemoteDecoderManagerParent.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/image/ImageMemoryReporter.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/layers/APZInputBridgeParent.h"
+#include "mozilla/layers/APZPublicUtils.h"  // for apz::InitializeGlobalState
 #include "mozilla/layers/APZThreadUtils.h"
-#include "mozilla/layers/APZPublicUtils.h"  // for apz::InitializeGlobalState
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorManagerParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
+#include "mozilla/layers/MemoryReportingMLGPU.h"
 #include "mozilla/layers/UiCompositorControllerParent.h"
-#include "mozilla/layers/MemoryReportingMLGPU.h"
 #include "mozilla/layers/VideoBridgeParent.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/webrender/WebRenderAPI.h"
-#include "mozilla/HangDetails.h"
-#include "mozilla/Preferences.h"
-#include "nscore.h"
 #include "nsDebugImpl.h"
 #include "nsIGfxInfo.h"
 #include "nsThreadManager.h"
+#include "nscore.h"
 #include "prenv.h"
-#include "ProcessUtils.h"
-#include "VRGPUChild.h"
-#include "VRManager.h"
-#include "VRManagerParent.h"
-#include "VsyncBridgeParent.h"
-#include "cairo.h"
 #include "skia/include/core/SkGraphics.h"
 #if defined(XP_WIN)
+#  include <dwrite.h>
+#  include <process.h>
+
+#  include "mozilla/WindowsVersion.h"
 #  include "mozilla/gfx/DeviceManagerDx.h"
 #  include "mozilla/widget/WinCompositorWindowThread.h"
-#  include "mozilla/WindowsVersion.h"
-#  include <process.h>
-#  include <dwrite.h>
 #else
 #  include <unistd.h>
 #endif
 #ifdef MOZ_WIDGET_GTK
 #  include <gtk/gtk.h>
+
 #  include "skia/include/ports/SkTypeface_cairo.h"
 #endif
 #ifdef MOZ_GECKO_PROFILER
 #  include "ChildProfilerController.h"
 #endif
 #include "nsAppRunner.h"
 
 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
@@ -137,19 +141,17 @@ bool GPUParent::Init(base::ProcessId aPa
 #endif
 
   CompositorThreadHolder::Start();
   APZThreadUtils::SetControllerThread(NS_GetCurrentThread());
   apz::InitializeGlobalState();
   LayerTreeOwnerTracker::Initialize();
   CompositorBridgeParent::InitializeStatics();
   mozilla::ipc::SetThisProcessName("GPU Process");
-#ifdef XP_WIN
-  wmf::MFStartup();
-#endif
+
   return true;
 }
 
 void GPUParent::NotifyDeviceReset() {
   if (!NS_IsMainThread()) {
     NS_DispatchToMainThread(NS_NewRunnableFunction(
         "gfx::GPUParent::NotifyDeviceReset",
         []() -> void { GPUParent::GetSingleton()->NotifyDeviceReset(); }));
@@ -290,16 +292,29 @@ mozilla::ipc::IPCResult GPUParent::RecvI
 #endif
 
   VRManager::ManagerInit();
   // Send a message to the UI process that we're done.
   GPUDeviceData data;
   RecvGetDeviceStatus(&data);
   Unused << SendInitComplete(data);
 
+  // Dispatch a task to run when idle that will determine which codecs are
+  // usable. The primary goal is to determine if the media feature pack is
+  // installed.
+  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThreadQueue(
+      NS_NewRunnableFunction(
+          "GPUParent::Supported",
+          []() {
+            auto supported = PDMFactory::Supported();
+            Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
+                supported);
+          }),
+      2000 /* 2 seconds timeout */, EventQueuePriority::Idle));
+
   Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS,
                                  mLaunchTime);
   return IPC_OK();
 }
 
 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
 mozilla::ipc::IPCResult GPUParent::RecvInitSandboxTesting(
     Endpoint<PSandboxTestingChild>&& aEndpoint) {
@@ -358,16 +373,28 @@ mozilla::ipc::IPCResult GPUParent::RecvI
     Endpoint<PProfilerChild>&& aEndpoint) {
 #ifdef MOZ_GECKO_PROFILER
   mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
 #endif
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
+#if defined(XP_WIN)
+  auto scopeExit = MakeScopeExit(
+      [couldUseHWDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding()] {
+        if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) {
+          // The capabilities of the system may have changed, force a refresh by
+          // re-initializing the WMF PDM.
+          WMFDecoderModule::Init();
+          Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
+              PDMFactory::Supported(true /* force refresh */));
+        }
+      });
+#endif
   gfxVars::ApplyUpdate(aUpdate);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) {
   Preferences::SetPreference(aPref);
   return IPC_OK();
 }
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -30,16 +30,17 @@ using mozilla::Telemetry::HistogramAccum
 using mozilla::Telemetry::KeyedHistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using mozilla::gfx::Feature from "gfxFeature.h";
 using mozilla::gfx::Fallback from "gfxFallback.h";
 using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
+using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
 
 namespace mozilla {
 namespace gfx {
 
 struct LayerTreeIdMapping {
   LayersId layersId;
   ProcessId ownerId;
 };
@@ -149,12 +150,16 @@ child:
   // Update the UI process after a feature's status has changed. This is used
   // outside of the normal startup flow.
   async UpdateFeature(Feature aFeature, FeatureFailure aChange);
 
   // Notify about:support/Telemetry that a fallback occurred.
   async UsedFallback(Fallback aFallback, nsCString message);
 
   async BHRThreadHang(HangDetails aDetails);
+
+  // Update the cached list of codec supported following a check in the
+  // GPU parent.
+  async UpdateMediaCodecsSupported(MediaCodecsSupported aSupported);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/src/FilterSupport.cpp
+++ b/gfx/src/FilterSupport.cpp
@@ -943,23 +943,25 @@ static already_AddRefed<FilterNode> Filt
                              coefficients.Elements(), coefficients.Length());
         filter->SetInput(IN_ARITHMETIC_COMBINE_IN, mSources[0]);
         filter->SetInput(IN_ARITHMETIC_COMBINE_IN2, mSources[1]);
       } else {
         filter = mDT->CreateFilter(FilterType::COMPOSITE);
         if (!filter) {
           return nullptr;
         }
-        static const uint8_t operators[SVG_FECOMPOSITE_OPERATOR_ARITHMETIC] = {
-            COMPOSITE_OPERATOR_OVER,  // SVG_FECOMPOSITE_OPERATOR_UNKNOWN
-            COMPOSITE_OPERATOR_OVER,  // SVG_FECOMPOSITE_OPERATOR_OVER
-            COMPOSITE_OPERATOR_IN,    // SVG_FECOMPOSITE_OPERATOR_IN
-            COMPOSITE_OPERATOR_OUT,   // SVG_FECOMPOSITE_OPERATOR_OUT
-            COMPOSITE_OPERATOR_ATOP,  // SVG_FECOMPOSITE_OPERATOR_ATOP
-            COMPOSITE_OPERATOR_XOR    // SVG_FECOMPOSITE_OPERATOR_XOR
+        static const uint8_t operators[SVG_FECOMPOSITE_OPERATOR_LIGHTER + 1] = {
+            COMPOSITE_OPERATOR_OVER,    // SVG_FECOMPOSITE_OPERATOR_UNKNOWN
+            COMPOSITE_OPERATOR_OVER,    // SVG_FECOMPOSITE_OPERATOR_OVER
+            COMPOSITE_OPERATOR_IN,      // SVG_FECOMPOSITE_OPERATOR_IN
+            COMPOSITE_OPERATOR_OUT,     // SVG_FECOMPOSITE_OPERATOR_OUT
+            COMPOSITE_OPERATOR_ATOP,    // SVG_FECOMPOSITE_OPERATOR_ATOP
+            COMPOSITE_OPERATOR_XOR,     // SVG_FECOMPOSITE_OPERATOR_XOR
+            COMPOSITE_OPERATOR_OVER,    // Unused, arithmetic is handled above
+            COMPOSITE_OPERATOR_LIGHTER  // SVG_FECOMPOSITE_OPERATOR_LIGHTER
         };
         filter->SetAttribute(ATT_COMPOSITE_OPERATOR, (uint32_t)operators[op]);
         filter->SetInput(IN_COMPOSITE_IN_START, mSources[1]);
         filter->SetInput(IN_COMPOSITE_IN_START + 1, mSources[0]);
       }
       return filter.forget();
     }
 
--- a/gfx/src/FilterSupport.h
+++ b/gfx/src/FilterSupport.h
@@ -95,16 +95,17 @@ const unsigned short SVG_TURBULENCE_TYPE
 // Composite Operators
 const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_IN = 2;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_OUT = 3;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_ATOP = 4;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5;
 const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
+const unsigned short SVG_FECOMPOSITE_OPERATOR_LIGHTER = 7;
 
 struct FilterAttribute;
 
 // Limits
 const float kMaxStdDeviation = 500;
 
 // Simple PrimitiveAttributes:
 
--- a/js/src/jit/Bailouts.h
+++ b/js/src/jit/Bailouts.h
@@ -37,17 +37,17 @@ namespace jit {
 // * js::jit::ExceptionHandlerBailout - Ion doesn't implement `catch` or
 //     `finally`. If an exception is thrown and would be caught by an Ion frame,
 //     we bail out instead.
 //
 // *   js::jit::InvalidationBailout - We returned to Ion code that was
 //     invalidated while it was on the stack. See "OSI" below. Ion code can be
 //     invalidated for several reasons: when GC evicts Ion code to save memory,
 //     for example, or when assumptions baked into the jitted code are
-//     invalidated by the VM (see callers of IonBuilder::constraints()).
+//     invalidated by the VM.
 //
 // (Some stack inspection can be done without bailing out, including GC stack
 // marking, Error object construction, and Gecko profiler sampling.)
 //
 // Consider the first case. When an Ion guard fails, we can't continue in
 // Ion. There's no IC fallback case coming to save us; we've got a broken
 // assumption baked into the code we're running. So we jump to an out-of-line
 // code path that's responsible for abandoning Ion execution and resuming in
--- a/js/src/jit/BytecodeAnalysis.cpp
+++ b/js/src/jit/BytecodeAnalysis.cpp
@@ -27,19 +27,19 @@ bool BytecodeAnalysis::init(TempAllocato
   if (!infos_.growByUninitialized(script_->length())) {
     return false;
   }
 
   // Clear all BytecodeInfo.
   mozilla::PodZero(infos_.begin(), infos_.length());
   infos_[0].init(/*stackDepth=*/0);
 
-  // Because IonBuilder and WarpBuilder can compile try-blocks but don't compile
-  // the catch-body, we need some special machinery to prevent OSR into Ion/Warp
-  // in the following cases:
+  // Because WarpBuilder can compile try-blocks but doesn't compile the
+  // catch-body, we need some special machinery to prevent OSR into Warp code in
+  // the following cases:
   //
   // (1) Loops in catch/finally blocks:
   //
   //       try {
   //         ..
   //       } catch (e) {
   //         while (..) {} // Can't OSR here.
   //       }
--- a/js/src/jit/BytecodeAnalysis.h
+++ b/js/src/jit/BytecodeAnalysis.h
@@ -72,17 +72,17 @@ class BytecodeAnalysis {
     return nullptr;
   }
 
   bool hasTryFinally() const { return hasTryFinally_; }
 
   void checkWarpSupport(JSOp op);
 };
 
-// Bytecode analysis pass necessary for IonBuilder. The result is cached in
+// Bytecode analysis pass necessary for WarpBuilder. The result is cached in
 // JitScript.
 struct IonBytecodeInfo;
 IonBytecodeInfo AnalyzeBytecodeForIon(JSContext* cx, JSScript* script);
 
 }  // namespace jit
 }  // namespace js
 
 #endif /* jit_BytecodeAnalysis_h */
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1754,21 +1754,19 @@ AttachDecision GetPropIRGenerator::tryAt
 
   JSFunction& fun = shape->getterValue().toObject().as<JSFunction>();
   if (!TypedArrayObject::isOriginalLengthGetter(fun.native())) {
     return AttachDecision::NoAction;
   }
 
   maybeEmitIdGuard(id);
   // Emit all the normal guards for calling this native, but specialize
-  // callNativeGetterResult. Also store the getter itself to enable
-  // AddCacheIRGetPropFunction to read it from the IC stub, which is needed for
-  // Ion-inlining.
+  // callNativeGetterResult.
   EmitCallGetterResultGuards(writer, obj, holder, shape, objId, mode_);
-  writer.loadTypedArrayLengthResult(objId, &fun);
+  writer.loadTypedArrayLengthResult(objId);
   writer.returnFromIC();
 
   trackAttached("TypedArrayLength");
   return AttachDecision::Attach;
 }
 
 AttachDecision GetPropIRGenerator::tryAttachFunction(HandleObject obj,
                                                      ObjOperandId objId,
@@ -7660,19 +7658,17 @@ AttachDecision CallIRGenerator::tryAttac
 
   ValOperandId argId = writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_);
   ObjOperandId objArgId = writer.guardToObject(argId);
 
   if (isPossiblyWrapped) {
     writer.guardIsNotProxy(objArgId);
   }
 
-  // Note: the "getter" argument is a hint for IonBuilder. Just pass |callee|,
-  // the field isn't used for this intrinsic call.
-  writer.loadTypedArrayLengthResult(objArgId, callee);
+  writer.loadTypedArrayLengthResult(objArgId);
   writer.returnFromIC();
 
   trackAttached("TypedArrayLength");
   return AttachDecision::Attach;
 }
 
 AttachDecision CallIRGenerator::tryAttachArrayBufferByteLength(
     HandleFunction callee, bool isPossiblyWrapped) {
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -3167,18 +3167,17 @@ bool CacheIRCompiler::emitLoadArrayBuffe
   AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
   masm.loadArrayBufferByteLengthInt32(obj, scratch);
 
   EmitStoreResult(masm, scratch, JSVAL_TYPE_INT32, output);
   return true;
 }
 
-bool CacheIRCompiler::emitLoadTypedArrayLengthResult(ObjOperandId objId,
-                                                     uint32_t getterOffset) {
+bool CacheIRCompiler::emitLoadTypedArrayLengthResult(ObjOperandId objId) {
   JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
   AutoOutputRegister output(*this);
   Register obj = allocator.useRegister(masm, objId);
   AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
   masm.loadArrayBufferViewLengthInt32(obj, scratch);
   EmitStoreResult(masm, scratch, JSVAL_TYPE_INT32, output);
   return true;
--- a/js/src/jit/CacheIROps.yaml
+++ b/js/src/jit/CacheIROps.yaml
@@ -1746,17 +1746,16 @@
     obj: ObjId
 
 - name: LoadTypedArrayLengthResult
   shared: true
   transpile: true
   cost_estimate: 1
   args:
     obj: ObjId
-    getter: ObjectField
 
 - name: LoadStringCharResult
   shared: false
   transpile: true
   cost_estimate: 5
   args:
     str: StringId
     index: Int32Id
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5687,17 +5687,17 @@ void CodeGenerator::visitCallGeneric(LCa
   uint32_t descriptor = MakeFrameDescriptor(
       masm.framePushed(), FrameType::IonJS, JitFrameLayout::Size());
   masm.Push(Imm32(call->numActualArgs()));
   masm.PushCalleeToken(calleereg, call->mir()->isConstructing());
   masm.Push(Imm32(descriptor));
 
   // Check whether the provided arguments satisfy target argc.
   // We cannot have lowered to LCallGeneric with a known target. Assert that we
-  // didn't add any undefineds in IonBuilder. NB: MCall::numStackArgs includes
+  // didn't add any undefineds in WarpBuilder. NB: MCall::numStackArgs includes
   // |this|.
   DebugOnly<unsigned> numNonArgsOnStack = 1 + call->isConstructing();
   MOZ_ASSERT(call->numActualArgs() ==
              call->mir()->numStackArgs() - numNonArgsOnStack);
   masm.load16ZeroExtend(Address(calleereg, JSFunction::offsetOfNargs()),
                         nargsreg);
   masm.branch32(Assembler::Above, nargsreg, Imm32(call->numActualArgs()),
                 &thunk);
@@ -5752,17 +5752,17 @@ void CodeGenerator::visitCallKnown(LCall
   Register calleereg = ToRegister(call->getFunction());
   Register objreg = ToRegister(call->getTempObject());
   uint32_t unusedStack = StackOffsetOfPassedArg(call->argslot());
   WrappedFunction* target = call->getSingleTarget();
 
   // Native single targets (except wasm) are handled by LCallNative.
   MOZ_ASSERT(target->hasJitEntry());
 
-  // Missing arguments must have been explicitly appended by the IonBuilder.
+  // Missing arguments must have been explicitly appended by WarpBuilder.
   DebugOnly<unsigned> numNonArgsOnStack = 1 + call->isConstructing();
   MOZ_ASSERT(target->nargs() <=
              call->mir()->numStackArgs() - numNonArgsOnStack);
 
   MOZ_ASSERT_IF(call->isConstructing(), target->isConstructor());
 
   masm.checkStackAlignment();
 
--- a/js/src/jit/InlineScriptTree.h
+++ b/js/src/jit/InlineScriptTree.h
@@ -14,18 +14,18 @@
 
 namespace js {
 namespace jit {
 
 // The compiler at various points needs to be able to store references to the
 // current inline path (the sequence of scripts and call-pcs that lead to the
 // current function being inlined).
 //
-// To support this, the top-level IonBuilder keeps a tree that records the
-// inlinings done during compilation.
+// To support this, use a tree that records the inlinings done during
+// compilation.
 class InlineScriptTree {
   // InlineScriptTree for the caller
   InlineScriptTree* caller_;
 
   // PC in the caller corresponding to this script.
   jsbytecode* callerPc_;
 
   // Script for this entry.
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1806,17 +1806,17 @@ static bool CanIonCompileOrInlineScript(
     if (script->isModule()) {
       *reason = "async module";
       return false;
     }
   }
 
   if (script->hasNonSyntacticScope() && !script->function()) {
     // Support functions with a non-syntactic global scope but not other
-    // scripts. For global scripts, IonBuilder currently uses the global
+    // scripts. For global scripts, WarpBuilder currently uses the global
     // object as scope chain, this is not valid when the script has a
     // non-syntactic global scope.
     *reason = "has non-syntactic global scope";
     return false;
   }
 
   if (script->functionHasExtraBodyVarScope() &&
       script->functionExtraBodyVarScope()->hasEnvironment()) {
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2356,17 +2356,17 @@ bool jit::RemoveUnmarkedBlocks(MIRGenera
       // need to worry about whether an unmarked block is a loop or not.
       if (block->isLoopHeader()) {
         block->clearLoopHeader();
       }
 
       for (size_t i = 0, e = block->numSuccessors(); i != e; ++i) {
         block->getSuccessor(i)->removePredecessor(block);
       }
-      graph.removeBlockIncludingPhis(block);
+      graph.removeBlock(block);
     }
   }
 
   // Renumber the blocks and update the dominator tree.
   return AccountForCFGChanges(mir, graph, /*updateAliasAnalysis=*/false);
 }
 
 // A Simple, Fast Dominance Algorithm by Cooper et al.
@@ -3390,31 +3390,18 @@ static bool TryEliminateBoundsCheck(Boun
 
   dominating->setMinimum(newMinimum);
   dominating->setMaximum(newMaximum);
   dominating->setBailoutKind(BailoutKind::HoistBoundsCheck);
 
   return true;
 }
 
-static bool TryOptimizeLoadObjectOrNull(MDefinition* def,
-                                        MDefinitionVector* peliminateList) {
-  if (def->type() != MIRType::Value) {
-    return true;
-  }
-
-  // TODO(no-TI): remove more code.
-  return true;
-}
-
 // Eliminate checks which are redundant given each other or other instructions.
 //
-// A type barrier is considered redundant if all missing types have been tested
-// for by earlier control instructions.
-//
 // A bounds check is considered redundant if it's dominated by another bounds
 // check with the same length and the indexes differ by only a constant amount.
 // In this case we eliminate the redundant bounds check and update the other one
 // to cover the ranges of both checks.
 //
 // Bounds checks are added to a hash map and since the hash function ignores
 // differences in constant offset, this offers a fast way to find redundant
 // checks.
@@ -3448,33 +3435,24 @@ bool jit::EliminateRedundantChecks(MIRGr
     if (!worklist.append(block->immediatelyDominatedBlocksBegin(),
                          block->immediatelyDominatedBlocksEnd())) {
       return false;
     }
 
     for (MDefinitionIterator iter(block); iter;) {
       MDefinition* def = *iter++;
 
+      if (!def->isBoundsCheck()) {
+        continue;
+      }
+
       bool eliminated = false;
-
-      switch (def->op()) {
-        case MDefinition::Opcode::BoundsCheck:
-          if (!TryEliminateBoundsCheck(checks, index, def->toBoundsCheck(),
-                                       &eliminated)) {
-            return false;
-          }
-          break;
-        case MDefinition::Opcode::LoadFixedSlot:
-        case MDefinition::Opcode::LoadDynamicSlot:
-          if (!TryOptimizeLoadObjectOrNull(def, &eliminateList)) {
-            return false;
-          }
-          break;
-        default:
-          break;
+      if (!TryEliminateBoundsCheck(checks, index, def->toBoundsCheck(),
+                                   &eliminated)) {
+        return false;
       }
 
       if (eliminated) {
         block->discardDef(def);
       }
     }
     index++;
   }
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -350,29 +350,20 @@ bool IonGetNameIC::update(JSContext* cx,
   RootedObject obj(cx);
   RootedObject holder(cx);
   Rooted<PropertyResult> prop(cx);
   if (!LookupName(cx, name, envChain, &obj, &holder, &prop)) {
     return false;
   }
 
   if (JSOp(*GetNextPc(pc)) == JSOp::Typeof) {
-    if (!FetchName<GetNameMode::TypeOf>(cx, obj, holder, name, prop, res)) {
-      return false;
-    }
-  } else {
-    if (!FetchName<GetNameMode::Normal>(cx, obj, holder, name, prop, res)) {
-      return false;
-    }
+    return FetchName<GetNameMode::TypeOf>(cx, obj, holder, name, prop, res);
   }
 
-  // No need to call JitScript::Monitor, IonBuilder always inserts a type
-  // barrier after GetName ICs.
-
-  return true;
+  return FetchName<GetNameMode::Normal>(cx, obj, holder, name, prop, res);
 }
 
 /* static */
 JSObject* IonBindNameIC::update(JSContext* cx, HandleScript outerScript,
                                 IonBindNameIC* ic, HandleObject envChain) {
   IonScript* ionScript = outerScript->ionScript();
   jsbytecode* pc = ic->pc();
   RootedPropertyName name(cx, ic->script()->getName(pc));
--- a/js/src/jit/JitContext.h
+++ b/js/src/jit/JitContext.h
@@ -81,18 +81,17 @@ static_assert(sizeof(AbortReasonOr<uint1
 
 class JitContext {
   JitContext* prev_ = nullptr;
   CompileRealm* realm_ = nullptr;
   int assemblerCount_ = 0;
 
 #ifdef DEBUG
   // Whether this thread is actively Ion compiling (does not include Wasm or
-  // IonBuilder).
-  // TODO(no-TI): fix IonBuilder references in comments.
+  // WarpOracle).
   bool inIonBackend_ = false;
 
   bool isCompilingWasm_ = false;
   bool oom_ = false;
 #endif
 
  public:
   // Running context when executing on the main thread. Not available during
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -417,17 +417,17 @@ static bool ProcessTryNotesBaseline(JSCo
       }
 
       case TryNoteKind::Destructuring: {
         uint8_t* framePointer;
         uint8_t* stackPointer;
         BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer,
                                                  &stackPointer);
         // Note: if this ever changes, also update the
-        // TryNoteKind::Destructuring code in IonBuilder.cpp!
+        // TryNoteKind::Destructuring code in WarpBuilder.cpp!
         RootedValue doneValue(cx, *(reinterpret_cast<Value*>(stackPointer)));
         MOZ_RELEASE_ASSERT(!doneValue.isMagic());
         bool done = ToBoolean(doneValue);
         if (!done) {
           Value iterValue(*(reinterpret_cast<Value*>(stackPointer) + 1));
           RootedObject iterObject(cx, &iterValue.toObject());
           if (!IteratorCloseForException(cx, iterObject)) {
             SettleOnTryNote(cx, tn, frame, ei, rfe, pc);
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -70,19 +70,16 @@ DefaultJitOptions::DefaultJitOptions() {
   // are not modified before its OsiPoint.
   SET_DEFAULT(checkOsiPointRegisters, false);
 #endif
 
   // Whether to enable extra code to perform dynamic validation of
   // RangeAnalysis results.
   SET_DEFAULT(checkRangeAnalysis, false);
 
-  // Toggles whether IonBuilder fallbacks to a call if we fail to inline.
-  SET_DEFAULT(disableInlineBacktracking, false);
-
   // Toggles whether Alignment Mask Analysis is globally disabled.
   SET_DEFAULT(disableAma, false);
 
   // Toggles whether Effective Address Analysis is globally disabled.
   SET_DEFAULT(disableEaa, false);
 
   // Toggles whether Edge Case Analysis is gobally disabled.
   SET_DEFAULT(disableEdgeCaseAnalysis, false);
@@ -138,17 +135,17 @@ DefaultJitOptions::DefaultJitOptions() {
 
   // Whether the IonMonkey and Baseline JITs are enabled for Trusted Principals.
   // (Ignored if ion or baselineJit is set to true.)
   SET_DEFAULT(jitForTrustedPrincipals, false);
 
   // Whether the RegExp JIT is enabled.
   SET_DEFAULT(nativeRegExp, true);
 
-  // Whether IonBuilder should prefer IC generation above specialized MIR.
+  // Whether Warp should use ICs instead of transpiling Baseline CacheIR.
   SET_DEFAULT(forceInlineCaches, false);
 
   // Toggles whether large scripts are rejected.
   SET_DEFAULT(limitScriptSize, true);
 
   // Toggles whether functions may be entered at loop headers.
   SET_DEFAULT(osr, true);
 
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -34,17 +34,16 @@ static inline mozilla::Maybe<IonRegister
 
 struct DefaultJitOptions {
   bool checkGraphConsistency;
 #ifdef CHECK_OSIPOINT_REGISTERS
   bool checkOsiPointRegisters;
 #endif
   bool checkRangeAnalysis;
   bool runExtraChecks;
-  bool disableInlineBacktracking;
   bool disableAma;
   bool disableEaa;
   bool disableEdgeCaseAnalysis;
   bool disableGvn;
   bool disableInlining;
   bool disableLicm;
   bool disablePgo;
   bool disableInstructionReordering;
--- a/js/src/jit/JitScript.h
+++ b/js/src/jit/JitScript.h
@@ -18,17 +18,17 @@
 
 class JS_PUBLIC_API JSScript;
 
 namespace js {
 namespace jit {
 
 class JitZone;
 
-// Information about a script's bytecode, used by IonBuilder. This is cached
+// Information about a script's bytecode, used by WarpBuilder. This is cached
 // in JitScript.
 struct IonBytecodeInfo {
   bool usesEnvironmentChain = false;
   bool modifiesArguments = false;
   bool hasTryFinally = false;
 };
 
 // Magic BaselineScript value indicating Baseline compilation has been disabled.
@@ -233,18 +233,18 @@ class alignas(uintptr_t) JitScript final
 
   // Allocated space for fallback IC stubs.
   FallbackICStubSpace fallbackStubSpace_ = {};
 
   // Profile string used by the profiler for Baseline Interpreter frames.
   const char* profileString_ = nullptr;
 
   // Data allocated lazily the first time this script is compiled, inlined, or
-  // analyzed by IonBuilder. This is done lazily to improve performance and
-  // memory usage as most scripts are never Ion-compiled.
+  // analyzed by WarpBuilder. This is done lazily to improve performance and
+  // memory usage as most scripts are never Warp-compiled.
   struct CachedIonData {
     // For functions with a call object, template objects to use for the call
     // object and decl env object (linked via the call object's enclosing
     // scope).
     const HeapPtr<EnvironmentObject*> templateEnv = nullptr;
 
     // Analysis information based on the script and its bytecode.
     IonBytecodeInfo bytecodeInfo = {};
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2030,17 +2030,17 @@ bool MPhi::typeIncludes(MDefinition* def
     // This phi must be able to be any value.
     return this->type() == MIRType::Value;
   }
 
   return this->mightBeType(def->type());
 }
 
 void MCall::addArg(size_t argnum, MDefinition* arg) {
-  // The operand vector is initialized in reverse order by the IonBuilder.
+  // The operand vector is initialized in reverse order by WarpBuilder.
   // It cannot be checked for consistency until all arguments are added.
   // FixedList doesn't initialize its elements, so do an unchecked init.
   initOperand(argnum + NumNonArgumentOperands, arg);
 }
 
 static inline bool IsConstant(MDefinition* def, double v) {
   if (!def->isConstant()) {
     return false;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -6488,20 +6488,16 @@ class MPhi final : public MDefinition,
   PhiUsage usageAnalysis_;
 
 #if DEBUG
   bool specialized_;
 #endif
 
  protected:
   MUse* getUseFor(size_t index) override {
-    // Note: after the initial IonBuilder pass, it is OK to change phi
-    // operands such that they do not include the type sets of their
-    // operands. This can arise during e.g. value numbering, where
-    // definitions producing the same value may have different type sets.
     MOZ_ASSERT(index < numOperands());
     return &inputs_[index];
   }
   const MUse* getUseFor(size_t index) const override { return &inputs_[index]; }
 
  public:
   INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(Phi)
   virtual const TypePolicy* typePolicy();
@@ -11486,18 +11482,17 @@ class MResumePoint final : public MNode
     ResumeAfter,  // Resume after the current instruction
     Outer         // State before inlining.
   };
 
  private:
   friend class MBasicBlock;
   friend void AssertBasicGraphCoherency(MIRGraph& graph, bool force);
 
-  // List of stack slots needed to reconstruct the frame corresponding to the
-  // function which is compiled by IonBuilder.
+  // List of stack slots needed to reconstruct the BaselineFrame.
   FixedList<MUse> operands_;
 
   // List of stores needed to reconstruct the content of objects which are
   // emulated by EmulateStateOf variants.
   MStoresToRecoverList stores_;
 
   jsbytecode* pc_;
   MInstruction* instruction_;
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -74,17 +74,17 @@ class MIRGenerator final {
                                                  const char* message, ...)
       MOZ_FORMAT_PRINTF(3, 4);
 
   mozilla::GenericErrorResult<AbortReason> abortFmt(AbortReason r,
                                                     const char* message,
                                                     va_list ap)
       MOZ_FORMAT_PRINTF(3, 0);
 
-  // Collect the evaluation result of phases after IonBuilder, such that
+  // Collect the evaluation result of phases after WarpOracle, such that
   // off-thread compilation can report what error got encountered.
   void setOffThreadStatus(AbortReasonOr<Ok>&& result) {
     MOZ_ASSERT(offThreadStatus_.isOk());
     offThreadStatus_ = std::move(result);
   }
   const AbortReasonOr<Ok>& getOffThreadStatus() const {
     return offThreadStatus_;
   }
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -98,105 +98,16 @@ void MIRGraph::insertBlockAfter(MBasicBl
 }
 
 void MIRGraph::insertBlockBefore(MBasicBlock* at, MBasicBlock* block) {
   block->setId(blockIdGen_++);
   blocks_.insertBefore(at, block);
   numBlocks_++;
 }
 
-bool MIRGraph::removeSuccessorBlocks(MBasicBlock* start) {
-  if (!start->hasLastIns()) {
-    return true;
-  }
-
-  start->mark();
-
-  // Mark all successors.
-  Vector<MBasicBlock*, 4, SystemAllocPolicy> blocks;
-  for (size_t i = 0; i < start->numSuccessors(); i++) {
-    if (!start->getSuccessor(i)) {
-      continue;
-    }
-    if (start->getSuccessor(i)->isMarked()) {
-      continue;
-    }
-    if (!blocks.append(start->getSuccessor(i))) {
-      return false;
-    }
-    start->getSuccessor(i)->mark();
-  }
-  for (size_t i = 0; i < blocks.length(); i++) {
-    MBasicBlock* block = blocks[i];
-    if (!block->hasLastIns()) {
-      continue;
-    }
-
-    for (size_t j = 0; j < block->numSuccessors(); j++) {
-      if (!block->getSuccessor(j)) {
-        continue;
-      }
-      if (block->getSuccessor(j)->isMarked()) {
-        continue;
-      }
-      if (!blocks.append(block->getSuccessor(j))) {
-        return false;
-      }
-      block->getSuccessor(j)->mark();
-    }
-  }
-
-  if (osrBlock()) {
-    if (osrBlock()->getSuccessor(0)->isMarked()) {
-      osrBlock()->mark();
-    }
-  }
-
-  // Remove blocks.
-  // If they don't have any predecessor
-  for (size_t i = 0; i < blocks.length(); i++) {
-    MBasicBlock* block = blocks[i];
-    bool allMarked = true;
-    for (size_t i = 0; i < block->numPredecessors(); i++) {
-      if (block->getPredecessor(i)->isMarked()) {
-        continue;
-      }
-      allMarked = false;
-      break;
-    }
-    if (allMarked) {
-      removeBlock(block);
-    } else {
-      MOZ_ASSERT(block != osrBlock());
-      for (size_t j = 0; j < block->numPredecessors();) {
-        if (!block->getPredecessor(j)->isMarked()) {
-          j++;
-          continue;
-        }
-        block->removePredecessor(block->getPredecessor(j));
-      }
-      // This shouldn't have any instructions yet.
-      MOZ_ASSERT(block->begin() == block->end());
-    }
-  }
-
-  if (osrBlock()) {
-    if (osrBlock()->getSuccessor(0)->isDead()) {
-      removeBlock(osrBlock());
-    }
-  }
-
-  for (size_t i = 0; i < blocks.length(); i++) {
-    blocks[i]->unmark();
-  }
-  start->unmark();
-
-  return true;
-}
-
 void MIRGraph::removeBlock(MBasicBlock* block) {
   // Remove a block from the graph. It will also cleanup the block.
 
   if (block == osrBlock_) {
     osrBlock_ = nullptr;
   }
 
   if (returnAccumulator_) {
@@ -214,23 +125,16 @@ void MIRGraph::removeBlock(MBasicBlock* 
   block->markAsDead();
 
   if (block->isInList()) {
     blocks_.remove(block);
     numBlocks_--;
   }
 }
 
-void MIRGraph::removeBlockIncludingPhis(MBasicBlock* block) {
-  // removeBlock doesn't clear phis because of IonBuilder constraints. Here,
-  // we want to totally clear everything.
-  removeBlock(block);
-  block->discardAllPhis();
-}
-
 void MIRGraph::unmarkBlocks() {
   for (MBasicBlockIterator i(blocks_.begin()); i != blocks_.end(); i++) {
     i->unmark();
   }
 }
 
 MBasicBlock* MBasicBlock::New(MIRGraph& graph, size_t stackDepth,
                               const CompileInfo& info, MBasicBlock* maybePred,
@@ -313,17 +217,17 @@ MBasicBlock* MBasicBlock::NewSplitEdge(M
   MBasicBlock* split = nullptr;
   if (!succ->pc()) {
     // The predecessor does not have a PC, this is a Wasm compilation.
     split = MBasicBlock::New(graph, succ->info(), pred, SPLIT_EDGE);
     if (!split) {
       return nullptr;
     }
   } else {
-    // The predecessor has a PC, this is an IonBuilder compilation.
+    // The predecessor has a PC, this is a Warp compilation.
     MResumePoint* succEntry = succ->entryResumePoint();
 
     BytecodeSite* site =
         new (graph.alloc()) BytecodeSite(succ->trackedTree(), succEntry->pc());
     split =
         new (graph.alloc()) MBasicBlock(graph, succ->info(), site, SPLIT_EDGE);
 
     if (!split->init()) {
@@ -786,29 +690,26 @@ void MBasicBlock::discardAllInstructions
     // as discarded.  Also we do not assert that we have no uses as blocks
     // might be removed in reverse post order.
     MInstruction* ins = *iter++;
     prepareForDiscard(ins, RefType_DefaultNoAssert);
     instructions_.remove(ins);
   }
 }
 
-void MBasicBlock::discardAllPhiOperands() {
+void MBasicBlock::discardAllPhis() {
   for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) {
     iter->removeAllOperands();
   }
 
   for (MBasicBlock** pred = predecessors_.begin(); pred != predecessors_.end();
        pred++) {
     (*pred)->clearSuccessorWithPhis();
   }
-}
 
-void MBasicBlock::discardAllPhis() {
-  discardAllPhiOperands();
   phis_.clear();
 }
 
 void MBasicBlock::discardAllResumePoints(bool discardEntry) {
   if (outerResumePoint_) {
     clearOuterResumePoint();
   }
 
@@ -826,22 +727,17 @@ void MBasicBlock::discardAllResumePoints
     MOZ_ASSERT(iter == resumePointsEnd());
   }
 #endif
 }
 
 void MBasicBlock::clear() {
   discardAllInstructions();
   discardAllResumePoints();
-
-  // Note: phis are disconnected from the rest of the graph, but are not
-  // removed entirely. If the block being removed is a loop header then
-  // IonBuilder may need to access these phis to more quickly converge on the
-  // possible types in the graph. See IonBuilder::analyzeNewLoopTypes.
-  discardAllPhiOperands();
+  discardAllPhis();
 }
 
 void MBasicBlock::insertBefore(MInstruction* at, MInstruction* ins) {
   MOZ_ASSERT(at->block() == this);
   ins->setBlock(this);
   graph().allocDefinitionId(ins);
   instructions_.insertBefore(at, ins);
   ins->setTrackedSite(at->trackedSite());
@@ -1352,104 +1248,16 @@ MTest* MBasicBlock::immediateDominatorBr
 
     *pdirection = (test->ifTrue() == this) ? TRUE_BRANCH : FALSE_BRANCH;
     return test;
   }
 
   return nullptr;
 }
 
-MBasicBlock::BackupPoint::BackupPoint(MBasicBlock* current)
-    : current_(current),
-      lastIns_(current->hasAnyIns() ? *current->rbegin() : nullptr),
-      stackPosition_(current->stackDepth()),
-      slots_()
-#ifdef DEBUG
-      ,
-      lastPhi_(!current->phisEmpty() ? *current->phis_.rbegin() : nullptr),
-      predecessorsCheckSum_(computePredecessorsCheckSum(current)),
-      instructionsCheckSum_(computeInstructionsCheckSum(current)),
-      id_(current->id()),
-      callerResumePoint_(current->callerResumePoint()),
-      entryResumePoint_(current->entryResumePoint())
-#endif
-{
-  // The block is not yet jumping into a block of an inlined function yet.
-  MOZ_ASSERT(current->outerResumePoint_ == nullptr);
-}
-
-bool MBasicBlock::BackupPoint::init(TempAllocator& alloc) {
-  if (!slots_.init(alloc, stackPosition_)) {
-    return false;
-  }
-  for (size_t i = 0, e = stackPosition_; i < e; ++i) {
-    slots_[i] = current_->slots_[i];
-  }
-  return true;
-}
-
-#ifdef DEBUG
-uintptr_t MBasicBlock::BackupPoint::computePredecessorsCheckSum(
-    MBasicBlock* block) {
-  uintptr_t hash = 0;
-  for (size_t i = 0; i < block->numPredecessors(); i++) {
-    MBasicBlock* pred = block->getPredecessor(i);
-    uintptr_t data = reinterpret_cast<uintptr_t>(pred);
-    hash = data + (hash << 6) + (hash << 16) - hash;
-  }
-  return hash;
-}
-
-HashNumber MBasicBlock::BackupPoint::computeInstructionsCheckSum(
-    MBasicBlock* block) {
-  HashNumber h = 0;
-  MOZ_ASSERT_IF(lastIns_, lastIns_->block() == block);
-  for (MInstructionIterator ins = block->begin(); ins != block->end(); ++ins) {
-    h += ins->valueHash();
-    h += h << 10;
-    h ^= h >> 6;
-  }
-  return h;
-}
-#endif
-
-MBasicBlock* MBasicBlock::BackupPoint::restore() {
-  // No extra Phi got added.
-  MOZ_ASSERT((!current_->phisEmpty() ? *current_->phis_.rbegin() : nullptr) ==
-             lastPhi_);
-
-  MOZ_ASSERT_IF(lastIns_, lastIns_->block() == current_);
-  MOZ_ASSERT_IF(lastIns_, !lastIns_->isDiscarded());
-
-  if (!current_->graph().removeSuccessorBlocks(current_)) {
-    return nullptr;
-  }
-
-  MInstructionIterator lastIns(lastIns_ ? ++(current_->begin(lastIns_))
-                                        : current_->begin());
-  current_->discardAllInstructionsStartingAt(lastIns);
-  current_->clearOuterResumePoint();
-
-  MOZ_ASSERT(current_->slots_.length() >= stackPosition_);
-  if (current_->stackPosition_ != stackPosition_) {
-    current_->setStackDepth(stackPosition_);
-  }
-  for (size_t i = 0, e = stackPosition_; i < e; ++i) {
-    current_->slots_[i] = slots_[i];
-  }
-
-  MOZ_ASSERT(current_->id() == id_);
-  MOZ_ASSERT(predecessorsCheckSum_ == computePredecessorsCheckSum(current_));
-  MOZ_ASSERT(instructionsCheckSum_ == computeInstructionsCheckSum(current_));
-  MOZ_ASSERT(current_->callerResumePoint() == callerResumePoint_);
-  MOZ_ASSERT(current_->entryResumePoint() == entryResumePoint_);
-
-  return current_;
-}
-
 void MBasicBlock::dumpStack(GenericPrinter& out) {
 #ifdef DEBUG
   out.printf(" %-3s %-16s %-6s %-10s\n", "#", "name", "copyOf", "first/next");
   out.printf("-------------------------------------------\n");
   for (uint32_t i = 0; i < stackPosition_; i++) {
     out.printf(" %-3u", i);
     out.printf(" %-16p\n", (void*)slots_[i]);
   }
--- a/js/src/jit/MIRGraph.h
+++ b/js/src/jit/MIRGraph.h
@@ -319,17 +319,16 @@ class MBasicBlock : public TempObject, p
                               IgnoreTop ignore = IgnoreNone);
 
   // Removes an instruction with the intention to discard it.
   void discard(MInstruction* ins);
   void discardLastIns();
   void discardDef(MDefinition* def);
   void discardAllInstructions();
   void discardAllInstructionsStartingAt(MInstructionIterator iter);
-  void discardAllPhiOperands();
   void discardAllPhis();
   void discardAllResumePoints(bool discardEntry = true);
   void clear();
 
   // Same as |void discard(MInstruction* ins)| but assuming that
   // all operands are already discarded.
   void discardIgnoreOperands(MInstruction* ins);
 
@@ -605,45 +604,16 @@ class MBasicBlock : public TempObject, p
   BytecodeSite* trackedSite() const { return trackedSite_; }
   jsbytecode* trackedPc() const {
     return trackedSite_ ? trackedSite_->pc() : nullptr;
   }
   InlineScriptTree* trackedTree() const {
     return trackedSite_ ? trackedSite_->tree() : nullptr;
   }
 
-  // This class is used for reverting the graph within IonBuilder.
-  class BackupPoint {
-    friend MBasicBlock;
-
-    MBasicBlock* current_;
-    MInstruction* lastIns_;
-    uint32_t stackPosition_;
-    FixedList<MDefinition*> slots_;
-#ifdef DEBUG
-    // The following fields should remain identical during IonBuilder
-    // construction, these are used for assertions.
-    MPhi* lastPhi_;
-    uintptr_t predecessorsCheckSum_;
-    HashNumber instructionsCheckSum_;
-    uint32_t id_;
-    MResumePoint* callerResumePoint_;
-    MResumePoint* entryResumePoint_;
-
-    size_t computePredecessorsCheckSum(MBasicBlock* block);
-    HashNumber computeInstructionsCheckSum(MBasicBlock* block);
-#endif
-   public:
-    explicit BackupPoint(MBasicBlock* current);
-    [[nodiscard]] bool init(TempAllocator& alloc);
-    MBasicBlock* restore();
-  };
-
-  friend BackupPoint;
-
  private:
   MIRGraph& graph_;
   const CompileInfo& info_;  // Each block originates from a particular script.
   InlineList<MInstruction> instructions_;
   Vector<MBasicBlock*, 1, JitAllocPolicy> predecessors_;
   InlineList<MPhi> phis_;
   FixedList<MDefinition*> slots_;
   uint32_t stackPosition_;
@@ -761,19 +731,17 @@ class MIRGraph {
   PostorderIterator poBegin() { return blocks_.rbegin(); }
   PostorderIterator poBegin(MBasicBlock* at) { return blocks_.rbegin(at); }
   PostorderIterator poEnd() { return blocks_.rend(); }
   ReversePostorderIterator rpoBegin() { return blocks_.begin(); }
   ReversePostorderIterator rpoBegin(MBasicBlock* at) {
     return blocks_.begin(at);
   }
   ReversePostorderIterator rpoEnd() { return blocks_.end(); }
-  [[nodiscard]] bool removeSuccessorBlocks(MBasicBlock* block);
   void removeBlock(MBasicBlock* block);
-  void removeBlockIncludingPhis(MBasicBlock* block);
   void moveBlockToEnd(MBasicBlock* block) {
     blocks_.remove(block);
     MOZ_ASSERT_IF(!blocks_.empty(), block->id());
     blocks_.pushBack(block);
   }
   void moveBlockBefore(MBasicBlock* at, MBasicBlock* block) {
     MOZ_ASSERT(block->id());
     blocks_.remove(block);
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -1033,17 +1033,17 @@ bool StoreUnboxedScalarPolicy::adjustVal
     case Scalar::Int32:
     case Scalar::Uint32:
       if (value->type() != MIRType::Int32) {
         value = MTruncateToInt32::New(alloc, value);
         ins->block()->insertBefore(ins, value->toInstruction());
       }
       break;
     case Scalar::Uint8Clamped:
-      // IonBuilder should have inserted ClampToUint8.
+      // The transpiler should have inserted MClampToUint8.
       MOZ_ASSERT(value->type() == MIRType::Int32);
       break;
     case Scalar::Float32:
       if (value->type() != MIRType::Float32) {
         value = MToFloat32::New(alloc, value);
         ins->block()->insertBefore(ins, value->toInstruction());
       }
       break;
--- a/js/src/jit/WarpCacheIRTranspiler.cpp
+++ b/js/src/jit/WarpCacheIRTranspiler.cpp
@@ -1601,18 +1601,17 @@ bool WarpCacheIRTranspiler::emitLoadArra
 
   auto* length = MArrayBufferByteLengthInt32::New(alloc(), obj);
   add(length);
 
   pushResult(length);
   return true;
 }
 
-bool WarpCacheIRTranspiler::emitLoadTypedArrayLengthResult(
-    ObjOperandId objId, uint32_t getterOffset) {
+bool WarpCacheIRTranspiler::emitLoadTypedArrayLengthResult(ObjOperandId objId) {
   MDefinition* obj = getOperand(objId);
 
   auto* length = MArrayBufferViewLength::New(alloc(), obj);
   add(length);
 
   pushResult(length);
   return true;
 }
--- a/js/src/jit/WarpSnapshot.h
+++ b/js/src/jit/WarpSnapshot.h
@@ -533,19 +533,17 @@ class WarpScriptSnapshot
   void trace(JSTracer* trc);
 
 #ifdef JS_JITSPEW
   void dump(GenericPrinter& out) const;
 #endif
 };
 
 // Captures information from previous bailouts to prevent bailout/recompile
-// loops. This mostly exists for compatibility with IonBuilder and the MIR
-// backend.
-// TODO: overhaul bailout tracking once IonBuilder is gone.
+// loops.
 class WarpBailoutInfo {
   // True if any script in the compilation has the failedBoundsCheck flag. In
   // this case mark bounds checks as non-movable to prevent hoisting them in
   // TryEliminateBoundsCheck.
   bool failedBoundsCheck_ = false;
 
   // True if any script in the compilation has the failedLexicalCheck flag. In
   // this case mark lexical checks as non-movable.
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5232,32 +5232,32 @@ JS_PUBLIC_API void JS_SetGlobalJitCompil
         jit::JitOptions.enableGvn(true);
         JitSpew(js::jit::JitSpew_IonScripts, "Enable ion's GVN");
       }
       break;
     case JSJITCOMPILER_ION_FORCE_IC:
       if (value == 0) {
         jit::JitOptions.forceInlineCaches = false;
         JitSpew(js::jit::JitSpew_IonScripts,
-                "IonBuilder: Enable non-IC optimizations.");
+                "Ion: Enable non-IC optimizations.");
       } else {
         jit::JitOptions.forceInlineCaches = true;
         JitSpew(js::jit::JitSpew_IonScripts,
-                "IonBuilder: Disable non-IC optimizations.");
+                "Ion: Disable non-IC optimizations.");
       }
       break;
     case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
       if (value == 0) {
         jit::JitOptions.checkRangeAnalysis = false;
         JitSpew(js::jit::JitSpew_IonScripts,
-                "IonBuilder: Enable range analysis checks.");
+                "Ion: Enable range analysis checks.");
       } else {
         jit::JitOptions.checkRangeAnalysis = true;
         JitSpew(js::jit::JitSpew_IonScripts,
-                "IonBuilder: Disable range analysis checks.");
+                "Ion: Disable range analysis checks.");
       }
       break;
     case JSJITCOMPILER_ION_ENABLE:
       if (value == 1) {
         jit::JitOptions.ion = true;
         JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
       } else if (value == 0) {
         jit::JitOptions.ion = false;
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -391,19 +391,19 @@ void JSRuntime::addSizeOfIncludingThis(m
         scriptDataTable(lock).shallowSizeOfExcludingThis(mallocSizeOf);
     for (SharedImmutableScriptDataTable::Range r = scriptDataTable(lock).all();
          !r.empty(); r.popFront()) {
       rtSizes->scriptData += r.front()->sizeOfIncludingThis(mallocSizeOf);
     }
   }
 
   if (jitRuntime_) {
-    // Sizes of the IonBuilders we are holding for lazy linking
-    for (auto builder : jitRuntime_->ionLazyLinkList(this)) {
-      rtSizes->jitLazyLink += builder->sizeOfExcludingThis(mallocSizeOf);
+    // Sizes of the IonCompileTasks we are holding for lazy linking
+    for (auto* task : jitRuntime_->ionLazyLinkList(this)) {
+      rtSizes->jitLazyLink += task->sizeOfExcludingThis(mallocSizeOf);
     }
   }
 
   rtSizes->wasmRuntime +=
       wasmInstances.lock()->sizeOfExcludingThis(mallocSizeOf);
 }
 
 static bool HandleInterrupt(JSContext* cx, bool invokeCallback) {
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -217,17 +217,16 @@ void TraceLoggerThreadState::enableIonLo
   enabledTextIds[TraceLogger_ReorderInstructions] = true;
   enabledTextIds[TraceLogger_EdgeCaseAnalysis] = true;
   enabledTextIds[TraceLogger_EliminateRedundantChecks] = true;
   enabledTextIds[TraceLogger_AddKeepAliveInstructions] = true;
   enabledTextIds[TraceLogger_GenerateLIR] = true;
   enabledTextIds[TraceLogger_RegisterAllocation] = true;
   enabledTextIds[TraceLogger_GenerateCode] = true;
   enabledTextIds[TraceLogger_Scripts] = true;
-  enabledTextIds[TraceLogger_IonBuilderRestartLoop] = true;
 }
 
 void TraceLoggerThreadState::enableFrontendLogging() {
   enabledTextIds[TraceLogger_Frontend] = true;
   enabledTextIds[TraceLogger_ParsingFull] = true;
   enabledTextIds[TraceLogger_ParsingSyntax] = true;
   enabledTextIds[TraceLogger_BytecodeEmission] = true;
   enabledTextIds[TraceLogger_BytecodeFoldConstants] = true;
@@ -1150,17 +1149,17 @@ bool TraceLoggerThreadState::init() {
           "RangeAnalysis,\n"
           "                 LoopUnrolling, FoldLinearArithConstants, "
           "EffectiveAddressAnalysis,\n"
           "                 AlignmentMaskAnalysis, EliminateDeadCode, "
           "ReorderInstructions,\n"
           "                 EdgeCaseAnalysis, EliminateRedundantChecks,\n"
           "                 AddKeepAliveInstructions, GenerateLIR, "
           "RegisterAllocation,\n"
-          "                 GenerateCode, Scripts, IonBuilderRestartLoop\n"
+          "                 GenerateCode, Scripts\n"
           "\n"
           "  VMSpecific     Output the specific name of the VM call\n"
           "\n"
           "  Frontend       Output all information about frontend compilation. "
           "It includes:\n"
           "                 Frontend, ParsingFull, ParsingSyntax, Tokenizing,\n"
           "                 BytecodeEmission, BytecodeFoldConstants, "
           "BytecodeNameFunctions\n"
--- a/js/src/vm/TraceLoggingTypes.h
+++ b/js/src/vm/TraceLoggingTypes.h
@@ -81,17 +81,16 @@ class JSLinearString;
   _(EliminateDeadCode)                         \
   _(ReorderInstructions)                       \
   _(EdgeCaseAnalysis)                          \
   _(EliminateRedundantChecks)                  \
   _(AddKeepAliveInstructions)                  \
   _(GenerateLIR)                               \
   _(RegisterAllocation)                        \
   _(GenerateCode)                              \
-  _(IonBuilderRestartLoop)                     \
   _(VMSpecific)
 
 // Log items, with timestamp only.
 #define TRACELOGGER_LOG_ITEMS(_) \
   _(Bailout)                     \
   _(Invalidation)                \
   _(Disable)                     \
   _(Enable)                      \
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -454,17 +454,17 @@ class nsFlexContainerFrame::FlexItem fin
   // Indicates whether this item received a preliminary "measuring" reflow
   // before its actual reflow.
   bool HadMeasuringReflow() const { return mHadMeasuringReflow; }
 
   // Indicates whether this item's computed cross-size property is 'auto'.
   bool IsCrossSizeAuto() const;
 
   // Indicates whether the cross-size property is set to something definite,
-  // for the purpose of intrinsic aspect ratio calculations.
+  // for the purpose of preferred aspect ratio calculations.
   bool IsCrossSizeDefinite(const ReflowInput& aItemReflowInput) const;
 
   // Indicates whether this item's cross-size has been stretched (from having
   // "align-self: stretch" with an auto cross-size and no auto margins in the
   // cross axis).
   bool IsStretched() const { return mIsStretched; }
 
   // Indicates whether we need to resolve an 'auto' value for the main-axis
@@ -536,18 +536,18 @@ class nsFlexContainerFrame::FlexItem fin
       // avoid performing mFlexShrink * mFlexBaseSize = inf * 0 = undefined.)
       return 0.0f;
     }
     return mFlexShrink * mFlexBaseSize;
   }
 
   bool TreatBSizeAsIndefinite() const { return mTreatBSizeAsIndefinite; }
 
-  const AspectRatio& IntrinsicRatio() const { return mIntrinsicRatio; }
-  bool HasIntrinsicRatio() const { return !!mIntrinsicRatio; }
+  const AspectRatio& GetAspectRatio() const { return mAspectRatio; }
+  bool HasAspectRatio() const { return !!mAspectRatio; }
 
   // Getters for margin:
   // ===================
   LogicalMargin Margin() const { return mMargin; }
   nsMargin PhysicalMargin() const { return mMargin.GetPhysicalMargin(mCBWM); }
 
   // Returns the margin component for a given LogicalSide in flex container's
   // writing-mode.
@@ -736,33 +736,37 @@ class nsFlexContainerFrame::FlexItem fin
   void SetMarginComponentForSide(LogicalSide aSide, nscoord aLength) {
     MOZ_ASSERT(mIsFrozen, "main size should be resolved before this");
     mMargin.Side(aSide, mCBWM) = aLength;
   }
 
   void ResolveStretchedCrossSize(nscoord aLineCrossSize);
 
   // Resolves flex base size if flex-basis' used value is 'content', using this
-  // item's intrinsic ratio and cross size.
-  void ResolveFlexBaseSizeFromAspectRatio(
-      const ReflowInput& aItemReflowInput,
-      const FlexboxAxisTracker& aAxisTracker);
+  // item's preferred aspect ratio and cross size.
+  void ResolveFlexBaseSizeFromAspectRatio(const ReflowInput& aItemReflowInput);
 
   uint32_t NumAutoMarginsInMainAxis() const {
     return NumAutoMarginsInAxis(MainAxis());
   };
 
   uint32_t NumAutoMarginsInCrossAxis() const {
     return NumAutoMarginsInAxis(CrossAxis());
   };
 
   // Once the main size has been resolved, should we bother doing layout to
   // establish the cross size?
   bool CanMainSizeInfluenceCrossSize() const;
 
+  // Returns a main size, clamped by any definite min and max cross size
+  // converted through the preferred aspect ratio. The caller is responsible for
+  // ensuring that the flex item's preferred aspect ratio is not zero.
+  nscoord ClampMainSizeViaCrossAxisConstraints(
+      nscoord aMainSize, const ReflowInput& aItemReflowInput) const;
+
   // Indicates whether we think this flex item needs a "final" reflow
   // (after its final flexed size & final position have been determined).
   //
   // @param aAvailableBSizeForItem the available block-size for this item (in
   //                               flex container's writing-mode)
   // @return true if such a reflow is needed, or false if we believe it can
   // simply be moved to its final position and skip the reflow.
   bool NeedsFinalReflow(const nscoord aAvailableBSizeForItem) const;
@@ -778,17 +782,17 @@ class nsFlexContainerFrame::FlexItem fin
 
   uint32_t NumAutoMarginsInAxis(LogicalAxis aAxis) const;
 
   // Values that we already know in constructor, and remain unchanged:
   // The flex item's frame.
   nsIFrame* mFrame = nullptr;
   float mFlexGrow = 0.0f;
   float mFlexShrink = 0.0f;
-  AspectRatio mIntrinsicRatio;
+  AspectRatio mAspectRatio;
 
   // The flex item's writing mode.
   WritingMode mWM;
 
   // The flex container's writing mode.
   WritingMode mCBWM;
 
   // The flex container's main axis in flex container's writing mode.
@@ -1384,19 +1388,19 @@ FlexItem* nsFlexContainerFrame::Generate
 
   // Construct the flex item!
   FlexItem* item = aLine.Items().EmplaceBack(
       childRI, flexGrow, flexShrink, flexBaseSize, mainMinSize, mainMaxSize,
       tentativeCrossSize, crossMinSize, crossMaxSize, aAxisTracker);
 
   // We may be about to do computations based on our item's cross-size
   // (e.g. using it as a constraint when measuring our content in the
-  // main axis, or using it with the intrinsic ratio to obtain a main size).
-  // BEFORE WE DO THAT, we need let the item "pre-stretch" its cross size (if
-  // it's got 'align-self:stretch'), for a certain case where the spec says
+  // main axis, or using it with the preferred aspect ratio to obtain a main
+  // size). BEFORE WE DO THAT, we need let the item "pre-stretch" its cross size
+  // (if it's got 'align-self:stretch'), for a certain case where the spec says
   // the stretched cross size is considered "definite". That case is if we
   // have a single-line (nowrap) flex container which itself has a definite
   // cross-size.  Otherwise, we'll wait to do stretching, since (in other
   // cases) we don't know how much the item should stretch yet.
   const bool isSingleLine =
       StyleFlexWrap::Nowrap == aParentReflowInput.mStylePosition->mFlexWrap;
   if (isSingleLine) {
     // XXXdholbert Maybe this should share logic with ComputeCrossSize()...
@@ -1416,17 +1420,17 @@ FlexItem* nsFlexContainerFrame::Generate
       item->ResolveStretchedCrossSize(containerCrossSize);
     }
   }
 
   // Before thinking about freezing the item at its base size, we need to give
   // it a chance to recalculate the base size from its cross size and aspect
   // ratio (since its cross size might've *just* now become definite due to
   // 'stretch' above)
-  item->ResolveFlexBaseSizeFromAspectRatio(childRI, aAxisTracker);
+  item->ResolveFlexBaseSizeFromAspectRatio(childRI);
 
   // If we're inflexible, we can just freeze to our hypothetical main-size
   // up-front. Similarly, if we're a fixed-size widget, we only have one
   // valid size, so we freeze to keep ourselves from flexing.
   if (isFixedSizeWidget || (flexGrow == 0.0f && flexShrink == 0.0f)) {
     item->Freeze();
     if (flexBaseSize < mainMinSize) {
       item->SetWasMinClamped();
@@ -1439,57 +1443,19 @@ FlexItem* nsFlexContainerFrame::Generate
   // require us to reflow the item to measure content height)
   ResolveAutoFlexBasisAndMinSize(*item, childRI, aAxisTracker,
                                  aHasLineClampEllipsis);
   return item;
 }
 
 // Static helper-functions for ResolveAutoFlexBasisAndMinSize():
 // -------------------------------------------------------------
-// Convenience function; returns a main-size, given a cross-size and an
-// intrinsic ratio. The caller is responsible for ensuring that the passed-in
-// intrinsic ratio is not zero.
-static nscoord MainSizeFromAspectRatio(nscoord aCrossSize,
-                                       const AspectRatio& aIntrinsicRatio,
-                                       const FlexboxAxisTracker& aAxisTracker) {
-  MOZ_ASSERT(aIntrinsicRatio,
-             "Invalid ratio; will divide by 0! Caller should've checked...");
-  AspectRatio ratio = aAxisTracker.IsMainAxisHorizontal()
-                          ? aIntrinsicRatio
-                          : aIntrinsicRatio.Inverted();
-
-  return ratio.ApplyTo(aCrossSize);
-}
-
-// Returns a main size, clamped by any definite min and max cross size converted
-// through the intrinsic ratio. The caller is responsible for ensuring that the
-// passed-in intrinsic ratio is not zero.
-static nscoord ClampMainSizeViaCrossAxisConstraints(
-    nscoord aMainSize, const FlexItem& aFlexItem,
-    const FlexboxAxisTracker& aAxisTracker) {
-  MOZ_ASSERT(aFlexItem.HasIntrinsicRatio(),
-             "Caller should've checked the ratio is valid!");
-
-  const auto& aspectRatio = aFlexItem.IntrinsicRatio();
-  const nscoord mainMinSizeFromRatio = MainSizeFromAspectRatio(
-      aFlexItem.CrossMinSize(), aspectRatio, aAxisTracker);
-  nscoord clampedMainSize = std::max(aMainSize, mainMinSizeFromRatio);
-
-  if (aFlexItem.CrossMaxSize() != NS_UNCONSTRAINEDSIZE) {
-    const nscoord mainMaxSizeFromRatio = MainSizeFromAspectRatio(
-        aFlexItem.CrossMaxSize(), aspectRatio, aAxisTracker);
-    clampedMainSize = std::min(clampedMainSize, mainMaxSizeFromRatio);
-  }
-
-  return clampedMainSize;
-}
-
 // Partially resolves "min-[width|height]:auto" and returns the resulting value.
 // By "partially", I mean we don't consider the min-content size (but we do
-// consider the main-size and main max-size properties, and the intrinsic aspect
+// consider the main-size and main max-size properties, and the preferred aspect
 // ratio). The caller is responsible for computing & considering the min-content
 // size in combination with the partially-resolved value that this function
 // returns.
 //
 // Basically, this function gets the specified size suggestion; if not, the
 // transferred size suggestion; if both sizes do not exist, return nscoord_MAX.
 //
 // Spec reference: https://drafts.csswg.org/css-flexbox-1/#min-size-auto
@@ -1550,26 +1516,26 @@ static nscoord PartiallyResolveAutoMinSi
     // to consider transferred size suggestion.
     FLEX_LOGV(" Specified size suggestion: %d", specifiedSizeSuggestion);
     return specifiedSizeSuggestion;
   }
 
   // Compute the transferred size suggestion, which is the cross size converted
   // through the aspect ratio (if the item has an aspect ratio and a definite
   // cross size).
-  if (aFlexItem.HasIntrinsicRatio() &&
-      aFlexItem.IsCrossSizeDefinite(aItemReflowInput)) {
+  if (const auto& aspectRatio = aFlexItem.GetAspectRatio();
+      aspectRatio && aFlexItem.IsCrossSizeDefinite(aItemReflowInput)) {
     // We have a usable aspect ratio. (not going to divide by 0)
-    nscoord transferredSizeSuggestion = MainSizeFromAspectRatio(
-        aFlexItem.CrossSize(), aFlexItem.IntrinsicRatio(), aAxisTracker);
+    nscoord transferredSizeSuggestion = aspectRatio.ComputeRatioDependentSize(
+        aFlexItem.MainAxis(), cbWM, aFlexItem.CrossSize(), boxSizingAdjust);
 
     // Clamp the transferred size suggestion by any definite min and max
     // cross size converted through the aspect ratio.
-    transferredSizeSuggestion = ClampMainSizeViaCrossAxisConstraints(
-        transferredSizeSuggestion, aFlexItem, aAxisTracker);
+    transferredSizeSuggestion = aFlexItem.ClampMainSizeViaCrossAxisConstraints(
+        transferredSizeSuggestion, aItemReflowInput);
 
     FLEX_LOGV(" Transferred size suggestion: %d", transferredSizeSuggestion);
     return transferredSizeSuggestion;
   }
 
   return nscoord_MAX;
 }
 
@@ -1668,19 +1634,19 @@ void nsFlexContainerFrame::ResolveAutoFl
       if (flexBasisNeedsToMeasureContent) {
         aFlexItem.SetFlexBaseSizeAndMainSize(contentBSize);
       }
     }
 
     if (minSizeNeedsToMeasureContent) {
       // Clamp the content size suggestion by any definite min and max cross
       // size converted through the aspect ratio.
-      if (aFlexItem.IntrinsicRatio()) {
-        contentSizeSuggestion = ClampMainSizeViaCrossAxisConstraints(
-            contentSizeSuggestion, aFlexItem, aAxisTracker);
+      if (aFlexItem.HasAspectRatio()) {
+        contentSizeSuggestion = aFlexItem.ClampMainSizeViaCrossAxisConstraints(
+            contentSizeSuggestion, aItemReflowInput);
       }
 
       FLEX_LOGV(" Content size suggestion: %d", contentSizeSuggestion);
       resolvedMinSize = std::min(resolvedMinSize, contentSizeSuggestion);
 
       // Clamp the resolved min main size by the max main size if it's definite.
       if (aFlexItem.MainMaxSize() != NS_UNCONSTRAINEDSIZE) {
         resolvedMinSize = std::min(resolvedMinSize, aFlexItem.MainMaxSize());
@@ -2002,17 +1968,17 @@ FlexItem::FlexItem(ReflowInput& aFlexIte
                    float aFlexShrink, nscoord aFlexBaseSize,
                    nscoord aMainMinSize, nscoord aMainMaxSize,
                    nscoord aTentativeCrossSize, nscoord aCrossMinSize,
                    nscoord aCrossMaxSize,
                    const FlexboxAxisTracker& aAxisTracker)
     : mFrame(aFlexItemReflowInput.mFrame),
       mFlexGrow(aFlexGrow),
       mFlexShrink(aFlexShrink),
-      mIntrinsicRatio(mFrame->GetAspectRatio()),
+      mAspectRatio(mFrame->GetAspectRatio()),
       mWM(aFlexItemReflowInput.GetWritingMode()),
       mCBWM(aAxisTracker.GetWritingMode()),
       mMainAxis(aAxisTracker.MainAxis()),
       mBorderPadding(aFlexItemReflowInput.ComputedLogicalBorderPadding(mCBWM)),
       mMargin(aFlexItemReflowInput.ComputedLogicalMargin(mCBWM)),
       mMainMinSize(aMainMinSize),
       mMainMaxSize(aMainMaxSize),
       mCrossMinSize(aCrossMinSize),
@@ -2069,17 +2035,17 @@ FlexItem::FlexItem(ReflowInput& aFlexIte
   if (mIsInlineAxisMainAxis) {
     // The item's block-axis is the flex container's cross axis. We don't need
     // any special handling to treat cross sizes as indefinite, because the
     // cases where we stomp on the cross size with a definite value are all...
     // - situations where the spec requires us to treat the cross size as
     // definite; specifically, `align-self:stretch` whose cross size is
     // definite.
     // - situations where definiteness doesn't matter (e.g. for an element with
-    // an intrinsic aspect ratio, which for now are all leaf nodes and hence
+    // an aspect ratio, which for now are all leaf nodes and hence
     // can't have any percent-height descendants that would care about the
     // definiteness of its size. (Once bug 1528375 is fixed, we might need to
     // be more careful about definite vs. indefinite sizing on flex items with
     // aspect ratios.)
     mTreatBSizeAsIndefinite = false;
   } else {
     // The item's block-axis is the flex container's main axis. So, the flex
     // item's main size is its BSize, and is considered definite under certain
@@ -2242,33 +2208,36 @@ bool FlexItem::IsCrossSizeDefinite(const
     return !pos->ISize(itemWM).IsAuto();
   }
 
   nscoord cbBSize = aItemReflowInput.mContainingBlockSize.BSize(itemWM);
   return !nsLayoutUtils::IsAutoBSize(pos->BSize(itemWM), cbBSize);
 }
 
 void FlexItem::ResolveFlexBaseSizeFromAspectRatio(
-    const ReflowInput& aItemReflowInput,
-    const FlexboxAxisTracker& aAxisTracker) {
+    const ReflowInput& aItemReflowInput) {
   // This implements the Flex Layout Algorithm Step 3B:
   // https://drafts.csswg.org/css-flexbox-1/#algo-main-item
   // If the flex item has ...
-  //  - an intrinsic aspect ratio,
+  //  - an aspect ratio,
   //  - a [used] flex-basis of 'content', and
   //  - a definite cross size
   // then the flex base size is calculated from its inner cross size and the
-  // flex item's intrinsic aspect ratio.
-  if (HasIntrinsicRatio() &&
+  // flex item's preferred aspect ratio.
+  if (HasAspectRatio() &&
       nsFlexContainerFrame::IsUsedFlexBasisContent(
           aItemReflowInput.mStylePosition->mFlexBasis,
           aItemReflowInput.mStylePosition->Size(MainAxis(), mCBWM)) &&
       IsCrossSizeDefinite(aItemReflowInput)) {
-    const nscoord mainSizeFromRatio =
-        MainSizeFromAspectRatio(CrossSize(), IntrinsicRatio(), aAxisTracker);
+    const LogicalSize contentBoxSizeToBoxSizingAdjust =
+        aItemReflowInput.mStylePosition->mBoxSizing == StyleBoxSizing::Border
+            ? BorderPadding().Size(mCBWM)
+            : LogicalSize(mCBWM);
+    const nscoord mainSizeFromRatio = mAspectRatio.ComputeRatioDependentSize(
+        MainAxis(), mCBWM, CrossSize(), contentBoxSizeToBoxSizingAdjust);
     SetFlexBaseSizeAndMainSize(mainSizeFromRatio);
   }
 }
 
 uint32_t FlexItem::NumAutoMarginsInAxis(LogicalAxis aAxis) const {
   uint32_t numAutoMargins = 0;
   const auto& styleMargin = mFrame->StyleMargin()->mMargin;
   for (const auto edge : {eLogicalEdgeStart, eLogicalEdgeEnd}) {
@@ -2294,18 +2263,18 @@ bool FlexItem::CanMainSizeInfluenceCross
   }
 
   if (mIsStrut) {
     // Struts (for visibility:collapse items) have a predetermined size;
     // no need to measure anything.
     return false;
   }
 
-  if (HasIntrinsicRatio()) {
-    // For flex items that have an intrinsic ratio (and maintain it, i.e. are
+  if (HasAspectRatio()) {
+    // For flex items that have an aspect ratio (and maintain it, i.e. are
     // not stretched, which we already checked above): changes to main-size
     // *do* influence the cross size.
     return true;
   }
 
   if (IsInlineAxisCrossAxis()) {
     // If we get here, this function is really asking: "can changes to this
     // item's block size have an influence on its inline size"?  For blocks and
@@ -2329,16 +2298,38 @@ bool FlexItem::CanMainSizeInfluenceCross
     // adds flex lines (i.e. grows in inline axis) depending on its block size.
   }
 
   // Default assumption, if we haven't proven otherwise: the resolved main size
   // *can* change the cross size.
   return true;
 }
 
+nscoord FlexItem::ClampMainSizeViaCrossAxisConstraints(
+    nscoord aMainSize, const ReflowInput& aItemReflowInput) const {
+  MOZ_ASSERT(HasAspectRatio(), "Caller should've checked the ratio is valid!");
+
+  const LogicalSize contentBoxSizeToBoxSizingAdjust =
+      aItemReflowInput.mStylePosition->mBoxSizing == StyleBoxSizing::Border
+          ? BorderPadding().Size(mCBWM)
+          : LogicalSize(mCBWM);
+
+  const nscoord mainMinSizeFromRatio = mAspectRatio.ComputeRatioDependentSize(
+      MainAxis(), mCBWM, CrossMinSize(), contentBoxSizeToBoxSizingAdjust);
+  nscoord clampedMainSize = std::max(aMainSize, mainMinSizeFromRatio);
+
+  if (CrossMaxSize() != NS_UNCONSTRAINEDSIZE) {
+    const nscoord mainMaxSizeFromRatio = mAspectRatio.ComputeRatioDependentSize(
+        MainAxis(), mCBWM, CrossMaxSize(), contentBoxSizeToBoxSizingAdjust);
+    clampedMainSize = std::min(clampedMainSize, mainMaxSizeFromRatio);
+  }
+
+  return clampedMainSize;
+}
+
 /**
  * Returns true if aFrame or any of its children have the
  * NS_FRAME_CONTAINS_RELATIVE_BSIZE flag set -- i.e. if any of these frames (or
  * their descendants) might have a relative-BSize dependency on aFrame (or its
  * ancestors).
  */
 static bool FrameHasRelativeBSizeDependency(nsIFrame* aFrame) {
   if (aFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
@@ -4175,17 +4166,17 @@ nscoord nsFlexContainerFrame::ComputeCro
     NS_WARNING_ASSERTION(
         aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
         "Unconstrained inline size; this should only result from huge sizes "
         "(not intrinsic sizing w/ orthogonal flows)");
     *aIsDefinite = true;
     // FIXME: Bug 1661847 - there are cases where aReflowInput.ComputedISize()
     // might not be the right thing to return here. Specifically: if our cross
     // size is an intrinsic size, and we have flex items that are flexible and
-    // have intrinsic aspect ratios, then we may need to take their post-flexing
+    // have aspect ratios, then we may need to take their post-flexing
     // main sizes into account (multiplied through their aspect ratios to get
     // their cross sizes), in order to determine their flex line's size & the
     // flex container's cross size (e.g. as `aSumLineCrossSizes`).
     return aReflowInput.ComputedISize();
   }
 
   nscoord effectiveComputedBSize =
       GetEffectiveComputedBSize(aReflowInput, aConsumedBSize);
@@ -4608,17 +4599,17 @@ void nsFlexContainerFrame::Reflow(nsPres
 // instead of using this class.)
 class MOZ_RAII AutoFlexItemMainSizeOverride final {
  public:
   explicit AutoFlexItemMainSizeOverride(FlexItem& aItem)
       : mItemFrame(aItem.Frame()) {
     MOZ_ASSERT(!mItemFrame->HasProperty(nsIFrame::FlexItemMainSizeOverride()),
                "FlexItemMainSizeOverride prop shouldn't be set already; "
                "it should only be set temporarily (& not recursively)");
-    NS_ASSERTION(aItem.HasIntrinsicRatio(),
+    NS_ASSERTION(aItem.HasAspectRatio(),
                  "This should only be needed for items with an aspect ratio");
 
     nscoord mainSizeOverrideVal = aItem.MainSize();
     // Note: aItem.MainSize() is the item's *content-box* main-size.  If we
     // have 'box-sizing: border-box', then we have to add our main-axis border
     // and padding in order to produce an appopriate "override" value that
     // gets us the content-box size that we expect.
     if (aItem.Frame()->StylePosition()->mBoxSizing == StyleBoxSizing::Border) {
@@ -4982,17 +4973,17 @@ void nsFlexContainerFrame::DoFlexLayout(
   // at the end of the following for-loop.
   nscoord sumLineCrossSizes = aCrossGapSize * (aLines.Length() - 1);
   for (FlexLine& line : aLines) {
     for (FlexItem& item : line.Items()) {
       // The item may already have the correct cross-size; only recalculate
       // if the item's main size resolution (flexing) could have influenced it:
       if (item.CanMainSizeInfluenceCrossSize()) {
         Maybe<AutoFlexItemMainSizeOverride> sizeOverride;
-        if (item.HasIntrinsicRatio()) {
+        if (item.HasAspectRatio()) {
           // For flex items with an aspect ratio, we have to impose an override
           // for the main-size property *before* we even instantiate the reflow
           // input, in order for aspect ratio calculations to produce the right
           // cross size in the reflow input. (For other flex items, it's OK
           // (and cheaper) to impose our main size *after* the reflow input has
           // been constructed, since the main size shouldn't influence anything
           // about cross-size measurement until we actually reflow the child.)
           sizeOverride.emplace(item);
@@ -5005,16 +4996,17 @@ void nsFlexContainerFrame::DoFlexLayout(
                                      availSize);
         childReflowInput.mFlags.mInsideLineClamp = GetLineClampValue() != 0;
         if (!sizeOverride) {
           // Directly override the computed main-size, by tweaking reflow input:
           if (item.IsInlineAxisMainAxis()) {
             childReflowInput.SetComputedISize(item.MainSize());
           } else {
             childReflowInput.SetComputedBSize(item.MainSize());
+            childReflowInput.mFlags.mBSizeIsSetByAspectRatio = false;
             if (item.TreatBSizeAsIndefinite()) {
               childReflowInput.mFlags.mTreatBSizeAsIndefinite = true;
             }
           }
         }
 
         SizeItemInCrossAxis(childReflowInput, item);
       }
@@ -5443,41 +5435,43 @@ nsReflowStatus nsFlexContainerFrame::Ref
   bool didOverrideComputedBSize = false;
 
   // Override computed main-size
   if (aItem.IsInlineAxisMainAxis()) {
     childReflowInput.SetComputedISize(aItem.MainSize());
     didOverrideComputedISize = true;
   } else {
     childReflowInput.SetComputedBSize(aItem.MainSize());
+    childReflowInput.mFlags.mBSizeIsSetByAspectRatio = false;
     didOverrideComputedBSize = true;
     if (aItem.TreatBSizeAsIndefinite()) {
       childReflowInput.mFlags.mTreatBSizeAsIndefinite = true;
     }
   }
 
   // Override reflow input's computed cross-size if either:
   // - the item was stretched (in which case we're imposing a cross size)
   // ...or...
   // - the item it has an aspect ratio (in which case the cross-size that's
   // currently in the reflow input is based on arithmetic involving a stale
   // main-size value that we just stomped on above). (Note that we could handle
   // this case using an AutoFlexItemMainSizeOverride, as we do elsewhere; but
   // given that we *already know* the correct cross size to use here, it's
   // cheaper to just directly set it instead of setting a frame property.)
-  if (aItem.IsStretched() || aItem.HasIntrinsicRatio()) {
+  if (aItem.IsStretched() || aItem.HasAspectRatio()) {
     if (aItem.IsInlineAxisCrossAxis()) {
       childReflowInput.SetComputedISize(aItem.CrossSize());
       didOverrideComputedISize = true;
     } else {
       // Note that in the above cases we don't need to worry about the BSize
       // needing to be treated as indefinite, because this is for cases where
       // the block size would always be considered definite (or where its
       // definiteness would be irrelevant).
       childReflowInput.SetComputedBSize(aItem.CrossSize());
+      childReflowInput.mFlags.mBSizeIsSetByAspectRatio = false;
       didOverrideComputedBSize = true;
     }
   }
   if (aItem.IsStretched() && aItem.IsBlockAxisCrossAxis()) {
     // This item is stretched (in the cross axis), and that axis is its block
     // axis.  That stretching effectively gives it a relative BSize.
     // XXXdholbert This flag only makes a difference if we use the flex items'
     // frame-state when deciding whether to reflow them -- and we don't, as of
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/feComposite-operator-lighter-ref.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<style>* { margin: 0; padding: 0; }</style>
+<canvas id="canvas" width="200" height="200"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext('2d');
+var width = canvas.width;
+var height = canvas.height;
+
+ctx.globalCompositeOperation = 'lighter';
+ctx.fillStyle = '#f00';
+ctx.fillRect(0,0,width,height);
+
+gradient = ctx.createLinearGradient(0, 0, 0, height);
+gradient.addColorStop(0, "#0f0");
+gradient.addColorStop(1, "#00f");
+ctx.fillStyle = gradient;
+ctx.fillRect(0, 0, width, height);
+</script>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/feComposite-operator-lighter.svg
@@ -0,0 +1,11 @@
+<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
+    <filter id="f" x="0" y="0" width="1" height="1" color-interpolation-filters="sRGB">
+        <feFlood flood-color="red"/>
+        <feComposite operator="lighter" in2="SourceGraphic"/>
+    </filter>
+    <linearGradient id="g2b" x1="0" x2="0" y1="0" y2="1">
+        <stop offset="0" stop-color="#0f0"/>
+        <stop offset="1" stop-color="#00f"/>
+    </linearGradient>
+    <rect width="200" height="200" fill="url(#g2b)" filter="url(#f)"/>
+</svg>
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -91,16 +91,17 @@ fails == filter-marked-line-01.svg pass.
 == filter-region-01b.html pass.svg
 == filter-transform-01.svg pass.svg
 
 == feColorMatrix-saturate-01.svg pass.svg
 
 == feComponentTransfer-03.svg pass.svg
 == feComponentTransfer-04.svg pass.svg
 == feComposite-arguments-01.svg pass.svg
+fuzzy-if(winWidget&&webrender,0-1,0-39600) == feComposite-operator-lighter.svg feComposite-operator-lighter-ref.html
 fuzzy(0-1,0-26732) == feComposite-paint-01.svg feComposite-paint-01-ref.svg
 fuzzy(0-1,0-10000) == feConvolveMatrix-bias-01.svg feConvolveMatrix-bias-01-ref.svg
 == feConvolveMatrix-order-01.svg feConvolveMatrix-order-01-ref.svg
 
 fuzzy-if(skiaContent,0-1,0-400) == feDisplacementMap-alpha-01.svg pass.svg
 fuzzy(0-2,0-500) == feDisplacementMap-colour-01.svg feDisplacementMap-colour-01-ref.svg
 == feDisplacementMap-scale-01.svg pass.svg
 
--- a/mobile/android/moz.build
+++ b/mobile/android/moz.build
@@ -16,17 +16,16 @@ DIRS += [
 ]
 
 DIRS += [
     "actors",
     "base",
     "chrome",
     "components",
     "modules",
-    "themes/core",
     "themes/geckoview",
     "geckoview/src/androidTest/assets",
     "app",
     "fonts",
 ]
 
 TEST_HARNESS_FILES.testing.mochitest.tests.junit += [
     "geckoview/src/androidTest/assets/www/hello.html",
deleted file mode 100644
--- a/mobile/android/themes/core/aboutAccounts.css
+++ /dev/null
@@ -1,91 +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/. */
-
-html, body {
-  height: 100%;
-  width: 100%;
-}
-
-div {
-  transition: opacity 0.4s ease-in;
-}
-
-#spinner {
-  transition: opacity 0.2s ease-in;
-}
-
-#remote {
-  border: 0;
-  opacity: 0;
-  transition: opacity 0.4s ease-in;
-}
-
-.text {
-  color: #363B40;
-  font-size: 25px;
-  font-weight: lighter;
-  margin-bottom: 20px;
-}
-
-.hint {
-  color: #777777;
-  font-size: 20px;
-  margin-bottom: 20px;
-}
-
-a {
-  color: #0096DD; /* link_blue */
-  text-decoration: none;
-  font-size: 20px;
-  margin-bottom: 20px;
-}
-
-a:active {
-  color: #0082C6; /* link_blue_pressed */
-}
-
-.toplevel {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-}
-
-.container {
-  height: 100%;
-  padding-left: 30px;
-  padding-right: 30px;
-}
-
-.text-container {
-  padding-top: 60px;
-  padding-left: 30px;
-  padding-right: 30px;
-}
-
-.flex-column {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  text-align: center;
-}
-
-.button-row {
-  flex: 0;
-  width: 100%;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  text-align: center;
-  justify-content: center;
-}
-
-.button {
-  flex: 1;
-  height: 60px;
-  background-color: #0979D9; /*matched to action_accent in java codebase*/
-  color: #FFFFFF;
-  font-size: 20px;
-  border-radius: 4px;
-  border-width: 0px;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutAddons.css
+++ /dev/null
@@ -1,196 +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/. */
-
-@import "defines.css";
-
-html[details] {
-  background-color: var(--color_about_item);
-}
-
-iframe {
-  padding: 0;
-  margin: 0;
-  border:none;
-}
-
-a {
-  text-decoration: none;
-  color: #0096DD;
-}
-
-a:active {
-  color: #0082C6;
-}
-
-.details {
-  width: 100%;
-}
-
-.details > div {
-  display: inline;
-}
-
-.hidden {
-  display: none;
-}
-
-.version {
-  /* title is not localized, so keep the margin on the left side */
-  margin-left: .67em;
-}
-
-.description {
-  width: 100%;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
-
-.warn-unsigned {
-  border-top: 1px solid var(--color_about_item_border);
-  border-bottom: 1px solid var(--color_about_item_border);
-  margin-top: 1em;
-  margin-bottom: 1em;
-  padding: 1em;
-  padding-inline-start: calc(var(--icon-size) + var(--icon-margin) * 2);
-  background-image: url("chrome://browser/skin/images/grey-caution.svg");
-  background-size: var(--icon-size);
-  background-position: var(--icon-margin);
-  background-repeat: no-repeat;
-  display: none;
-}
-
-.addon-item[isUnsigned="true"] .warn-unsigned {
-  display: block;
-}
-
-.status {
-  border-top: 1px solid var(--color_about_item_border);
-  font-weight: bold;
-  padding: 0.5em;
-  width: 100%;
-}
-
-.addon-item[isDisabled="true"] .options-header,
-.addon-item[optionsURL=""] .options-header,
-.addon-item[isDisabled="true"] .options-box,
-.addon-item[optionsURL=""] .options-box {
-  display: none;
-}
-
-.update-indicator {
-  position: absolute;
-  right: var(--icon-margin);
-  top: var(--icon-margin);
-  width: var(--icon-size);
-  height: var(--icon-size);
-}
-
-.addon-item[hasUpdate="false"] > .update-indicator {
-  display: none;
-}
-
-#addons-details > .list-item {
-  margin-bottom: 42px;
-  border-bottom: none;
-}
-
-#addons-details > .list-item:active {
-  background-color: #fff;
-}
-
-/* Buttons */
-
-.buttons {
-  display: grid;
-  width: 100%;
-  position: fixed;
-  bottom: 0px;
-}
-
-.buttons::after {
-  content: "";
-  border-right: 1px solid var(--color_about_item_border);
-}
-
-.buttons > button {
-  appearance: none;
-  font-size: 1em;
-  border: 1px solid transparent;
-  border-right: none;
-  border-top-color: var(--color_about_item_border);
-  border-inline-start-color: var(--color_about_item_border);
-  background-color: var(--color_about_item);
-  padding: 0.75em 0.5em;
-  border-radius: 0;
-}
-
-button#update-btn {
-  grid-row: 1;
-  grid-column: span 2;
-}
-
-button:not(#update-btn) {
-  grid-row: 2;
-}
-
-.buttons > button:active {
-  background-color: #eeeeee;
-}
-
-.buttons > button[disabled="true"] {
-  color: #b5b5b5;
-}
-
-.buttons > button[hidden="true"] {
-  display: none;
-}
-
-.buttons:first-child {
-  border-inline-start-color: transparent;
-}
-
-.hide-on-enable,
-.show-on-error,
-.show-on-uninstall,
-.show-on-install,
-.show-on-restart,
-div[isDisabled="true"] .hide-on-disable {
-  display: none;
-}
-
-div[error] .show-on-error,
-div[opType="needs-restart"] .show-on-restart,
-div[opType="needs-uninstall"] .show-on-uninstall,
-div[opType="needs-install"] .show-on-install,
-div[opType="needs-enable"] .show-on-enable,
-div[opType="needs-disable"] .show-on-disable,
-div[isDisabled="true"] .show-on-disable {
-  display: -moz-box;
-}
-
-div[opType="needs-restart"] .hide-on-restart,
-div[opType="needs-uninstall"] .hide-on-uninstall,
-div[isDisabled="true"][opType="needs-uninstall"],
-div[opType="needs-install"] .hide-on-install,
-div[opType="needs-enable"] .hide-on-enable,
-div[opType="needs-disable"] .hide-on-disable {
-  display: none;
-}
-
-#browse-title:dir(rtl) {
-  background-position: left;
-  background-image: url("chrome://browser/skin/images/chevron-rtl.png");
-}
-
-/* open_in_tab options button style */
-
-button#open-addon-options {
-  font-size: 1em;
-  border: 1px solid var(--color_about_item_border);
-  background-color: var(--color_about_item);
-  width: 100%;
-  padding: 0.75em 0.5em;
-  border-radius: 0;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutBase.css
+++ /dev/null
@@ -1,113 +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/. */
-
-@import "defines.css";
-
-html {
-  font-family: sans-serif;
-  font-size: 14px;
-  background-color: var(--color_about_background);
-  -moz-text-size-adjust: none;
-  user-select: none;
-  --icon-size: 1.8em;
-  --icon-margin: 1.35em;
-}
-
-body {
-  margin: 0;
-}
-
-input {
-  user-select: text;
-}
-
-.header {
-  color: #363B40;
-  font-size: 1.1em;
-  font-weight: bold;
-  background-color: #f5f5f5;
-  border-bottom: 2px solid #0A84FF;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  height: 48px;
-}
-
-.header > div {
-  flex: 1;
-  padding: 10px;
-  padding-inline-start: 16px;
-}
-
-#header-button {
-  background-repeat: no-repeat;
-  background-position: center center;
-  background-size: 33px 33px;
-  flex: 0;
-  height: 100%;
-}
-
-.list {
-  padding: 0px;
-  margin: 0px;
-  width: 100%;
-}
-
-.list-item {
-  color: #363B40;
-  background-color: var(--color_about_item);
-  border-bottom: 1px solid var(--color_about_item_border);
-  position: relative;
-  list-style-type: none;
-  list-style-image: none;
-  margin: 0px;
-  padding: 0px;
-  min-height: calc(var(--icon-size) + var(--icon-margin) * 2);
-}
-
-.list-item:active {
-  background-color: #eeeeee;
-}
-
-.list-item[isDisabled="true"] {
-  color: #999999;
-}
-
-.inner {
-  margin-inline-start: calc(var(--icon-size) + var(--icon-margin) * 2 - 1em);
-  padding: 1em;
-}
-
-.icon {
-  border: none;
-  width: var(--icon-size);
-  height: var(--icon-size);
-  top: var(--icon-margin);
-  margin-inline-start: var(--icon-margin);
-  position: absolute;
-  pointer-events: none;
-}
-
-.list-item[isDisabled="true"] .favicon {
-  opacity: 0.3;
-}
-
-.row {
-  display: flex;
-  width: 100%;
-}
-
-.title {
-  font-weight: bold;
-  overflow: hidden;
-  flex: 1;
-}
-
-#browse-title {
-  margin: 0.5em 0;
-  background-image: url("chrome://browser/skin/images/chevron.png");
-  background-size: 8px 20px;
-  background-position: right;
-  background-repeat: no-repeat;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutDownloads.css
+++ /dev/null
@@ -1,50 +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/. */
-
-include "defines.css"
-
-.list-item > a {
-  color: inherit;
-  text-decoration: none;
-}
-
-#private-downloads-list .list-item {
-  background-color: #393e43;
-  color: #ddd;
-}
-
-.details {
-  margin-inline-start: calc(var(--icon-size) + var(--icon-margin) * 2 - 1em);
-  padding: 1em;
-}
-
-.date {
-  color: gray;
-  margin-inline-start: 0.5em;
-}
-
-.domain,
-.size {
-  display: inline;
-}
-
-.state {
-  color: gray;
-  margin-bottom: -3px; /* Prevent overflow that hides bottom border */
-}
-
-.size:after {
-  content: " - ";
-  white-space: pre;
-}
-
-#no-downloads-indicator {
-  display: none;
-}
-
-#private-downloads-list:empty + #public-downloads-list:empty + #no-downloads-indicator {
-  display: block;
-  text-align: center;
-  padding-top: 3.9em;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutExperiments.css
+++ /dev/null
@@ -1,19 +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/. */
-
-ul {
-  list-style: none;
-  margin: 0;
-  padding: 0;
-}
-li {
-  padding: 25px;
-  margin-bottom: 5px;
-}
-li[isEnabled="true"] {
-  background-color: #c5e1a5;
-}
-li[isEnabled="false"] {
-  background-color: #ef9a9a;
-}
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/themes/core/aboutLogins.css
+++ /dev/null
@@ -1,238 +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/. */
-
-@import "defines.css";
-
-html {
-  height: 100%;
-}
-
-body {
-  height: 100%;
-}
-
-.hidden {
-  display: none;
-}
-
-.username {
-  width: 100%;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
-
-.origin {
-  font-weight: bold;
-  overflow: hidden;
-  flex: 1;
-}
-
-.realm {
-  /* origin is not localized, so keep the margin on the left side */
-  margin-left: .67em;
-}
-
-.toolbar-buttons {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-  height: 48px;
-  width: 48px;
-}
-
-.toolbar-buttons > li {
-  background-position: center;
-  background-size: 24px 24px;
-  background-repeat: no-repeat;
-  height: 20px;
-  width: 20px;
-}
-
-#filter-input-container {
-  position: fixed;
-  bottom: 0;
-  width: 100%;
-  padding: 10px 0;
-  display: flex;
-  background: var(--color_about_background);
-  border-top: 2px solid var(--color_about_item_border);
-}
-
-#filter-input-container[hidden] {
-  display: none;
-}
-
-#filter-input {
-  flex: 1;
-  padding: 5px;
-  margin-inline-start: 10px;
-  border-radius: 3px;
-}
-
-#filter-button {
-  background-image: url("resource://android/res/drawable-mdpi-v4/ab_search.png");
-}
-
-#filter-clear {
-  background-image: url("resource://android/res/drawable-mdpi-v4/ic_cancel_nm.png");
-  background-position: center;
-  background-size: 12px 12px;
-  background-repeat: no-repeat;
-  height: 32px;
-  width: 32px;
-  margin: 0 5px;
-}
-
-.edit-login-icon {
-  background-image: url("resource://android/res/drawable-hdpi-v4/favicon_globe.png");
-  background-position: center;
-  background-size: 32px 32px;
-  background-repeat: no-repeat;
-  height: 32px;
-  width: 32px;
-  padding: 5px;
-}
-
-#edit-login-page {
-  background-color: #FFFFFF;
-  height: 100%;
-}
-
-#edit-login-header {
-  background-color: #F5F5F5;
-}
-
-.update-button {
-  flex: 1;
-  height: 60px;
-  background-color: #0979D9; /*matched to action_accent in java codebase*/
-  color: #FFFFFF;
-  font-size: 20px;
-  font-weight: bold;
-  border-radius: 4px;
-  border-width: 0px;
-  margin-top: 10px;
-}
-
-.disabled-btn {
-  background-color: #BFBFBF; /*matched to disabled_grey in the java codebase,in colors.xml*/
-}
-
-.password-btn-hide {
-  background-color: #777777;
-  color: white;
-}
-
-.edit-login-input {
-  flex: 1;
-  height: 36px;
-  font-size: 15px;
-  color: #222222;
-  border-radius: 4px;
-  border: solid 1px #AFB1B3;
-  padding-left: 10px;
-}
-
-.edit-login-div {
-  margin: 20px 30px;
-  display: flex;
-  flex-flow: row;
-  align-items: center;
-}
-
-#password-btn {
-  border-radius: 4px;
-  border-top-left-radius: 0em 0em;
-  border-bottom-left-radius: 0em  0em;
-  font-size: 15px;
-  height: 40px;
-}
-
-#password {
-  margin: none;
-  border-top-right-radius: 0em 0em;
-  border-bottom-right-radius: 0em  0em;
-}
-
-.icon {
-  background-image: url("resource://android/res/drawable-mdpi-v4/favicon_globe.png");
-  background-position: center;
-  background-size: 32px 32px;
-  background-repeat: no-repeat;
-  height: 32px;
-  width: 32px;
-  visibility: hidden;
-}
-
-@media screen and (min-resolution: 1.25dppx) {
-  #filter-button {
-    background-image: url("resource://android/res/drawable-hdpi-v4/ab_search.png");
-  }
-
-  #filter-clear {
-    background-image: url("resource://android/res/drawable-hdpi-v4/ic_cancel_nm.png");
-  }
-
-  .icon {
-    background-image: url("resource://android/res/drawable-hdpi-v4/favicon_globe.png");
-  }
-}
-
-@media screen and (min-resolution: 2dppx) {
-  #filter-button {
-    background-image: url("resource://android/res/drawable-xhdpi-v4/ab_search.png");
-  }
-
-  #filter-clear {
-    background-image: url("resource://android/res/drawable-hdpi-v4/ic_cancel_nm.png");
-  }
-
-  .icon {
-    background-image: url("resource://android/res/drawable-xhdpi-v4/favicon_globe.png");
-  }
-}
-
-#loading-img-container{
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-#spinner {
-  margin-top: 60px;
-}
-
-#empty-body {
-  padding-left: 60px;
-  padding-right: 60px;
-}
-
-#empty-obj-text-container {
-  display: flex;
-  flex-flow: column;
-  align-items: center;
-  text-align: center;
-  justify-content: center;
-}
-
-.empty-text {
-  color: #363B40;
-  font-size: 25px;
-  font-weight: lighter;
-  margin-bottom: 20px;
-}
-
-.empty-hint {
-  color: #777777;
-  font-size: 20px;
-}
-
-#empty-icon {
-  margin-top: 60px;
-  margin-bottom: 20px;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutPage.css
+++ /dev/null
@@ -1,117 +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/. */
-
-body {
-  -moz-text-size-adjust: none;
-  font-family: sans-serif;
-  font-size: 23px;
-  color: #222222;
-  background-color: #ced7de;
-}
-
-#header {
-  height: 80px;
-}
-
-#wordmark {
-  margin: 30px 0 0 15px;
-  width: 123px;
-  height: 36px;
-  background: url("chrome://browser/skin/images/wordmark-hdpi.png") no-repeat;
-}
-
-#version {
-  margin: 0 0 0 15px;
-  font-size: 15px;
-}
-
-#banner {
-  min-height: 150px;
-  background-color: #bdc7ce;
-}
-
-#logo {
-  position: absolute;
-  top: 0;
-  right: 0;
-  width: 375px;
-  height: 300px;
-  background: url("chrome://browser/skin/images/logo-hdpi.png") no-repeat;
-}
-
-#updateBox {
-  position: relative;
-  top: 40px;
-  margin: 0 auto;
-  width: 60%; /* looks much larger!? */
-  padding: 20px 1em;
-  text-align: center;
-  background-image: url("chrome://browser/skin/images/about-btn-darkgrey.png");
-  background-size: contain;
-  border-bottom-width: 4px;
-  border-bottom-style: solid;
-  border-bottom-color: #3A3F44;
-  border-radius: 8px;
-  box-shadow: 0 5px 5px rgba(0, 0, 0, 0.3);
-}
-
-#update-message-checking,
-#update-message-none,
-#update-message-found,
-#update-message-downloading,
-#update-message-downloaded {
-  display: none;
-}
-
-#messages {
-  position: relative;
-  width: 70%;
-  margin: 40px auto 0 auto;
-  padding: 10px 0;
-  font-size: 15px;
-  text-align: center;
-}
-
-#telemetry a {
-  text-decoration: underline;
-}
-
-#aboutLinks {
-  margin: 0 0 15px 0;
-  padding: 0;
-}
-
-#aboutLinks > li {
-  line-height: 2.6;
-  border-top: 1px solid white;
-  border-bottom: 1px solid #C1C7CC;
-}
-
-#aboutLinks > li > a {
-  padding-inline-start: 25px;
-  display: block;
-}
-
-#aboutDetails {
-  padding-left: 15px;
-  font-size: 15px;
-}
-
-.top-border {
-  border-bottom: 1px solid #C1C7CC;
-}
-
-.bottom-border {
-  border-top: 1px solid white;
-}
-
-a, span {
-  text-decoration: none;
-  color: #222222;
-}
-
-#updateBox > a,
-#updateBox > span {
-  color: #e5f2ff;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutPrivateBrowsing.css
+++ /dev/null
@@ -1,84 +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/. */
-
-body {
-  font-family: sans-serif;
-  font-size: 16px;
-  text-align: center;
-  padding: 0 30px 0;
-}
-
-body.normal  .showPrivate,
-body.private .showNormal {
-  display: none;
-}
-
-div.contentSection {
-  max-width: 400px;
-  margin:auto;
-}
-
-body.private {
-  background-color: #363b40; /* text_and_tabs_tray_grey */
-  color: #afb1b3; /* tabs_tray_icon_grey */
-}
-
-body.normal {
-  background-color: #eeeeee;
-  color: #777777; /* placeholder gray */
-}
-
-h1 {
-  font-size: 20px;
-  font-weight: 100;
-  text-align: center;
-  margin: 0;
-}
-
-body.normal h1 {
-  color: #363b40; /* text_and_tabs_tray_grey */
-}
-
-a {
-  color: #0096DD; /* link_blue */
-  text-decoration: none;
-}
-
-.masq {
-  display: block;
-  height: auto;
-  margin: 0 auto 20px auto;
-}
-
-.masq.showNormal {
-  width: 80px;
-}
-
-.masq.showPrivate {
-  width: 160px;
-}
-
-@media all and (max-height: 399px) {
-  body {
-    margin-top: 30px;
-  }
-}
-
-@media all and (min-height: 400px) and (max-height: 599px) {
-  body {
-    margin-top: 60px;
-  }
-}
-
-@media all and (min-height: 600px) and (max-height: 799px) {
-  body {
-    margin-top: 120px;
-  }
-}
-
-@media all and (min-height: 800px) {
-  body {
-    margin-top: 240px;
-  }
-}
deleted file mode 100644
--- a/mobile/android/themes/core/aboutReader.css
+++ /dev/null
@@ -1,560 +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/. */
-
-/* Avoid adding ID selector rules in this style sheet, since they could
- * inadvertently match elements in the article content. */
-
-html {
-  -moz-text-size-adjust: none;
-}
-
-body {
-  padding: 20px;
-  transition-property: background-color, color;
-  transition-duration: 0.4s;
-  max-width: 35em;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-body.light {
-  background-color: #ffffff;
-  color: #222222;
-}
-
-body.dark {
-  background-color: #222222;
-  color: #eeeeee;
-}
-
-body.sepia {
-  color: #5b4636;
-  background-color: #f4ecd8;
-}
-
-body.sans-serif {
-  font-family: sans-serif;
-}
-
-body.serif {
-  font-family: serif;
-}
-
-.container {
-  --font-size: 12;
-  font-size: var(--font-size);
-}
-
-/* Override some controls and content styles based on color scheme */
-
-body.light > .container > .header > .domain {
-  color: #ee7600;
-  border-bottom-color: #d0d0d0;
-}
-
-body.light > .container > .header > h1 {
-  color: #222222;
-}
-
-body.light > .container > .header > .credits {
-  color: #898989;
-}
-
-body.dark > .container > .header > .domain {
-  color: #ff9400;
-  border-bottom-color: #777777;
-}
-
-body.dark > .container > .header > h1 {
-  color: #eeeeee;
-}
-
-body.dark > .container > .header > .credits {
-  color: #aaaaaa;
-}
-
-body.sepia > .container > .header > .domain {
-  border-bottom-color: #5b4636;
-}
-
-body.sepia > .container > .header > h1 {
-  color: #5b4636;
-}
-
-body.sepia > .container > .header > .credits {
-  color: #5b4636;
-}
-
-body.light > .container > .content .caption,
-body.light > .container > .content .wp-caption-text,
-body.light > .container > .content figcaption {
-  color: #898989;
-}
-
-body.dark > .container > .content .caption,
-body.dark > .container > .content .wp-caption-text,
-body.dark > .container > .content figcaption {
-  color: #aaaaaa;
-}
-
-body.sepia > .container > .content .caption,
-body.sepia > .container > .content .wp-caption-text,
-body.sepia > .container > .content figcaption {
-  color: #5b4636;
-}
-
-body.light > .container > .content blockquote {
-  color: #898989 !important;
-  border-left-color: #d0d0d0 !important;
-}
-
-body.dark > .container > .content blockquote {
-  color: #aaaaaa !important;
-  border-left-color: #777777 !important;
-}
-
-body.sepia > .container > .content blockquote {
-  color: #5b4636 !important;
-  border-left-color: #777777 !important;
-}
-
-.reader-message {
-  margin-top: 40px;
-  display: none;
-  text-align: center;
-  width: 100%;
-  font-size: 0.9em;
-}
-
-.header {
-  text-align: start;
-  display: none;
-}
-
-.domain,
-.credits {
-  font-size: 0.9em;
-  font-family: sans-serif;
-}
-
-.domain {
-  margin-top: 10px;
-  padding-bottom: 10px;
-  color: #00acff !important;
-  text-decoration: none;
-}
-
-.domain-border {
-  margin-top: 15px;
-  border-bottom: 1.5px solid #777777;
-  width: 50%;
-}
-
-.header > h1 {
-  font-size: 1.33em;
-  font-weight: 700;
-  line-height: 1.1em;
-  width: 100%;
-  margin: 0px;
-  margin-top: 32px;
-  margin-bottom: 16px;
-  padding: 0px;
-}
-
-.header > .credits {
-  padding: 0px;
-  margin: 0px;
-  margin-bottom: 32px;
-}
-
-/*======= Controls toolbar =======*/
-
-.toolbar {
-  font-family: sans-serif;
-  position: fixed;
-  width: 100%;
-  left: 0;
-  margin: 0;
-  padding: 0;
-  bottom: 0;
-  list-style: none;
-  pointer-events: none;
-  transition: opacity 420ms linear;
-}
-
-.toolbar > * {
-  float: right;
-}
-
-.button {
-  width: 56px;
-  height: 56px;
-  display: block;
-  background-position: center;
-  background-size: 26px 16px;
-  background-repeat: no-repeat;
-  background-color: #0979D9;
-  border-radius: 10000px;
-  margin: 20px;
-  border: 0;
-  box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.40);
-}
-
-.button:active {
-  background-color: #086ACC;
-}
-
-/* Remove dotted border when button is focused */
-.button::-moz-focus-inner,
-.dropdown-popup > div > button::-moz-focus-inner {
-  border: 0;
-}
-
-.button[hidden],
-.toolbar[hidden] {
-  display: none;
-}
-
-.dropdown-toggle,
-.dropdown-popup {
-  pointer-events: auto;
-}
-
-.dropdown {
-  left: 0;
-  text-align: center;
-  display: inline-block;
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-}
-
-/*======= Font style popup =======*/
-
-.dropdown-popup {
-  position: absolute;
-  left: 0;
-  width: calc(100% - 30px);
-  margin: 15px;
-  z-index: 1000;
-  background: #EBEBF0;
-  visibility: hidden;
-  border: 0;
-  border-radius: 4px;
-  box-shadow: 0px 4px 8px 0px rgba(0,0,0,0.40);
-  user-select: none;
-}
-
-/* Only used on desktop */
-.dropdown-popup > hr,
-.dropdown-arrow,
-.font-type-buttons > button > .name,
-.content-width-buttons,
-.line-height-buttons {
-  display: none;
-}
-
-.open > .dropdown-popup {
-  visibility: visible;
-  bottom: 0;
-}
-
-.font-type-buttons,
-.font-size-buttons,
-.color-scheme-buttons {
-  display: flex;
-  flex-direction: row;
-}
-
-.font-type-buttons > button,
-.color-scheme-buttons > button {
-  text-align: center;
-}
-
-.font-type-buttons > button,
-.font-size-buttons > button {
-  width: 50%;
-  background-color: transparent;
-  border: 0;
-}
-
-.font-type-buttons > button {
-  font-size: 24px;
-  color: #AFB1B3;
-  padding: 15px 0;
-}
-
-.font-type-buttons > button:active,
-.font-type-buttons > button.selected {
-  color: #222222;
-}
-
-.font-size-sample {
-  flex: 0;
-  font-size: 24px;
-  color: #000000;
-  margin: 0 30px;
-  padding: 0 10px;
-}
-
-.serif-button {
-  font-family: serif;
-}
-
-.minus-button,
-.plus-button {
-  background-color: transparent;
-  border: 0;
-  height: 60px;
-  background-size: 18px 18px;
-  background-repeat: no-repeat;
-  background-position: center;
-}
-
-.minus-button {
-  background-size: 24px 6px;
-  margin-left: 50px;
-  padding: 0 5px;
-}
-
-.plus-button {
-  background-size: 24px 24px;
-  margin-right: 50px;
-  padding: 0 5px;
-}
-
-.color-scheme-buttons > button {
-  width: 33%;
-  border-radius: 4px;
-  border: 1px solid #BFBFBF;
-  padding: 10px;
-  margin: 15px 10px;
-  font-size: 14px;
-}
-
-.color-scheme-buttons > button:active,
-.color-scheme-buttons > button.selected {
-  border: 2px solid #0A84FF;
-}
-
-.dark-button {
-  color: #eeeeee;
-  background-color: #333333;
-}
-
-.sepia-button {
-  color: #5b4636;
-  background-color: #f4ecd8;
-}
-
-.auto-button {
-  color: #000000;
-  background-color: transparent;
-}
-
-.light-button {
-  color: #333333;
-  background-color: #ffffff;
-}
-
-/*======= Toolbar icons =======*/
-
-/* desktop-only controls */
-.close-button {
-  display: none;
-}
-
-.style-button {
-  background-image: url('chrome://browser/skin/images/reader-style-icon-hdpi.png');
-}
-
-.minus-button {
-  background-image: url('chrome://browser/skin/images/reader-minus-hdpi.png');
-}
-
-.plus-button {
-  background-image: url('chrome://browser/skin/images/reader-plus-hdpi.png');
-}
-
-@media screen and (min-resolution: 2dppx) {
-  .style-button {
-    background-image: url('chrome://browser/skin/images/reader-style-icon-xhdpi.png');
-  }
-
-  .minus-button {
-    background-image: url('chrome://browser/skin/images/reader-minus-xhdpi.png');
-  }
-
-  .plus-button {
-    background-image: url('chrome://browser/skin/images/reader-plus-xhdpi.png');
-  }
-}
-
-@media screen and (min-resolution: 3dppx) {
-  .style-button {
-    background-image: url('chrome://browser/skin/images/reader-style-icon-xxhdpi.png');
-  }
-
-  .minus-button {
-    background-image: url('chrome://browser/skin/images/reader-minus-xxhdpi.png');
-  }
-
-  .plus-button {
-    background-image: url('chrome://browser/skin/images/reader-plus-xxhdpi.png');
-  }
-}
-
-@media screen and (min-width: 960px) {
-  .dropdown-popup {
-    width: 350px;
-    left: auto;
-    right: 0;
-  }
-}
-
-/*======= Article content =======*/
-
-/* Note that any class names from the original article that we want to match on
- * must be added to CLASSES_TO_PRESERVE in ReaderMode.jsm, so that
- * Readability.js doesn't strip them out */
-
-.moz-reader-content {
-  display: none;
-  font-size: 1em;
-}
-
-.moz-reader-content a {
-  text-decoration: underline !important;
-  font-weight: normal;
-}
-
-.moz-reader-content a,
-.moz-reader-content a:visited,
-.moz-reader-content a:hover,
-.moz-reader-content a:active {
-  color: #00acff !important;
-}
-
-.moz-reader-content * {
-  max-width: 100% !important;
-  height: auto !important;
-}
-
-.moz-reader-content p {
-  line-height: 1.4em !important;
-  margin: 0px !important;
-  margin-bottom: 20px !important;
-}
-
-table,
-th,
-td {
-  border: 1px solid currentColor;
-  border-collapse: collapse;
-  padding: 6px;
-  vertical-align: top;
-}
-
-table {
-  margin: 5px;
-}
-
-/* Covers all images showing edge-to-edge using a
-   an optional caption text */
-.moz-reader-content .wp-caption,
-.moz-reader-content figure {
-  display: block !important;
-  width: 100% !important;
-  margin: 0px !important;
-  margin-bottom: 32px !important;
-}
-
-/* Images marked to be shown edge-to-edge with an
-   optional captio ntext */
-.moz-reader-content p > img:only-child,
-.moz-reader-content p > a:only-child > img:only-child,
-.moz-reader-content .wp-caption img,
-.moz-reader-content figure img {
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-/* Account for body padding to make image full width */
-.moz-reader-content img[moz-reader-full-width] {
-  width: calc(100% + 40px);
-  margin-left: -20px;
-  margin-right: -20px;
-  max-width: none !important;
-}
-
-/* Image caption text */
-.moz-reader-content .caption,
-.moz-reader-content .wp-caption-text,
-.moz-reader-content figcaption {
-  font-size: 0.9em;
-  font-family: sans-serif;
-  margin: 0px !important;
-  padding-top: 4px !important;
-}
-
-/* Ensure all pre-formatted code inside the reader content
-   are properly wrapped inside content width */
-.moz-reader-content code,
-.moz-reader-content pre {
-  white-space: pre-wrap !important;
-  margin-bottom: 20px !important;
-}
-
-.moz-reader-content blockquote {
-  margin: 0px !important;
-  margin-bottom: 20px !important;
-  padding: 0px !important;
-  padding-inline-start: 16px !important;
-  border: 0px !important;
-  border-left: 2px solid !important;
-}
-
-.moz-reader-content ul,
-.moz-reader-content ol {
-  margin: 0px !important;
-  margin-bottom: 20px !important;
-  padding: 0px !important;
-  line-height: 1.5em;
-}
-
-.moz-reader-content ul {
-  padding-inline-start: 30px !important;
-  list-style: disc !important;
-}
-
-.moz-reader-content ol {
-  padding-inline-start: 35px !important;
-  list-style: decimal !important;
-}
-
-/* Hide elements with common "hidden" class names */
-.moz-reader-content .visually-hidden,
-.moz-reader-content .visuallyhidden,
-.moz-reader-content .hidden,
-.moz-reader-content .invisible,
-.moz-reader-content .sr-only {
-  display: none;
-}
-
-/* Enforce wordpress and similar emoji/smileys aren't sized to be full-width,
- * see bug 1399616 for context. */
-.moz-reader-content img.wp-smiley,
-.moz-reader-content img.emoji {
-  display: inline-block;
-  border-width: 0;
-  /* height: auto is implied from `.moz-reader-content *` rule. */
-  width: 1em;
-  margin: 0 .07em;
-  padding: 0;
-}
-
-.reader-show-element {
-  display: initial;
-}
deleted file mode 100644
--- a/mobile/android/themes/core/defines.css
+++ /dev/null
@@ -1,11 +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/. */
-
-:root {
-	--color_about_background: #f5f5f5;
-	--color_about_item: #ffffff;
-	--color_about_item_border: #d7d9db;
-
-	--margin_snormal: 0.64mm;
-}
deleted file mode 100644
index 6784c2239cce19144c595b2396f62681b6c3cfd9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index b99f7dbcc13b5de2a9b60bdf45028c4c830ef327..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 3920aff3c8971b6ce35c5d1fcce32697999a2ae8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 3e1e6694197886a30064761868f8a7a284d7ac96..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 1aa730a3531760eba463196cd9b12830dc36ea43..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index d93824427230192591d439d573ea1343b1a9dcae..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 835b3b36b7362796deb25196d150abc76f708a0b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 5089b7fa97bebb3573a7abe163031dff1960e7b7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f9c8bdea0653cf06a759a31984dd1638a1bfbe4c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index fac10c17ac8465036a185917e88d82ebe29e0edf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index d362d1b14b9901151c8da6a4dae5205212d58e10..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7080dac5c8fd13b3cfddcb80cc3413a87a9432cc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a3a96d628afc4b405d56a832cfb984de6f415506..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/mobile/android/themes/core/images/extension-update.svg
+++ /dev/null
@@ -1,7 +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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
-    <rect width="16" height="16" fill="#00FEFF" rx="8"/>
-    <path stroke="#008EA4" stroke-linecap="round" stroke-width="2" d="M8,2 L8,14 M8,2 L4,6 M8,2 L12,6"/>
-</svg>
deleted file mode 100644
--- a/mobile/android/themes/core/images/grey-caution.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- 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/. -->
-<svg width="60px" height="60px" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
-  <path d="M34.6570853,3.89861537 L61.6191658,57.8227763 C62.6631009,60.0994422 61.4905756,62 58.9609325,62 L5.03677158,62 C2.50636943,62 1.33487292,60.0971201 2.37853829,57.8227763 L29.3406187,3.89861537 C30.6694576,1.36596731 33.3285163,1.36828938 34.6570853,3.89861537 Z M28.2013759,23.6360478 C28.2013759,21.5439751 29.9058314,19.8480151 31.998852,19.8480151 C34.0961402,19.8480151 35.7963281,21.5419679 35.7963281,23.6360478 L35.7963281,38.844839 C35.7963281,40.9369118 34.0918726,42.6328718 31.998852,42.6328718 C29.9015639,42.6328718 28.2013759,40.938919 28.2013759,38.844839 L28.2013759,23.6360478 Z M31.998852,54.7847954 C34.0961402,54.7847954 35.7963281,53.0846074 35.7963281,50.9873193 C35.7963281,48.8900311 34.0961402,47.1898431 31.998852,47.1898431 C29.9015639,47.1898431 28.2013759,48.8900311 28.2013759,50.9873193 C28.2013759,53.0846074 29.9015639,54.7847954 31.998852,54.7847954 Z" fill="#AFB1B3" fill-rule="evenodd" transform="translate(-2,-2)"/>
-</svg>
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/themes/core/images/icon_key_emptypage.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- 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/. -->
-
-<svg width="60px" height="60px" viewBox="0 0 180 180" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
-  <title>Key</title>
-    <g sketch:type="MSArtboardGroup" fill="#bfbfbf">
-      <path d="M72,60.75 C72,60.75 59.625,72 59.625,72 C57.375,74.25 58.5,76.5 59.625,77.625 L65.25,82.125 C66.375,83.25 67.5,84.375 65.25,86.625 L0,157.5 L0,176.625 C0,178.875 1.125,180 3.375,180 L33.75,180 C34.875,180 36,178.875 36,177.75 L36,168.75 L48.375,167.625 L47.25,156.375 L55.125,156.375 C55.125,156.375 56.25,156.375 56.25,155.25 L56.25,148.5 L65.25,148.5 L65.25,132.75 L78.75,132.75 L94.5,115.875 C96.75,113.625 99,113.625 101.25,115.875 L106.875,121.5 C109.125,123.75 111.375,123.75 113.625,121.5 L122.625,109.125 C157.125,108.963211 180,82.6329431 180,55.125 C179.4,24.0802676 155.4,0 124.875,0 C95.4,0 68.025,26.3302676 72,60.75 Z M139,54 C131.85,54 126,48.15 126,41 C126,33.85 131.85,28 139,28 C146.15,28 152,33.85 152,41 C152,48.15 146.15,54 139,54 L139,54 Z" sketch:type="MSShapeGroup"></path>
-    </g>
-</svg>
\ No newline at end of file
deleted file mode 100644
index 20406becaa99bd71ca034aac847fa222f47ede1c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/mobile/android/themes/core/images/placeholder_image.svg
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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/. -->
-<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 42 42" style="enable-background:new 0 0 42 42;" xml:space="preserve">
-<style type="text/css">
-	.st0{fill:#FFFFFF;filter:url(#Adobe_OpacityMaskFilter);}
-	.st1{fill:#010101;}
-	.st2{mask:url(#mask-cutout-blocked-sign_1_);}
-	.st3{fill:#F1F1F2;}
-	.st4{fill:#7F8081;}
-	.st5{fill:#4D4D4E;}
-	.st6{fill:#979899;}
-	.st7{fill:#010101;filter:url(#Adobe_OpacityMaskFilter_1_);}
-	.st8{fill:#FFFFFF;}
-	.st9{mask:url(#mask-cutout-frame_1_);fill:#656667;}
-	.st10{fill:#FFFFFF;filter:url(#Adobe_OpacityMaskFilter_2_);}
-	.st11{mask:url(#mask-cutout-blocked-sign-inner_1_);fill:#656667;}
-	.st12{fill:none;stroke:#656667;stroke-width:2;}
-</style>
-<g id="Layer_1">
-	<defs>
-		<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="5" y="5" width="32" height="32">
-			<feColorMatrix type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
-		</filter>
-	</defs>
-	<mask maskUnits="userSpaceOnUse" x="5" y="5" width="32" height="32" id="mask-cutout-blocked-sign_1_">
-		<rect x="5" y="5" class="st0" width="32" height="32"/>
-		<circle class="st1" cx="30" cy="30" r="8"/>
-	</mask>
-	<g id="icon-frame" class="st2">
-		<path id="shape-background" class="st3" d="M10,9h22c1.7,0,3,1.3,3,3v18c0,1.7-1.3,3-3,3H10c-1.7,0-3-1.3-3-3V12    C7,10.3,8.3,9,10,9z"/>
-		<polygon class="st4" points="8,31 16,21 23,31   "/>
-		<polygon class="st5" points="16,31 28,15 36,25 36,31   "/>
-		<circle class="st6" cx="14" cy="16" r="3"/>
-		<defs>
-			<filter id="Adobe_OpacityMaskFilter_1_" filterUnits="userSpaceOnUse" x="5" y="5" width="32" height="32">
-				<feColorMatrix type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
-			</filter>
-		</defs>
-		<mask maskUnits="userSpaceOnUse" x="5" y="5" width="32" height="32" id="mask-cutout-frame_1_">
-			<rect x="5" y="5" class="st7" width="32" height="32"/>
-			<path class="st8" d="M10,9h22c1.7,0,3,1.3,3,3v18c0,1.7-1.3,3-3,3H10c-1.7,0-3-1.3-3-3V12C7,10.3,8.3,9,10,9z"/>
-			<path class="st1" d="M11,11h20c1.1,0,2,0.9,2,2v16c0,1.1-0.9,2-2,2H11c-1.1,0-2-0.9-2-2V13C9,11.9,9.9,11,11,11z"/>
-		</mask>
-		<rect x="5" y="5" class="st9" width="32" height="32"/>
-	</g>
-	<g id="icon-blocked-sign">
-		<defs>
-			<filter id="Adobe_OpacityMaskFilter_2_" filterUnits="userSpaceOnUse" x="24" y="24" width="12" height="12">
-				<feColorMatrix type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0"/>
-			</filter>
-		</defs>
-		<mask maskUnits="userSpaceOnUse" x="24" y="24" width="12" height="12" id="mask-cutout-blocked-sign-inner_1_">
-			<rect x="5" y="5" class="st10" width="32" height="32"/>
-			<circle class="st1" cx="30" cy="30" r="4"/>
-		</mask>
-		<circle class="st11" cx="30" cy="30" r="6"/>
-		<line class="st12" x1="26" y1="34" x2="34" y2="26"/>
-	</g>
-</g>
-<g id="Layer_2">
-</g>
-</svg>
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/themes/core/images/privatebrowsing-mask-and-shield.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- 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/. -->
-
-<svg width="400" height="138" viewBox="0 0 400 138" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-  <defs>
-    <path d="M72.29 136.64C28.48 137.22 0.29 72.46 0.29 41.98L0.29 4.65C7.14 11.12 24.29 17.93 44.86 11.31 65.43 0.89 99.71-5.92 120.29 7.31 140.86-5.92 175.14 0.89 195.71 11.31 216.29 17.93 233.43 11.12 240.29 4.65L240.29 41.98C240.29 72.46 212.1 137.22 168.29 136.64 140.85 136.28 130.57 130.36 120.29 129.98 110 130.36 99.73 136.28 72.29 136.64ZM100.28 85.11C100.12 75.55 100.11 58.19 76.48 54.7 52.63 51.25 42.46 61.67 32.28 61.46 32.28 79.03 66.2 92.91 100.28 85.11ZM140.28 85.11C140.45 75.55 140.46 58.19 164.08 54.7 187.93 51.25 198.11 61.67 208.28 61.46 208.28 79.03 174.36 92.91 140.28 85.11Z" id="path-1"/>
-  </defs>
-  <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-    <g id="XXHDPI" transform="translate(-178.000000, -1050.000000)">
-      <g id="graphic-2" transform="translate(178.000000, 1050.901172)">
-        <path d="M399.38 24.32C399.36 19.92 396.45 16.4 392.71 15.32L349.86 8.32 307 15.32C303.26 16.4 300.35 19.92 300.33 24.32 300.31 34.22 300.37 52.28 301.29 60.32 303.17 83.36 307.43 94.81 317.48 108.32 330.16 126.08 349.86 128.32 349.86 128.32 349.86 128.32 369.56 126.08 382.24 108.32 392.28 94.81 396.54 83.36 398.43 60.32 399.34 52.28 399.4 34.22 399.38 24.32L399.38 24.32 399.38 24.32ZM390.81 59.32C388.95 82.65 384.72 92.07 376.52 103.32 367.16 116.27 353.36 119.66 349.86 120.32 346.31 119.65 332.54 116.26 323.19 103.32 314.99 92.07 310.76 82.65 308.9 59.32 308.17 53.88 307.91 40.97 307.95 24.32 307.96 23.78 308.17 23.56 308.9 23.32L349.86 16.32 390.81 23.32C391.54 23.56 391.75 23.78 391.76 24.32 391.8 40.96 391.54 53.87 390.81 59.32ZM326.05 98.32C318.68 87.15 315.78 78.92 314.62 59.32 313.99 54.06 313.66 45.26 313.67 30.32L348.9 23.32 348.9 113.32C344.72 112.4 334.23 108.99 326.05 98.32Z" id="XXHDPI" fill="#FFFFFF"/>
-        <g id="Path-Copy">
-          <use fill="none" xlink:href="#path-1"/>
-          <use fill="none" xlink:href="#path-1"/>
-          <use fill="#5F6368" fill-rule="evenodd" xlink:href="#path-1"/>
-        </g>
-      </g>
-    </g>
-  </g>
-</svg>
\ No newline at end of file
deleted file mode 100644
index e62cdbe137ce32dfb52bf157edbf74c7bd10291c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 5ac0ee84b937016eb37f3a639a952c75e23ef9ec..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 5597200540dec6ec86b9a189bfb171a6baa0db4c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 355d82f9fd6db39c6f0862d6f3bfa337e02b86e9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 82640847932d7a0c7e41a6e099d6fd687b031d92..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 68cfa536b275d63d47e56bc49566ec0beae276aa..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6f475c5d3de85415e922389dcac980fa8ba115e0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 4f83b369a29472cccd852f26f0bacb5485b83c89..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 59f90a9c036287ae1fe0e4f54356deabfee77fe5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f419e861f8a2a03fa632483b0498802034f24569..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 827d7fd487f9c2333471ac09cda550cd55d31f69..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/mobile/android/themes/core/jar.mn
+++ /dev/null
@@ -1,51 +0,0 @@
-#filter substitution
-# 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/.
-
-chrome.jar:
-% skin browser classic/1.0 %skin/
-  skin/aboutPage.css                        (aboutPage.css)
-  skin/aboutAccounts.css                    (aboutAccounts.css)
-  skin/aboutAddons.css                      (aboutAddons.css)
-  skin/aboutBase.css                        (aboutBase.css)
-  skin/aboutDownloads.css                   (aboutDownloads.css)
-  skin/aboutExperiments.css                 (aboutExperiments.css)
-  skin/aboutPrivateBrowsing.css             (aboutPrivateBrowsing.css)
-  skin/aboutReader.css                      (aboutReader.css)
-  skin/defines.css                          (defines.css)
-  skin/spinner.css                          (spinner.css)
-% override chrome://global/skin/aboutReader.css chrome://browser/skin/aboutReader.css
-
-  skin/aboutLogins.css                      (aboutLogins.css)
-
-  skin/images/amo-logo.png                  (images/amo-logo.png)
-  skin/images/blocked-warning.png           (images/blocked-warning.png)
-  skin/images/checkbox_checked.png          (images/checkbox_checked.png)
-  skin/images/checkbox_checked_disabled.png (images/checkbox_checked_disabled.png)
-  skin/images/checkbox_checked_pressed.png  (images/checkbox_checked_pressed.png)
-  skin/images/checkbox_unchecked.png          (images/checkbox_unchecked.png)
-  skin/images/checkbox_unchecked_disabled.png (images/checkbox_unchecked_disabled.png)
-  skin/images/checkbox_unchecked_pressed.png  (images/checkbox_unchecked_pressed.png)
-  skin/images/chevron.png                   (images/chevron.png)
-  skin/images/chevron-rtl.png               (images/chevron-rtl.png)
-  skin/images/errorpage-warning.png         (images/errorpage-warning.png)
-  skin/images/grey-caution.svg              (images/grey-caution.svg)
-  skin/images/certerror-warning.png         (images/certerror-warning.png)
-  skin/images/placeholder_image.svg         (images/placeholder_image.svg)
-  skin/images/about-btn-darkgrey.png        (images/about-btn-darkgrey.png)
-  skin/images/logo-hdpi.png                 (images/logo-hdpi.png)
-  skin/images/wordmark-hdpi.png             (images/wordmark-hdpi.png)
-  skin/images/reader-minus-hdpi.png              (images/reader-minus-hdpi.png)
-  skin/images/reader-minus-xhdpi.png             (images/reader-minus-xhdpi.png)
-  skin/images/reader-minus-xxhdpi.png            (images/reader-minus-xxhdpi.png)
-  skin/images/reader-plus-hdpi.png               (images/reader-plus-hdpi.png)
-  skin/images/reader-plus-xhdpi.png              (images/reader-plus-xhdpi.png)
-  skin/images/reader-plus-xxhdpi.png             (images/reader-plus-xxhdpi.png)
-  skin/images/reader-style-icon-hdpi.png         (images/reader-style-icon-hdpi.png)
-  skin/images/reader-style-icon-xhdpi.png        (images/reader-style-icon-xhdpi.png)
-  skin/images/reader-style-icon-xxhdpi.png       (images/reader-style-icon-xxhdpi.png)
-  skin/images/privatebrowsing-mask.png           (images/privatebrowsing-mask.png)
-  skin/images/privatebrowsing-mask-and-shield.svg (images/privatebrowsing-mask-and-shield.svg)
-  skin/images/icon_key_emptypage.svg             (images/icon_key_emptypage.svg)
-  skin/images/extension-update.svg               (images/extension-update.svg)
deleted file mode 100644
--- a/mobile/android/themes/core/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-JAR_MANIFESTS += ["jar.mn"]
deleted file mode 100644
--- a/mobile/android/themes/core/spinner.css
+++ /dev/null
@@ -1,124 +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/. */
-
-.mui-refresh-main {
-  padding: 0;
-  overflow: hidden;
-  border-radius: 999px;
-  position: relative;
-}
-
-.mui-refresh-wrapper {
-  width: 60px;
-  height: 60px;
-}
-
-.mui-spinner-main {
-  width: 60px;
-  height: 60px;
-  position: relative;
-  animation: sporadic-rotate 5.25s cubic-bezier(.35, 0, .25, 1) infinite;
-}
-
-.mui-spinner-wrapper {
-  animation: outer-rotate 2.91667s linear infinite;
-}
-
-.mui-spinner-left, .mui-spinner-right {
-  position: absolute;
-  top: 0;
-  height: 60px;
-  width: 30px;
-  overflow: hidden;
-}
-
-.mui-spinner-left {
-  left: 0;
-}
-
-.mui-spinner-right {
-  right: 0;
-}
-
-.mui-half-circle-left, .mui-half-circle-right  {
-  position: absolute;
-  top: 0;
-  width: 60px;
-  height: 60px;
-  box-sizing: border-box;
-  border-width: 5px;
-  border-style: solid;
-  border-color: #000 #000 transparent;
-  border-radius: 999px;
-  animation-iteration-count: infinite;
-  animation-duration: 1.3125s;
-  animation-timing-function: cubic-bezier(.35, 0, .25, 1);
-}
-
-.mui-half-circle-left {
-  left: 0;
-  border-right-color: transparent;
-  border-top-color: #0A84FF; /*matched to fennec_ui_accent in java codebase*/
-  border-left-color: #0A84FF; /*matched to fennec_ui_accent n java codebase*/
-  animation-name: left-wobble;
-}
-
-.mui-half-circle-right {
-  right: 0;
-  border-left-color: transparent;
-  border-top-color: #0A84FF; /*matched to fennec_ui_accent n java codebase*/
-  border-right-color: #0A84FF; /*matched to fennec_ui_accent n java codebase*/
-  animation-name: right-wobble;
-}
-
-@keyframes outer-rotate {
-  100% {
-    transform: rotate(360deg);
-  }
-}
-
-@keyframes left-wobble {
-  0%, 100% {
-    transform: rotate(130deg);
-  }
-  50% {
-    transform: rotate(-5deg);
-  }
-}
-
-@keyframes right-wobble {
-  0%, 100% {
-    transform: rotate(-130deg);
-  }
-  50% {
-    transform: rotate(5deg);
-  }
-}
-
-@keyframes sporadic-rotate {
-  12.5% {
-    transform: rotate(135deg);
-  }
-  25% {
-    transform: rotate(270deg);
-  }
-  37.5% {
-    transform: rotate(405deg);
-  }
-  50% {
-    transform: rotate(540deg);
-  }
-  62.5% {
-    transform: rotate(675deg);
-  }
-  75% {
-    transform: rotate(810deg);
-  }
-  87.5% {
-    transform: rotate(945deg);
-  }
-  100% {
-    transform: rotate(1080deg);
-  }
-}
--- a/netwerk/protocol/http/nsHttpHeaderArray.cpp
+++ b/netwerk/protocol/http/nsHttpHeaderArray.cpp
@@ -290,21 +290,23 @@ nsresult nsHttpHeaderArray::VisitHeaders
   nsresult rv;
 
   uint32_t i, count = mHeaders.Length();
   for (i = 0; i < count; ++i) {
     const nsEntry& entry = mHeaders[i];
     if (filter == eFilterSkipDefault &&
         entry.variety == eVarietyRequestDefault) {
       continue;
-    } else if (filter == eFilterResponse &&
-               entry.variety == eVarietyResponseNetOriginal) {
+    }
+    if (filter == eFilterResponse &&
+        entry.variety == eVarietyResponseNetOriginal) {
       continue;
-    } else if (filter == eFilterResponseOriginal &&
-               entry.variety == eVarietyResponse) {
+    }
+    if (filter == eFilterResponseOriginal &&
+        entry.variety == eVarietyResponse) {
       continue;
     }
 
     nsAutoCString hdr;
     if (entry.headerNameOriginal.IsEmpty()) {
       hdr = nsDependentCString(entry.header);
     } else {
       hdr = entry.headerNameOriginal;
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -646,17 +646,17 @@ nsIContent** nsHtml5Highlighter::Current
 }
 
 void nsHtml5Highlighter::Push(
     nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
     mozilla::dom::HTMLContentCreatorFunction aCreator) {
   MOZ_ASSERT(mStack.Length() >= 1, "Pushing without root.");
   nsIContent** elt = CreateElement(aName, aAttributes, CurrentNode(),
                                    aCreator);  // Don't inline below!
-  opAppend operation(elt, CurrentNode());
+  opAppend operation(elt, CurrentNode(), mozilla::dom::FROM_PARSER_NETWORK);
   mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
   mStack.AppendElement(elt);
 }
 
 void nsHtml5Highlighter::Pop() {
   MOZ_ASSERT(mStack.Length() >= 2, "Popping when stack too short.");
   mStack.RemoveLastElement();
 }
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -603,29 +603,33 @@ void nsHtml5TreeBuilder::detachFromParen
 void nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild,
                                        nsIContentHandle* aParent) {
   MOZ_ASSERT(aChild, "Null child");
   MOZ_ASSERT(aParent, "Null parent");
 
   if (mBuilder) {
     nsresult rv = nsHtml5TreeOperation::Append(
         static_cast<nsIContent*>(aChild), static_cast<nsIContent*>(aParent),
-        mBuilder);
+        mozilla::dom::FROM_PARSER_FRAGMENT, mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
     }
     return;
   }
 
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
   if (MOZ_UNLIKELY(!treeOp)) {
     MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  opAppend operation(aChild, aParent);
+
+  opAppend operation(aChild, aParent,
+                     (!!mSpeculativeLoadStage)
+                         ? mozilla::dom::FROM_PARSER_NETWORK
+                         : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
   treeOp->Init(mozilla::AsVariant(operation));
 }
 
 void nsHtml5TreeBuilder::appendChildrenToNewParent(
     nsIContentHandle* aOldParent, nsIContentHandle* aNewParent) {
   MOZ_ASSERT(aOldParent, "Null old parent");
   MOZ_ASSERT(aNewParent, "Null new parent");
 
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -251,16 +251,36 @@ nsresult nsHtml5TreeOperation::Append(ns
   rv = aParent->AppendChildTo(aNode, false);
   if (NS_SUCCEEDED(rv)) {
     aNode->SetParserHasNotified();
     MutationObservers::NotifyContentAppended(aParent, aNode);
   }
   return rv;
 }
 
+nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent,
+                                      mozilla::dom::FromParser aFromParser,
+                                      nsHtml5DocumentBuilder* aBuilder) {
+  Maybe<nsHtml5AutoPauseUpdate> autoPause;
+  Maybe<dom::AutoCEReaction> autoCEReaction;
+  dom::DocGroup* docGroup = aParent->OwnerDoc()->GetDocGroup();
+  if (docGroup && aFromParser != mozilla::dom::FROM_PARSER_FRAGMENT) {
+    autoCEReaction.emplace(docGroup->CustomElementReactionsStack(), nullptr);
+  }
+  nsresult rv = Append(aNode, aParent, aBuilder);
+  // Pause the parser only when there are reactions to be invoked to avoid
+  // pausing parsing too aggressive.
+  if (autoCEReaction.isSome() && docGroup &&
+      docGroup->CustomElementReactionsStack()
+          ->IsElementQueuePushedForCurrentRecursionDepth()) {
+    autoPause.emplace(aBuilder);
+  }
+  return rv;
+}
+
 nsresult nsHtml5TreeOperation::AppendToDocument(
     nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder) {
   MOZ_ASSERT(aBuilder);
   MOZ_ASSERT(aBuilder->GetDocument() == aNode->OwnerDoc());
   MOZ_ASSERT(aBuilder->IsInDocUpdate());
   nsresult rv = NS_OK;
 
   Document* doc = aBuilder->GetDocument();
@@ -757,17 +777,18 @@ nsresult nsHtml5TreeOperation::Perform(n
           mStreamEnded(aStreamEnded) {}
 
     nsHtml5TreeOpExecutor* mBuilder;
     nsIContent** mScriptElement;
     bool* mInterrupted;
     bool* mStreamEnded;
 
     nsresult operator()(const opAppend& aOperation) {
-      return Append(*(aOperation.mChild), *(aOperation.mParent), mBuilder);
+      return Append(*(aOperation.mChild), *(aOperation.mParent),
+                    aOperation.mFromNetwork, mBuilder);
     }
 
     nsresult operator()(const opDetach& aOperation) {
       Detach(*(aOperation.mElement), mBuilder);
       return NS_OK;
     }
 
     nsresult operator()(const opAppendChildrenToNewParent& aOperation) {
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -31,18 +31,21 @@ struct opDetach {
   explicit opDetach(nsIContentHandle* aElement) {
     mElement = static_cast<nsIContent**>(aElement);
   };
 };
 
 struct opAppend {
   nsIContent** mChild;
   nsIContent** mParent;
+  mozilla::dom::FromParser mFromNetwork;
 
-  explicit opAppend(nsIContentHandle* aChild, nsIContentHandle* aParent) {
+  explicit opAppend(nsIContentHandle* aChild, nsIContentHandle* aParent,
+                    mozilla::dom::FromParser aFromNetwork)
+      : mFromNetwork(aFromNetwork) {
     mChild = static_cast<nsIContent**>(aChild);
     mParent = static_cast<nsIContent**>(aParent);
   };
 };
 
 struct opAppendChildrenToNewParent {
   nsIContent** mOldParent;
   nsIContent** mNewParent;
@@ -512,16 +515,20 @@ class nsHtml5TreeOperation final {
 
   static nsresult AppendText(const char16_t* aBuffer, uint32_t aLength,
                              nsIContent* aParent,
                              nsHtml5DocumentBuilder* aBuilder);
 
   static nsresult Append(nsIContent* aNode, nsIContent* aParent,
                          nsHtml5DocumentBuilder* aBuilder);
 
+  static nsresult Append(nsIContent* aNode, nsIContent* aParent,
+                         mozilla::dom::FromParser aFromParser,
+                         nsHtml5DocumentBuilder* aBuilder);
+
   static nsresult AppendToDocument(nsIContent* aNode,
                                    nsHtml5DocumentBuilder* aBuilder);
 
   static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder);
 
   static nsresult AppendChildrenToNewParent(nsIContent* aNode,
                                             nsIContent* aParent,
                                             nsHtml5DocumentBuilder* aBuilder);
--- a/parser/htmlparser/tests/mochitest/mochitest.ini
+++ b/parser/htmlparser/tests/mochitest/mochitest.ini
@@ -144,8 +144,9 @@ skip-if = (verify && debug && (os == 'li
 #		file_bug568470.sjs
 #		file_bug568470-script.sjs
 # Disable test due to frequent orange on Mac
 #		test_bug534293.html
 [test_bug1209658.html]
 [test_bug1364399.html]
 [test_bug1646140-1.html]
 [test_bug1646140-2.html]
+skip-if = headless # Bug 1685088
--- a/taskcluster/ci/build/windows-mingw.yml
+++ b/taskcluster/ci/build/windows-mingw.yml
@@ -43,16 +43,17 @@ win32-mingwclang/opt:
             - linux64-wine
             - linux64-sccache
             - linux64-cbindgen
             - linux64-nasm
             - linux64-node
             - linux64-clang-mingw-x86
             - linux64-mingw32-nsis
             - linux64-mingw-fxc2-x86
+            - linux64-dump-syms
 
 win32-mingwclang/debug:
     description: "Win32 MinGW-Clang Debug"
     index:
         product: firefox
         job-name: win32-mingwclang-debug
     treeherder:
         platform: windows-mingw32/all
@@ -77,16 +78,17 @@ win32-mingwclang/debug:
             - linux64-wine
             - linux64-sccache
             - linux64-cbindgen
             - linux64-nasm
             - linux64-node
             - linux64-clang-mingw-x86
             - linux64-mingw32-nsis
             - linux64-mingw-fxc2-x86
+            - linux64-dump-syms
 
 win64-mingwclang/opt:
     description: "Win64 MinGW-Clang Opt"
     index:
         product: firefox
         job-name: win64-mingwclang-opt
     treeherder:
         platform: windows-mingw32/all
@@ -111,16 +113,17 @@ win64-mingwclang/opt:
             - linux64-wine
             - linux64-sccache
             - linux64-cbindgen
             - linux64-nasm
             - linux64-node
             - linux64-clang-mingw-x64
             - linux64-mingw32-nsis
             - linux64-mingw-fxc2-x86
+            - linux64-dump-syms
 
 win64-mingwclang/debug:
     description: "Win64 MinGW-Clang Debug"
     index:
         product: firefox
         job-name: win64-mingwclang-debug
     treeherder:
         platform: windows-mingw32/all
@@ -145,8 +148,9 @@ win64-mingwclang/debug:
             - linux64-wine
             - linux64-sccache
             - linux64-cbindgen
             - linux64-nasm
             - linux64-node
             - linux64-clang-mingw-x64
             - linux64-mingw32-nsis
             - linux64-mingw-fxc2-x86
+            - linux64-dump-syms
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -1438,29 +1438,27 @@ class Marionette(object):
         return self.switch_to_frame()
 
     def switch_to_parent_frame(self):
         """
         Switch to the Parent Frame
         """
         self._send_message("WebDriver:SwitchToParentFrame")
 
-    def switch_to_frame(self, frame=None, focus=True):
+    def switch_to_frame(self, frame=None):
         """Switch the current context to the specified frame. Subsequent
         commands will operate in the context of the specified frame,
         if applicable.
 
         :param frame: A reference to the frame to switch to.  This can
             be an :class:`~marionette_driver.marionette.HTMLElement`,
             or an integer index. If you call ``switch_to_frame`` without an
             argument, it will switch to the top-level frame.
-        :param focus: A boolean value which determins whether to focus
-            the frame that we just switched to.
         """
-        body = {"focus": focus}
+        body = {}
         if isinstance(frame, HTMLElement):
             body["element"] = frame.id
         elif frame is not None:
             body["id"] = frame
 
         self._send_message("WebDriver:SwitchToFrame", body)
 
     def get_url(self):
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1824,31 +1824,29 @@ GeckoDriver.prototype.switchToParentFram
   }
 
   await this.listener.switchToParentFrame();
 };
 
 /**
  * Switch to a given frame within the current window.
  *
- * @param {boolean=} focus
- *     Focus the frame if set to true. Defaults to false.
  * @param {(string|Object)=} element
  *     A web element reference of the frame or its element id.
  * @param {number=} id
  *     The index of the frame to switch to.
  *     If both element and id are not defined, switch to top-level frame.
  *
  * @throws {NoSuchWindowError}
  *     Browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.switchToFrame = async function(cmd) {
-  const { element: el, focus = false, id } = cmd.parameters;
+  const { element: el, id } = cmd.parameters;
 
   if (typeof id == "number") {
     assert.unsignedShort(id, `Expected id to be unsigned short, got ${id}`);
   }
 
   const top = id == null && el == null;
   assert.open(this.getBrowsingContext({ top }));
   await this._handleUserPrompts();
@@ -1912,20 +1910,16 @@ GeckoDriver.prototype.switchToFrame = as
       }
       browsingContext = context;
     }
 
     this.contentBrowsingContext = browsingContext;
 
     const frameWindow = browsingContext.window;
     await checkLoad(frameWindow);
-
-    if (focus) {
-      frameWindow.focus();
-    }
   } else if (this.context == Context.Content) {
     cmd.commandID = cmd.id;
     await this.listener.switchToFrame(cmd.parameters);
   }
 };
 
 GeckoDriver.prototype.getTimeouts = function() {
   return this.timeouts;
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -757,26 +757,24 @@ function switchToParentFrame(msg) {
   });
 
   sendOk(msg.json.commandID);
 }
 
 /**
  * Switch to the specified frame.
  *
- * @param {boolean=} focus
- *     Focus the frame if set to true. Defaults to false.
  * @param {(string|Object)=} element
  *     A web element reference of the frame or its element id.
  * @param {number=} id
  *     The index of the frame to switch to.
  *     If both element and id are not defined, switch to top-level frame.
  */
 function switchToFrame({ json }) {
-  let { commandID, element, focus, id } = json;
+  let { commandID, element, id } = json;
 
   let foundFrame;
   let wantedFrame = null;
 
   // check if curContainer.frame reference is dead
   let frames = [];
   try {
     frames = curContainer.frame.frames;
@@ -788,20 +786,16 @@ function switchToFrame({ json }) {
 
   // switch to top-level frame
   if (id == null && !element) {
     curContainer.frame = content;
     sendSyncMessage("Marionette:switchedToFrame", {
       browsingContextId: curContainer.id,
     });
 
-    if (focus) {
-      curContainer.frame.focus();
-    }
-
     sendOk(commandID);
     return;
   }
 
   let webEl;
   if (typeof element != "undefined") {
     webEl = WebElement.fromUUID(element, "content");
   }
@@ -853,20 +847,16 @@ function switchToFrame({ json }) {
           } else {
             // If foundFrame is null at this point then we have the top
             // level browsing context so should treat it accordingly.
             curContainer.frame = content;
             sendSyncMessage("Marionette:switchedToFrame", {
               browsingContextId: curContainer.id,
             });
 
-            if (focus) {
-              curContainer.frame.focus();
-            }
-
             sendOk(commandID);
             return;
           }
         }
       } catch (e) {
         // Since window.frames does not return OOP frames it will throw
         // and we land up here. Let's not give up and check if there are
         // iframes and switch to the indexed frame there
@@ -888,20 +878,16 @@ function switchToFrame({ json }) {
   }
 
   curContainer.frame = foundFrame;
 
   sendSyncMessage("Marionette:switchedToFrame", {
     browsingContextId: curContainer.id,
   });
 
-  if (focus) {
-    curContainer.frame.focus();
-  }
-
   sendOk(commandID);
 }
 
 /**
  * Returns the rect of the element to screenshot.
  *
  * Because the screen capture takes place in the parent process the dimensions
  * for the screenshot have to be determined in the appropriate child process.
--- a/testing/talos/talos/tests/devtools/addon/api.js
+++ b/testing/talos/talos/tests/devtools/addon/api.js
@@ -49,17 +49,16 @@ this.damp = class extends ExtensionAPI {
             "resource://devtools/shared/Loader.jsm"
           );
 
           // The loader should already support the damp-test path mapping.
           // We add two additional globals.
           loader.loader.globals.rootURI = rootURI;
           loader.loader.globals.dampWindow = context.appWindow;
 
-          dump("[damp-api] Instanciate the DAMP runner and start the test\n");
-          const { Damp } = require("damp-test/damp");
-          const damp = new Damp();
+          dump("[damp-api] Retrieve the DAMP runner and start the test\n");
+          const { damp } = require("damp-test/damp");
           return damp.startTest();
         },
       },
     };
   }
 };
--- a/testing/talos/talos/tests/devtools/addon/content/damp.js
+++ b/testing/talos/talos/tests/devtools/addon/content/damp.js
@@ -14,17 +14,16 @@ const {
   requestIdleCallback,
 } = dampWindow;
 
 const ChromeUtils = require("ChromeUtils");
 const Services = require("Services");
 const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
 
 const DampLoadParentModule = require("damp-test/actors/DampLoadParent.jsm");
-const dampTestHead = require("damp-test/tests/head.js");
 const DAMP_TESTS = require("damp-test/damp-tests.js");
 
 const env = Cc["@mozilla.org/process/environment;1"].getService(
   Ci.nsIEnvironment
 );
 
 // Record allocation count in new subtests if DEBUG_DEVTOOLS_ALLOCATIONS is set to
 // "normal". Print allocation sites to stdout if DEBUG_DEVTOOLS_ALLOCATIONS is set to
@@ -240,19 +239,16 @@ Damp.prototype = {
   _timeout: null,
 
   // The unix time at which the current test started (ms)
   _startTime: null,
 
   // Name of the test currently executed (i.e. path from /tests folder)
   _currentTest: null,
 
-  // Is DAMP finished executing? Help preventing async execution when DAMP had an error
-  _done: false,
-
   _runNextTest() {
     clearTimeout(this._timeout);
 
     if (this._nextTestIndex >= this._tests.length) {
       this._onSequenceComplete();
       return;
     }
 
@@ -335,16 +331,17 @@ Damp.prototype = {
       this.testDone({ testResults, testNames });
     } else {
       // alert(out);
     }
   },
 
   _doneInternal() {
     // Ignore any duplicated call to this method
+    // Call startTest() again in order to reset this flag.
     if (this._done) {
       return;
     }
     this._done = true;
 
     if (this.allocationTracker) {
       this.allocationTracker.stop();
       this.allocationTracker = null;
@@ -433,18 +430,18 @@ Damp.prototype = {
    * testing/talos/talos/tests/devtools/addon/api
    */
   startTest() {
     let promise = new Promise(resolve => {
       this.testDone = resolve;
     });
 
     try {
-      dump("Initialize the head file with a reference to this DAMP instance\n");
-      dampTestHead.initialize(this);
+      // Is DAMP finished executing? Help preventing async execution when DAMP had an error
+      this._done = false;
 
       this._registerDampLoadActors();
 
       this._win = Services.wm.getMostRecentWindow("navigator:browser");
       this._dampTab = this._win.gBrowser.selectedTab;
       this._win.gBrowser.selectedBrowser.focus(); // Unfocus the URL bar to avoid caret blink
 
       // Filter tests via `./mach --subtests filter` command line argument
@@ -533,9 +530,9 @@ Damp.prototype = {
   },
 
   _unregisterDampLoadActors() {
     dump(`[DampLoad helper] Unregister DampLoad actors\n`);
     ChromeUtils.unregisterWindowActor("DampLoad");
   },
 };
 
-exports.Damp = Damp;
+exports.damp = new Damp();
--- a/testing/talos/talos/tests/devtools/addon/content/tests/head.js
+++ b/testing/talos/talos/tests/devtools/addon/content/tests/head.js
@@ -26,23 +26,17 @@ exports.PAGES_BASE_URL = PAGES_BASE_URL;
 exports.SIMPLE_URL = PAGES_BASE_URL + "simple.html";
 
 // The test page in fis/tp5n/bild.de contains a modified version of the initial
 // bild.de test website, where same-site iframes have been replaced with remote
 // frames.
 exports.COMPLICATED_URL =
   "http://www.bild.de-talos/fis/tp5n/bild.de/www.bild.de/index.html";
 
-let damp = null;
-/*
- * This method should be called by js before starting the tests.
- */
-exports.initialize = function(_damp) {
-  damp = _damp;
-};
+const { damp } = require("damp-test/damp");
 
 function garbageCollect() {
   return damp.garbageCollect();
 }
 exports.garbageCollect = garbageCollect;
 
 function runTest(label, record) {
   return damp.runTest(label, record);
deleted file mode 100644
--- a/testing/web-platform/meta/custom-elements/parser/parser-sets-attributes-and-children.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[parser-sets-attributes-and-children.html]
-  [HTML parser should call connectedCallback before appending child nodes.]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+  <title>CSS aspect-ratio: Test flex item's resolved width/min-width with border-box box-sizing in a row flex container</title>
+  <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
+  <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+  <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
+  <link rel="match" href="../../reference/ref-filled-green-200px-square.html" />
+  <style>
+  .flexContainer {
+    display: flex;
+    flex-direction: row;
+    width: 1px;
+  }
+  .item {
+    background: green;
+    padding-top: 15px;
+    box-sizing: border-box;
+  }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+  <!-- In the following four flex containers, the aspect-ratio works with border-box. -->
+  <div class="flexContainer" style="width: auto;">
+    <!-- The border-box height 25px is transferred to the main axis,
+         yielding a resolved flex base size of 200px. -->
+    <div class="item" style="min-width:0; height: 25px; aspect-ratio: 8/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box height 25px is transferred to the main axis,
+         yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="height: 25px; aspect-ratio: 8/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box min-height 25px is transferred to the main axis,
+         yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="min-height: 25px; aspect-ratio: 8/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box height 25px (clamped by max-height) is transferred to the main axis,
+         yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="max-height: 25px; height: 100px; aspect-ratio: 8/1;"></div>
+  </div>
+
+  <!-- In the following four flex containers, the aspect-ratio works with content-box
+       because its value contains 'auto'. -->
+  <div class="flexContainer" style="width: auto;">
+    <!-- The content-box height 10px is transferred to the main axis,
+         yielding a resolved flex base size of 200px. -->
+    <div class="item" style="min-width:0; height: 25px; aspect-ratio: auto 20/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box height 10px is transferred to the main axis,
+         yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="height: 25px; aspect-ratio: auto 20/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box min-height 10px is transferred to the main axis,
+         yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="min-height: 25px; aspect-ratio: auto 20/1;"></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box height 10px (clamped by max-height) is transferred
+         to the main axis, yielding a resolved min-width:auto of 200px. -->
+    <div class="item" style="max-height: 25px; height: 100px; aspect-ratio: auto 20/1;"></div>
+  </div>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+  <title>CSS aspect-ratio: Test flex item's resolved height/min-height with border-box box-sizing in a column flex container</title>
+  <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
+  <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+  <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
+  <link rel="match" href="../../reference/ref-filled-green-200px-square.html" />
+  <style>
+  .flexContainer {
+    display: flex;
+    flex-direction: column;
+    float: left;
+    height: 1px;
+  }
+  .item {
+    background: green;
+    padding-left: 15px;
+    box-sizing: border-box;
+  }
+  .item > div {
+    height: 500px; /* Set a large content size suggestion for flex item. */
+  }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+  <!-- In the following four flex containers, the aspect-ratio works with border-box. -->
+  <div class="flexContainer" style="height: auto;">
+    <!-- The border-box width 25px is transferred to the main axis,
+         yielding a resolved flex base size of 200px. -->
+    <div class="item" style="min-height:0; width: 25px; aspect-ratio: 1/8;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box width 25px is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="width: 25px; aspect-ratio: 1/8;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box min-width 25px is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="min-width: 25px; aspect-ratio: 1/8;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The border-box width 25px (clamped by max-width) is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="max-width: 25px; width: 100px; aspect-ratio: 1/8;"><div></div></div>
+  </div>
+
+  <!-- In the following four flex containers, the aspect-ratio works with content-box
+       because its value contains 'auto'. -->
+  <div class="flexContainer" style="height: auto;">
+    <!-- The content-box width 10px is transferred to the main axis,
+         yielding a resolved flex base size of 200px. -->
+    <div class="item" style="min-height:0; width: 25px; aspect-ratio: auto 1/20;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box width 10px is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="width: 25px; aspect-ratio: auto 1/20;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box min-width 10px is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="min-width: 25px; aspect-ratio: auto 1/20;"><div></div></div>
+  </div>
+
+  <div class="flexContainer">
+    <!-- The content-box width 10px (clamped by max-width) is transferred to the main axis,
+         yielding a resolved min-height:auto of 200px. -->
+    <div class="item" style="max-width: 25px; width: 100px; aspect-ratio: auto 1/20;"><div></div></div>
+  </div>
+</html>
--- a/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
+++ b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
@@ -9,24 +9,35 @@
 <link rel="help" href="https://html.spec.whatwg.org/#document.write()">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 
-class MyCustomElement extends HTMLElement { }
+var numberOfChildNodesInConnectedCallback = 0;
+
+class MyCustomElement extends HTMLElement {
+    connectedCallback() {
+        numberOfChildNodesInConnectedCallback = this.childNodes.length;
+    }
+}
 customElements.define('my-custom-element', MyCustomElement);
 
-document.write('<my-custom-element></my-custom-element>');
+document.write('<my-custom-element>hello <b>world</b></my-custom-element>');
 
 test(function () {
     var instance = document.querySelector('my-custom-element');
 
     assert_true(instance instanceof HTMLElement);
     assert_true(instance instanceof MyCustomElement);
 
 }, 'HTML parser must instantiate custom elements inside document.write');
 
+test(function () {
+  assert_equals(numberOfChildNodesInConnectedCallback, 0);
+
+}, 'HTML parser should call connectedCallback before appending child nodes inside document.write');
+
 </script>
 </body>
 </html>
--- a/testing/web-platform/tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html
+++ b/testing/web-platform/tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html
@@ -29,37 +29,37 @@ test(function() {
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP);
   assert_equals(feCompositeElement.getAttribute('operator'), "atop");
 
   // Switch to 'xor'
   feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR;
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR);
   assert_equals(feCompositeElement.getAttribute('operator'), "xor");
 
+  // Switch to 'lighter'.
+  feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER;
+  assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER);
+  assert_equals(feCompositeElement.getAttribute('operator'), "lighter");
+
   // Switch to 'arithmetic'.
   feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC;
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
   assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
 
   // Try setting invalid values.
-  assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = 7; });
+  assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = 8; });
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
   assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
 
   assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = -1; });
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
   assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
 
   assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = 0; });
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
   assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
 
   // Switch to 'over'.
   feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER;
   assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
   assert_equals(feCompositeElement.getAttribute('operator'), "over");
-
-  // Switch to 'lighter'.
-  assert_equals(SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER, undefined);
-  feCompositeElement.setAttribute("operator", "lighter");
-  assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_UNKNOWN);
 });
-</script>
\ No newline at end of file
+</script>
--- a/toolkit/components/aboutmemory/content/aboutMemory.css
+++ b/toolkit/components/aboutmemory/content/aboutMemory.css
@@ -1,15 +1,15 @@
 /* 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/. */
 
 /*
  * The version used for mobile is located at
- * mobile/android/themes/core/aboutMemory.css.
+ * toolkit/themes/mobile/global/aboutMemory.css.
  * Desktop-specific stuff is at the bottom of this file.
  */
 
 html {
   background: -moz-Dialog;
   color: -moz-DialogText;
   font: message-box;
 }
--- a/toolkit/components/bitsdownload/Cargo.toml
+++ b/toolkit/components/bitsdownload/Cargo.toml
@@ -3,18 +3,14 @@ name = "bitsdownload"
 version = "0.1.0"
 authors = ["Kirk Steuber <bytesized@mozilla.com>"]
 license = "MPL-2.0"
 
 [dependencies]
 bits_client = { path = "./bits_client" }
 comedy = "0.2.0"
 crossbeam-utils = "0.6.3"
-failure_derive = "0.1.3"
 libc = "0.2"
 log = "0.4"
 moz_task = { path = "../../../xpcom/rust/moz_task" }
 nserror = { path = "../../../xpcom/rust/nserror" }
 nsstring = { path = "../../../xpcom/rust/nsstring" }
 xpcom = { path = "../../../xpcom/rust/xpcom" }
-
-[dependencies.failure]
-version = "0.1.3"
--- a/toolkit/components/bitsdownload/bits_client/Cargo.toml
+++ b/toolkit/components/bitsdownload/bits_client/Cargo.toml
@@ -4,21 +4,16 @@ version = "0.2.0"
 authors = ["Adam Gashlin <agashlin@mozilla.com>"]
 license = "MPL-2.0"
 publish = false
 
 [dependencies]
 bits = { path = "./bits" }
 comedy = "0.2.0"
 guid_win = "0.2.0"
-
-[dependencies.failure]
-version = "0.1.3"
-
-[dependencies.failure_derive]
-version = "0.1.3"
+thiserror = "1"
 
 [dev-dependencies]
 #ctrlc = "3.1.1"
 lazy_static = "1.0.1"
 rand = "0.7"
 regex = { version = "1", default_features = false, features = ["perf", "std"] }
 tempfile = "3"
--- a/toolkit/components/bitsdownload/bits_client/examples/test_client.rs
+++ b/toolkit/components/bitsdownload/bits_client/examples/test_client.rs
@@ -1,85 +1,61 @@
 /* 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 https://mozilla.org/MPL/2.0/. */
 
 extern crate bits_client;
 extern crate comedy;
 //extern crate ctrlc;
-extern crate failure;
-extern crate failure_derive;
 extern crate guid_win;
+extern crate thiserror;
 
-use std::convert;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::process;
 use std::str::FromStr;
 use std::sync::{Arc, Mutex};
 
-use failure::{AsFail, Fail};
+use thiserror::Error;
 
 use bits_client::bits_protocol::HResultMessage;
 use bits_client::{BitsClient, BitsJobState, BitsMonitorClient, BitsProxyUsage, Guid, PipeError};
 
-#[derive(Debug, Fail)]
+#[derive(Debug, Error)]
 enum MyError {
-    #[fail(display = "{}", _0)]
+    #[error("{0}")]
     Msg(String),
-    #[fail(display = "HResult")]
-    HResult(#[fail(cause)] comedy::HResult),
-    #[fail(display = "Win32Error")]
-    Win32Error(#[fail(cause)] comedy::Win32Error),
-    #[fail(display = "PipeError")]
-    PipeError(#[fail(cause)] PipeError),
-    #[fail(display = "HResultMessage")]
-    HResultMessage(#[fail(cause)] HResultMessage),
-}
-
-impl convert::From<PipeError> for MyError {
-    fn from(err: PipeError) -> MyError {
-        MyError::PipeError(err)
-    }
-}
-
-impl convert::From<comedy::HResult> for MyError {
-    fn from(err: comedy::HResult) -> MyError {
-        MyError::HResult(err)
-    }
-}
-
-impl convert::From<comedy::Win32Error> for MyError {
-    fn from(err: comedy::Win32Error) -> MyError {
-        MyError::Win32Error(err)
-    }
-}
-
-impl convert::From<HResultMessage> for MyError {
-    fn from(err: HResultMessage) -> MyError {
-        MyError::HResultMessage(err)
-    }
+    #[error("HResult")]
+    HResult(#[from] comedy::HResult),
+    #[error("Win32Error")]
+    Win32Error(#[from] comedy::Win32Error),
+    #[error("PipeError")]
+    PipeError(#[from] PipeError),
+    #[error("HResultMessage")]
+    HResultMessage(#[from] HResultMessage),
 }
 
 macro_rules! bail {
     ($e:expr) => {
         return Err($crate::MyError::Msg($e.to_string()));
     };
     ($fmt:expr, $($arg:tt)*) => {
         return Err($crate::MyError::Msg(format!($fmt, $($arg)*)));
     };
 }
 
 type Result = std::result::Result<(), MyError>;
 
 pub fn main() {
     if let Err(err) = entry() {
         eprintln!("{}", err);
-        for cause in err.as_fail().iter_causes() {
-            eprintln!("caused by {}", cause);
+        let mut err: &dyn std::error::Error = &err;
+        while let Some(source) = err.source() {
+            eprintln!("caused by {}", source);
+            err = source;
         }
 
         process::exit(1);
     } else {
         println!("OK");
     }
 }
 
--- a/toolkit/components/bitsdownload/bits_client/src/bits_protocol.rs
+++ b/toolkit/components/bitsdownload/bits_client/src/bits_protocol.rs
@@ -1,38 +1,41 @@
 /* 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 https://mozilla.org/MPL/2.0/. */
 
 //! Command, response, and status types.
 
 use std::ffi::OsString;
+use std::error::Error as StdError;
 use std::fmt;
 use std::result;
 
-use failure::Fail;
 use guid_win::Guid;
+use thiserror::Error;
 
 use super::{BitsErrorContext, BitsJobProgress, BitsJobState, BitsJobTimes, BitsProxyUsage};
 
 type HRESULT = i32;
 
 /// An HRESULT with a descriptive message
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug)]
 pub struct HResultMessage {
     pub hr: HRESULT,
     pub message: String,
 }
 
 impl fmt::Display for HResultMessage {
     fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
         self.message.fmt(f)
     }
 }
 
+impl StdError for HResultMessage {}
+
 /// Commands which can be sent to the server.
 ///
 /// This is currently unused as the out-of-process Local Service server is not finished.
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub enum Command {
     StartJob(StartJobCommand),
     MonitorJob(MonitorJobCommand),
@@ -44,17 +47,17 @@ pub enum Command {
     CompleteJob(CompleteJobCommand),
     CancelJob(CancelJobCommand),
 }
 
 /// Combine a [`Command`](enum.Command.html) with its success and failure result types.
 #[doc(hidden)]
 pub trait CommandType {
     type Success;
-    type Failure: Fail;
+    type Failure: StdError;
     fn wrap(command: Self) -> Command;
 }
 
 // Start Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct StartJobCommand {
     pub url: OsString,
@@ -79,33 +82,33 @@ pub struct MonitorConfig {
     pub interval_millis: u32,
 }
 
 #[derive(Clone, Debug)]
 pub struct StartJobSuccess {
     pub guid: Guid,
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum StartJobFailure {
-    #[fail(display = "Argument validation failed: {}", _0)]
+    #[error("Argument validation failed: {0}")]
     ArgumentValidation(String),
-    #[fail(display = "Create job: {}", _0)]
+    #[error("Create job: {0}")]
     Create(HResultMessage),
-    #[fail(display = "Add file to job: {}", _0)]
+    #[error("Add file to job: {0}")]
     AddFile(HResultMessage),
-    #[fail(display = "Apply settings to job: {}", _0)]
+    #[error("Apply settings to job: {0}")]
     ApplySettings(HResultMessage),
-    #[fail(display = "Resume job: {}", _0)]
+    #[error("Resume job: {0}")]
     Resume(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Monitor Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct MonitorJobCommand {
     pub guid: Guid,
@@ -115,29 +118,29 @@ pub struct MonitorJobCommand {
 impl CommandType for MonitorJobCommand {
     type Success = ();
     type Failure = MonitorJobFailure;
     fn wrap(cmd: Self) -> Command {
         Command::MonitorJob(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum MonitorJobFailure {
-    #[fail(display = "Argument validation failed: {}", _0)]
+    #[error("Argument validation failed: {0}")]
     ArgumentValidation(String),
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Suspend Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct SuspendJobCommand {
     pub guid: Guid,
@@ -146,29 +149,29 @@ pub struct SuspendJobCommand {
 impl CommandType for SuspendJobCommand {
     type Success = ();
     type Failure = SuspendJobFailure;
     fn wrap(cmd: Self) -> Command {
         Command::SuspendJob(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum SuspendJobFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Suspend job: {}", _0)]
+    #[error("Suspend job: {0}")]
     SuspendJob(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Resume Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct ResumeJobCommand {
     pub guid: Guid,
@@ -177,29 +180,29 @@ pub struct ResumeJobCommand {
 impl CommandType for ResumeJobCommand {
     type Success = ();
     type Failure = ResumeJobFailure;
     fn wrap(cmd: Self) -> Command {
         Command::ResumeJob(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum ResumeJobFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Resume job: {}", _0)]
+    #[error("Resume job: {0}")]
     ResumeJob(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Set Job Priority
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct SetJobPriorityCommand {
     pub guid: Guid,
@@ -209,29 +212,29 @@ pub struct SetJobPriorityCommand {
 impl CommandType for SetJobPriorityCommand {
     type Success = ();
     type Failure = SetJobPriorityFailure;
     fn wrap(cmd: Self) -> Command {
         Command::SetJobPriority(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum SetJobPriorityFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Apply settings to job: {}", _0)]
+    #[error("Apply settings to job: {0}")]
     ApplySettings(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Set No Progress Timeout
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct SetNoProgressTimeoutCommand {
     pub guid: Guid,
@@ -241,29 +244,29 @@ pub struct SetNoProgressTimeoutCommand {
 impl CommandType for SetNoProgressTimeoutCommand {
     type Success = ();
     type Failure = SetNoProgressTimeoutFailure;
     fn wrap(cmd: Self) -> Command {
         Command::SetNoProgressTimeout(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum SetNoProgressTimeoutFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Apply settings to job: {}", _0)]
+    #[error("Apply settings to job: {0}")]
     ApplySettings(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Set Update Interval
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct SetUpdateIntervalCommand {
     pub guid: Guid,
@@ -273,23 +276,23 @@ pub struct SetUpdateIntervalCommand {
 impl CommandType for SetUpdateIntervalCommand {
     type Success = ();
     type Failure = SetUpdateIntervalFailure;
     fn wrap(cmd: Self) -> Command {
         Command::SetUpdateInterval(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum SetUpdateIntervalFailure {
-    #[fail(display = "Argument validation: {}", _0)]
+    #[error("Argument validation: {0}")]
     ArgumentValidation(String),
-    #[fail(display = "Monitor not found")]
+    #[error("Monitor not found")]
     NotFound,
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Complete Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct CompleteJobCommand {
     pub guid: Guid,
@@ -298,31 +301,31 @@ pub struct CompleteJobCommand {
 impl CommandType for CompleteJobCommand {
     type Success = ();
     type Failure = CompleteJobFailure;
     fn wrap(cmd: Self) -> Command {
         Command::CompleteJob(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum CompleteJobFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Complete job: {}", _0)]
+    #[error("Complete job: {0}")]
     CompleteJob(HResultMessage),
-    #[fail(display = "Job only partially completed")]
+    #[error("Job only partially completed")]
     PartialComplete,
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 // Cancel Job
 #[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct CancelJobCommand {
     pub guid: Guid,
@@ -331,29 +334,29 @@ pub struct CancelJobCommand {
 impl CommandType for CancelJobCommand {
     type Success = ();
     type Failure = CancelJobFailure;
     fn wrap(cmd: Self) -> Command {
         Command::CancelJob(cmd)
     }
 }
 
-#[derive(Clone, Debug, Fail)]
+#[derive(Clone, Debug, Error)]
 pub enum CancelJobFailure {
-    #[fail(display = "Job not found")]
+    #[error("Job not found")]
     NotFound,
-    #[fail(display = "Get job: {}", _0)]
+    #[error("Get job: {0}")]
     GetJob(HResultMessage),
-    #[fail(display = "Cancel job: {}", _0)]
+    #[error("Cancel job: {0}")]
     CancelJob(HResultMessage),
-    #[fail(display = "Connect to BackgroundCopyManager: {}", _0)]
+    #[error("Connect to BackgroundCopyManager: {0}")]
     ConnectBcm(HResultMessage),
-    #[fail(display = "BITS error: {}", _0)]
+    #[error("BITS error: {0}")]
     OtherBITS(HResultMessage),
-    #[fail(display = "Other failure: {}", _0)]
+    #[error("Other failure: {0}")]
     Other(String),
 }
 
 /// Job status report
 ///
 /// This includes a URL which updates with redirect but is otherwise the same as
 /// `bits::status::BitsJobStatus`.
 #[derive(Clone, Debug)]
@@ -363,15 +366,15 @@ pub struct JobStatus {
     pub error_count: u32,
     pub error: Option<JobError>,
     pub times: BitsJobTimes,
     /// None means same as last time
     pub url: Option<OsString>,
 }
 
 /// Job error report
-#[derive(Clone, Debug, Fail)]
-#[fail(display = "Job error in context {}: {}", context_str, error)]
+#[derive(Clone, Debug, Error)]
+#[error("Job error in context {context_str}: {error}")]
 pub struct JobError {
     pub context: BitsErrorContext,
     pub context_str: String,
     pub error: HResultMessage,
 }
--- a/toolkit/components/bitsdownload/bits_client/src/lib.rs
+++ b/toolkit/components/bitsdownload/bits_client/src/lib.rs
@@ -12,54 +12,46 @@
 //! [`BitsMonitorClient`](enum.BitsMonitorClient.html) delivers periodic status reports about a
 //! job.
 //!
 //! Microsoft's documentation for BITS can be found at
 //! <https://docs.microsoft.com/en-us/windows/desktop/Bits/background-intelligent-transfer-service-portal>
 
 extern crate bits;
 extern crate comedy;
-extern crate failure;
-extern crate failure_derive;
 extern crate guid_win;
+extern crate thiserror;
 
 pub mod bits_protocol;
 
 mod in_process;
 
-use std::convert;
 use std::ffi;
 
 use bits_protocol::*;
-use failure::Fail;
+use thiserror::Error;
 
 pub use bits::status::{BitsErrorContext, BitsJobState, BitsJobTimes};
 pub use bits::{BitsJobProgress, BitsJobStatus, BitsProxyUsage};
 pub use bits_protocol::{JobError, JobStatus};
 pub use comedy::HResult;
 pub use guid_win::Guid;
 
 // These errors would come from a Local Service client but are mostly unused currently.
 // PipeError properly lives in the crate that deals with named pipes, but it isn't in use now.
-#[derive(Clone, Debug, Eq, Fail, PartialEq)]
+#[derive(Clone, Debug, Eq, Error, PartialEq)]
 pub enum PipeError {
-    #[fail(display = "Pipe is not connected")]
+    #[error("Pipe is not connected")]
     NotConnected,
-    #[fail(display = "Operation timed out")]
+    #[error("Operation timed out")]
     Timeout,
-    #[fail(display = "Should have written {} bytes, wrote {}", _0, _1)]
+    #[error("Should have written {0} bytes, wrote {1}")]
     WriteCount(usize, u32),
-    #[fail(display = "Windows API error")]
-    Api(#[fail(cause)] HResult),
-}
-
-impl convert::From<HResult> for PipeError {
-    fn from(err: HResult) -> PipeError {
-        PipeError::Api(err)
-    }
+    #[error("Windows API error")]
+    Api(#[from] HResult),
 }
 
 pub use PipeError as Error;
 
 /// A client for interacting with BITS.
 ///
 /// Methods on `BitsClient` return a `Result<Result<_, XyzFailure>, Error>`. The outer `Result`
 /// is `Err` if there was a communication error in sending the associated command or receiving
--- a/toolkit/components/bitsdownload/src/lib.rs
+++ b/toolkit/components/bitsdownload/src/lib.rs
@@ -8,17 +8,16 @@
 //! BITS (Background Intelligent Transfer Service). Further documentation can
 //! be found in the XPCOM interface definition, located in nsIBits.idl
 
 #![cfg(target_os = "windows")]
 
 extern crate bits_client;
 extern crate comedy;
 extern crate crossbeam_utils;
-extern crate failure;
 extern crate libc;
 extern crate log;
 extern crate moz_task;
 extern crate nserror;
 extern crate nsstring;
 extern crate xpcom;
 
 pub mod bits_interface;
--- a/tools/moztreedocs/requirements.in
+++ b/tools/moztreedocs/requirements.in
@@ -39,17 +39,17 @@ scandir==1.10.0
 sentry-sdk==0.14.3
 singledispatch==3.4.0.3
 six==1.15.0
 snowballstemmer==2.0.0
 Sphinx==3.4.2
 sphinx-copybutton==0.3.1
 sphinx-js==3.0.1
 sphinx-markdown-tables==0.0.15
-sphinx-rtd-theme==0.5.0
+sphinx-rtd-theme==0.5.1
 sphinxcontrib-applehelp==1.0.2
 sphinxcontrib-devhelp==1.0.2
 sphinxcontrib-htmlhelp==1.0.3
 sphinxcontrib-jsmath==1.0.1
 sphinxcontrib-mermaid==0.5.0
 sphinxcontrib-qthelp==1.0.3
 sphinxcontrib-serializinghtml==1.1.4
 tornado==6.0.4
--- a/tools/moztreedocs/requirements.txt
+++ b/tools/moztreedocs/requirements.txt
@@ -227,20 +227,19 @@ sphinx-copybutton==0.3.1 \
 sphinx-js==3.0.1 \
     --hash=sha256:00d8d8bb4fe0e4c8cf940c7412af257c7fb83eaedc69d79765f9a012d719ce20 \
     --hash=sha256:6dd8e79c5ad09fef389af5021d7a672066f6e12a51130497f6c611544d62734b \
     # via -r requirements.in
 sphinx-markdown-tables==0.0.15 \
     --hash=sha256:24a37662d86ee8bceb7d4f7003df0b25bc52401369d1ddc40d13ae7b58697031 \
     --hash=sha256:c5f423a018aed9447aad1fbbada32c21c7565183aaf2da3c7fdb7bf4dffa3a0b \
     # via -r requirements.in
-sphinx-rtd-theme==0.5.0 \
-    --hash=sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d \
-    --hash=sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82 \
-    # via -r requirements.in
+sphinx-rtd-theme==0.5.1 \
+    --hash=sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5 \
+    --hash=sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113
 Sphinx==3.4.2 \
     --hash=sha256:77dec5ac77ca46eee54f59cf477780f4fb23327b3339ef39c8471abb829c1285 \
     --hash=sha256:b8aa4eb5502c53d3b5ca13a07abeedacd887f7770c198952fd5b9530d973e767
 sphinxcontrib-applehelp==1.0.2 \
     --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \
     --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 \
     # via -r requirements.in, sphinx
 sphinxcontrib-devhelp==1.0.2 \
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -1426,16 +1426,17 @@ STATIC_ATOMS = [
     Atom("k2", "k2"),
     Atom("k3", "k3"),
     Atom("k4", "k4"),
     Atom("kernelMatrix", "kernelMatrix"),
     Atom("kernelUnitLength", "kernelUnitLength"),
     Atom("lengthAdjust", "lengthAdjust"),
     Atom("letter_spacing", "letter-spacing"),
     Atom("lighten", "lighten"),
+    Atom("lighter", "lighter"),
     Atom("lighting_color", "lighting-color"),
     Atom("limitingConeAngle", "limitingConeAngle"),
     Atom("linear", "linear"),
     Atom("linearGradient", "linearGradient"),
     Atom("list_item", "list-item"),
     Atom("list_style_type", "list-style-type"),
     Atom("luminanceToAlpha", "luminanceToAlpha"),
     Atom("luminosity", "luminosity"),