merge mozilla-central to autoland. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 05 Sep 2017 12:37:56 +0200
changeset 428383 6f458218dda9687d1405cb6a894f89ddfc2336f8
parent 428382 f12d13ff72de26051890ebd07d423b28579c8087 (current diff)
parent 428369 3ecda4678c49ca255c38b1697142b9118cdd27e7 (diff)
child 428384 e6f46ebcbd90cd87a8e8a66252d2c831f9037970
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-central to autoland. r=merge a=merge
testing/web-platform/meta/IndexedDB/idb-binary-key-roundtrip.htm.ini
testing/web-platform/meta/IndexedDB/idbcursor-continuePrimaryKey.htm.ini
xpcom/ds/nsAtomService.cpp
xpcom/ds/nsAtomService.h
xpcom/ds/nsIAtomService.idl
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -69,18 +69,16 @@ file, You can obtain one at http://mozil
                                 .getService(Components.interfaces.nsIPrefService)
                                 .getBranch("browser.urlbar.");
         this._prefs.addObserver("", this);
 
         this._defaultPrefs = Components.classes["@mozilla.org/preferences-service;1"]
                                        .getService(Components.interfaces.nsIPrefService)
                                        .getDefaultBranch("browser.urlbar.");
 
-        Services.prefs.addObserver("browser.search.openintab", this);
-        this.browserSearchOpenInTab = Services.prefs.getBoolPref("browser.search.openintab");
         Services.prefs.addObserver("browser.search.suggest.enabled", this);
         this.browserSearchSuggestEnabled = Services.prefs.getBoolPref("browser.search.suggest.enabled");
 
         this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
         this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
         this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
         this.speculativeConnectEnabled = this._prefs.getBoolPref("speculativeConnect.enabled");
         this.urlbarSearchSuggestEnabled = this._prefs.getBoolPref("suggest.searches");
@@ -134,17 +132,16 @@ file, You can obtain one at http://mozil
         // to handle cases like backspace, autofill or repeated searches.
         // Ensure to clear those internal caches when switching tabs.
         gBrowser.tabContainer.addEventListener("TabSelect", this);
       ]]></constructor>
 
       <destructor><![CDATA[
         this._prefs.removeObserver("", this);
         this._prefs = null;
-        Services.prefs.removeObserver("browser.search.openintab", this);
         Services.prefs.removeObserver("browser.search.suggest.enabled", this);
         this.inputField.controllers.removeController(this._copyCutController);
         this.inputField.removeEventListener("paste", this);
         this.inputField.removeEventListener("mousedown", this);
         this.inputField.removeEventListener("mousemove", this);
         this.inputField.removeEventListener("mouseout", this);
         this.inputField.removeEventListener("overflow", this);
         this.inputField.removeEventListener("underflow", this);
@@ -561,18 +558,16 @@ file, You can obtain one at http://mozil
             selectedOneOff.doCommand();
             return;
           }
 
           let where = openUILinkWhere;
           if (!where) {
             if (isMouseEvent) {
               where = whereToOpenLink(event, false, false);
-            } else if (this.browserSearchOpenInTab) {
-              where = "tab";
             } else {
               // If the current tab is empty, ignore Alt+Enter (reuse this tab)
               let altEnter = !isMouseEvent &&
                              event &&
                              event.altKey &&
                              !isTabEmpty(gBrowser.selectedTab);
               where = altEnter ? "tab" : "current";
             }
@@ -1099,19 +1094,16 @@ file, You can obtain one at http://mozil
                 this.timeout = this._prefs.getIntPref(aData);
                 break;
               case "formatting.enabled":
                 this._formattingEnabled = this._prefs.getBoolPref(aData);
                 break;
               case "speculativeConnect.enabled":
                 this.speculativeConnectEnabled = this._prefs.getBoolPref(aData);
                 break;
-              case "browser.search.openintab":
-                this.browserSearchOpenInTab = Services.prefs.getBoolPref(aData);
-                break;
               case "browser.search.suggest.enabled":
                 this.browserSearchSuggestEnabled = Services.prefs.getBoolPref(aData);
                 break;
               case "suggest.searches":
                 this.urlbarSearchSuggestEnabled = this._prefs.getBoolPref(aData);
               case "userMadeSearchSuggestionsChoice":
                 // Mirror the value for future use, see the comment in the
                 // binding's constructor.
@@ -2000,16 +1992,17 @@ file, You can obtain one at http://mozil
           // around that problem by disabling the listbox animation.
           this.richlistbox.flex = 0;
           this.setAttribute("dontanimate", "true");
 
           this.classList.add("showSearchSuggestionsNotification");
           // Don't show the one-off buttons if we are showing onboarding and
           // there's no result, since it would be ugly and pointless.
           this.footer.collapsed = this._matchCount == 0;
+          this.input.tabScrolling = this._matchCount != 0;
 
           // This event allows accessibility APIs to see the notification.
           if (!this.popupOpen) {
             let event = document.createEvent("Events");
             event.initEvent("AlertActive", true, true);
             this.searchSuggestionsNotification.dispatchEvent(event);
           }
           ]]>
@@ -2218,16 +2211,17 @@ file, You can obtain one at http://mozil
                 let engine = Services.search.currentEngine;
                 engine.speculativeConnect({window,
                                            originAttributes: gBrowser.contentPrincipal.originAttributes});
               }
             }
 
             // When a result is present the footer should always be visible.
             this.footer.collapsed = false;
+            this.input.tabScrolling = true;
 
             this.input.gotResultForCurrentQuery = true;
             this.input.maybeReplayDeferredKeyEvents();
           ]]>
         </body>
       </method>
 
       <method name="_onSearchBegin">
--- a/browser/components/extensions/ext-browser.js
+++ b/browser/components/extensions/ext-browser.js
@@ -718,17 +718,17 @@ class Window extends WindowBase {
 
     if (options.width !== null || options.height !== null) {
       let width = options.width !== null ? options.width : window.outerWidth;
       let height = options.height !== null ? options.height : window.outerHeight;
       window.resizeTo(width, height);
     }
   }
 
-  get title() {
+  get _title() {
     return this.window.document.title;
   }
 
   setTitlePreface(titlePreface) {
     this.window.document.documentElement.setAttribute("titlepreface", titlePreface);
   }
 
   get focused() {
@@ -823,16 +823,22 @@ class Window extends WindowBase {
   * getTabs() {
     let {tabManager} = this.extension;
 
     for (let nativeTab of this.window.gBrowser.tabs) {
       yield tabManager.getWrapper(nativeTab);
     }
   }
 
+  get activeTab() {
+    let {tabManager} = this.extension;
+
+    return tabManager.getWrapper(this.window.gBrowser.selectedTab);
+  }
+
   /**
    * Converts session store data to an object compatible with the return value
    * of the convert() method, representing that data.
    *
    * @param {Extension} extension
    *        The extension for which to convert the data.
    * @param {Object} windowData
    *        Session store data for a closed window, as returned by
--- a/browser/components/extensions/test/browser/browser_ext_windows.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows.js
@@ -59,16 +59,19 @@ add_task(async function testWindowTitle(
                               "Window has the expected title text after update.");
         browser.test.sendMessage("updated", win);
       }
     });
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     background,
+    manifest: {
+      permissions: ["tabs"],
+    },
   });
 
   await extension.startup();
   let {Management: {global: {windowTracker}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
 
   async function createApiWin(options) {
     let promiseLoaded = BrowserTestUtils.waitForNewWindow(true, START_URL);
     extension.sendMessage("create", options);
@@ -134,16 +137,67 @@ add_task(async function testWindowTitle(
       text: NEW_TITLE,
     },
   };
   await updateWindow({titlePreface: PREFACE2}, apiWin, expected);
 
   await extension.unload();
 });
 
+// Test that the window title is only available with the correct tab
+// permissions.
+add_task(async function testWindowTitlePermissions() {
+  let tab = await BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.com/");
+
+  let extension = ExtensionTestUtils.loadExtension({
+    async background() {
+      function awaitMessage(name) {
+        return new Promise(resolve => {
+          browser.test.onMessage.addListener(function listener(...msg) {
+            if (msg[0] === name) {
+              browser.test.onMessage.removeListener(listener);
+              resolve(msg[1]);
+            }
+          });
+        });
+      }
+
+      let window = await browser.windows.getCurrent();
+
+      browser.test.assertEq(undefined, window.title,
+                            "Window title should be null without tab permission");
+
+      browser.test.sendMessage("grant-activeTab");
+      let expectedTitle = await awaitMessage("title");
+
+      window = await browser.windows.getCurrent();
+      browser.test.assertEq(expectedTitle, window.title,
+                            "Window should have the expected title with tab permission granted");
+
+      await browser.test.notifyPass("window-title-permissions");
+    },
+    manifest: {
+      permissions: ["activeTab"],
+      browser_action: {},
+    },
+  });
+
+  await extension.startup();
+
+  await extension.awaitMessage("grant-activeTab");
+  await clickBrowserAction(extension);
+  extension.sendMessage("title", document.title);
+
+  await extension.awaitFinish("window-title-permissions");
+
+  await extension.unload();
+
+  await BrowserTestUtils.removeTab(tab);
+});
+
 add_task(async function testInvalidWindowId() {
   let extension = ExtensionTestUtils.loadExtension({
     async background() {
       await browser.test.assertRejects(
         // Assuming that this windowId does not exist.
         browser.windows.get(123456789),
         /Invalid window/,
         "Should receive invalid window");
--- a/devtools/client/inspector/layout/components/Accordion.css
+++ b/devtools/client/inspector/layout/components/Accordion.css
@@ -12,17 +12,17 @@
   width: 100%;
 }
 
 .accordion ._header {
   background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   cursor: pointer;
   font-size: 12px;
-  padding: 5px;
+  padding: 4px;
   transition: all 0.25s ease;
   width: 100%;
   align-items: center;
   display: flex;
 
   -moz-user-select: none;
 }
 
--- a/devtools/client/shared/developer-toolbar.js
+++ b/devtools/client/shared/developer-toolbar.js
@@ -221,16 +221,17 @@ Object.defineProperty(DeveloperToolbar.p
  */
 DeveloperToolbar.prototype.createToolbar = function () {
   if (this._element) {
     return;
   }
   let toolbar = this._doc.createElement("toolbar");
   toolbar.setAttribute("id", "developer-toolbar");
   toolbar.setAttribute("hidden", "true");
+  toolbar.setAttribute("fullscreentoolbar", "true");
 
   let close = this._doc.createElement("toolbarbutton");
   close.setAttribute("id", "developer-toolbar-closebutton");
   close.setAttribute("class", "close-icon");
   close.addEventListener("command", (event) => {
     this.hide();
   });
   let closeTooltip = L10N.getStr("toolbar.closeButton.tooltip");
--- a/devtools/client/themes/inspector.css
+++ b/devtools/client/themes/inspector.css
@@ -6,24 +6,16 @@
 :root {
   --eyedropper-image: url(images/command-eyedropper.svg);
 }
 
 .theme-firebug {
   --eyedropper-image: url(images/firebug/command-eyedropper.svg);
 }
 
-:root.theme-light {
-  --breadcrumbs-border-color: #f3f3f3;
-}
-
-:root.theme-dark {
-  --breadcrumbs-border-color: #454d5d;
-}
-
 * {
   box-sizing: border-box;
 }
 
 /* Make sure to hide scroll bars for the parent window */
 window {
   overflow: hidden;
 }
@@ -119,20 +111,18 @@ window {
 #inspector-sidebar-toggle-box {
   line-height: initial;
 }
 
 #inspector-breadcrumbs-toolbar {
   padding: 0px;
   border-bottom-width: 0px;
   border-top-width: 1px;
-  border-top-color: var(--breadcrumbs-border-color);
-  /* Bug 1262668 - Use the same background as the body so the breadcrumbs toolbar doesn't
-     get mistaken as a splitter */
-  background-color: var(--theme-body-background);
+  border-top-color: var(--theme-splitter-color);
+  background-color: var(--theme-toolbar-background);
   display: block;
   position: relative;
 }
 
 #inspector-breadcrumbs-toolbar,
 #inspector-breadcrumbs-toolbar * {
   box-sizing: border-box;
 }
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -217,17 +217,17 @@
 .ruleview-rule-source:not([unselectable]):hover {
   text-decoration: underline;
 }
 
 .ruleview-header {
   background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   font-size: 12px;
-  padding: 5px;
+  padding: 4px;
   width: 100%;
   align-items: center;
   display: flex;
 
   -moz-user-select: none;
 }
 
 .theme-firebug .ruleview-header {
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -38,24 +38,21 @@
   --command-rulers-image: url(images/firebug/command-rulers.svg);
   --command-measure-image: url(images/firebug/command-measure.svg);
 }
 
 /* Toolbox tabbar */
 
 .devtools-tabbar {
   -moz-appearance: none;
+  display: flex;
+  background: var(--theme-tab-toolbar-background);
+  border-bottom: 1px solid var(--theme-splitter-color);
+  box-sizing: border-box;
   min-height: 29px;
-  border: 0px solid;
-  border-bottom-width: 1px;
-  padding: 0;
-  background: var(--theme-tab-toolbar-background);
-  border-bottom-color: var(--theme-splitter-color);
-  display: flex;
-  box-sizing: border-box;
 }
 
 .toolbox-tabs-wrapper {
   position: relative;
   display: flex;
   flex: 1;
 }
 
@@ -140,22 +137,20 @@
 
 /* Save space on the tab-strip in Firebug theme */
 .theme-firebug .devtools-tab {
   -moz-box-flex: initial;
 }
 
 .theme-dark .devtools-tab {
   color: var(--theme-body-color-alt);
-  border-color: #42484f;
 }
 
 .theme-light .devtools-tab {
   color: var(--theme-body-color);
-  border-color: var(--theme-splitter-color);
 }
 
 .theme-dark .devtools-tab:hover {
   color: #ced3d9;
 }
 
 .devtools-tab:hover {
   background-color: var(--theme-toolbar-hover);
@@ -210,31 +205,16 @@
 }
 
 .devtools-tab:hover > img,
 .devtools-tab:active > img,
 .devtools-tab.selected > img {
   opacity: 1;
 }
 
-.toolbox-tabs .devtools-tab.selected,
-.toolbox-tabs .devtools-tab.highlighted,
-.toolbox-tabs .devtools-tab.selected + .devtools-tab,
-.toolbox-tabs .devtools-tab.highlighted + .devtools-tab {
-  border-inline-start-color: transparent;
-}
-
-.toolbox-tabs .devtools-tab:first-child {
-  border-inline-start-width: 0;
-}
-
-.toolbox-tabs .devtools-tab:last-child {
-  border-inline-end-width: 1px;
-}
-
 .devtools-tab:not(.highlighted) > .highlighted-icon,
 .devtools-tab.selected > .highlighted-icon,
 .devtools-tab:not(.selected).highlighted > .default-icon {
   display: none;
 }
 
 /* The options tab is special - it doesn't have the same parent
    as the other tabs (toolbox-option-container vs toolbox-tabs) */
@@ -275,25 +255,16 @@
 #toolbox-dock-bottom-minimize::before {
   background-image: url("chrome://devtools/skin/images/dock-bottom-minimize@2x.png");
 }
 
 #toolbox-dock-bottom-minimize.minimized::before {
   background-image: url("chrome://devtools/skin/images/dock-bottom-maximize@2x.png");
 }
 
-/**
- * Ensure that when the toolbar collapses in on itself when there is not enough room
- * that it still looks reasonable.
- */
-.devtools-tabbar > div {
-  background-color: var(--theme-tab-toolbar-background);
-  z-index: 0;
-}
-
 /* Command buttons */
 
 .command-button,
 #toolbox-controls > button,
 #toolbox-dock-buttons > button {
   /* !important is needed to override .devtools-button rules in common.css */
   padding: 0 !important;
   margin: 0 !important;
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -16,22 +16,25 @@
  * so the formatting should be consistent (i.e. no '}' inside a rule).
  */
 
 :root.theme-light {
   --theme-body-background: white;
   --theme-sidebar-background: white;
   --theme-contrast-background: #e6b064;
 
-  --theme-tab-toolbar-background: #fcfcfc;
-  --theme-toolbar-background: #fcfcfc;
+  /* Toolbar */
+  --theme-tab-toolbar-background: var(--grey-10);
+  --theme-toolbar-background: var(--grey-10);
   --theme-toolbar-background-hover: rgba(221, 225, 228, 0.66);
   --theme-toolbar-background-alt: #f5f5f5;
   --theme-toolbar-hover: rgba(170, 170, 170, .2);
   --theme-toolbar-hover-active: rgba(170, 170, 170, .4);
+
+  /* Selection */
   --theme-selection-background: var(--blue-55);
   --theme-selection-background-hover: #F0F9FE;
   --theme-selection-color: #f5f7fa;
 
   /* Border color that splits the toolbars/panels/headers.
    * This needs to be sync with commandline.css and commandline-browser.css. */
   --theme-splitter-color: #e0e0e1;
 
@@ -84,26 +87,29 @@
   /* Command line */
   --theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme);
   --theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme-focus);
 
   --theme-codemirror-gutter-background: #f4f4f4;
 }
 
 :root.theme-dark {
-  --theme-body-background: #393f4c;
-  --theme-sidebar-background: #393f4c;
+  --theme-body-background: var(--grey-80);
+  --theme-sidebar-background: var(--grey-80);
   --theme-contrast-background: #ffb35b;
 
-  --theme-tab-toolbar-background: #272b35;
-  --theme-toolbar-background: #272b35;
+  /* Toolbar */
+  --theme-tab-toolbar-background: var(--grey-90);
+  --theme-toolbar-background: var(--grey-90);
   --theme-toolbar-background-hover: #20232B;
   --theme-toolbar-background-alt: #2F343E;
   --theme-toolbar-hover: rgba(110, 120, 130, 0.1);
   --theme-toolbar-hover-active: rgba(110, 120, 130, 0.2);
+
+  /* Selection */
   --theme-selection-background: #204E8A;
   --theme-selection-background-hover: #353B48;
   --theme-selection-color: #f5f7fa;
 
   /* Border color that splits the toolbars/panels/headers.
    * This needs to be sync with commandline.css and commandline-browser.css. */
   --theme-splitter-color: #3c3c3d;
 
--- a/devtools/client/themes/widgets.css
+++ b/devtools/client/themes/widgets.css
@@ -228,17 +228,17 @@
   background-repeat: no-repeat;
   /* Given the 1/2 aspect ratio of the separator pseudo-element and the 45deg angle of
      the arrow shape, we need the arrow edges to be at this position from the start of
      the gradient line. */
   --position: 66.5%;
   /* The color of the thin line in the arrow-shaped separator between 2 unselected
      crumbs. There is no theme variable for this, this used to be an image. */
   --line-color: #ACACAC;
-  --background-color: var(--theme-body-background);
+  --background-color: var(--theme-toolbar-background);
 }
 
 #debugger-toolbar .breadcrumbs-widget-item::before {
   --background-color: var(--theme-toolbar-background);
 }
 
 .theme-dark .breadcrumbs-widget-item::before {
   --line-color: #6E6E6E;
--- a/devtools/client/webconsole/new-console-output/components/filter-bar.js
+++ b/devtools/client/webconsole/new-console-output/components/filter-bar.js
@@ -216,16 +216,19 @@ const FilterBar = createClass({
         className: "devtools-toolbar webconsole-filterbar-primary",
         key: "primary-bar",
       },
         dom.button({
           className: "devtools-button devtools-clear-icon",
           title: l10n.getStr("webconsole.clearButton.tooltip"),
           onClick: this.onClickMessagesClear
         }),
+        dom.div({
+          className: "devtools-separator",
+        }),
         dom.button({
           className: "devtools-button devtools-filter-icon" + (
             filterBarVisible ? " checked" : ""),
           title: l10n.getStr("webconsole.toggleFilterButton.tooltip"),
           onClick: this.onClickFilterBarToggle
         }),
         dom.input({
           className: "devtools-plaininput text-filter",
--- a/devtools/docs/getting-started/development-profiles.md
+++ b/devtools/docs/getting-started/development-profiles.md
@@ -10,22 +10,22 @@ Here's [a support article](https://suppo
 
 ## Create a permanent profile
 
 We were using a temporary profile in the previous step, [building DevTools](./build.md). The contents of this profile are deleted each time the browser is closed, which means any preferences we set will not persist.
 
 The solution is to create a new profile:
 
 ```
-./mach -P development
+./mach run -P development
 ```
 
 If this profile doesn't exist yet (quite likely), a window will open offering you options to create a new profile, and asking you which name you want to use. Create a new one, and name it `development`. Then start Firefox by clicking on `Start Nightly`.
 
-Next time you start Firefox with `./mach -P development`, the new profile will be automatically used, and settings will persist between browser launches.
+Next time you start Firefox with `./mach run -P development`, the new profile will be automatically used, and settings will persist between browser launches.
 
 ## Enable additional logging
 
 You can change the value of these preferences by going to `about:config`:
 
 | Preference name | Value | Comments |
 | --------------- | --------------- | -------- |
 | `browser.dom.window.dump.enabled` | `true` | Adds global `dump` function to log strings to `stdout` |
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -265,16 +265,79 @@ function drawRoundedRect(ctx, x, y, widt
   ctx.arcTo(x + width, y, x + width - radius, y, radius);
   ctx.lineTo(x + radius, y);
   ctx.arcTo(x, y, x, y + radius, radius);
   ctx.stroke();
   ctx.fill();
 }
 
 /**
+ * Utility method to draw an arrow-bubble rectangle in the provided canvas context.
+ *
+ * @param  {CanvasRenderingContext2D} ctx
+ *         The 2d canvas context.
+ * @param  {Number} x
+ *         The x-axis origin of the rectangle.
+ * @param  {Number} y
+ *         The y-axis origin of the rectangle.
+ * @param  {Number} width
+ *         The width of the rectangle.
+ * @param  {Number} height
+ *         The height of the rectangle.
+ * @param  {Number} radius
+ *         The radius of the rounding.
+ * @param  {Number} margin
+ *         The distance of the origin point from the pointer.
+ * @param  {Number} arrowSize
+ *         The size of the arrow.
+ * @param  {String} alignment
+ *         The alignment of the rectangle in relation to its position to the grid.
+ */
+function drawBubbleRect(ctx, x, y, width, height, radius, margin, arrowSize, alignment) {
+  let angle = 0;
+
+  if (alignment === "bottom") {
+    angle = 180;
+  } else if (alignment === "right") {
+    angle = 90;
+    [width, height] = [height, width];
+  } else if (alignment === "left") {
+    [width, height] = [height, width];
+    angle = 270;
+  }
+
+  let originX = x;
+  let originY = y;
+
+  ctx.save();
+  ctx.translate(originX, originY);
+  ctx.rotate(angle * (Math.PI / 180));
+  ctx.translate(-originX, -originY);
+  ctx.translate(-width / 2, -height - arrowSize - margin);
+
+  ctx.beginPath();
+  ctx.moveTo(x, y + radius);
+  ctx.lineTo(x, y + height - radius);
+  ctx.arcTo(x, y + height, x + radius, y + height, radius);
+  ctx.lineTo(x + width / 2 - arrowSize, y + height);
+  ctx.lineTo(x + width / 2, y + height + arrowSize);
+  ctx.lineTo(x + width / 2 + arrowSize, y + height);
+  ctx.arcTo(x + width, y + height, x + width, y + height - radius, radius);
+  ctx.lineTo(x + width, y + radius);
+  ctx.arcTo(x + width, y, x + width - radius, y, radius);
+  ctx.lineTo(x + radius, y);
+  ctx.arcTo(x, y, x, y + radius, radius);
+
+  ctx.stroke();
+  ctx.fill();
+
+  ctx.restore();
+}
+
+/**
  * The CssGridHighlighter is the class that overlays a visual grid on top of
  * display:[inline-]grid elements.
  *
  * Usage example:
  * let h = new CssGridHighlighter(env);
  * h.show(node, options);
  * h.hide();
  * h.destroy();
@@ -1523,82 +1586,121 @@ class CssGridHighlighter extends AutoRef
     this.ctx.save();
     let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
     this.ctx.translate(offset - canvasX, offset - canvasY);
 
     let fontSize = (GRID_FONT_SIZE * displayPixelRatio);
     this.ctx.font = fontSize + "px " + GRID_FONT_FAMILY;
 
-    let textWidth = this.ctx.measureText(lineNumber).width;
-
-    // The width of the character 'm' approximates the height of the text.
+    // For a general grid box, the height of the character "m" will be its minimum width
+    // and height. If line number's text width is greater then grid box's text width
+    // will use that instead.
     let textHeight = this.ctx.measureText("m").width;
+    let textWidth = Math.max(textHeight, this.ctx.measureText(lineNumber).width);
 
     // Padding in pixels for the line number text inside of the line number container.
     let padding = 3 * displayPixelRatio;
+    let offsetFromEdge = 2 * displayPixelRatio;
 
     let boxWidth = textWidth + 2 * padding;
     let boxHeight = textHeight + 2 * padding;
 
-    // Calculate the x & y coordinates for the line number container, so that it is
-    // centered on the line, and in the middle of the gap if there is any.
+     // Calculate the x & y coordinates for the line number container, so that its arrow
+     // tip is centered on the line (or the gap if there is one), and is offset by the
+     // calculated padding value from the grid container edge.
     let x, y;
 
-    let startOffset = (boxHeight + 2) / devicePixelRatio;
-
-    if (Services.prefs.getBoolPref(NEGATIVE_LINE_NUMBERS_PREF)) {
-      // If the line number is negative, offset it from the grid container edge,
-      // (downwards if its a column, rightwards if its a row).
-      if (lineNumber < 0) {
-        startPos += startOffset;
-      } else {
-        startPos -= startOffset;
-      }
-    }
-
     if (dimensionType === COLUMNS) {
       x = linePos + breadth / 2;
       y = startPos;
-    } else {
+
+      if (lineNumber > 0) {
+        y -= offsetFromEdge;
+      } else {
+        y += offsetFromEdge;
+      }
+    } else if (dimensionType === ROWS) {
       x = startPos;
       y = linePos + breadth / 2;
+
+      if (lineNumber > 0) {
+        x -= offsetFromEdge;
+      } else {
+        x += offsetFromEdge;
+      }
     }
 
     [x, y] = apply(this.currentMatrix, [x, y]);
 
-    x -= boxWidth / 2;
-    y -= boxHeight / 2;
-
     if (stackedLineIndex) {
       // Offset the stacked line number by half of the box's width/height
       const xOffset = boxWidth / 4;
       const yOffset = boxHeight / 4;
 
-      x += xOffset;
-      y += yOffset;
+      if (lineNumber > 0) {
+        x -= xOffset;
+        y -= yOffset;
+      } else {
+        x += xOffset;
+        y += yOffset;
+      }
     }
 
     if (!this.hasNodeTransformations) {
       x = Math.max(x, padding);
       y = Math.max(y, padding);
     }
 
-    // Draw a rounded rectangle with a border width of 2 pixels, a border color matching
-    // the grid color and a white background (the line number will be written in black).
+    // Draw a bubble rectanglular arrow with a border width of 2 pixels, a border color
+    // matching the grid color and a white background (the line number will be written in
+    // black).
     this.ctx.lineWidth = 2 * displayPixelRatio;
     this.ctx.strokeStyle = this.color;
     this.ctx.fillStyle = "white";
+
+    // See param definitions of drawBubbleRect
     let radius = 2 * displayPixelRatio;
-    drawRoundedRect(this.ctx, x, y, boxWidth, boxHeight, radius);
+    let margin = 2 * displayPixelRatio;
+    let arrowSize = 8 * displayPixelRatio;
+
+    let minBoxSize = arrowSize * 2 + padding;
+    boxWidth = Math.max(boxWidth, minBoxSize);
+    boxHeight = Math.max(boxHeight, minBoxSize);
+
+    if (dimensionType === COLUMNS) {
+      if (lineNumber > 0) {
+        drawBubbleRect(this.ctx, x, y, boxWidth, boxHeight, radius, margin, arrowSize,
+          "top");
+        // After drawing the number box, we need to center the x/y coordinates of the
+        // number text written it.
+        y -= (boxHeight + arrowSize + radius) - boxHeight / 2;
+      } else {
+        drawBubbleRect(this.ctx, x, y, boxWidth, boxHeight, radius, margin, arrowSize,
+          "bottom");
+        y += (boxHeight + arrowSize + radius) - boxHeight / 2;
+      }
+    } else if (dimensionType === ROWS) {
+      if (lineNumber > 0) {
+        drawBubbleRect(this.ctx, x, y, boxWidth, boxHeight, radius, margin, arrowSize,
+          "left");
+        x -= (boxWidth + arrowSize + radius) - boxWidth / 2;
+      } else {
+        drawBubbleRect(this.ctx, x, y, boxWidth, boxHeight, radius, margin, arrowSize,
+          "right");
+        x += (boxWidth + arrowSize + radius) - boxWidth / 2;
+      }
+    }
 
     // Write the line number inside of the rectangle.
+    this.ctx.textAlign = "center";
+    this.ctx.textBaseline = "middle";
     this.ctx.fillStyle = "black";
     const numberText = stackedLineIndex ? "" : lineNumber;
-    this.ctx.fillText(numberText, x + padding, y + textHeight + padding);
+    this.ctx.fillText(numberText, x, y);
 
     this.ctx.restore();
   }
 
   /**
    * Render the grid gap area on the css grid highlighter canvas.
    *
    * @param  {Number} linePos
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -1253,18 +1253,17 @@ TimeoutManager::BudgetThrottlingEnabled(
   }
 
   // Check if there are any active IndexedDB databases
   if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
     return false;
   }
 
   // Check if we have active GetUserMedia
-  if (MediaManager::Exists() &&
-      MediaManager::Get()->IsWindowStillActive(mWindow.WindowID())) {
+  if (mWindow.AsInner()->HasActiveUserMedia()) {
     return false;
   }
 
   // Check if we have active PeerConnection
   if (mWindow.AsInner()->HasActivePeerConnections()) {
     return false;
   }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1034,17 +1034,18 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMW
   mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
   mOuterWindow(aOuterWindow),
   // Make sure no actual window ends up with mWindowID == 0
   mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
   mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
   mLargeAllocStatus(LargeAllocStatus::NONE),
   mHasTriedToCacheTopInnerWindow(false),
   mNumOfIndexedDBDatabases(0),
-  mNumOfOpenWebSockets(0)
+  mNumOfOpenWebSockets(0),
+  mNumOfActiveUserMedia(0)
 {
   if (aOuterWindow) {
     mTimeoutManager =
       MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindow::Cast(AsInner()));
   }
 }
 
 template<class T>
@@ -4378,29 +4379,41 @@ void
 nsPIDOMWindowInner::SyncStateFromParentWindow()
 {
   nsGlobalWindow::Cast(this)->SyncStateFromParentWindow();
 }
 
 void
 nsPIDOMWindowInner::AddPeerConnection()
 {
-  nsGlobalWindow::Cast(this)->AddPeerConnection();
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsInnerWindow());
+  mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections++
+                  : mActivePeerConnections++;
 }
 
 void
 nsPIDOMWindowInner::RemovePeerConnection()
 {
-  nsGlobalWindow::Cast(this)->RemovePeerConnection();
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsInnerWindow());
+  MOZ_ASSERT(mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
+                             : mActivePeerConnections);
+
+  mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections--
+                  : mActivePeerConnections--;
 }
 
 bool
 nsPIDOMWindowInner::HasActivePeerConnections()
 {
-  return nsGlobalWindow::Cast(this)->HasActivePeerConnections();
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsInnerWindow());
+  return mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
+                         : mActivePeerConnections;
 }
 
 bool
 nsPIDOMWindowInner::IsPlayingAudio()
 {
   for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
     if (mAudioContexts[i]->IsRunning()) {
       return true;
@@ -4520,16 +4533,40 @@ nsPIDOMWindowInner::HasOpenWebSockets() 
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return (mTopInnerWindow ? mTopInnerWindow->mNumOfOpenWebSockets
                           : mNumOfOpenWebSockets) > 0;
 }
 
 void
+nsPIDOMWindowInner::UpdateUserMediaCount(int32_t aDelta)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (aDelta == 0) {
+    return;
+  }
+
+  uint32_t& counter = mTopInnerWindow ? mTopInnerWindow->mNumOfActiveUserMedia
+                                      : mNumOfActiveUserMedia;
+
+  MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 || ((aDelta + counter) < counter));
+
+  counter += aDelta;
+}
+
+bool
+nsPIDOMWindowInner::HasActiveUserMedia() const
+{
+  return (mTopInnerWindow ? mTopInnerWindow->mNumOfActiveUserMedia
+                          : mNumOfActiveUserMedia) > 0;
+}
+
+void
 nsPIDOMWindowOuter::MaybeActiveMediaComponents()
 {
   if (IsInnerWindow()) {
     return mOuterWindow->MaybeActiveMediaComponents();
   }
 
   if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
     return;
@@ -12613,41 +12650,16 @@ nsGlobalWindow::SyncStateFromParentWindo
 
   // Now apply only the number of Suspend() calls to reach the target
   // suspend count after applying the Freeze() calls.
   for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
     Suspend();
   }
 }
 
-void
-nsGlobalWindow::AddPeerConnection()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
-  mActivePeerConnections++;
-}
-
-void
-nsGlobalWindow::RemovePeerConnection()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
-  MOZ_ASSERT(mActivePeerConnections);
-  mActivePeerConnections--;
-}
-
-bool
-nsGlobalWindow::HasActivePeerConnections()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
-  return mActivePeerConnections;
-}
-
 template<typename Method>
 void
 nsGlobalWindow::CallOnChildren(Method aMethod)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(AsInner()->IsCurrentInnerWindow());
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -400,19 +400,16 @@ public:
 
   void Suspend();
   void Resume();
   virtual bool IsSuspended() const override;
   void Freeze();
   void Thaw();
   virtual bool IsFrozen() const override;
   void SyncStateFromParentWindow();
-  void AddPeerConnection();
-  void RemovePeerConnection();
-  bool HasActivePeerConnections();
 
   virtual nsresult FireDelayedDOMEvents() override;
 
   // Outer windows only.
   virtual bool WouldReuseInnerWindow(nsIDocument* aNewDocument) override;
 
   virtual void SetDocShell(nsIDocShell* aDocShell) override;
   virtual void DetachFromDocShell() override;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -746,16 +746,19 @@ protected:
   // could be null and we don't want it to be set multiple times.
   bool mHasTriedToCacheTopInnerWindow;
 
   // The number of active IndexedDB databases. Inner window only.
   uint32_t mNumOfIndexedDBDatabases;
 
   // The number of open WebSockets. Inner window only.
   uint32_t mNumOfOpenWebSockets;
+
+  // The number of active user media. Inner window only.
+  uint32_t mNumOfActiveUserMedia;
 };
 
 #define NS_PIDOMWINDOWINNER_IID \
 { 0x775dabc9, 0x8f43, 0x4277, \
   { 0x9a, 0xdb, 0xf1, 0x99, 0x0d, 0x77, 0xcf, 0xfb } }
 
 #define NS_PIDOMWINDOWOUTER_IID \
   { 0x769693d4, 0xb009, 0x4fe2, \
@@ -931,16 +934,22 @@ public:
 
   // Increase/Decrease the number of open WebSockets.
   void UpdateWebSocketCount(int32_t aDelta);
 
   // Return true if there are any open WebSockets that could block
   // timeout-throttling.
   bool HasOpenWebSockets() const;
 
+  // Increase/Decrease the number of active user media.
+  void UpdateUserMediaCount(int32_t aDelta);
+
+  // Return true if there are any currently ongoing user media.
+  bool HasActiveUserMedia() const;
+
 protected:
   void CreatePerformanceObjectIfNeeded();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)
 
 // NB: It's very very important that these two classes have identical vtables
 // and memory layout!
--- a/dom/fetch/FetchConsumer.cpp
+++ b/dom/fetch/FetchConsumer.cpp
@@ -37,19 +37,17 @@ public:
 
   ~FetchBodyWorkerHolder() = default;
 
   bool Notify(workers::Status aStatus) override
   {
     MOZ_ASSERT(aStatus > workers::Running);
     if (!mWasNotified) {
       mWasNotified = true;
-      // This will probably cause the releasing of the consumer.
-      // The WorkerHolder will be released as well.
-      mConsumer->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr);
+      mConsumer->ShutDownMainThreadConsuming();
     }
 
     return true;
   }
 };
 
 template <class Derived>
 class BeginConsumeBodyRunnable final : public Runnable
@@ -210,22 +208,16 @@ public:
                    const uint8_t* aResult) override
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     // The loading is completed. Let's nullify the pump before continuing the
     // consuming of the body.
     mFetchBodyConsumer->NullifyConsumeBodyPump();
 
-    // If the binding requested cancel, we don't need to call
-    // ContinueConsumeBody, since that is the originator.
-    if (aStatus == NS_BINDING_ABORTED) {
-      return NS_OK;
-    }
-
     uint8_t* nonconstResult = const_cast<uint8_t*>(aResult);
     if (mFetchBodyConsumer->GetWorkerPrivate()) {
       RefPtr<ContinueConsumeBodyRunnable<Derived>> r =
         new ContinueConsumeBodyRunnable<Derived>(mFetchBodyConsumer,
                                                  aStatus,
                                                  aResultLength,
                                                  nonconstResult);
       if (!r->Dispatch()) {
@@ -247,16 +239,20 @@ public:
                                   nsresult aRv) override
   {
     // On error.
     if (NS_FAILED(aRv)) {
       OnStreamComplete(nullptr, nullptr, aRv, 0, nullptr);
       return;
     }
 
+    // The loading is completed. Let's nullify the pump before continuing the
+    // consuming of the body.
+    mFetchBodyConsumer->NullifyConsumeBodyPump();
+
     MOZ_ASSERT(aBlob);
 
     if (mFetchBodyConsumer->GetWorkerPrivate()) {
       RefPtr<ContinueConsumeBlobBodyRunnable<Derived>> r =
         new ContinueConsumeBlobBodyRunnable<Derived>(mFetchBodyConsumer,
                                                      aBlob->Impl());
 
       if (!r->Dispatch()) {
@@ -278,68 +274,58 @@ NS_IMPL_ADDREF(ConsumeBodyDoneObserver<D
 template <class Derived>
 NS_IMPL_RELEASE(ConsumeBodyDoneObserver<Derived>)
 template <class Derived>
 NS_INTERFACE_MAP_BEGIN(ConsumeBodyDoneObserver<Derived>)
   NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamLoaderObserver)
 NS_INTERFACE_MAP_END
 
-template <class Derived>
-class ShutDownMainThreadConsumingRunnable final : public WorkerMainThreadRunnable
-{
-  RefPtr<FetchBodyConsumer<Derived>> mBodyConsumer;
-
-public:
-  explicit ShutDownMainThreadConsumingRunnable(FetchBodyConsumer<Derived>* aBodyConsumer)
-    : WorkerMainThreadRunnable(aBodyConsumer->GetWorkerPrivate(),
-                               NS_LITERAL_CSTRING("Fetch :: Cancel Pump"))
-    , mBodyConsumer(aBodyConsumer)
-  {}
-
-  bool
-  MainThreadRun() override
-  {
-    mBodyConsumer->ShutDownMainThreadConsuming();
-    return true;
-  }
-};
-
 } // anonymous
 
 template <class Derived>
 /* static */ already_AddRefed<Promise>
 FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
                                    nsIEventTarget* aMainThreadEventTarget,
                                    FetchBody<Derived>* aBody,
                                    AbortSignal* aSignal,
                                    FetchConsumeType aType,
                                    ErrorResult& aRv)
 {
   MOZ_ASSERT(aBody);
   MOZ_ASSERT(aMainThreadEventTarget);
 
+  nsCOMPtr<nsIInputStream> bodyStream;
+  aBody->DerivedClass()->GetBody(getter_AddRefs(bodyStream));
+  if (!bodyStream) {
+    aRv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), EmptyCString());
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
+  }
+
   RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   WorkerPrivate* workerPrivate = nullptr;
   if (!NS_IsMainThread()) {
     workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(workerPrivate);
   }
 
   RefPtr<FetchBodyConsumer<Derived>> consumer =
     new FetchBodyConsumer<Derived>(aMainThreadEventTarget, aGlobal,
-                                   workerPrivate, aBody, promise, aType);
+                                   workerPrivate, aBody, bodyStream, promise,
+                                   aType);
 
   if (!NS_IsMainThread()) {
     MOZ_ASSERT(workerPrivate);
-    if (NS_WARN_IF(!consumer->RegisterWorkerHolder(workerPrivate))) {
+    if (NS_WARN_IF(!consumer->RegisterWorkerHolder())) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
   } else {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (NS_WARN_IF(!os)) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
@@ -380,66 +366,88 @@ FetchBodyConsumer<Derived>::ReleaseObjec
     if (os) {
       os->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
       os->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
     }
   }
 
   mGlobal = nullptr;
   mWorkerHolder = nullptr;
+
+#ifdef DEBUG
   mBody = nullptr;
+#endif
 
   Unfollow();
 }
 
 template <class Derived>
 FetchBodyConsumer<Derived>::FetchBodyConsumer(nsIEventTarget* aMainThreadEventTarget,
                                               nsIGlobalObject* aGlobalObject,
                                               WorkerPrivate* aWorkerPrivate,
                                               FetchBody<Derived>* aBody,
+                                              nsIInputStream* aBodyStream,
                                               Promise* aPromise,
                                               FetchConsumeType aType)
   : mTargetThread(NS_GetCurrentThread())
   , mMainThreadEventTarget(aMainThreadEventTarget)
+#ifdef DEBUG
   , mBody(aBody)
+#endif
+  , mBodyStream(aBodyStream)
+  , mBlobStorageType(MutableBlobStorage::eOnlyInMemory)
   , mGlobal(aGlobalObject)
   , mWorkerPrivate(aWorkerPrivate)
   , mConsumeType(aType)
   , mConsumePromise(aPromise)
   , mBodyConsumed(false)
   , mShuttingDown(false)
 {
   MOZ_ASSERT(aMainThreadEventTarget);
   MOZ_ASSERT(aBody);
+  MOZ_ASSERT(aBodyStream);
   MOZ_ASSERT(aPromise);
+
+  const mozilla::UniquePtr<mozilla::ipc::PrincipalInfo>& principalInfo =
+    aBody->DerivedClass()->GetPrincipalInfo();
+  // We support temporary file for blobs only if the principal is known and
+  // it's system or content not in private Browsing.
+  if (principalInfo &&
+      (principalInfo->type() == mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo ||
+       (principalInfo->type() == mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
+        principalInfo->get_ContentPrincipalInfo().attrs().mPrivateBrowsingId == 0))) {
+    mBlobStorageType = MutableBlobStorage::eCouldBeInTemporaryFile;
+  }
+
+  mBodyMimeType = aBody->MimeType();
 }
 
 template <class Derived>
 FetchBodyConsumer<Derived>::~FetchBodyConsumer()
 {
 }
 
 template <class Derived>
 void
 FetchBodyConsumer<Derived>::AssertIsOnTargetThread() const
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mTargetThread);
 }
 
 template <class Derived>
 bool
-FetchBodyConsumer<Derived>::RegisterWorkerHolder(WorkerPrivate* aWorkerPrivate)
+FetchBodyConsumer<Derived>::RegisterWorkerHolder()
 {
-  MOZ_ASSERT(aWorkerPrivate);
-  aWorkerPrivate->AssertIsOnWorkerThread();
+  MOZ_ASSERT(mWorkerPrivate);
+  mWorkerPrivate->AssertIsOnWorkerThread();
 
   MOZ_ASSERT(!mWorkerHolder);
   mWorkerHolder.reset(new FetchBodyWorkerHolder<Derived>(this));
 
-  if (!mWorkerHolder->HoldWorker(aWorkerPrivate, Closing)) {
+  if (!mWorkerHolder->HoldWorker(mWorkerPrivate, Closing)) {
     NS_WARNING("Failed to add workerHolder");
     mWorkerHolder = nullptr;
     return false;
   }
 
   return true;
 }
 
@@ -449,62 +457,40 @@ FetchBodyConsumer<Derived>::RegisterWork
  * reflected in a lack of error return code.
  */
 template <class Derived>
 void
 FetchBodyConsumer<Derived>::BeginConsumeBodyMainThread()
 {
   AssertIsOnMainThread();
 
-  // Nothing to do.
+  AutoFailConsumeBody<Derived> autoReject(this);
+
   if (mShuttingDown) {
+    // We haven't started yet, but we have been terminated. AutoFailConsumeBody
+    // will dispatch a runnable to release resources.
     return;
   }
 
-  AutoFailConsumeBody<Derived> autoReject(this);
-
-  nsresult rv;
-  nsCOMPtr<nsIInputStream> stream;
-  mBody->DerivedClass()->GetBody(getter_AddRefs(stream));
-  if (!stream) {
-    rv = NS_NewCStringInputStream(getter_AddRefs(stream), EmptyCString());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-  }
-
   nsCOMPtr<nsIInputStreamPump> pump;
-  rv = NS_NewInputStreamPump(getter_AddRefs(pump),
-                             stream, -1, -1, 0, 0, false,
-                             mMainThreadEventTarget);
+  nsresult rv = NS_NewInputStreamPump(getter_AddRefs(pump),
+                                      mBodyStream, -1, -1, 0, 0, false,
+                                      mMainThreadEventTarget);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   RefPtr<ConsumeBodyDoneObserver<Derived>> p =
    new ConsumeBodyDoneObserver<Derived>(this);
 
   nsCOMPtr<nsIStreamListener> listener;
   if (mConsumeType == CONSUME_BLOB) {
-    MutableBlobStorage::MutableBlobStorageType type =
-      MutableBlobStorage::eOnlyInMemory;
-
-    const mozilla::UniquePtr<mozilla::ipc::PrincipalInfo>& principalInfo =
-      mBody->DerivedClass()->GetPrincipalInfo();
-    // We support temporary file for blobs only if the principal is known and
-    // it's system or content not in private Browsing.
-    if (principalInfo &&
-        (principalInfo->type() == mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo ||
-         (principalInfo->type() == mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
-          principalInfo->get_ContentPrincipalInfo().attrs().mPrivateBrowsingId == 0))) {
-      type = MutableBlobStorage::eCouldBeInTemporaryFile;
-    }
-
-    listener = new MutableBlobStreamListener(type, nullptr, mBody->MimeType(),
-                                             p, mMainThreadEventTarget);
+    listener = new MutableBlobStreamListener(mBlobStorageType, nullptr,
+                                             mBodyMimeType, p,
+                                             mMainThreadEventTarget);
   } else {
     nsCOMPtr<nsIStreamLoader> loader;
     rv = NS_NewStreamLoader(getter_AddRefs(loader), p);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
     listener = loader;
@@ -561,31 +547,26 @@ FetchBodyConsumer<Derived>::ContinueCons
   auto autoReleaseObject = mozilla::MakeScopeExit([&] {
     self->ReleaseObject();
   });
 
   if (NS_WARN_IF(NS_FAILED(aStatus))) {
     localPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
   }
 
-  // We need to nullify mConsumeBodyPump on the main-thread and, in case it has
-  // not been created yet, we need to block the creation setting mShuttingDown
-  // to true.
-  ShutDownMainThreadConsuming();
-
   // Don't warn here since we warned above.
   if (NS_FAILED(aStatus)) {
     return;
   }
 
   // Finish successfully consuming body according to type.
   MOZ_ASSERT(aResult);
 
   AutoJSAPI jsapi;
-  if (!jsapi.Init(mBody->DerivedClass()->GetParentObject())) {
+  if (!jsapi.Init(mGlobal)) {
     localPromise->MaybeReject(NS_ERROR_UNEXPECTED);
     return;
   }
 
   JSContext* cx = jsapi.cx();
   ErrorResult error;
 
   switch (mConsumeType) {
@@ -609,18 +590,17 @@ FetchBodyConsumer<Derived>::ContinueCons
       break;
     }
     case CONSUME_FORMDATA: {
       nsCString data;
       data.Adopt(reinterpret_cast<char*>(aResult), aResultLength);
       aResult = nullptr;
 
       RefPtr<dom::FormData> fd =
-        BodyUtil::ConsumeFormData(mBody->DerivedClass()->GetParentObject(),
-                                  mBody->MimeType(), data, error);
+        BodyUtil::ConsumeFormData(mGlobal, mBodyMimeType, data, error);
       if (!error.Failed()) {
         localPromise->MaybeResolve(fd);
       }
       break;
     }
     case CONSUME_TEXT:
       // fall through handles early exit.
     case CONSUME_JSON: {
@@ -662,48 +642,36 @@ FetchBodyConsumer<Derived>::ContinueCons
 
   // Just a precaution to ensure ContinueConsumeBody is not called out of
   // sync with a body read.
   MOZ_ASSERT(mBody->BodyUsed());
 
   MOZ_ASSERT(mConsumePromise);
   RefPtr<Promise> localPromise = mConsumePromise.forget();
 
-  // Release the pump.
-  ShutDownMainThreadConsuming();
-
-  RefPtr<dom::Blob> blob =
-    dom::Blob::Create(mBody->DerivedClass()->GetParentObject(), aBlobImpl);
+  RefPtr<dom::Blob> blob = dom::Blob::Create(mGlobal, aBlobImpl);
   MOZ_ASSERT(blob);
 
   localPromise->MaybeResolve(blob);
 
   ReleaseObject();
 }
 
 template <class Derived>
 void
 FetchBodyConsumer<Derived>::ShutDownMainThreadConsuming()
 {
   if (!NS_IsMainThread()) {
-    MOZ_ASSERT(mWorkerPrivate);
-    // In case of worker thread, we block the worker while the request is
-    // canceled on the main thread. This ensures that OnStreamComplete has a
-    // valid FetchConsumer around to call ShutDownMainThreadConsuming and we
-    // don't release the FetchConsumer on the main thread.
-    RefPtr<ShutDownMainThreadConsumingRunnable<Derived>> r =
-      new ShutDownMainThreadConsumingRunnable<Derived>(this);
+    RefPtr<FetchBodyConsumer<Derived>> self = this;
 
-    IgnoredErrorResult rv;
-    r->Dispatch(Killing, rv);
-    if (NS_WARN_IF(rv.Failed())) {
-      return;
-    }
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      "FetchBodyConsumer::ShutDownMainThreadConsuming",
+      [self] () { self->ShutDownMainThreadConsuming(); });
 
-    MOZ_DIAGNOSTIC_ASSERT(mShuttingDown);
+    mMainThreadEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
     return;
   }
 
   // We need this because maybe, mConsumeBodyPump has not been created yet. We
   // must be sure that we don't try to do it.
   mShuttingDown = true;
 
   if (mConsumeBodyPump) {
--- a/dom/fetch/FetchConsumer.h
+++ b/dom/fetch/FetchConsumer.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_FetchConsumer_h
 #define mozilla_dom_FetchConsumer_h
 
 #include "Fetch.h"
 #include "mozilla/dom/AbortSignal.h"
+#include "mozilla/dom/MutableBlobStorage.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 
 class nsIThread;
 
 namespace mozilla {
 namespace dom {
 
@@ -44,22 +45,16 @@ public:
          FetchBody<Derived>* aBody,
          AbortSignal* aSignal,
          FetchConsumeType aType,
          ErrorResult& aRv);
 
   void
   ReleaseObject();
 
-  FetchBody<Derived>*
-  Body() const
-  {
-    return mBody;
-  }
-
   void
   BeginConsumeBodyMainThread();
 
   void
   ContinueConsumeBody(nsresult aStatus, uint32_t aLength, uint8_t* aResult);
 
   void
   ContinueConsumeBlobBody(BlobImpl* aBlobImpl);
@@ -71,41 +66,51 @@ public:
   GetWorkerPrivate() const
   {
     return mWorkerPrivate;
   }
 
   void
   NullifyConsumeBodyPump()
   {
+    mShuttingDown = true;
     mConsumeBodyPump = nullptr;
   }
 
   // AbortFollower
   void Abort() override;
 
 private:
   FetchBodyConsumer(nsIEventTarget* aMainThreadEventTarget,
                     nsIGlobalObject* aGlobalObject,
                     workers::WorkerPrivate* aWorkerPrivate,
                     FetchBody<Derived>* aBody,
+                    nsIInputStream* aBodyStream,
                     Promise* aPromise,
                     FetchConsumeType aType);
 
   ~FetchBodyConsumer();
 
   void
   AssertIsOnTargetThread() const;
 
   bool
-  RegisterWorkerHolder(workers::WorkerPrivate* aWorkerPrivate);
+  RegisterWorkerHolder();
 
   nsCOMPtr<nsIThread> mTargetThread;
   nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
+
+#ifdef DEBUG
+  // This is used only to check if the body has been correctly consumed.
   RefPtr<FetchBody<Derived>> mBody;
+#endif
+
+  nsCOMPtr<nsIInputStream> mBodyStream;
+  MutableBlobStorage::MutableBlobStorageType mBlobStorageType;
+  nsCString mBodyMimeType;
 
   // Set when consuming the body is attempted on a worker.
   // Unset when consumption is done/aborted.
   // This WorkerHolder keeps alive the consumer via a cycle.
   UniquePtr<workers::WorkerHolder> mWorkerHolder;
 
   nsCOMPtr<nsIGlobalObject> mGlobal;
 
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -28453,19 +28453,21 @@ OpenOp::DoIndexDatabaseWork(DatabaseConn
         openLimit;
       mCursor->mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND sort_column >= :current_key") +
         directionClause +
         openLimit;
       mCursor->mContinuePrimaryKeyQuery =
         queryStart +
-        NS_LITERAL_CSTRING(" AND sort_column >= :current_key "
-                            "AND index_table.object_data_key >= :object_key "
-                          ) +
+        NS_LITERAL_CSTRING(" AND ("
+          "(sort_column == :current_key AND "
+             "index_table.object_data_key >= :object_key) OR "
+          "sort_column > :current_key"
+        ")") +
         directionClause +
         openLimit;
       break;
     }
 
     case IDBCursor::NEXT_UNIQUE: {
       Key upper;
       bool open;
@@ -28505,19 +28507,21 @@ OpenOp::DoIndexDatabaseWork(DatabaseConn
         openLimit;
       mCursor->mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND sort_column <= :current_key") +
         directionClause +
         openLimit;
       mCursor->mContinuePrimaryKeyQuery =
         queryStart +
-        NS_LITERAL_CSTRING(" AND sort_column <= :current_key "
-                            "AND index_table.object_data_key <= :object_key "
-                          ) +
+        NS_LITERAL_CSTRING(" AND ("
+          "(sort_column == :current_key AND "
+             "index_table.object_data_key <= :object_key) OR "
+          "sort_column < :current_key"
+        ")") +
         directionClause +
         openLimit;
       break;
     }
 
     case IDBCursor::PREV_UNIQUE: {
       Key lower;
       bool open;
@@ -28687,19 +28691,21 @@ OpenOp::DoIndexKeyDatabaseWork(DatabaseC
         openLimit;
       mCursor->mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND sort_column >= :current_key ") +
         directionClause +
         openLimit;
       mCursor->mContinuePrimaryKeyQuery =
         queryStart +
-        NS_LITERAL_CSTRING(" AND sort_column >= :current_key "
-                            "AND object_data_key >= :object_key "
-                          ) +
+        NS_LITERAL_CSTRING(" AND ("
+          "(sort_column == :current_key AND "
+             "object_data_key >= :object_key) OR "
+          "sort_column > :current_key"
+        ")") +
         directionClause +
         openLimit;
       break;
     }
 
     case IDBCursor::NEXT_UNIQUE: {
       Key upper;
       bool open;
@@ -28739,19 +28745,21 @@ OpenOp::DoIndexKeyDatabaseWork(DatabaseC
         openLimit;
       mCursor->mContinueToQuery =
         queryStart +
         NS_LITERAL_CSTRING(" AND sort_column <= :current_key ") +
         directionClause +
         openLimit;
       mCursor->mContinuePrimaryKeyQuery =
         queryStart +
-        NS_LITERAL_CSTRING(" AND sort_column <= :current_key "
-                            "AND object_data_key <= :object_key "
-                          ) +
+        NS_LITERAL_CSTRING(" AND ("
+          "(sort_column == :current_key AND "
+             "object_data_key <= :object_key) OR "
+          "sort_column < :current_key"
+        ")") +
         directionClause +
         openLimit;
       break;
     }
 
     case IDBCursor::PREV_UNIQUE: {
       Key lower;
       bool open;
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -87,39 +87,29 @@ IDBKeyRange::FromJSVal(JSContext* aCx,
 
   if (aVal.isNullOrUndefined()) {
     // undefined and null returns no IDBKeyRange.
     keyRange.forget(aKeyRange);
     return NS_OK;
   }
 
   JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
-  bool isValidKey = aVal.isPrimitive();
-  if (!isValidKey) {
-    js::ESClass cls;
-    if (!js::GetBuiltinClass(aCx, obj, &cls)) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    isValidKey = cls == js::ESClass::Array || cls == js::ESClass::Date;
-  }
-  if (isValidKey) {
-    // A valid key returns an 'only' IDBKeyRange.
-    keyRange = new IDBKeyRange(nullptr, false, false, true);
 
-    nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
+  // Unwrap an IDBKeyRange object if possible.
+  if (obj && NS_SUCCEEDED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
+    MOZ_ASSERT(keyRange);
+    keyRange.forget(aKeyRange);
+    return NS_OK;
   }
-  else {
-    MOZ_ASSERT(aVal.isObject());
-    // An object is not permitted unless it's another IDBKeyRange.
-    if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
-      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
-    }
+
+  // A valid key returns an 'only' IDBKeyRange.
+  keyRange = new IDBKeyRange(nullptr, false, false, true);
+  nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
+  if (NS_FAILED(rv)) {
+    return rv;
   }
 
   keyRange.forget(aKeyRange);
   return NS_OK;
 }
 
 // static
 already_AddRefed<IDBKeyRange>
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -2921,31 +2921,39 @@ MediaManager::AddWindowID(uint64_t aWind
   // Store the WindowID in a hash table and mark as active. The entry is removed
   // when this window is closed or navigated away from.
   // This is safe since we're on main-thread, and the windowlist can only
   // be invalidated from the main-thread (see OnNavigation)
   if (IsWindowStillActive(aWindowId)) {
     MOZ_ASSERT(false, "Window already added");
     return;
   }
+
+  auto* window = nsGlobalWindow::GetInnerWindowWithId(aWindowId);
+  if (window) {
+    window->AsInner()->UpdateUserMediaCount(1);
+  }
+
   GetActiveWindows()->Put(aWindowId, aListener);
 }
 
 void
 MediaManager::RemoveWindowID(uint64_t aWindowId)
 {
   mActiveWindows.Remove(aWindowId);
 
   // get outer windowID
   auto* window = nsGlobalWindow::GetInnerWindowWithId(aWindowId);
   if (!window) {
     LOG(("No inner window for %" PRIu64, aWindowId));
     return;
   }
 
+  window->AsInner()->UpdateUserMediaCount(-1);
+
   nsPIDOMWindowOuter* outer = window->AsInner()->GetOuterWindow();
   if (!outer) {
     LOG(("No outer window for inner %" PRIu64, aWindowId));
     return;
   }
 
   uint64_t outerID = outer->WindowID();
 
--- a/dom/tests/mochitest/fetch/mochitest.ini
+++ b/dom/tests/mochitest/fetch/mochitest.ini
@@ -51,21 +51,21 @@ support-files =
 [test_fetch_basic.html]
 [test_fetch_basic_sw_reroute.html]
 [test_fetch_basic_sw_empty_reroute.html]
 [test_fetch_basic_http.html]
 [test_fetch_basic_http_sw_reroute.html]
 [test_fetch_basic_http_sw_empty_reroute.html]
 [test_fetch_cached_redirect.html]
 [test_fetch_cors.html]
-skip-if = toolkit == 'android' && debug # Bug 1210282
+skip-if = toolkit == 'android' # Bug 1210282
 [test_fetch_cors_sw_reroute.html]
-skip-if = toolkit == 'android' && debug # Bug 1210282
+skip-if = toolkit == 'android' # Bug 1210282
 [test_fetch_cors_sw_empty_reroute.html]
-skip-if = toolkit == 'android' && debug # Bug 1210282
+skip-if = toolkit == 'android' # Bug 1210282
 [test_fetch_csp_block.html]
 [test_fetch_observer.html]
 [test_fetch_user_control_rp.html]
 [test_formdataparsing.html]
 skip-if = asan # Bug 1325942
 [test_formdataparsing_sw_reroute.html]
 skip-if = asan # Bug 1325942
 [test_request.html]
--- a/gfx/layers/composite/GPUVideoTextureHost.cpp
+++ b/gfx/layers/composite/GPUVideoTextureHost.cpp
@@ -117,23 +117,23 @@ GPUVideoTextureHost::GetWRImageKeys(nsTA
 {
   MOZ_ASSERT(mWrappedTextureHost);
   MOZ_ASSERT(aImageKeys.IsEmpty());
 
   mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator);
 }
 
 void
-GPUVideoTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
+GPUVideoTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                 Range<const wr::ImageKey>& aImageKeys,
                                 const wr::ExternalImageId& aExtID)
 {
   MOZ_ASSERT(mWrappedTextureHost);
 
-  mWrappedTextureHost->AddWRImage(aAPI, aImageKeys, aExtID);
+  mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID);
 }
 
 void
 GPUVideoTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                        const wr::LayoutRect& aBounds,
                                        const wr::LayoutRect& aClip,
                                        wr::ImageRendering aFilter,
                                        Range<const wr::ImageKey>& aImageKeys)
--- a/gfx/layers/composite/GPUVideoTextureHost.h
+++ b/gfx/layers/composite/GPUVideoTextureHost.h
@@ -46,17 +46,17 @@ public:
 
   virtual bool HasIntermediateBuffer() const override;
 
   virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -581,48 +581,48 @@ BufferTextureHost::GetWRImageKeys(nsTArr
     aImageKeys.AppendElement(aImageKeyAllocator());
     aImageKeys.AppendElement(aImageKeyAllocator());
     aImageKeys.AppendElement(aImageKeyAllocator());
     MOZ_ASSERT(aImageKeys.Length() == 3);
   }
 }
 
 void
-BufferTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
+BufferTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources,
                               Range<const wr::ImageKey>& aImageKeys,
                               const wr::ExternalImageId& aExtID)
 {
   if (GetFormat() != gfx::SurfaceFormat::YUV) {
     MOZ_ASSERT(aImageKeys.length() == 1);
 
     wr::ImageDescriptor descriptor(GetSize(),
                                    ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width),
                                    GetFormat());
-    aAPI->AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID);
+    aResources.AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID);
   } else {
     MOZ_ASSERT(aImageKeys.length() == 3);
 
     const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8);
     wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8);
-    aAPI->AddExternalImage(aImageKeys[0],
-                           yDescriptor,
-                           aExtID,
-                           wr::WrExternalImageBufferType::ExternalBuffer,
-                           0);
-    aAPI->AddExternalImage(aImageKeys[1],
-                           cbcrDescriptor,
-                           aExtID,
-                           wr::WrExternalImageBufferType::ExternalBuffer,
-                           1);
-    aAPI->AddExternalImage(aImageKeys[2],
-                           cbcrDescriptor,
-                           aExtID,
-                           wr::WrExternalImageBufferType::ExternalBuffer,
-                           2);
+    aResources.AddExternalImage(aImageKeys[0],
+                                yDescriptor,
+                                aExtID,
+                                wr::WrExternalImageBufferType::ExternalBuffer,
+                                0);
+    aResources.AddExternalImage(aImageKeys[1],
+                                cbcrDescriptor,
+                                aExtID,
+                                wr::WrExternalImageBufferType::ExternalBuffer,
+                                1);
+    aResources.AddExternalImage(aImageKeys[2],
+                                cbcrDescriptor,
+                                aExtID,
+                                wr::WrExternalImageBufferType::ExternalBuffer,
+                                2);
   }
 }
 
 void
 BufferTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                      const wr::LayoutRect& aBounds,
                                      const wr::LayoutRect& aClip,
                                      wr::ImageRendering aFilter,
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -36,17 +36,17 @@
 class MacIOSurface;
 namespace mozilla {
 namespace ipc {
 class Shmem;
 } // namespace ipc
 
 namespace wr {
 class DisplayListBuilder;
-class WebRenderAPI;
+class ResourceUpdateQueue;
 }
 
 namespace layers {
 
 class BufferDescriptor;
 class BufferTextureHost;
 class Compositor;
 class CompositableParentManager;
@@ -628,19 +628,19 @@ public:
   // the new ImageKey.
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator)
   {
     MOZ_ASSERT(aImageKeys.IsEmpty());
     MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this TextureHost type.");
   }
 
-  // Add all necessary textureHost informations to WebrenderAPI. Then, WR could
-  // use these informations to compose this textureHost.
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  // Add all necessary TextureHost informations to the resource update queue.
+  // Then, WR will use this informations to read from the TextureHost.
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID)
   {
     MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this TextureHost type.");
   }
 
   // Put all necessary WR commands into DisplayListBuilder for this textureHost rendering.
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
@@ -745,17 +745,17 @@ public:
 
   const BufferDescriptor& GetBufferDescriptor() const { return mDescriptor; }
 
   virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -1058,52 +1058,52 @@ DXGITextureHostD3D11::GetWRImageKeys(nsT
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
 void
-DXGITextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
+DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                  Range<const wr::ImageKey>& aImageKeys,
                                  const wr::ExternalImageId& aExtID)
 {
   MOZ_ASSERT(mHandle);
 
   switch (mFormat) {
     case gfx::SurfaceFormat::R8G8B8X8:
     case gfx::SurfaceFormat::R8G8B8A8:
     case gfx::SurfaceFormat::B8G8R8A8:
     case gfx::SurfaceFormat::B8G8R8X8: {
       MOZ_ASSERT(aImageKeys.length() == 1);
 
       wr::ImageDescriptor descriptor(GetSize(), GetFormat());
-      aAPI->AddExternalImage(aImageKeys[0],
-                             descriptor,
-                             aExtID,
-                             wr::WrExternalImageBufferType::Texture2DHandle,
-                             0);
+      aResources.AddExternalImage(aImageKeys[0],
+                                  descriptor,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::Texture2DHandle,
+                                  0);
       break;
     }
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
 
       wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8);
       wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8);
-      aAPI->AddExternalImage(aImageKeys[0],
-                             descriptor0,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureExternalHandle,
-                             0);
-      aAPI->AddExternalImage(aImageKeys[1],
-                             descriptor1,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureExternalHandle,
-                             1);
+      aResources.AddExternalImage(aImageKeys[0],
+                                  descriptor0,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureExternalHandle,
+                                  0);
+      aResources.AddExternalImage(aImageKeys[1],
+                                  descriptor1,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureExternalHandle,
+                                  1);
       break;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
@@ -1308,17 +1308,17 @@ DXGIYCbCrTextureHostD3D11::GetWRImageKey
   MOZ_ASSERT(aImageKeys.IsEmpty());
 
   // 1 image key
   aImageKeys.AppendElement(aImageKeyAllocator());
   MOZ_ASSERT(aImageKeys.Length() == 1);
 }
 
 void
-DXGIYCbCrTextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
+DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                       Range<const wr::ImageKey>& aImageKeys,
                                       const wr::ExternalImageId& aExtID)
 {
   MOZ_ASSERT(mTextures[0] && mTextures[1] && mTextures[2]);
   MOZ_ASSERT(aImageKeys.length() == 1);
 
   // There are 3 A8 channel data in DXGIYCbCrTextureHostD3D11, but ANGLE doesn't
   // support for converting the D3D A8 texture to OpenGL texture handle. So, we
@@ -1333,17 +1333,17 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr
   DataSourceSurface::MappedSurface map;
   if (!dataSourceSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
     return;
   }
 
   IntSize size = dataSourceSurface->GetSize();
   wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat());
   auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
-  aAPI->AddImage(aImageKeys[0], descriptor, slice);
+  aResources.AddImage(aImageKeys[0], descriptor, slice);
 
   dataSourceSurface->Unmap();
 }
 
 void
 DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                              const wr::LayoutRect& aBounds,
                                              const wr::LayoutRect& aClip,
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -333,17 +333,17 @@ public:
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
@@ -396,17 +396,17 @@ public:
     return nullptr;
   }
 
   virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -42,38 +42,30 @@ parent:
   async ReleaseCompositable(CompositableHandle compositable);
 
   // Creates a set of mappings between TextureReadLocks and an associated
   // ReadLockHandle that can be used in Update, and persist until the
   // next Update call.
   async InitReadLocks(ReadLockInit[] locks);
 
   sync Create(IntSize aSize);
-  async AddImage(ImageKey aImageKey, IntSize aSize, uint32_t aStride,
-                 SurfaceFormat aFormat, ByteBuffer aBytes);
-  async AddBlobImage(ImageKey aImageKey, IntSize aSize, uint32_t aStride,
-                     SurfaceFormat aFormat, ByteBuffer aBytes);
-  async UpdateImage(ImageKey aImageKey, IntSize aSize,
-                   SurfaceFormat aFormat, ByteBuffer aBytes);
-  async DeleteImage(ImageKey aImageKey);
   async DeleteCompositorAnimations(uint64_t[] aIds);
-  async AddRawFont(FontKey aFontKey, ByteBuffer aBytes, uint32_t aFontIndex);
-  async DeleteFont(FontKey aFontKey);
-  async AddFontInstance(FontInstanceKey aInstanceKey, FontKey aFontKey, float aGlyphSize,
-                        MaybeFontInstanceOptions aOptions, MaybeFontInstancePlatformOptions aPlatformOptions);
-  async DeleteFontInstance(FontInstanceKey aInstanceKey);
-  async DPBegin(IntSize aSize);
-  async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
-              LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
-              WebRenderScrollData aScrollData, IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
-  sync DPSyncEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
-                 LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
-                 WebRenderScrollData aScrollData, IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
+  async SetDisplayList(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+                       LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
+                       WebRenderScrollData aScrollData,
+                       ByteBuffer aResourceUpdates,
+                       IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
+  sync SetDisplayListSync(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+                          LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
+                          WebRenderScrollData aScrollData,
+                          ByteBuffer aResourceUpdates,
+                          IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
+  async UpdateResources(ByteBuffer aResourceUpdates);
   async ParentCommands(WebRenderParentCommand[] commands);
-  sync DPGetSnapshot(PTexture texture);
+  sync GetSnapshot(PTexture texture);
   async AddPipelineIdForCompositable(PipelineId aImageId, CompositableHandle aHandle, bool aAsync);
   async RemovePipelineIdForCompositable(PipelineId aPipelineId);
   async AddExternalImageIdForCompositable(ExternalImageId aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(ExternalImageId aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
   // Schedule a composite if one isn't already scheduled.
   async ForceComposite();
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -156,69 +156,69 @@ MacIOSurfaceTextureHostOGL::GetWRImageKe
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
 void
-MacIOSurfaceTextureHostOGL::AddWRImage(wr::WebRenderAPI* aAPI,
+MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                        Range<const wr::ImageKey>& aImageKeys,
                                        const wr::ExternalImageId& aExtID)
 {
   MOZ_ASSERT(mSurface);
 
   switch (GetFormat()) {
     case gfx::SurfaceFormat::R8G8B8X8:
     case gfx::SurfaceFormat::R8G8B8A8:
     case gfx::SurfaceFormat::B8G8R8A8:
     case gfx::SurfaceFormat::B8G8R8X8: {
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
       wr::ImageDescriptor descriptor(GetSize(), GetFormat());
-      aAPI->AddExternalImage(aImageKeys[0],
-                             descriptor,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureRectHandle,
-                             0);
+      aResources.AddExternalImage(aImageKeys[0],
+                                  descriptor,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureRectHandle,
+                                  0);
       break;
     }
     case gfx::SurfaceFormat::YUV422: {
       // This is the special buffer format. The buffer contents could be a
       // converted RGB interleaving data or a YCbCr interleaving data depending
       // on the different platform setting. (e.g. It will be RGB at OpenGL 2.1
       // and YCbCr at OpenGL 3.1)
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
       wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8);
-      aAPI->AddExternalImage(aImageKeys[0],
-                             descriptor,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureRectHandle,
-                             0);
+      aResources.AddExternalImage(aImageKeys[0],
+                                  descriptor,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureRectHandle,
+                                  0);
       break;
     }
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 2);
       wr::ImageDescriptor descriptor0(gfx::IntSize(mSurface->GetDevicePixelWidth(0), mSurface->GetDevicePixelHeight(0)),
                                       gfx::SurfaceFormat::A8);
       wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)),
                                       gfx::SurfaceFormat::R8G8);
-      aAPI->AddExternalImage(aImageKeys[0],
-                             descriptor0,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureRectHandle,
-                             0);
-      aAPI->AddExternalImage(aImageKeys[1],
-                             descriptor1,
-                             aExtID,
-                             wr::WrExternalImageBufferType::TextureRectHandle,
-                             1);
+      aResources.AddExternalImage(aImageKeys[0],
+                                  descriptor0,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureRectHandle,
+                                  0);
+      aResources.AddExternalImage(aImageKeys[1],
+                                  descriptor1,
+                                  aExtID,
+                                  wr::WrExternalImageBufferType::TextureRectHandle,
+                                  1);
       break;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
@@ -62,17 +62,17 @@ public:
 
   virtual MacIOSurface* GetMacIOSurface() override { return mSurface; }
 
   virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -52,19 +52,21 @@ AsyncImagePipelineManager::HasKeysToDele
 {
   return !mKeysToDelete.IsEmpty();
 }
 
 void
 AsyncImagePipelineManager::DeleteOldAsyncImages()
 {
   MOZ_ASSERT(!mDestroyed);
+  wr::ResourceUpdateQueue resources;
   for (wr::ImageKey key : mKeysToDelete) {
-    mApi->DeleteImage(key);
+    resources.DeleteImage(key);
   }
+  mApi->UpdateResources(resources);
   mKeysToDelete.Clear();
 }
 
 void
 AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
 {
   if (mDestroyed) {
     return;
@@ -120,20 +122,22 @@ AsyncImagePipelineManager::RemoveAsyncIm
   if (mDestroyed) {
     return;
   }
 
   uint64_t id = wr::AsUint64(aPipelineId);
   if (auto entry = mAsyncImagePipelines.Lookup(id)) {
     AsyncImagePipeline* holder = entry.Data();
     ++mAsyncImageEpoch; // Update webrender epoch
-    mApi->ClearRootDisplayList(wr::NewEpoch(mAsyncImageEpoch), aPipelineId);
+    mApi->ClearDisplayList(wr::NewEpoch(mAsyncImageEpoch), aPipelineId);
+    wr::ResourceUpdateQueue resources;
     for (wr::ImageKey key : holder->mKeys) {
-      mApi->DeleteImage(key);
+      resources.DeleteImage(key);
     }
+    mApi->UpdateResources(resources);
     entry.Remove();
     RemovePipeline(aPipelineId, wr::NewEpoch(mAsyncImageEpoch));
   }
 }
 
 void
 AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
                                                     const LayerRect& aScBounds,
@@ -154,28 +158,30 @@ AsyncImagePipelineManager::UpdateAsyncIm
   pipeline->mScBounds = aScBounds;
   pipeline->mScTransform = aScTransform;
   pipeline->mScaleToSize = aScaleToSize;
   pipeline->mFilter = aFilter;
   pipeline->mMixBlendMode = aMixBlendMode;
 }
 
 bool
-AsyncImagePipelineManager::GenerateImageKeyForTextureHost(TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys)
+AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueue& aResources,
+                                                          TextureHost* aTexture,
+                                                          nsTArray<wr::ImageKey>& aKeys)
 {
   MOZ_ASSERT(aKeys.IsEmpty());
   MOZ_ASSERT(aTexture);
 
   WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost();
 
   if (!gfxEnv::EnableWebRenderRecording() && wrTexture) {
     wrTexture->GetWRImageKeys(aKeys, std::bind(&AsyncImagePipelineManager::GenerateImageKey, this));
     MOZ_ASSERT(!aKeys.IsEmpty());
     Range<const wr::ImageKey> keys(&aKeys[0], aKeys.Length());
-    wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
+    wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey());
     return true;
   } else {
     RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
     if (!dSurf) {
       NS_ERROR("TextureHost does not return DataSourceSurface");
       return false;
     }
     gfx::DataSourceSurface::MappedSurface map;
@@ -184,24 +190,25 @@ AsyncImagePipelineManager::GenerateImage
       return false;
     }
     gfx::IntSize size = dSurf->GetSize();
     wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
     auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
 
     wr::ImageKey key = GenerateImageKey();
     aKeys.AppendElement(key);
-    mApi->AddImage(key, descriptor, slice);
+    aResources.AddImage(key, descriptor, slice);
     dSurf->Unmap();
   }
   return false;
 }
 
 bool
-AsyncImagePipelineManager::UpdateImageKeys(bool& aUseExternalImage,
+AsyncImagePipelineManager::UpdateImageKeys(wr::ResourceUpdateQueue& aResources,
+                                           bool& aUseExternalImage,
                                            AsyncImagePipeline* aImageMgr,
                                            nsTArray<wr::ImageKey>& aKeys,
                                            nsTArray<wr::ImageKey>& aKeysToDelete)
 {
   MOZ_ASSERT(aKeys.IsEmpty());
   MOZ_ASSERT(aImageMgr);
   TextureHost* texture = aImageMgr->mImageHost->GetAsTextureHostForComposite();
 
@@ -229,17 +236,17 @@ AsyncImagePipelineManager::UpdateImageKe
   aImageMgr->mKeys.Clear();
   aImageMgr->mCurrentTexture = nullptr;
 
   // No txture to render
   if (!texture) {
     return true;
   }
 
-  aUseExternalImage = aImageMgr->mUseExternalImage = GenerateImageKeyForTextureHost(texture, aKeys);
+  aUseExternalImage = aImageMgr->mUseExternalImage = GenerateImageKeyForTextureHost(aResources, texture, aKeys);
   MOZ_ASSERT(!aKeys.IsEmpty());
   aImageMgr->mKeys.AppendElements(aKeys);
   aImageMgr->mCurrentTexture = texture;
   return true;
 }
 
 void
 AsyncImagePipelineManager::ApplyAsyncImages()
@@ -247,23 +254,26 @@ AsyncImagePipelineManager::ApplyAsyncIma
   if (mDestroyed || mAsyncImagePipelines.Count() == 0) {
     return;
   }
 
   ++mAsyncImageEpoch; // Update webrender epoch
   wr::Epoch epoch = wr::NewEpoch(mAsyncImageEpoch);
   nsTArray<wr::ImageKey> keysToDelete;
 
+  wr::ResourceUpdateQueue resourceUpdates;
+
   for (auto iter = mAsyncImagePipelines.Iter(); !iter.Done(); iter.Next()) {
     wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
     AsyncImagePipeline* pipeline = iter.Data();
 
     nsTArray<wr::ImageKey> keys;
     bool useExternalImage = false;
-    bool updateDisplayList = UpdateImageKeys(useExternalImage,
+    bool updateDisplayList = UpdateImageKeys(resourceUpdates,
+                                             useExternalImage,
                                              pipeline,
                                              keys,
                                              keysToDelete);
     if (!updateDisplayList) {
       continue;
     }
 
     wr::LayoutSize contentSize { pipeline->mScBounds.Width(), pipeline->mScBounds.Height() };
@@ -304,19 +314,20 @@ AsyncImagePipelineManager::ApplyAsyncIma
                           keys[0]);
       }
       builder.PopStackingContext();
     }
 
     wr::BuiltDisplayList dl;
     wr::LayoutSize builderContentSize;
     builder.Finalize(builderContentSize, dl);
-    mApi->SetRootDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(pipeline->mScBounds.Width(), pipeline->mScBounds.Height()),
-                             pipelineId, builderContentSize,
-                             dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length);
+    mApi->SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(pipeline->mScBounds.Width(), pipeline->mScBounds.Height()),
+                         pipelineId, builderContentSize,
+                         dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length,
+                         resourceUpdates);
   }
   DeleteOldAsyncImages();
   mKeysToDelete.SwapElements(keysToDelete);
 }
 
 void
 AsyncImagePipelineManager::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
 {
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -98,17 +98,19 @@ private:
   wr::IdNamespace GetNamespace() { return mIdNamespace; }
   wr::ImageKey GenerateImageKey()
   {
     wr::ImageKey key;
     key.mNamespace = GetNamespace();
     key.mHandle = GetNextResourceId();
     return key;
   }
-  bool GenerateImageKeyForTextureHost(TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys);
+  bool GenerateImageKeyForTextureHost(wr::ResourceUpdateQueue& aResources,
+                                      TextureHost* aTexture,
+                                      nsTArray<wr::ImageKey>& aKeys);
 
   struct ForwardingTextureHost {
     ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture)
       : mEpoch(aEpoch)
       , mTexture(aTexture)
     {}
     wr::Epoch mEpoch;
     CompositableTextureHostRef mTexture;
@@ -131,17 +133,18 @@ private:
     gfx::MaybeIntSize mScaleToSize;
     wr::ImageRendering mFilter;
     wr::MixBlendMode mMixBlendMode;
     RefPtr<WebRenderImageHost> mImageHost;
     CompositableTextureHostRef mCurrentTexture;
     nsTArray<wr::ImageKey> mKeys;
   };
 
-  bool UpdateImageKeys(bool& aUseExternalImage,
+  bool UpdateImageKeys(wr::ResourceUpdateQueue& aResourceUpdates,
+                       bool& aUseExternalImage,
                        AsyncImagePipeline* aImageMgr,
                        nsTArray<wr::ImageKey>& aKeys,
                        nsTArray<wr::ImageKey>& aKeysToDelete);
 
   RefPtr<wr::WebRenderAPI> mApi;
   wr::IdNamespace mIdNamespace;
   uint32_t mResourceId;
 
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -66,22 +66,21 @@ WebRenderBridgeChild::AddWebRenderParent
 void
 WebRenderBridgeChild::AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands)
 {
   MOZ_ASSERT(mIsInTransaction);
   mParentCommands.AppendElements(aCommands);
 }
 
 bool
-WebRenderBridgeChild::DPBegin(const gfx::IntSize& aSize)
+WebRenderBridgeChild::BeginTransaction(const gfx::IntSize& aSize)
 {
   MOZ_ASSERT(!mDestroyed);
 
   UpdateFwdTransactionId();
-  this->SendDPBegin(aSize);
   mIsInTransaction = true;
   mReadLockSequenceNumber = 0;
   mReadLocks.AppendElement();
   return true;
 }
 
 void
 WebRenderBridgeChild::ClearReadLocks()
@@ -94,42 +93,59 @@ WebRenderBridgeChild::ClearReadLocks()
       }
     }
   }
 
   mReadLocks.Clear();
 }
 
 void
-WebRenderBridgeChild::DPEnd(wr::DisplayListBuilder &aBuilder,
-                            const gfx::IntSize& aSize,
-                            bool aIsSync,
-                            uint64_t aTransactionId,
-                            const WebRenderScrollData& aScrollData,
-                            const mozilla::TimeStamp& aTxnStartTime)
+WebRenderBridgeChild::UpdateResources(wr::ResourceUpdateQueue& aResources)
+{
+  if (!IPCOpen()) {
+    aResources.Clear();
+    return;
+  }
+  wr::ByteBuffer serializedUpdates(Move(aResources.Serialize()));
+  this->SendUpdateResources(serializedUpdates);
+}
+
+void
+WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
+                                     const gfx::IntSize& aSize,
+                                     bool aIsSync,
+                                     uint64_t aTransactionId,
+                                     const WebRenderScrollData& aScrollData,
+                                     const mozilla::TimeStamp& aTxnStartTime)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   wr::BuiltDisplayList dl;
   wr::LayoutSize contentSize;
   aBuilder.Finalize(contentSize, dl);
   ByteBuffer dlData(Move(dl.dl));
 
   TimeStamp fwdTime;
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   fwdTime = TimeStamp::Now();
 #endif
 
+  wr::ByteBuffer resourceUpdates(Move(aBuilder.Resources().Serialize()));
+
   if (aIsSync) {
-    this->SendDPSyncEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
-                        contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace, aTxnStartTime, fwdTime);
+    this->SendSetDisplayListSync(aSize, mParentCommands, mDestroyedActors,
+                                 GetFwdTransactionId(), aTransactionId,
+                                 contentSize, dlData, dl.dl_desc, aScrollData,
+                                 resourceUpdates, mIdNamespace, aTxnStartTime, fwdTime);
   } else {
-    this->SendDPEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
-                    contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace, aTxnStartTime, fwdTime);
+    this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
+                             GetFwdTransactionId(), aTransactionId,
+                             contentSize, dlData, dl.dl_desc, aScrollData,
+                             resourceUpdates, mIdNamespace, aTxnStartTime, fwdTime);
   }
 
   mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 void
@@ -251,65 +267,70 @@ WebRenderBridgeChild::GetFontKeyForScale
   wr::FontInstanceKey instanceKey = { wr::IdNamespace { 0 }, 0 };
   if (mFontInstanceKeys.Get(aScaledFont, &instanceKey)) {
     return instanceKey;
   }
 
   RefPtr<gfx::UnscaledFont> unscaled = aScaledFont->GetUnscaledFont();
   MOZ_ASSERT(unscaled);
 
+  wr::ResourceUpdateQueue resources;
+
   wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0};
   if (!mFontKeys.Get(unscaled, &fontKey)) {
     FontFileData data;
     if (!unscaled->GetFontFileData(WriteFontFileData, &data) ||
         !data.mFontBuffer.mData) {
       return instanceKey;
     }
 
     fontKey.mNamespace = GetNamespace();
     fontKey.mHandle = GetNextResourceId();
 
-    SendAddRawFont(fontKey, data.mFontBuffer, data.mFontIndex);
+    resources.AddRawFont(fontKey, data.mFontBuffer.AsSlice(), data.mFontIndex);
 
     mFontKeys.Put(unscaled, fontKey);
   }
 
   instanceKey.mNamespace = GetNamespace();
   instanceKey.mHandle = GetNextResourceId();
 
-  SendAddFontInstance(instanceKey, fontKey, aScaledFont->GetSize(), Nothing(), Nothing());
+  resources.AddFontInstance(instanceKey, fontKey, aScaledFont->GetSize(), nullptr, nullptr);
+  UpdateResources(resources);
 
   mFontInstanceKeys.Put(aScaledFont, instanceKey);
 
   return instanceKey;
 }
 
 void
 WebRenderBridgeChild::RemoveExpiredFontKeys()
 {
   uint32_t counter = gfx::ScaledFont::DeletionCounter();
+  wr::ResourceUpdateQueue resources;
   if (mFontInstanceKeysDeleted != counter) {
     mFontInstanceKeysDeleted = counter;
     for (auto iter = mFontInstanceKeys.Iter(); !iter.Done(); iter.Next()) {
       if (!iter.Key()) {
-        SendDeleteFontInstance(iter.Data());
+        resources.DeleteFontInstance(iter.Data());
         iter.Remove();
       }
     }
   }
   counter = gfx::UnscaledFont::DeletionCounter();
   if (mFontKeysDeleted != counter) {
     mFontKeysDeleted = counter;
     for (auto iter = mFontKeys.Iter(); !iter.Done(); iter.Next()) {
       if (!iter.Key()) {
-        SendDeleteFont(iter.Data());
+        resources.DeleteFont(iter.Data());
         iter.Remove();
       }
     }
   }
+  UpdateResources(resources);
 }
 
 CompositorBridgeChild*
 WebRenderBridgeChild::GetCompositorBridgeChild()
 {
   return static_cast<CompositorBridgeChild*>(Manager());
 }
 
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -13,16 +13,17 @@
 namespace mozilla {
 
 namespace widget {
 class CompositorWidget;
 }
 
 namespace wr {
 class DisplayListBuilder;
+class ResourceUpdateQueue;
 }
 
 namespace layers {
 
 class CompositableClient;
 class CompositorBridgeChild;
 class StackingContextHelper;
 class TextureForwarder;
@@ -59,21 +60,22 @@ class WebRenderBridgeChild final : publi
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild, override)
 
 public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
   void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
 
-  bool DPBegin(const  gfx::IntSize& aSize);
-  void DPEnd(wr::DisplayListBuilder &aBuilder, const gfx::IntSize& aSize,
-             bool aIsSync, uint64_t aTransactionId,
-             const WebRenderScrollData& aScrollData,
-             const mozilla::TimeStamp& aTxnStartTime);
+  void UpdateResources(wr::ResourceUpdateQueue& aResources);
+  bool BeginTransaction(const  gfx::IntSize& aSize);
+  void EndTransaction(wr::DisplayListBuilder &aBuilder, const gfx::IntSize& aSize,
+                      bool aIsSync, uint64_t aTransactionId,
+                      const WebRenderScrollData& aScrollData,
+                      const mozilla::TimeStamp& aTxnStartTime);
   void ProcessWebRenderParentCommands();
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   wr::PipelineId GetPipeline() { return mPipelineId; }
 
   // KnowsCompositor
   TextureForwarder* GetTextureForwarder() override;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -217,203 +217,24 @@ WebRenderBridgeParent::Destroy()
   if (mDestroyed) {
     return;
   }
   mDestroyed = true;
   ClearResources();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddImage(const wr::ImageKey& aImageKey,
-                                    const gfx::IntSize& aSize,
-                                    const uint32_t& aStride,
-                                    const gfx::SurfaceFormat& aFormat,
-                                    const ByteBuffer& aBuffer)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-
-  // Check if key is obsoleted.
-  if (aImageKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(mApi);
-  MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
-
-  wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
-  mActiveImageKeys.insert(wr::AsUint64(aImageKey));
-  mApi->AddImage(aImageKey, descriptor,
-                 aBuffer.AsSlice());
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddBlobImage(const wr::ImageKey& aImageKey,
-                                        const gfx::IntSize& aSize,
-                                        const uint32_t& aStride,
-                                        const gfx::SurfaceFormat& aFormat,
-                                        const ByteBuffer& aBuffer)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-
-  // Check if key is obsoleted.
-  if (aImageKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(mApi);
-  MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
-
-  wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
-  mActiveImageKeys.insert(wr::AsUint64(aImageKey));
-  mApi->AddBlobImage(aImageKey, descriptor,
-                     aBuffer.AsSlice());
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddRawFont(const wr::FontKey& aFontKey,
-                                      const ByteBuffer& aBuffer,
-                                      const uint32_t& aFontIndex)
+WebRenderBridgeParent::RecvUpdateResources(const wr::ByteBuffer& aUpdates)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
 
-  // Check if key is obsoleted.
-  if (aFontKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(mApi);
-  MOZ_ASSERT(mFontKeys.find(wr::AsUint64(aFontKey)) == mFontKeys.end());
-
-  auto slice = aBuffer.AsSlice();
-  mFontKeys.insert(wr::AsUint64(aFontKey));
-  mApi->AddRawFont(aFontKey, slice, aFontIndex);
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDeleteFont(const wr::FontKey& aFontKey)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  MOZ_ASSERT(mApi);
-
-  // Check if key is obsoleted.
-  if (aFontKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  if (mFontKeys.erase(wr::AsUint64(aFontKey)) > 0) {
-    mApi->DeleteFont(aFontKey);
-  } else {
-    MOZ_ASSERT_UNREACHABLE("invalid FontKey");
-  }
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddFontInstance(const wr::FontInstanceKey& aInstanceKey,
-                                           const wr::FontKey& aFontKey,
-                                           const float& aGlyphSize,
-                                           const MaybeFontInstanceOptions& aOptions,
-                                           const MaybeFontInstancePlatformOptions& aPlatformOptions)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-
-  // Check if key is obsoleted.
-  if (aInstanceKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  MOZ_ASSERT(mApi);
-  MOZ_ASSERT(mFontInstanceKeys.find(wr::AsUint64(aInstanceKey)) == mFontInstanceKeys.end());
-
-  mFontInstanceKeys.insert(wr::AsUint64(aInstanceKey));
-  mApi->AddFontInstance(aInstanceKey, aFontKey, aGlyphSize,
-                        aOptions.ptrOr(nullptr), aPlatformOptions.ptrOr(nullptr));
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDeleteFontInstance(const wr::FontInstanceKey& aInstanceKey)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  MOZ_ASSERT(mApi);
-
-  // Check if key is obsoleted.
-  if (aInstanceKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  if (mFontInstanceKeys.erase(wr::AsUint64(aInstanceKey)) > 0) {
-    mApi->DeleteFontInstance(aInstanceKey);
-  } else {
-    MOZ_ASSERT_UNREACHABLE("invalid FontInstanceKey");
-  }
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvUpdateImage(const wr::ImageKey& aImageKey,
-                                       const gfx::IntSize& aSize,
-                                       const gfx::SurfaceFormat& aFormat,
-                                       const ByteBuffer& aBuffer)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  MOZ_ASSERT(mApi);
-
-  // Check if key is obsoleted.
-  if (aImageKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  wr::ImageDescriptor descriptor(aSize, aFormat);
-  mApi->UpdateImageBuffer(aImageKey, descriptor, aBuffer.AsSlice());
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDeleteImage(const wr::ImageKey& aImageKey)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  MOZ_ASSERT(mApi);
-
-  // Check if key is obsoleted.
-  if (aImageKey.mNamespace != mIdNamespace) {
-    return IPC_OK();
-  }
-
-  if (mActiveImageKeys.erase(wr::AsUint64(aImageKey)) > 0) {
-    mKeysToDelete.push_back(aImageKey);
-  } else {
-    MOZ_ASSERT_UNREACHABLE("invalid ImageKey");
-  }
+  wr::ResourceUpdateQueue updates = wr::ResourceUpdateQueue::Deserialize(aUpdates.AsSlice());
+  mApi->UpdateResources(updates);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds)
 {
   if (mDestroyed) {
     return IPC_OK();
@@ -425,70 +246,16 @@ WebRenderBridgeParent::RecvDeleteComposi
     } else {
       NS_ERROR("Tried to delete invalid animation");
     }
   }
 
   return IPC_OK();
 }
 
-
-mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPBegin(const gfx::IntSize& aSize)
-{
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  return IPC_OK();
-}
-
-void
-WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
-                                 InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                                 InfallibleTArray<OpDestroy>&& aToDestroy,
-                                 const uint64_t& aFwdTransactionId,
-                                 const uint64_t& aTransactionId,
-                                 const wr::LayoutSize& aContentSize,
-                                 const wr::ByteBuffer& dl,
-                                 const wr::BuiltDisplayListDescriptor& dlDesc,
-                                 const WebRenderScrollData& aScrollData,
-                                 const wr::IdNamespace& aIdNamespace,
-                                 const TimeStamp& aTxnStartTime,
-                                 const TimeStamp& aFwdTime)
-{
-  AutoProfilerTracing tracing("Paint", "DPTransaction");
-  UpdateFwdTransactionId(aFwdTransactionId);
-  AutoClearReadLocks clearLocks(mReadLocks);
-
-  if (mDestroyed) {
-    for (const auto& op : aToDestroy) {
-      DestroyActor(op);
-    }
-    return;
-  }
-  // This ensures that destroy operations are always processed. It is not safe
-  // to early-return from RecvDPEnd without doing so.
-  AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
-
-  uint32_t wrEpoch = GetNextWrEpoch();
-  ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(wrEpoch),
-                           aContentSize, dl, dlDesc, aIdNamespace);
-  HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
-
-  mScrollData = aScrollData;
-  UpdateAPZ();
-
-  if (mIdNamespace != aIdNamespace) {
-    // Pretend we composited since someone is wating for this event,
-    // though DisplayList was not pushed to webrender.
-    TimeStamp now = TimeStamp::Now();
-    mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now);
-  }
-}
-
 CompositorBridgeParent*
 WebRenderBridgeParent::GetRootCompositorBridgeParent() const
 {
   if (!mCompositorBridge) {
     return nullptr;
   }
 
   if (mWidget) {
@@ -553,100 +320,127 @@ WebRenderBridgeParent::PushAPZStateToWR(
 const WebRenderScrollData&
 WebRenderBridgeParent::GetScrollData() const
 {
   MOZ_ASSERT(mozilla::layers::CompositorThreadHolder::IsInCompositorThread());
   return mScrollData;
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPEnd(const gfx::IntSize& aSize,
-                                 InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                                 InfallibleTArray<OpDestroy>&& aToDestroy,
-                                 const uint64_t& aFwdTransactionId,
-                                 const uint64_t& aTransactionId,
-                                 const wr::LayoutSize& aContentSize,
-                                 const wr::ByteBuffer& dl,
-                                 const wr::BuiltDisplayListDescriptor& dlDesc,
-                                 const WebRenderScrollData& aScrollData,
-                                 const wr::IdNamespace& aIdNamespace,
-                                 const TimeStamp& aTxnStartTime,
-                                 const TimeStamp& aFwdTime)
+WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
+                                          InfallibleTArray<WebRenderParentCommand>&& aCommands,
+                                          InfallibleTArray<OpDestroy>&& aToDestroy,
+                                          const uint64_t& aFwdTransactionId,
+                                          const uint64_t& aTransactionId,
+                                          const wr::LayoutSize& aContentSize,
+                                          const wr::ByteBuffer& dl,
+                                          const wr::BuiltDisplayListDescriptor& dlDesc,
+                                          const WebRenderScrollData& aScrollData,
+                                          const wr::ByteBuffer& aResourceUpdates,
+                                          const wr::IdNamespace& aIdNamespace,
+                                          const TimeStamp& aTxnStartTime,
+                                          const TimeStamp& aFwdTime)
 {
   if (mDestroyed) {
+    for (const auto& op : aToDestroy) {
+      DestroyActor(op);
+    }
     return IPC_OK();
   }
-  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
-              aContentSize, dl, dlDesc, aScrollData, aIdNamespace, aTxnStartTime, aFwdTime);
+
+  AutoProfilerTracing tracing("Paint", "SetDisplayList");
+  UpdateFwdTransactionId(aFwdTransactionId);
+  AutoClearReadLocks clearLocks(mReadLocks);
+
+  // This ensures that destroy operations are always processed. It is not safe
+  // to early-return from RecvDPEnd without doing so.
+  AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
+
+  wr::ResourceUpdateQueue resources = wr::ResourceUpdateQueue::Deserialize(aResourceUpdates.AsSlice());
+
+  uint32_t wrEpoch = GetNextWrEpoch();
+  ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(wrEpoch),
+                           aContentSize, dl, dlDesc, resources, aIdNamespace);
+  HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
+
+  mScrollData = aScrollData;
+  UpdateAPZ();
+
+  if (mIdNamespace != aIdNamespace) {
+    // Pretend we composited since someone is wating for this event,
+    // though DisplayList was not pushed to webrender.
+    TimeStamp now = TimeStamp::Now();
+    mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now);
+  }
+
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
-                                     InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                                     InfallibleTArray<OpDestroy>&& aToDestroy,
-                                     const uint64_t& aFwdTransactionId,
-                                     const uint64_t& aTransactionId,
-                                     const wr::LayoutSize& aContentSize,
-                                     const wr::ByteBuffer& dl,
-                                     const wr::BuiltDisplayListDescriptor& dlDesc,
-                                     const WebRenderScrollData& aScrollData,
-                                     const wr::IdNamespace& aIdNamespace,
-                                     const TimeStamp& aTxnStartTime,
-                                     const TimeStamp& aFwdTime)
+WebRenderBridgeParent::RecvSetDisplayListSync(const gfx::IntSize &aSize,
+                                              InfallibleTArray<WebRenderParentCommand>&& aCommands,
+                                              InfallibleTArray<OpDestroy>&& aToDestroy,
+                                              const uint64_t& aFwdTransactionId,
+                                              const uint64_t& aTransactionId,
+                                              const wr::LayoutSize& aContentSize,
+                                              const wr::ByteBuffer& dl,
+                                              const wr::BuiltDisplayListDescriptor& dlDesc,
+                                              const WebRenderScrollData& aScrollData,
+                                              const wr::ByteBuffer& aResourceUpdates,
+                                              const wr::IdNamespace& aIdNamespace,
+                                              const TimeStamp& aTxnStartTime,
+                                              const TimeStamp& aFwdTime)
 {
-  if (mDestroyed) {
-    return IPC_OK();
-  }
-  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
-              aContentSize, dl, dlDesc, aScrollData, aIdNamespace, aTxnStartTime, aFwdTime);
-  return IPC_OK();
+  return RecvSetDisplayList(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
+                            aContentSize, dl, dlDesc, aScrollData, aResourceUpdates,
+                            aIdNamespace, aTxnStartTime, aFwdTime);
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvParentCommands(nsTArray<WebRenderParentCommand>&& aCommands)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
-  ProcessWebRenderParentCommands(aCommands);
+  wr::ResourceUpdateQueue resources;
+  ProcessWebRenderParentCommands(aCommands, resources);
+  mApi->UpdateResources(resources);
   return IPC_OK();
 }
 
 void
-WebRenderBridgeParent::ProcessWebRenderParentCommands(InfallibleTArray<WebRenderParentCommand>& aCommands)
+WebRenderBridgeParent::ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands,
+                                                      wr::ResourceUpdateQueue& aResources)
 {
   for (InfallibleTArray<WebRenderParentCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
     const WebRenderParentCommand& cmd = aCommands[i];
     switch (cmd.type()) {
       case WebRenderParentCommand::TOpAddExternalImage: {
         const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
         Range<const wr::ImageKey> keys(&op.key(), 1);
         // Check if key is obsoleted.
         if (keys[0].mNamespace != mIdNamespace) {
           break;
         }
         MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
-        MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(keys[0])) == mActiveImageKeys.end());
-        mActiveImageKeys.insert(wr::AsUint64(keys[0]));
 
         RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
         if (!host) {
           NS_ERROR("CompositableHost does not exist");
           break;
         }
         if (!gfxEnv::EnableWebRenderRecording()) {
           TextureHost* texture = host->GetAsTextureHostForComposite();
           if (!texture) {
             NS_ERROR("TextureHost does not exist");
             break;
           }
           WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
           if (wrTexture) {
-            wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
+            wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey());
             break;
           }
         }
         RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
         if (!dSurf) {
           NS_ERROR("TextureHost does not return DataSourceSurface");
           break;
         }
@@ -655,17 +449,17 @@ WebRenderBridgeParent::ProcessWebRenderP
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           NS_ERROR("DataSourceSurface failed to map");
           break;
         }
 
         IntSize size = dSurf->GetSize();
         wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
         auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
-        mApi->AddImage(keys[0], descriptor, slice);
+        aResources.AddImage(keys[0], descriptor, slice);
 
         dSurf->Unmap();
         break;
       }
       case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
         const OpUpdateAsyncImagePipeline& op = cmd.get_OpUpdateAsyncImagePipeline();
         mAsyncImageManager->UpdateAsyncImagePipeline(op.pipelineId(),
                                                       op.scBounds(),
@@ -707,46 +501,48 @@ WebRenderBridgeParent::ProcessWebRenderP
   }
 }
 
 void
 WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
                                                 InfallibleTArray<WebRenderParentCommand>& aCommands, const wr::Epoch& aEpoch,
                                                 const wr::LayoutSize& aContentSize, const wr::ByteBuffer& dl,
                                                 const wr::BuiltDisplayListDescriptor& dlDesc,
+                                                wr::ResourceUpdateQueue& aResourceUpdates,
                                                 const wr::IdNamespace& aIdNamespace)
 {
   mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
-  ProcessWebRenderParentCommands(aCommands);
+  ProcessWebRenderParentCommands(aCommands, aResourceUpdates);
 
   // The command is obsoleted.
   // Do not set the command to webrender since it causes crash in webrender.
   if (mIdNamespace != aIdNamespace) {
     return;
   }
 
   if (mWidget) {
     LayoutDeviceIntSize size = mWidget->GetClientSize();
     mApi->SetWindowParameters(size);
   }
   gfx::Color color = mWidget ? gfx::Color(0.3f, 0.f, 0.f, 1.f) : gfx::Color(0.f, 0.f, 0.f, 0.f);
-  mApi->SetRootDisplayList(color, aEpoch, LayerSize(aSize.width, aSize.height),
-                           mPipelineId, aContentSize,
-                           dlDesc, dl.mData, dl.mLength);
+  mApi->SetDisplayList(color, aEpoch, LayerSize(aSize.width, aSize.height),
+                       mPipelineId, aContentSize,
+                       dlDesc, dl.mData, dl.mLength,
+                       aResourceUpdates);
 
   ScheduleComposition();
   DeleteOldImages();
 
   if (ShouldParentObserveEpoch()) {
     mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
   }
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
+WebRenderBridgeParent::RecvGetSnapshot(PTextureParent* aTexture)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   MOZ_ASSERT(!mPaused);
 
   RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
   if (!texture) {
@@ -900,17 +696,17 @@ mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvClearCachedResources()
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), false);
 
   // Clear resources
-  mApi->ClearRootDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
+  mApi->ClearDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
   // Schedule composition to clean up Pipeline
   mCompositorScheduler->ScheduleComposition();
   DeleteOldImages();
   // Remove animations.
   for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
     mAnimStorage->ClearById(*iter);
   }
   mActiveAnimations.clear();
@@ -1271,19 +1067,21 @@ uint64_t
 WebRenderBridgeParent::GetLayersId() const
 {
   return wr::AsUint64(mPipelineId);
 }
 
 void
 WebRenderBridgeParent::DeleteOldImages()
 {
+  wr::ResourceUpdateQueue resources;
   for (wr::ImageKey key : mKeysToDelete) {
-    mApi->DeleteImage(key);
+    resources.DeleteImage(key);
   }
+  mApi->UpdateResources(resources);
   mKeysToDelete.clear();
 }
 
 void
 WebRenderBridgeParent::ScheduleComposition()
 {
   if (mCompositorScheduler) {
     mCompositorScheduler->ScheduleComposition();
@@ -1343,23 +1141,20 @@ WebRenderBridgeParent::Resume()
 void
 WebRenderBridgeParent::ClearResources()
 {
   if (!mApi) {
     return;
   }
 
   uint32_t wrEpoch = GetNextWrEpoch();
-  mApi->ClearRootDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
+  mApi->ClearDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
   // Schedule composition to clean up Pipeline
   mCompositorScheduler->ScheduleComposition();
   // WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction.
-  mFontInstanceKeys.clear();
-  mFontKeys.clear();
-  mActiveImageKeys.clear();
   mKeysToDelete.clear();
   for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
     iter.Data()->ClearWrBridge();
   }
   mExternalImageIds.Clear();
   for (auto iter = mAsyncCompositables.Iter(); !iter.Done(); iter.Next()) {
     wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
     RefPtr<WebRenderImageHost> host = iter.Data();
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -67,69 +67,46 @@ public:
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   mozilla::ipc::IPCResult RecvInitReadLocks(ReadLockArray&& aReadLocks) override;
 
   mozilla::ipc::IPCResult RecvCreate(const gfx::IntSize& aSize) override;
   mozilla::ipc::IPCResult RecvShutdown() override;
   mozilla::ipc::IPCResult RecvShutdownSync() override;
-  mozilla::ipc::IPCResult RecvAddImage(const wr::ImageKey& aImageKey,
-                                       const gfx::IntSize& aSize,
-                                       const uint32_t& aStride,
-                                       const gfx::SurfaceFormat& aFormat,
-                                       const ByteBuffer& aBuffer) override;
-  mozilla::ipc::IPCResult RecvAddBlobImage(const wr::ImageKey& aImageKey,
-                                           const gfx::IntSize& aSize,
-                                           const uint32_t& aStride,
-                                           const gfx::SurfaceFormat& aFormat,
-                                           const ByteBuffer& aBuffer) override;
-  mozilla::ipc::IPCResult RecvUpdateImage(const wr::ImageKey& aImageKey,
-                                          const gfx::IntSize& aSize,
-                                          const gfx::SurfaceFormat& aFormat,
-                                          const ByteBuffer& aBuffer) override;
-  mozilla::ipc::IPCResult RecvDeleteImage(const wr::ImageKey& a1) override;
   mozilla::ipc::IPCResult RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds) override;
-  mozilla::ipc::IPCResult RecvAddRawFont(const wr::FontKey& aFontKey,
-                                         const ByteBuffer& aBuffer,
-                                         const uint32_t& aFontIndex) override;
-  mozilla::ipc::IPCResult RecvDeleteFont(const wr::FontKey& aFontKey) override;
-  mozilla::ipc::IPCResult RecvAddFontInstance(const wr::FontInstanceKey& aInstanceKey,
-                                              const wr::FontKey& aFontKey,
-                                              const float& aGlyphSize,
-                                              const MaybeFontInstanceOptions& aOptions,
-                                              const MaybeFontInstancePlatformOptions& aPlatformOptions) override;
-  mozilla::ipc::IPCResult RecvDeleteFontInstance(const wr::FontInstanceKey& aInstanceKey) override;
-  mozilla::ipc::IPCResult RecvDPBegin(const gfx::IntSize& aSize) override;
-  mozilla::ipc::IPCResult RecvDPEnd(const gfx::IntSize& aSize,
-                                    InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                                    InfallibleTArray<OpDestroy>&& aToDestroy,
-                                    const uint64_t& aFwdTransactionId,
-                                    const uint64_t& aTransactionId,
-                                    const wr::LayoutSize& aContentSize,
-                                    const wr::ByteBuffer& dl,
-                                    const wr::BuiltDisplayListDescriptor& dlDesc,
-                                    const WebRenderScrollData& aScrollData,
-                                    const wr::IdNamespace& aIdNamespace,
-                                    const TimeStamp& aTxnStartTime,
-                                    const TimeStamp& aFwdTime) override;
-  mozilla::ipc::IPCResult RecvDPSyncEnd(const gfx::IntSize& aSize,
-                                        InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                                        InfallibleTArray<OpDestroy>&& aToDestroy,
-                                        const uint64_t& aFwdTransactionId,
-                                        const uint64_t& aTransactionId,
-                                        const wr::LayoutSize& aContentSize,
-                                        const wr::ByteBuffer& dl,
-                                        const wr::BuiltDisplayListDescriptor& dlDesc,
-                                        const WebRenderScrollData& aScrollData,
-                                        const wr::IdNamespace& aIdNamespace,
-                                        const TimeStamp& aTxnStartTime,
-                                        const TimeStamp& aFwdTime) override;
+  mozilla::ipc::IPCResult RecvUpdateResources(const ByteBuffer& aUpdates) override;
+  mozilla::ipc::IPCResult RecvSetDisplayList(const gfx::IntSize& aSize,
+                                             InfallibleTArray<WebRenderParentCommand>&& aCommands,
+                                             InfallibleTArray<OpDestroy>&& aToDestroy,
+                                             const uint64_t& aFwdTransactionId,
+                                             const uint64_t& aTransactionId,
+                                             const wr::LayoutSize& aContentSize,
+                                             const wr::ByteBuffer& dl,
+                                             const wr::BuiltDisplayListDescriptor& dlDesc,
+                                             const WebRenderScrollData& aScrollData,
+                                             const wr::ByteBuffer& aResourceUpdates,
+                                             const wr::IdNamespace& aIdNamespace,
+                                             const TimeStamp& aTxnStartTime,
+                                             const TimeStamp& aFwdTime) override;
+  mozilla::ipc::IPCResult RecvSetDisplayListSync(const gfx::IntSize& aSize,
+                                                 InfallibleTArray<WebRenderParentCommand>&& aCommands,
+                                                 InfallibleTArray<OpDestroy>&& aToDestroy,
+                                                 const uint64_t& aFwdTransactionId,
+                                                 const uint64_t& aTransactionId,
+                                                 const wr::LayoutSize& aContentSize,
+                                                 const wr::ByteBuffer& dl,
+                                                 const wr::BuiltDisplayListDescriptor& dlDesc,
+                                                 const WebRenderScrollData& aScrollData,
+                                                 const wr::ByteBuffer& aResourceUpdates,
+                                                 const wr::IdNamespace& aIdNamespace,
+                                                 const TimeStamp& aTxnStartTime,
+                                                 const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
-  mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
+  mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvAddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds,
                                                            const CompositableHandle& aHandle,
                                                            const bool& aAsync) override;
   mozilla::ipc::IPCResult RecvRemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId) override;
 
   mozilla::ipc::IPCResult RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
                                                                 const CompositableHandle& aHandle) override;
@@ -204,39 +181,29 @@ public:
                        CompositorAnimationStorage* aAnimStorage);
 
 private:
   explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
   virtual ~WebRenderBridgeParent();
 
   uint64_t GetLayersId() const;
   void DeleteOldImages();
-  void ProcessWebRenderParentCommands(InfallibleTArray<WebRenderParentCommand>& aCommands);
+  void ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands,
+                                      wr::ResourceUpdateQueue& aResources);
   void ProcessWebRenderCommands(const gfx::IntSize &aSize,
                                 InfallibleTArray<WebRenderParentCommand>& commands,
                                 const wr::Epoch& aEpoch,
                                 const wr::LayoutSize& aContentSize,
                                 const wr::ByteBuffer& dl,
                                 const wr::BuiltDisplayListDescriptor& dlDesc,
+                                wr::ResourceUpdateQueue& aResourceUpdates,
                                 const wr::IdNamespace& aIdNamespace);
   void ClearResources();
   uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
-  void HandleDPEnd(const gfx::IntSize& aSize,
-                   InfallibleTArray<WebRenderParentCommand>&& aCommands,
-                   InfallibleTArray<OpDestroy>&& aToDestroy,
-                   const uint64_t& aFwdTransactionId,
-                   const uint64_t& aTransactionId,
-                   const wr::LayoutSize& aContentSize,
-                   const wr::ByteBuffer& dl,
-                   const wr::BuiltDisplayListDescriptor& dlDesc,
-                   const WebRenderScrollData& aScrollData,
-                   const wr::IdNamespace& aIdNamespace,
-                   const TimeStamp& aTxnStartTime,
-                   const TimeStamp& aFwdTime);
   mozilla::ipc::IPCResult HandleShutdown();
 
   void AdvanceAnimations();
   void SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
 
   CompositorBridgeParent* GetRootCompositorBridgeParent() const;
 
@@ -269,21 +236,16 @@ private:
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
   RefPtr<wr::WebRenderAPI> mApi;
   RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
   RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
   RefPtr<CompositorAnimationStorage> mAnimStorage;
   std::vector<wr::ImageKey> mKeysToDelete;
-  // mActiveImageKeys and mFontKeys are used to avoid leaking animations when
-  // WebRenderBridgeParent is destroyed abnormally and Tab move between different windows.
-  std::unordered_set<uint64_t> mActiveImageKeys;
-  std::unordered_set<uint64_t> mFontKeys;
-  std::unordered_set<uint64_t> mFontInstanceKeys;
   // mActiveAnimations is used to avoid leaking animations when WebRenderBridgeParent is
   // destroyed abnormally and Tab move between different windows.
   std::unordered_set<uint64_t> mActiveAnimations;
   nsDataHashtable<nsUint64HashKey, RefPtr<WebRenderImageHost>> mAsyncCompositables;
   nsDataHashtable<nsUint64HashKey, RefPtr<WebRenderImageHost>> mExternalImageIds;
 
   TimeStamp mPreviousFrameTimeStamp;
   // These fields keep track of the latest layer observer epoch values in the child and the
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -98,17 +98,17 @@ WebRenderLayerManager::DoDestroy(bool aI
   }
 
   mWidget->CleanupWebRenderWindowOverlay(WrBridge());
 
   LayerManager::Destroy();
 
   if (WrBridge()) {
     // Just clear ImageKeys, they are deleted during WebRenderAPI destruction.
-    mImageKeysToDelete.clear();
+    mImageKeysToDelete.Clear();
     // CompositorAnimations are cleared by WebRenderBridgeParent.
     mDiscardedCompositorAnimationsIds.Clear();
     WrBridge()->Destroy(aIsSync);
   }
 
   mLastCanvasDatas.Clear();
 
   if (mTransactionIdAllocator) {
@@ -574,19 +574,20 @@ WebRenderLayerManager::GenerateFallbackD
       RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
       // TODO: should use 'format' to replace gfx::SurfaceFormat::B8G8R8X8. Currently blob image doesn't support A8 format.
       RefPtr<gfx::DrawTarget> dummyDt =
         gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8X8);
       RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
       PaintItemByDrawTarget(aItem, dt, aImageRect, aOffset, aDisplayListBuilder);
       recorder->Finish();
 
-      wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
+      Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
       wr::ImageKey key = WrBridge()->GetNextImageKey();
-      WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), 0, dt->GetFormat(), bytes);
+      wr::ImageDescriptor descriptor(imageSize.ToUnknownSize(), 0, dt->GetFormat());
+      aBuilder.Resources().AddBlobImage(key, descriptor, bytes);
       fallbackData->SetKey(key);
     } else {
       fallbackData->CreateImageClientIfNeeded();
       RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
       RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
 
       {
         UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize(), format);
@@ -694,17 +695,17 @@ WebRenderLayerManager::EndTransactionInt
   if (gfxPrefs::LayersDump()) {
     this->Dump();
   }
 
   // Since we don't do repeat transactions right now, just set the time
   mAnimationReadyTime = TimeStamp::Now();
 
   LayoutDeviceIntSize size = mWidget->GetClientSize();
-  if (!WrBridge()->DPBegin(size.ToUnknownSize())) {
+  if (!WrBridge()->BeginTransaction(size.ToUnknownSize())) {
     return false;
   }
   DiscardCompositorAnimations();
 
   wr::LayoutSize contentSize { (float)size.width, (float)size.height };
   wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
 
   if (mEndTransactionWithoutLayers) {
@@ -810,17 +811,18 @@ WebRenderLayerManager::EndTransactionInt
     if (WrBridge()->GetSyncObject() &&
         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
       WrBridge()->GetSyncObject()->Synchronize();
     }
   }
   {
     AutoProfilerTracing
       tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
-    WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, mScrollData, transactionStart);
+    WrBridge()->EndTransaction(builder, size.ToUnknownSize(), sync,
+                               mLatestTransactionId, mScrollData, transactionStart);
   }
 
   MakeSnapshotIfRequired(size);
   mNeedsComposite = false;
 
   ClearDisplayItemLayers();
 
   // this may result in Layers being deleted, which results in
@@ -865,17 +867,17 @@ WebRenderLayerManager::MakeSnapshotIfReq
   }
 
   texture->InitIPDLActor(WrBridge());
   if (!texture->GetIPDLActor()) {
     return;
   }
 
   IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
-  if (!WrBridge()->SendDPGetSnapshot(texture->GetIPDLActor())) {
+  if (!WrBridge()->SendGetSnapshot(texture->GetIPDLActor())) {
     return;
   }
 
   TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
   if (!autoLock.Succeeded()) {
     return;
   }
   RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
@@ -903,28 +905,23 @@ WebRenderLayerManager::MakeSnapshotIfReq
   dt->FillRect(dst, pattern);
 
   mTarget = nullptr;
 }
 
 void
 WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
 {
-  mImageKeysToDelete.push_back(key);
+  mImageKeysToDelete.DeleteImage(key);
 }
 
 void
 WebRenderLayerManager::DiscardImages()
 {
-  if (WrBridge()->IPCOpen()) {
-    for (auto key : mImageKeysToDelete) {
-      WrBridge()->SendDeleteImage(key);
-    }
-  }
-  mImageKeysToDelete.clear();
+  WrBridge()->UpdateResources(mImageKeysToDelete);
 }
 
 void
 WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
 {
   mDiscardedCompositorAnimationsIds.AppendElement(aId);
 }
 
@@ -939,17 +936,17 @@ WebRenderLayerManager::DiscardCompositor
 }
 
 void
 WebRenderLayerManager::DiscardLocalImages()
 {
   // Removes images but doesn't tell the parent side about them
   // This is useful in empty / failed transactions where we created
   // image keys but didn't tell the parent about them yet.
-  mImageKeysToDelete.clear();
+  mImageKeysToDelete.Clear();
 }
 
 void
 WebRenderLayerManager::Mutated(Layer* aLayer)
 {
   LayerManager::Mutated(aLayer);
   AddMutatedLayer(aLayer);
 }
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -236,17 +236,17 @@ private:
   bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags,
                               nsDisplayList* aDisplayList = nullptr,
                               nsDisplayListBuilder* aDisplayListBuilder = nullptr);
 
 private:
   nsIWidget* MOZ_NON_OWNING_REF mWidget;
-  std::vector<wr::ImageKey> mImageKeysToDelete;
+  wr::ResourceUpdateQueue mImageKeysToDelete;
   nsTArray<uint64_t> mDiscardedCompositorAnimationsIds;
 
   /* PaintedLayer callbacks; valid at the end of a transaciton,
    * while rendering */
   DrawPaintedLayerCallback mPaintedLayerCallback;
   void *mPaintedLayerCallbackData;
 
   RefPtr<WebRenderBridgeChild> mWrChild;
--- a/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
@@ -68,23 +68,24 @@ WebRenderPaintedLayerBlob::RenderLayer(w
     }
 
     recorder->Finish();
 
     AddToValidRegion(regionToPaint);
 
     wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
 
-    //XXX: We should switch to updating the blob image instead of adding a new one
-    //     That will get rid of this discard bit
     if (mImageKey.isSome()) {
-      WrManager()->AddImageKeyForDiscard(mImageKey.value());
+      //XXX: We should switch to updating the blob image instead of adding a new one
+      aBuilder.Resources().DeleteImage(mImageKey.value());
     }
     mImageKey = Some(GenerateImageKey());
-    WrBridge()->SendAddBlobImage(mImageKey.value(), imageSize, 0, dt->GetFormat(), bytes);
+
+    wr::ImageDescriptor descriptor(imageSize, 0, dt->GetFormat());
+    aBuilder.Resources().AddBlobImage(mImageKey.value(), descriptor, bytes.AsSlice());
     mImageBounds = visibleRegion.GetBounds();
   }
 
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
   StackingContextHelper sc(aSc, aBuilder, this);
   LayerRect rect = Bounds();
   DumpLayerInfo("PaintedLayer", rect);
 
--- a/gfx/layers/wr/WebRenderTextureHost.cpp
+++ b/gfx/layers/wr/WebRenderTextureHost.cpp
@@ -140,24 +140,24 @@ WebRenderTextureHost::GetWRImageKeys(nsT
 {
   MOZ_ASSERT(mWrappedTextureHost);
   MOZ_ASSERT(aImageKeys.IsEmpty());
 
   mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator);
 }
 
 void
-WebRenderTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
+WebRenderTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                  Range<const wr::ImageKey>& aImageKeys,
                                  const wr::ExternalImageId& aExtID)
 {
   MOZ_ASSERT(mWrappedTextureHost);
   MOZ_ASSERT(mExternalImageId == aExtID);
 
-  mWrappedTextureHost->AddWRImage(aAPI, aImageKeys, aExtID);
+  mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID);
 }
 
 void
 WebRenderTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                         const wr::LayoutRect& aBounds,
                                         const wr::LayoutRect& aClip,
                                         wr::ImageRendering aFilter,
                                         Range<const wr::ImageKey>& aImageKeys)
--- a/gfx/layers/wr/WebRenderTextureHost.h
+++ b/gfx/layers/wr/WebRenderTextureHost.h
@@ -61,17 +61,17 @@ public:
 
   wr::ExternalImageId GetExternalImageKey() { return mExternalImageId; }
 
   int32_t GetRGBStride();
 
   virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
                               const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
 
-  virtual void AddWRImage(wr::WebRenderAPI* aAPI,
+  virtual void AddWRImage(wr::ResourceUpdateQueue& aResources,
                           Range<const wr::ImageKey>& aImageKeys,
                           const wr::ExternalImageId& aExtID) override;
 
   virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                  const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  wr::ImageRendering aFilter,
                                  Range<const wr::ImageKey>& aImageKeys) override;
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -277,17 +277,22 @@ gfxDWriteFontFamily::ReadFaceNames(gfxPl
                                      aNeedFullnamePostscriptNames,
                                      aFontInfoData);
     }
 }
 
 void
 gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName)
 {
-    aLocalizedName.AssignLiteral("Unknown Font");
+    aLocalizedName = Name(); // just return canonical name in case of failure
+
+    if (!mDWFamily) {
+        return;
+    }
+
     HRESULT hr;
     nsAutoCString locale;
     // We use system locale here because it's what user expects to see.
     // See bug 1349454 for details.
     OSPreferences::GetInstance()->GetSystemLocale(locale);
 
     RefPtr<IDWriteLocalizedStrings> names;
 
@@ -350,16 +355,23 @@ gfxDWriteFontFamily::AddSizeOfIncludingT
 {
     aSizes->mFontListSize += aMallocSizeOf(this);
     AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // gfxDWriteFontEntry
 
+gfxFontEntry*
+gfxDWriteFontEntry::Clone() const
+{
+    MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
+    return new gfxDWriteFontEntry(Name(), mFont);
+}
+
 gfxDWriteFontEntry::~gfxDWriteFontEntry()
 {
 }
 
 bool
 gfxDWriteFontEntry::IsSymbolFont()
 {
     if (mFont) {
@@ -1261,17 +1273,17 @@ gfxDWriteFontList::GetStandardFamilyName
     }
 
     return false;
 }
 
 bool
 gfxDWriteFontList::FindAndAddFamilies(const nsAString& aFamily,
                                       nsTArray<gfxFontFamily*>* aOutput,
-                                      bool aDeferOtherFamilyNamesLoading,
+                                      FindFamiliesFlags aFlags,
                                       gfxFontStyle* aStyle,
                                       gfxFloat aDevToCssSize)
 {
     nsAutoString keyName(aFamily);
     BuildKeyNameFromFontName(keyName);
 
     gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
     if (ff) {
@@ -1280,17 +1292,17 @@ gfxDWriteFontList::FindAndAddFamilies(co
     }
 
     if (mNonExistingFonts.Contains(keyName)) {
         return false;
     }
 
     return gfxPlatformFontList::FindAndAddFamilies(aFamily,
                                                    aOutput,
-                                                   aDeferOtherFamilyNamesLoading,
+                                                   aFlags,
                                                    aStyle,
                                                    aDevToCssSize);
 }
 
 void
 gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                           FontListSizes* aSizes) const
 {
@@ -1700,16 +1712,22 @@ gfxDWriteFontList::CreateFontInfoData()
 #ifdef MOZ_BUNDLED_FONTS
                                 , mBundledFonts
 #endif
                                );
 
     return fi.forget();
 }
 
+gfxFontFamily*
+gfxDWriteFontList::CreateFontFamily(const nsAString& aName) const
+{
+    return new gfxDWriteFontFamily(aName, nullptr);
+}
+
 
 #ifdef MOZ_BUNDLED_FONTS
 
 #define IMPL_QI_FOR_DWRITE(_interface)                                        \
     public:                                                                   \
         IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject)       \
         {                                                                     \
             if (__uuidof(_interface) == riid) {                               \
--- a/gfx/thebes/gfxDWriteFontList.h
+++ b/gfx/thebes/gfxDWriteFontList.h
@@ -145,16 +145,18 @@ public:
     {
         mWeight = aWeight;
         mStretch = aStretch;
         mStyle = aStyle;
         mIsDataUserFont = true;
         mIsCJK = UNINITIALIZED_VALUE;
     }
 
+    gfxFontEntry* Clone() const override;
+
     virtual ~gfxDWriteFontEntry();
 
     virtual bool IsSymbolFont();
 
     virtual hb_blob_t* GetFontTable(uint32_t aTableTag) override;
 
     nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
 
@@ -354,16 +356,18 @@ public:
 
     static gfxDWriteFontList* PlatformFontList() {
         return static_cast<gfxDWriteFontList*>(sPlatformFontList);
     }
 
     // initialize font lists
     virtual nsresult InitFontListForPlatform() override;
 
+    gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
+
     virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
                                           uint16_t aWeight,
                                           int16_t aStretch,
                                           uint8_t aStyle);
 
     virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
                                            uint16_t aWeight,
                                            int16_t aStretch,
@@ -374,17 +378,17 @@ public:
     bool GetStandardFamilyName(const nsAString& aFontName,
                                  nsAString& aFamilyName);
 
     IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; }
     bool UseGDIFontTableAccess() { return mGDIFontTableAccess; }
 
     bool FindAndAddFamilies(const nsAString& aFamily,
                             nsTArray<gfxFontFamily*>* aOutput,
-                            bool aDeferOtherFamilyNamesLoading,
+                            FindFamiliesFlags aFlags,
                             gfxFontStyle* aStyle = nullptr,
                             gfxFloat aDevToCssSize = 1.0) override;
 
     gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; }
 
     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -223,16 +223,29 @@ FT2FontEntry::~FT2FontEntry()
 #ifndef ANDROID
     if (mFontFace) {
         cairo_font_face_destroy(mFontFace);
         mFontFace = nullptr;
     }
 #endif
 }
 
+gfxFontEntry*
+FT2FontEntry::Clone() const
+{
+    MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
+    FT2FontEntry* fe = new FT2FontEntry(Name());
+    fe->mFilename = mFilename;
+    fe->mFTFontIndex = mFTFontIndex;
+    fe->mWeight = mWeight;
+    fe->mStretch = mStretch;
+    fe->mStyle = mStyle;
+    return fe;
+}
+
 gfxFont*
 FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
 {
     cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontStyle);
     if (!scaledFont) {
         return nullptr;
     }
 
@@ -1491,16 +1504,22 @@ void
 gfxFT2FontList::GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray)
 {
     for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
         RefPtr<gfxFontFamily>& family = iter.Data();
         aFamilyArray.AppendElement(family);
     }
 }
 
+gfxFontFamily*
+gfxFT2FontList::CreateFontFamily(const nsAString& aName) const
+{
+    return new FT2FontFamily(aName);
+}
+
 void
 gfxFT2FontList::WillShutdown()
 {
     mozilla::scache::StartupCache* cache =
         mozilla::scache::StartupCache::GetSingleton();
     if (cache && mJarModifiedTime > 0) {
         cache->PutBuffer(JAR_LAST_MODIFED_TIME,
                          (char*)&mJarModifiedTime, sizeof(mJarModifiedTime));
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -29,16 +29,18 @@ public:
         mFTFace(nullptr),
         mFontFace(nullptr),
         mFTFontIndex(0)
     {
     }
 
     ~FT2FontEntry();
 
+    gfxFontEntry* Clone() const override;
+
     const nsString& GetName() const {
         return Name();
     }
 
     // create a font entry for a downloaded font
     static FT2FontEntry* 
     CreateFontEntry(const nsAString& aFontName,
                     uint16_t aWeight,
@@ -130,16 +132,18 @@ public:
     void GetSystemFontList(InfallibleTArray<FontListEntry>* retValue);
 
     static gfxFT2FontList* PlatformFontList() {
         return static_cast<gfxFT2FontList*>(gfxPlatformFontList::PlatformFontList());
     }
 
     virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray) override;
 
+    gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
+
     void WillShutdown();
 
 protected:
     typedef enum {
         kUnknown,
         kStandard
     } StandardFile;
 
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -240,16 +240,23 @@ gfxFontconfigFontEntry::gfxFontconfigFon
     // width
     int width;
     if (FcPatternGetInteger(aFontPattern, FC_WIDTH, 0, &width) != FcResultMatch) {
         width = FC_WIDTH_NORMAL;
     }
     mStretch = MapFcWidth(width);
 }
 
+gfxFontEntry*
+gfxFontconfigFontEntry::Clone() const
+{
+    MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
+    return new gfxFontconfigFontEntry(Name(), mFontPattern, mIgnoreFcCharmap);
+}
+
 gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
                                                uint16_t aWeight,
                                                int16_t aStretch,
                                                uint8_t aStyle,
                                                const uint8_t *aData,
                                                FT_Face aFace)
     : gfxFontEntry(aFaceName),
       mFTFace(aFace), mFTFaceInitialized(true),
@@ -1511,17 +1518,17 @@ gfxFcPlatformFontList::MakePlatformFont(
 
     return new gfxFontconfigFontEntry(aFontName, aWeight, aStretch,
                                       aStyle, aFontData, face);
 }
 
 bool
 gfxFcPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
                                           nsTArray<gfxFontFamily*>* aOutput,
-                                          bool aDeferOtherFamilyNamesLoading,
+                                          FindFamiliesFlags aFlags,
                                           gfxFontStyle* aStyle,
                                           gfxFloat aDevToCssSize)
 {
     nsAutoString familyName(aFamily);
     ToLowerCase(familyName);
     nsIAtom* language = (aStyle ? aStyle->language.get() : nullptr);
 
     // deprecated generic names are explicitly converted to standard generics
@@ -1596,17 +1603,17 @@ gfxFcPlatformFontList::FindAndAddFamilie
     {
         NS_ConvertUTF8toUTF16 subst(ToCharPtr(substName));
         if (sentinelFirstFamily &&
             FcStrCmp(substName, sentinelFirstFamily) == 0) {
             break;
         }
         gfxPlatformFontList::FindAndAddFamilies(subst,
                                                 &cachedFamilies,
-                                                aDeferOtherFamilyNamesLoading);
+                                                aFlags);
     }
 
     // Cache the resulting list, so we don't have to do this again.
     mFcSubstituteCache.Put(familyToFind, cachedFamilies);
 
     if (cachedFamilies.IsEmpty()) {
         return false;
     }
@@ -1879,17 +1886,17 @@ gfxFcPlatformFontList::FindGenericFamili
         FcChar8* mappedGeneric = nullptr;
 
         FcPatternGetString(font, FC_FAMILY, 0, &mappedGeneric);
         if (mappedGeneric) {
             NS_ConvertUTF8toUTF16 mappedGenericName(ToCharPtr(mappedGeneric));
             AutoTArray<gfxFontFamily*,1> genericFamilies;
             if (gfxPlatformFontList::FindAndAddFamilies(mappedGenericName,
                                                         &genericFamilies,
-                                                        true)) {
+                                                        FindFamiliesFlags(0))) {
                 MOZ_ASSERT(genericFamilies.Length() == 1,
                            "expected a single family");
                 if (!prefFonts->Contains(genericFamilies[0])) {
                     prefFonts->AppendElement(genericFamilies[0]);
                     bool foundLang =
                         !fcLang.IsEmpty() &&
                         PatternHasLang(font, ToFcChar8Ptr(fcLang.get()));
                     foundFontWithLang = foundFontWithLang || foundLang;
@@ -1971,16 +1978,22 @@ gfxFcPlatformFontList::CheckFontUpdates(
     gfxFcPlatformFontList *pfl = static_cast<gfxFcPlatformFontList*>(aThis);
     FcConfig* current = FcConfigGetCurrent();
     if (current != pfl->GetLastConfig()) {
         pfl->UpdateFontList();
         pfl->ForceGlobalReflow();
     }
 }
 
+gfxFontFamily*
+gfxFcPlatformFontList::CreateFontFamily(const nsAString& aName) const
+{
+    return new gfxFontconfigFontFamily(aName);
+}
+
 #ifdef MOZ_BUNDLED_FONTS
 void
 gfxFcPlatformFontList::ActivateBundledFonts()
 {
     if (!mBundledFontsInitialized) {
         mBundledFontsInitialized = true;
         nsCOMPtr<nsIFile> localDir;
         nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(localDir));
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -90,16 +90,18 @@ public:
 
     // used for @font-face local system fonts with explicit patterns
     explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                     FcPattern* aFontPattern,
                                     uint16_t aWeight,
                                     int16_t aStretch,
                                     uint8_t aStyle);
 
+    gfxFontEntry* Clone() const override;
+
     FcPattern* GetPattern() { return mFontPattern; }
 
     bool SupportsLangGroup(nsIAtom *aLangGroup) const override;
 
     nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
     bool TestCharacterMap(uint32_t aCh) override;
 
     hb_blob_t* GetFontTable(uint32_t aTableTag) override;
@@ -255,17 +257,17 @@ public:
     MakePlatformFont(const nsAString& aFontName, uint16_t aWeight,
                      int16_t aStretch,
                      uint8_t aStyle,
                      const uint8_t* aFontData,
                      uint32_t aLength) override;
 
     bool FindAndAddFamilies(const nsAString& aFamily,
                             nsTArray<gfxFontFamily*>* aOutput,
-                            bool aDeferOtherFamilyNamesLoading,
+                            FindFamiliesFlags aFlags,
                             gfxFontStyle* aStyle = nullptr,
                             gfxFloat aDevToCssSize = 1.0) override;
 
     bool GetStandardFamilyName(const nsAString& aFontName,
                                nsAString& aFamilyName) override;
 
     FcConfig* GetLastConfig() const { return mLastConfig; }
 
@@ -298,16 +300,18 @@ protected:
     // are all pref font settings set to use fontconfig generics?
     bool PrefFontListsUseOnlyGenerics();
 
     static void CheckFontUpdates(nsITimer *aTimer, void *aThis);
 
     virtual gfxFontFamily*
     GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override;
 
+    gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
+
 #ifdef MOZ_BUNDLED_FONTS
     void ActivateBundledFonts();
     nsCString mBundledFontsPath;
     bool mBundledFontsInitialized;
 #endif
 
     // to avoid enumerating all fonts, maintain a mapping of local font
     // names to family
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -1657,16 +1657,93 @@ gfxFontFamily::ReadOtherFamilyNames(gfxP
         gfxFontEntry::AutoTable nameTable(fe, kNAME);
         if (!nameTable) {
             continue;
         }
         ReadOtherFamilyNamesForFace(aPlatformFontList, nameTable);
     }
 }
 
+static bool
+LookForLegacyFamilyName(const nsAString& aCanonicalName,
+                        const char* aNameData,
+                        uint32_t aDataLength,
+                        nsAString& aLegacyName /* outparam */)
+{
+    const gfxFontUtils::NameHeader* nameHeader =
+        reinterpret_cast<const gfxFontUtils::NameHeader*>(aNameData);
+
+    uint32_t nameCount = nameHeader->count;
+    if (nameCount * sizeof(gfxFontUtils::NameRecord) > aDataLength) {
+        NS_WARNING("invalid font (name records)");
+        return false;
+    }
+
+    const gfxFontUtils::NameRecord* nameRecord =
+        reinterpret_cast<const gfxFontUtils::NameRecord*>
+            (aNameData + sizeof(gfxFontUtils::NameHeader));
+    uint32_t stringsBase = uint32_t(nameHeader->stringOffset);
+
+    for (uint32_t i = 0; i < nameCount; i++, nameRecord++) {
+        uint32_t nameLen = nameRecord->length;
+        uint32_t nameOff = nameRecord->offset;
+
+        if (stringsBase + nameOff + nameLen > aDataLength) {
+            NS_WARNING("invalid font (name table strings)");
+            return false;
+        }
+
+        if (uint16_t(nameRecord->nameID) == gfxFontUtils::NAME_ID_FAMILY) {
+            bool ok =
+                gfxFontUtils::DecodeFontName(aNameData + stringsBase + nameOff,
+                                             nameLen,
+                                             uint32_t(nameRecord->platformID),
+                                             uint32_t(nameRecord->encodingID),
+                                             uint32_t(nameRecord->languageID),
+                                             aLegacyName);
+            // it's only a legacy name if it differs from the canonical name
+            if (ok && aLegacyName != aCanonicalName) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+gfxFontFamily::CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList)
+{
+    if (mCheckedForLegacyFamilyNames) {
+        // we already did this, so there's nothing more to add
+        return false;
+    }
+    mCheckedForLegacyFamilyNames = true;
+    bool added = false;
+    const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
+    for (auto& fe : mAvailableFonts) {
+        if (!fe) {
+            continue;
+        }
+        gfxFontEntry::AutoTable nameTable(fe, kNAME);
+        if (!nameTable) {
+            continue;
+        }
+        nsAutoString legacyName;
+        uint32_t dataLength;
+        const char* nameData = hb_blob_get_data(nameTable, &dataLength);
+        if (LookForLegacyFamilyName(Name(), nameData, dataLength,
+                                    legacyName)) {
+            if (aFontList->AddWithLegacyFamilyName(legacyName, fe)) {
+                added = true;
+            }
+        }
+    }
+    return added;
+}
+
 void
 gfxFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList, 
                              bool aNeedFullnamePostscriptNames,
                              FontInfoData *aFontInfoData)
 {
     // if all needed names have already been read, skip
     if (mOtherFamilyNamesInitialized &&
         (mFaceNamesInitialized || !aNeedFullnamePostscriptNames))
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -103,16 +103,22 @@ public:
     typedef mozilla::gfx::DrawTarget DrawTarget;
     typedef mozilla::unicode::Script Script;
 
     // Used by stylo
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
 
     explicit gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
 
+    // Create a new entry that refers to the same font as this, but without
+    // additional state that may have been set up (such as family name).
+    // (This is only to be used for system fonts in the platform font list,
+    // not user fonts.)
+    virtual gfxFontEntry* Clone() const = 0;
+
     // unique name for the face, *not* the family; not necessarily the
     // "real" or user-friendly name, may be an internal identifier
     const nsString& Name() const { return mName; }
 
     // family name
     const nsString& FamilyName() const { return mFamilyName; }
 
     // The following two methods may be relatively expensive, as they
@@ -601,24 +607,33 @@ public:
         mOtherFamilyNamesInitialized(false),
         mHasOtherFamilyNames(false),
         mFaceNamesInitialized(false),
         mHasStyles(false),
         mIsSimpleFamily(false),
         mIsBadUnderlineFamily(false),
         mFamilyCharacterMapInitialized(false),
         mSkipDefaultFeatureSpaceCheck(false),
-        mCheckForFallbackFaces(false)
+        mCheckForFallbackFaces(false),
+        mCheckedForLegacyFamilyNames(false)
         { }
 
     const nsString& Name() { return mName; }
 
     virtual void LocalizedName(nsAString& aLocalizedName);
     virtual bool HasOtherFamilyNames();
-    
+
+    // See https://bugzilla.mozilla.org/show_bug.cgi?id=835204:
+    // check the font's 'name' table to see if it has a legacy family name
+    // that would have been used by GDI (e.g. to split extra-bold or light
+    // faces in a large family into separate "styled families" because of
+    // GDI's 4-faces-per-family limitation). If found, the styled family
+    // name will be added to the font list's "other family names" table.
+    bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList);
+
     nsTArray<RefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
     
     void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
         // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
         // of Times New Roman, because of buggy table in those fonts
         if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
             Name().EqualsLiteral("Times New Roman"))
         {
@@ -762,16 +777,17 @@ protected:
     bool mHasOtherFamilyNames : 1;
     bool mFaceNamesInitialized : 1;
     bool mHasStyles : 1;
     bool mIsSimpleFamily : 1;
     bool mIsBadUnderlineFamily : 1;
     bool mFamilyCharacterMapInitialized : 1;
     bool mSkipDefaultFeatureSpaceCheck : 1;
     bool mCheckForFallbackFaces : 1;  // check other faces for character
+    bool mCheckedForLegacyFamilyNames : 1;
 
     enum {
         // for "simple" families, the faces are stored in mAvailableFonts
         // with fixed positions:
         kRegularFaceIndex    = 0,
         kBoldFaceIndex       = 1,
         kItalicFaceIndex     = 2,
         kBoldItalicFaceIndex = 3,
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -132,16 +132,24 @@ GDIFontEntry::GDIFontEntry(const nsAStri
     mStretch = aStretch;
     if (IsType1())
         mForceGDI = true;
     mIsDataUserFont = aUserFontData != nullptr;
 
     InitLogFont(aFaceName, aFontType);
 }
 
+gfxFontEntry*
+GDIFontEntry::Clone() const
+{
+    MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
+    return new GDIFontEntry(Name(), mFontType, mStyle, mWeight, mStretch,
+                            nullptr, mFamilyHasItalicFace);
+}
+
 nsresult
 GDIFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
 {
     AUTO_PROFILER_LABEL("GDIFontEntry::ReadCMAP", OTHER);
 
     // attempt this once, if errors occur leave a blank cmap
     if (mCharacterMap) {
         return NS_OK;
@@ -907,17 +915,17 @@ gfxGDIFontList::MakePlatformFont(const n
     }
 
     return fe;
 }
 
 bool
 gfxGDIFontList::FindAndAddFamilies(const nsAString& aFamily,
                                    nsTArray<gfxFontFamily*>* aOutput,
-                                   bool aDeferOtherFamilyNamesLoading,
+                                   FindFamiliesFlags aFlags,
                                    gfxFontStyle* aStyle,
                                    gfxFloat aDevToCssSize)
 {
     nsAutoString keyName(aFamily);
     BuildKeyNameFromFontName(keyName);
 
     gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
     if (ff) {
@@ -926,17 +934,17 @@ gfxGDIFontList::FindAndAddFamilies(const
     }
 
     if (mNonExistingFonts.Contains(keyName)) {
         return false;
     }
 
     return gfxPlatformFontList::FindAndAddFamilies(aFamily,
                                                    aOutput,
-                                                   aDeferOtherFamilyNamesLoading,
+                                                   aFlags,
                                                    aStyle,
                                                    aDevToCssSize);
 }
 
 gfxFontFamily*
 gfxGDIFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
 {
     gfxFontFamily *ff = nullptr;
@@ -1165,16 +1173,22 @@ gfxGDIFontList::CreateFontInfoData()
         gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
 
     RefPtr<GDIFontInfo> fi =
         new GDIFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
 
     return fi.forget();
 }
 
+gfxFontFamily*
+gfxGDIFontList::CreateFontFamily(const nsAString& aName) const
+{
+    return new GDIFontFamily(aName);
+}
+
 #ifdef MOZ_BUNDLED_FONTS
 
 void
 gfxGDIFontList::ActivateBundledFonts()
 {
     nsCOMPtr<nsIFile> localDir;
     nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(localDir));
     if (NS_FAILED(rv)) {
--- a/gfx/thebes/gfxGDIFontList.h
+++ b/gfx/thebes/gfxGDIFontList.h
@@ -228,16 +228,18 @@ public:
         return !HasCmapTable(); // explicitly skip non-SFNT fonts
     }
 
     virtual bool TestCharacterMap(uint32_t aCh);
 
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
 
+    gfxFontEntry* Clone() const override;
+
     // create a font entry for a font with a given name
     static GDIFontEntry* CreateFontEntry(const nsAString& aName,
                                          gfxWindowsFontType aFontType,
                                          uint8_t aStyle,
                                          uint16_t aWeight, int16_t aStretch,
                                          gfxUserFontData* aUserFontData,
                                          bool aFamilyHasItalicFace);
 
@@ -282,17 +284,17 @@ protected:
 
     mozilla::WeakPtr<mozilla::gfx::UnscaledFont> mUnscaledFont;
 };
 
 // a single font family, referencing one or more faces
 class GDIFontFamily : public gfxFontFamily
 {
 public:
-    explicit GDIFontFamily(nsAString &aName) :
+    explicit GDIFontFamily(const nsAString& aName) :
         gfxFontFamily(aName) {}
 
     virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
 
 private:
     static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
                                             const NEWTEXTMETRICEXW *nmetrics,
                                             DWORD fontType, LPARAM data);
@@ -302,19 +304,21 @@ class gfxGDIFontList : public gfxPlatfor
 public:
     static gfxGDIFontList* PlatformFontList() {
         return static_cast<gfxGDIFontList*>(sPlatformFontList);
     }
 
     // initialize font lists
     virtual nsresult InitFontListForPlatform() override;
 
+    gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
+
     bool FindAndAddFamilies(const nsAString& aFamily,
                             nsTArray<gfxFontFamily*>* aOutput,
-                            bool aDeferOtherFamilyNamesLoading,
+                            FindFamiliesFlags aFlags,
                             gfxFontStyle* aStyle = nullptr,
                             gfxFloat aDevToCssSize = 1.0) override;
 
     virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
                                           uint16_t aWeight,
                                           int16_t aStretch,
                                           uint8_t aStyle);
 
--- a/gfx/thebes/gfxMacPlatformFontList.h
+++ b/gfx/thebes/gfxMacPlatformFontList.h
@@ -38,16 +38,18 @@ public:
     MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef,
                    uint16_t aWeight, uint16_t aStretch, uint8_t aStyle,
                    bool aIsDataUserFont, bool aIsLocal);
 
     virtual ~MacOSFontEntry() {
         ::CGFontRelease(mFontRef);
     }
 
+    gfxFontEntry* Clone() const override;
+
     CGFontRef GetFontRef();
 
     // override gfxFontEntry table access function to bypass table cache,
     // use CGFontRef API to get direct access to system font data
     hb_blob_t *GetFontTable(uint32_t aTag) override;
 
     void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                 FontListSizes* aSizes) const override;
@@ -83,16 +85,18 @@ protected:
 };
 
 class gfxMacPlatformFontList : public gfxPlatformFontList {
 public:
     static gfxMacPlatformFontList* PlatformFontList() {
         return static_cast<gfxMacPlatformFontList*>(sPlatformFontList);
     }
 
+    gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
+
     static int32_t AppleWeightToCSSWeight(int32_t aAppleWeight);
 
     bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) override;
 
     gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
                                   uint16_t aWeight,
                                   int16_t aStretch,
                                   uint8_t aStyle) override;
@@ -101,17 +105,17 @@ public:
                                    uint16_t aWeight,
                                    int16_t aStretch,
                                    uint8_t aStyle,
                                    const uint8_t* aFontData,
                                    uint32_t aLength) override;
 
     bool FindAndAddFamilies(const nsAString& aFamily,
                             nsTArray<gfxFontFamily*>* aOutput,
-                            bool aDeferOtherFamilyNamesLoading,
+                            FindFamiliesFlags aFlags,
                             gfxFontStyle* aStyle = nullptr,
                             gfxFloat aDevToCssSize = 1.0) override;
 
     // lookup the system font for a particular system font type and set
     // the name and style characteristics
     void LookupSystemFont(mozilla::LookAndFeel::FontID aSystemFontID,
                           nsAString& aSystemFontName,
                           gfxFontStyle &aFontStyle,
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -343,16 +343,28 @@ MacOSFontEntry::MacOSFontEntry(const nsA
     mStyle = aStyle;
 
     NS_ASSERTION(!(aIsDataUserFont && aIsLocalUserFont),
                  "userfont is either a data font or a local font");
     mIsDataUserFont = aIsDataUserFont;
     mIsLocalUserFont = aIsLocalUserFont;
 }
 
+gfxFontEntry*
+MacOSFontEntry::Clone() const
+{
+    MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
+    MacOSFontEntry* fe =
+        new MacOSFontEntry(Name(), mWeight, mStandardFace, mSizeHint);
+    fe->mStyle = mStyle;
+    fe->mStretch = mStretch;
+    fe->mFixedPitch = mFixedPitch;
+    return fe;
+}
+
 CGFontRef
 MacOSFontEntry::GetFontRef()
 {
     if (!mFontRefInitialized) {
         mFontRefInitialized = true;
         NSString *psname = GetNSStringForString(mName);
         mFontRef = ::CGFontCreateWithFontName(CFStringRef(psname));
         if (!mFontRef) {
@@ -1275,34 +1287,34 @@ gfxMacPlatformFontList::MakePlatformFont
 
 // Webkit code uses a system font meta name, so mimic that here
 // WebCore/platform/graphics/mac/FontCacheMac.mm
 static const char kSystemFont_system[] = "-apple-system";
 
 bool
 gfxMacPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
                                            nsTArray<gfxFontFamily*>* aOutput,
-                                           bool aDeferOtherFamilyNamesLoading,
+                                           FindFamiliesFlags aFlags,
                                            gfxFontStyle* aStyle,
                                            gfxFloat aDevToCssSize)
 {
     // search for special system font name, -apple-system
     if (aFamily.EqualsLiteral(kSystemFont_system)) {
         if (mUseSizeSensitiveSystemFont &&
             aStyle && (aStyle->size * aDevToCssSize) >= kTextDisplayCrossover) {
             aOutput->AppendElement(FindSystemFontFamily(mSystemDisplayFontFamilyName));
             return true;
         }
         aOutput->AppendElement(FindSystemFontFamily(mSystemTextFontFamilyName));
         return true;
     }
 
     return gfxPlatformFontList::FindAndAddFamilies(aFamily,
                                                    aOutput,
-                                                   aDeferOtherFamilyNamesLoading,
+                                                   aFlags,
                                                    aStyle,
                                                    aDevToCssSize);
 }
 
 void
 gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
                                          nsAString& aSystemFontName,
                                          gfxFontStyle &aFontStyle,
@@ -1511,16 +1523,22 @@ gfxMacPlatformFontList::CreateFontInfoDa
     bool loadCmaps = !UsesSystemFallback() ||
         gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
 
     RefPtr<MacFontInfo> fi =
         new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
     return fi.forget();
 }
 
+gfxFontFamily*
+gfxMacPlatformFontList::CreateFontFamily(const nsAString& aName) const
+{
+    return new gfxMacFontFamily(aName, 0.0);
+}
+
 void
 gfxMacPlatformFontList::ActivateFontsFromDir(nsIFile* aDir)
 {
     bool isDir;
     if (NS_FAILED(aDir->IsDirectory(&isDir)) || !isDir) {
         return;
     }
 
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -243,16 +243,35 @@ gfxPlatformFontList::ApplyWhitelist()
         nsString fontFamilyName(iter.Key());
         ToLowerCase(fontFamilyName);
         if (!familyNamesWhitelist.Contains(fontFamilyName)) {
             iter.Remove();
         }
     }
 }
 
+bool
+gfxPlatformFontList::AddWithLegacyFamilyName(const nsAString& aLegacyName,
+                                             gfxFontEntry* aFontEntry)
+{
+    bool added = false;
+    nsAutoString key;
+    ToLowerCase(aLegacyName, key);
+    gfxFontFamily* family = mOtherFamilyNames.GetWeak(key);
+    if (!family) {
+        family = CreateFontFamily(aLegacyName);
+        family->SetHasStyles(true); // we don't want the family to search for
+                                    // faces, we're adding them directly here
+        mOtherFamilyNames.Put(key, family);
+        added = true;
+    }
+    family->AddFontEntry(aFontEntry->Clone());
+    return added;
+}
+
 nsresult
 gfxPlatformFontList::InitFontList()
 {
     mFontlistInitCount++;
 
     if (LOG_FONTINIT_ENABLED()) {
         LOG_FONTINIT(("(fontinit) system fontlist initialization\n"));
     }
@@ -680,17 +699,17 @@ gfxPlatformFontList::CheckFamily(gfxFont
     }
 
     return aFamily;
 }
 
 bool
 gfxPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
                                         nsTArray<gfxFontFamily*>* aOutput,
-                                        bool aDeferOtherFamilyNamesLoading,
+                                        FindFamiliesFlags aFlags,
                                         gfxFontStyle* aStyle,
                                         gfxFloat aDevToCssSize)
 {
     nsAutoString key;
     GenerateFontListKey(aFamily, key);
 
     NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
 
@@ -703,29 +722,57 @@ gfxPlatformFontList::FindAndAddFamilies(
     }
 
     // if still not found and other family names not yet fully initialized,
     // initialize the rest of the list and try again.  this is done lazily
     // since reading name table entries is expensive.
     // although ASCII localized family names are possible they don't occur
     // in practice so avoid pulling in names at startup
     if (!familyEntry && !mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
-        InitOtherFamilyNames(aDeferOtherFamilyNamesLoading);
+        InitOtherFamilyNames(!(aFlags & FindFamiliesFlags::eForceOtherFamilyNamesLoading));
         familyEntry = mOtherFamilyNames.GetWeak(key);
         if (!familyEntry && !mOtherFamilyNamesInitialized) {
             // localized family names load timed out, add name to list of
             // names to check after localized names are loaded
             if (!mOtherNamesMissed) {
                 mOtherNamesMissed = MakeUnique<nsTHashtable<nsStringHashKey>>(2);
             }
             mOtherNamesMissed->PutEntry(key);
         }
     }
 
     familyEntry = CheckFamily(familyEntry);
+
+    // If we failed to find the requested family, check for a space in the
+    // name; if found, and if the "base" name (up to the last space) exists
+    // as a family, then this might be a legacy GDI-style family name for
+    // an additional weight/width. Try searching the faces of the base family
+    // and create any corresponding legacy families.
+    if (!familyEntry && !(aFlags & FindFamiliesFlags::eNoSearchForLegacyFamilyNames)) {
+        // We don't have nsAString::RFindChar, so look for a space manually
+        const char16_t* data = aFamily.BeginReading();
+        int32_t index = aFamily.Length();
+        while (--index > 0) {
+            if (data[index] == ' ') {
+                break;
+            }
+        }
+        if (index > 0) {
+            gfxFontFamily* base =
+                FindFamily(Substring(aFamily, 0, index),
+                           FindFamiliesFlags::eNoSearchForLegacyFamilyNames);
+            // If we found the "base" family name, and if it has members with
+            // legacy names, this will add corresponding font-family entries to
+            // the mOtherFamilyNames list; then retry the legacy-family search.
+            if (base && base->CheckForLegacyFamilyNames(this)) {
+                familyEntry = mOtherFamilyNames.GetWeak(key);
+            }
+        }
+    }
+
     if (familyEntry) {
         aOutput->AppendElement(familyEntry);
         return true;
     }
 
     return false;
 }
 
@@ -877,17 +924,18 @@ gfxPlatformFontList::ResolveGenericFontN
     NS_ASSERTION(langGroup, "null lang group for pref lang");
 
     // lookup and add platform fonts uniquely
     for (const nsString& genericFamily : genericFamilies) {
         gfxFontStyle style;
         style.language = langGroup;
         style.systemFont = false;
         AutoTArray<gfxFontFamily*,10> families;
-        FindAndAddFamilies(genericFamily, &families, true, &style);
+        FindAndAddFamilies(genericFamily, &families, FindFamiliesFlags(0),
+                           &style);
         for (gfxFontFamily* f : families) {
             if (!aGenericFamilies->Contains(f)) {
                 aGenericFamilies->AppendElement(f);
             }
         }
     }
 
 #if 0  // dump out generic mappings
@@ -1504,17 +1552,18 @@ gfxPlatformFontList::CleanupLoader()
                 break;
             }
         }
         mFaceNamesMissed = nullptr;
     }
 
     if (mOtherNamesMissed) {
         for (auto it = mOtherNamesMissed->Iter(); !it.Done(); it.Next()) {
-            if (FindFamily(it.Get()->GetKey(), false)) {
+            if (FindFamily(it.Get()->GetKey(),
+                           FindFamiliesFlags::eForceOtherFamilyNamesLoading)) {
                 forceReflow = true;
                 ForceGlobalReflow();
                 break;
             }
         }
         mOtherNamesMissed = nullptr;
     }
 
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -130,23 +130,40 @@ public:
 
     virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray);
 
     gfxFontEntry*
     SystemFindFontForChar(uint32_t aCh, uint32_t aNextCh,
                           Script aRunScript,
                           const gfxFontStyle* aStyle);
 
+    // Flags to control optional behaviors in FindAndAddFamilies. The sense
+    // of the bit flags have been chosen such that the default parameter of
+    // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired
+    // behavior, and only a few callsites need to explicitly pass other values.
+    enum class FindFamiliesFlags {
+        // If set, "other" (e.g. localized) family names should be loaded
+        // immediately; if clear, InitOtherFamilyNames is allowed to defer
+        // loading to avoid blocking.
+        eForceOtherFamilyNamesLoading = 1 << 0,
+        
+        // If set, FindAndAddFamilies should not check for legacy "styled
+        // family" names to add to the font list. This is used to avoid
+        // a recursive search when using FindFamily to find a potential base
+        // family name for a styled variant.
+        eNoSearchForLegacyFamilyNames = 1 << 1
+    };
+
     // Find family(ies) matching aFamily and append to the aOutput array
     // (there may be multiple results in the case of fontconfig aliases, etc).
     // Return true if any match was found and appended, false if none.
     virtual bool
     FindAndAddFamilies(const nsAString& aFamily,
                        nsTArray<gfxFontFamily*>* aOutput,
-                       bool aDeferOtherFamilyNamesLoading,
+                       FindFamiliesFlags aFlags,
                        gfxFontStyle* aStyle = nullptr,
                        gfxFloat aDevToCssSize = 1.0);
 
     gfxFontEntry* FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold);
 
     // name lookup table methods
 
     void AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName);
@@ -261,16 +278,19 @@ public:
 
     // Returns true if the font family whitelist is not empty.
     bool IsFontFamilyWhitelistActive();
 
     static void FontWhitelistPrefChanged(const char *aPref, void *aClosure) {
         gfxPlatformFontList::PlatformFontList()->UpdateFontList();
     }
 
+    bool AddWithLegacyFamilyName(const nsAString& aLegacyName,
+                                 gfxFontEntry* aFontEntry);
+
 protected:
     class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable
     {
     public:
         InitOtherFamilyNamesRunnable()
             : CancelableRunnable("gfxPlatformFontList::InitOtherFamilyNamesRunnable")
             , mIsCanceled(false)
         {
@@ -355,24 +375,24 @@ protected:
     explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
 
     static gfxPlatformFontList *sPlatformFontList;
 
     // Convenience method to return the first matching family (if any) as found
     // by FindAndAddFamilies().
     gfxFontFamily*
     FindFamily(const nsAString& aFamily,
-               bool aDeferOtherFamilyNamesLoading = true,
+               FindFamiliesFlags aFlags = FindFamiliesFlags(0),
                gfxFontStyle* aStyle = nullptr,
                gfxFloat aDevToCssSize = 1.0)
     {
         AutoTArray<gfxFontFamily*,1> families;
         return FindAndAddFamilies(aFamily,
                                   &families,
-                                  aDeferOtherFamilyNamesLoading,
+                                  aFlags,
                                   aStyle,
                                   aDevToCssSize) ? families[0] : nullptr;
     }
 
     // Lookup family name in global family list without substitutions or
     // localized family name lookup. Used for common font fallback families.
     gfxFontFamily* FindFamilyByCanonicalName(const nsAString& aFamily) {
         nsAutoString key;
@@ -472,16 +492,20 @@ protected:
     ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
                             eFontPrefLang aPrefLang,
                             nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies);
 
     virtual nsresult InitFontListForPlatform() = 0;
 
     void ApplyWhitelist();
 
+    // Create a new gfxFontFamily of the appropriate subclass for the platform,
+    // used when AddWithLegacyFamilyName needs to create a new family.
+    virtual gfxFontFamily* CreateFontFamily(const nsAString& aName) const = 0;
+
     typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontFamilyTable;
     typedef nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> FontEntryTable;
 
     // used by memory reporter to accumulate sizes of family names in the table
     static size_t
     SizeOfFontFamilyTableExcludingThis(const FontFamilyTable& aTable,
                                        mozilla::MallocSizeOf aMallocSizeOf);
     static size_t
@@ -560,9 +584,11 @@ protected:
     nsLanguageAtomService* mLangService;
 
     nsTArray<uint32_t> mCJKPrefLangs;
     nsTArray<mozilla::FontFamilyType> mDefaultGenericsLangGroup;
 
     bool mFontFamilyWhitelistActive;
 };
 
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
+
 #endif /* GFXPLATFORMFONTLIST_H_ */
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -1868,17 +1868,19 @@ gfxFontGroup::AddPlatformFont(const nsAS
         if (family) {
             aFamilyList.AppendElement(family);
             return;
         }
     }
 
     // Not known in the user font set ==> check system fonts
     gfxPlatformFontList::PlatformFontList()
-        ->FindAndAddFamilies(aName, &aFamilyList, true, &mStyle, mDevToCssSize);
+        ->FindAndAddFamilies(aName, &aFamilyList,
+                             gfxPlatformFontList::FindFamiliesFlags(0),
+                             &mStyle, mDevToCssSize);
 }
 
 void
 gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily)
 {
     NS_ASSERTION(aFamily, "trying to add a null font family to fontlist");
     AutoTArray<gfxFontEntry*,4> fontEntryList;
     bool needsBold;
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -625,18 +625,18 @@ public:
                  uint32_t aWeight,
                  int32_t aStretch,
                  uint8_t aStyle,
                  const nsTArray<gfxFontFeature>& aFeatureSettings,
                  uint32_t aLanguageOverride,
                  gfxCharacterMap* aUnicodeRanges,
                  uint8_t aFontDisplay);
 
-    virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
-                                        bool aNeedsBold);
+    gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
+                                bool aNeedsBold) override;
 
     gfxFontEntry* GetPlatformFontEntry() const { return mPlatformFontEntry; }
 
     // is the font loading or loaded, or did it fail?
     UserFontLoadState LoadState() const { return mUserFontLoadState; }
 
     // whether to wait before using fallback font or not
     bool WaitForUserFont() const {
@@ -668,16 +668,21 @@ public:
     // since we can't make that class a friend
     void SetLoader(nsFontFaceLoader* aLoader) { mLoader = aLoader; }
     nsFontFaceLoader* GetLoader() { return mLoader; }
     gfxFontSrcPrincipal* GetPrincipal() { return mPrincipal; }
     uint32_t GetSrcIndex() { return mSrcIndex; }
     void GetFamilyNameAndURIForLogging(nsACString& aFamilyName,
                                        nsACString& aURI);
 
+    gfxFontEntry* Clone() const override {
+        MOZ_ASSERT_UNREACHABLE("cannot Clone user fonts");
+        return nullptr;
+    }
+
 protected:
     const uint8_t* SanitizeOpenTypeData(const uint8_t* aData,
                                         uint32_t aLength,
                                         uint32_t& aSaneLength,
                                         gfxUserFontType aFontType);
 
     // attempt to load the next resource in the src list.
     void LoadNextSrc();
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -1,16 +1,17 @@
 [package]
 name = "webrender_bindings"
 version = "0.1.0"
 authors = ["The Mozilla Project Developers"]
 license = "MPL-2.0"
 
 [dependencies]
 webrender_api = {path = "../webrender_api", version = "0.50.0"}
+bincode = "0.8"
 rayon = "0.8"
 thread_profiler = "0.1.1"
 euclid = "0.15"
 app_units = "0.5"
 gleam = "0.4"
 
 [dependencies.webrender]
 path = "../webrender"
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -223,41 +223,42 @@ WebRenderAPI::GenerateFrame(const nsTArr
                                           nullptr : aOpacityArray.Elements(),
                                         aOpacityArray.Length(),
                                         aTransformArray.IsEmpty() ?
                                           nullptr : aTransformArray.Elements(),
                                         aTransformArray.Length());
 }
 
 void
-WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
-                                 Epoch aEpoch,
-                                 mozilla::LayerSize aViewportSize,
-                                 wr::WrPipelineId pipeline_id,
-                                 const LayoutSize& content_size,
-                                 wr::BuiltDisplayListDescriptor dl_descriptor,
-                                 uint8_t *dl_data,
-                                 size_t dl_size)
+WebRenderAPI::SetDisplayList(gfx::Color aBgColor,
+                             Epoch aEpoch,
+                             mozilla::LayerSize aViewportSize,
+                             wr::WrPipelineId pipeline_id,
+                             const LayoutSize& content_size,
+                             wr::BuiltDisplayListDescriptor dl_descriptor,
+                             uint8_t *dl_data,
+                             size_t dl_size,
+                             ResourceUpdateQueue& aResources)
 {
-    wr_api_set_root_display_list(mDocHandle,
-                                 ToColorF(aBgColor),
-                                 aEpoch,
-                                 aViewportSize.width, aViewportSize.height,
-                                 pipeline_id,
-                                 content_size,
-                                 dl_descriptor,
-                                 dl_data,
-                                 dl_size);
+  wr_api_set_display_list(mDocHandle,
+                          ToColorF(aBgColor),
+                          aEpoch,
+                          aViewportSize.width, aViewportSize.height,
+                          pipeline_id,
+                          content_size,
+                          dl_descriptor,
+                          dl_data,
+                          dl_size,
+                          aResources.Raw());
 }
 
 void
-WebRenderAPI::ClearRootDisplayList(Epoch aEpoch,
-                                   wr::WrPipelineId pipeline_id)
+WebRenderAPI::ClearDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id)
 {
-  wr_api_clear_root_display_list(mDocHandle, aEpoch, pipeline_id);
+  wr_api_clear_display_list(mDocHandle, aEpoch, pipeline_id);
 }
 
 void
 WebRenderAPI::SetWindowParameters(LayoutDeviceIntSize size)
 {
   wr_api_set_window_parameters(mDocHandle, size.width, size.height);
 }
 
@@ -419,130 +420,187 @@ WebRenderAPI::WaitFlushed()
 
 void
 WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
 {
   wr_api_set_root_pipeline(mDocHandle, aPipeline);
 }
 
 void
-WebRenderAPI::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
-                       Range<uint8_t> aBytes)
+WebRenderAPI::UpdateResources(ResourceUpdateQueue& aUpdates)
+{
+  wr_api_update_resources(mDocHandle, aUpdates.Raw());
+}
+
+ResourceUpdateQueue::ResourceUpdateQueue()
+{
+  mUpdates = wr_resource_updates_new();
+}
+
+ResourceUpdateQueue::ResourceUpdateQueue(ResourceUpdateQueue&& aFrom)
+{
+  mUpdates = aFrom.mUpdates;
+  aFrom.mUpdates = nullptr;
+}
+
+ResourceUpdateQueue&
+ResourceUpdateQueue::operator=(ResourceUpdateQueue&& aFrom)
 {
-  wr_api_add_image(mDocHandle,
-                   key,
-                   &aDescriptor,
-                   RangeToByteSlice(aBytes));
+  mUpdates = aFrom.mUpdates;
+  aFrom.mUpdates = nullptr;
+  return *this;
+}
+
+ResourceUpdateQueue::~ResourceUpdateQueue()
+{
+  if (mUpdates) {
+    wr_resource_updates_delete(mUpdates);
+  }
+}
+
+ByteBuffer
+ResourceUpdateQueue::Serialize()
+{
+  VecU8 data;
+  wr_resource_updates_serialize(mUpdates, &data);
+  ByteBuffer result(Move(data));
+  return result;
+}
+
+//static
+ResourceUpdateQueue
+ResourceUpdateQueue::Deserialize(Range<uint8_t> aData)
+{
+  auto slice = wr::RangeToByteSlice(aData);
+  ResourceUpdateQueue result(wr_resource_updates_deserialize(slice));
+  return result;
 }
 
 void
-WebRenderAPI::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
-                           Range<uint8_t> aBytes)
+ResourceUpdateQueue::Clear()
 {
-  wr_api_add_blob_image(mDocHandle,
-                        key,
-                        &aDescriptor,
-                        RangeToByteSlice(aBytes));
+  wr_resource_updates_clear(mUpdates);
+}
+
+void
+ResourceUpdateQueue::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
+                              Range<uint8_t> aBytes)
+{
+  wr_resource_updates_add_image(mUpdates,
+                                key,
+                                &aDescriptor,
+                                RangeToByteSlice(aBytes));
 }
 
 void
-WebRenderAPI::AddExternalImage(ImageKey key,
-                               const ImageDescriptor& aDescriptor,
-                               ExternalImageId aExtID,
-                               wr::WrExternalImageBufferType aBufferType,
-                               uint8_t aChannelIndex)
+ResourceUpdateQueue::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
+                                  Range<uint8_t> aBytes)
 {
-  wr_api_add_external_image(mDocHandle,
-                            key,
-                            &aDescriptor,
-                            aExtID,
-                            aBufferType,
-                            aChannelIndex);
+  wr_resource_updates_add_blob_image(mUpdates,
+                                     key,
+                                     &aDescriptor,
+                                     RangeToByteSlice(aBytes));
 }
 
 void
-WebRenderAPI::AddExternalImageBuffer(ImageKey aKey,
-                                     const ImageDescriptor& aDescriptor,
-                                     ExternalImageId aHandle)
+ResourceUpdateQueue::AddExternalImage(ImageKey key,
+                                      const ImageDescriptor& aDescriptor,
+                                      ExternalImageId aExtID,
+                                      wr::WrExternalImageBufferType aBufferType,
+                                      uint8_t aChannelIndex)
+{
+  wr_resource_updates_add_external_image(mUpdates,
+                                         key,
+                                         &aDescriptor,
+                                         aExtID,
+                                         aBufferType,
+                                         aChannelIndex);
+}
+
+void
+ResourceUpdateQueue::AddExternalImageBuffer(ImageKey aKey,
+                                            const ImageDescriptor& aDescriptor,
+                                            ExternalImageId aHandle)
 {
   auto channelIndex = 0;
   AddExternalImage(aKey, aDescriptor, aHandle,
                    wr::WrExternalImageBufferType::ExternalBuffer,
                    channelIndex);
 }
 
 void
-WebRenderAPI::UpdateImageBuffer(ImageKey aKey,
-                                const ImageDescriptor& aDescriptor,
-                                Range<uint8_t> aBytes)
+ResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey,
+                                       const ImageDescriptor& aDescriptor,
+                                       Range<uint8_t> aBytes)
 {
-  wr_api_update_image(mDocHandle,
-                      aKey,
-                      &aDescriptor,
-                      RangeToByteSlice(aBytes));
+  wr_resource_updates_update_image(mUpdates,
+                                   aKey,
+                                   &aDescriptor,
+                                   RangeToByteSlice(aBytes));
 }
 
 void
-WebRenderAPI::UpdateBlobImage(ImageKey aKey,
-                              const ImageDescriptor& aDescriptor,
-                              Range<uint8_t> aBytes)
+ResourceUpdateQueue::UpdateBlobImage(ImageKey aKey,
+                                     const ImageDescriptor& aDescriptor,
+                                     Range<uint8_t> aBytes)
 {
-  wr_api_update_blob_image(mDocHandle,
-                           aKey,
-                           &aDescriptor,
-                           RangeToByteSlice(aBytes));
+  wr_resource_updates_update_blob_image(mUpdates,
+                                        aKey,
+                                        &aDescriptor,
+                                        RangeToByteSlice(aBytes));
 }
 
 void
-WebRenderAPI::UpdateExternalImage(ImageKey aKey,
-                                  const ImageDescriptor& aDescriptor,
-                                  ExternalImageId aExtID,
-                                  wr::WrExternalImageBufferType aBufferType,
-                                  uint8_t aChannelIndex)
+ResourceUpdateQueue::UpdateExternalImage(ImageKey aKey,
+                                         const ImageDescriptor& aDescriptor,
+                                         ExternalImageId aExtID,
+                                         wr::WrExternalImageBufferType aBufferType,
+                                         uint8_t aChannelIndex)
 {
-  wr_api_update_external_image(mDocHandle,
-                               aKey,
-                               &aDescriptor,
-                               aExtID,
-                               aBufferType,
-                               aChannelIndex);
+  wr_resource_updates_update_external_image(mUpdates,
+                                            aKey,
+                                            &aDescriptor,
+                                            aExtID,
+                                            aBufferType,
+                                            aChannelIndex);
 }
 
 void
-WebRenderAPI::DeleteImage(ImageKey aKey)
+ResourceUpdateQueue::DeleteImage(ImageKey aKey)
 {
-  wr_api_delete_image(mDocHandle, aKey);
+  wr_resource_updates_delete_image(mUpdates, aKey);
 }
 
 void
-WebRenderAPI::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
+ResourceUpdateQueue::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
 {
-  wr_api_add_raw_font(mDocHandle, aKey, &aBytes[0], aBytes.length(), aIndex);
+  wr_resource_updates_add_raw_font(mUpdates, aKey, &aBytes[0], aBytes.length(), aIndex);
 }
 
 void
-WebRenderAPI::DeleteFont(wr::FontKey aKey)
+ResourceUpdateQueue::DeleteFont(wr::FontKey aKey)
 {
-  wr_api_delete_font(mDocHandle, aKey);
+  wr_resource_updates_delete_font(mUpdates, aKey);
 }
 
 void
-WebRenderAPI::AddFontInstance(wr::FontInstanceKey aKey,
-                              wr::FontKey aFontKey,
-                              float aGlyphSize,
-                              const wr::FontInstanceOptions* aOptions,
-                              const wr::FontInstancePlatformOptions* aPlatformOptions)
+ResourceUpdateQueue::AddFontInstance(wr::FontInstanceKey aKey,
+                                     wr::FontKey aFontKey,
+                                     float aGlyphSize,
+                                     const wr::FontInstanceOptions* aOptions,
+                                     const wr::FontInstancePlatformOptions* aPlatformOptions)
 {
-  wr_api_add_font_instance(mDocHandle, aKey, aFontKey, aGlyphSize, aOptions, aPlatformOptions);
+  wr_resource_updates_add_font_instance(mUpdates, aKey, aFontKey, aGlyphSize,
+                                        aOptions, aPlatformOptions);
 }
 
 void
-WebRenderAPI::DeleteFontInstance(wr::FontInstanceKey aKey)
+ResourceUpdateQueue::DeleteFontInstance(wr::FontInstanceKey aKey)
 {
-  wr_api_delete_font_instance(mDocHandle, aKey);
+  wr_resource_updates_delete_font_instance(mUpdates, aKey);
 }
 
 class FrameStartTime : public RendererEvent
 {
 public:
   explicit FrameStartTime(const TimeStamp& aTime)
     : mTime(aTime)
   {
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -43,52 +43,31 @@ struct Line {
   float start;
   float end;
   float width;
   wr::ColorF color;
   wr::LineOrientation orientation;
   wr::LineStyle style;
 };
 
-class WebRenderAPI
-{
-  NS_INLINE_DECL_REFCOUNTING(WebRenderAPI);
-
+/// Updates to retained resources such as images and fonts, applied within the
+/// same transaction.
+class ResourceUpdateQueue {
 public:
-  /// This can be called on the compositor thread only.
-  static already_AddRefed<WebRenderAPI> Create(layers::CompositorBridgeParentBase* aBridge,
-                                               RefPtr<widget::CompositorWidget>&& aWidget,
-                                               LayoutDeviceIntSize aSize);
-
-  already_AddRefed<WebRenderAPI> Clone();
-
-  wr::WindowId GetId() const { return mId; }
-
-  void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
-                            const layers::FrameMetrics::ViewID& aScrollId,
-                            const wr::LayoutPoint& aScrollPosition);
+  ResourceUpdateQueue();
+  ~ResourceUpdateQueue();
+  ResourceUpdateQueue(ResourceUpdateQueue&&);
+  ResourceUpdateQueue(const ResourceUpdateQueue&) = delete;
+  ResourceUpdateQueue& operator=(ResourceUpdateQueue&&);
+  ResourceUpdateQueue& operator=(const ResourceUpdateQueue&) = delete;
 
-  void GenerateFrame();
-  void GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
-                     const nsTArray<wr::WrTransformProperty>& aTransformArray);
+  /// Serializes into a buffer of bytes and clears the queue.
+  ByteBuffer Serialize();
 
-  void SetWindowParameters(LayoutDeviceIntSize size);
-  void SetRootDisplayList(gfx::Color aBgColor,
-                          Epoch aEpoch,
-                          mozilla::LayerSize aViewportSize,
-                          wr::WrPipelineId pipeline_id,
-                          const wr::LayoutSize& content_size,
-                          wr::BuiltDisplayListDescriptor dl_descriptor,
-                          uint8_t *dl_data,
-                          size_t dl_size);
-
-  void ClearRootDisplayList(Epoch aEpoch,
-                            wr::WrPipelineId pipeline_id);
-
-  void SetRootPipeline(wr::PipelineId aPipeline);
+  static ResourceUpdateQueue Deserialize(Range<uint8_t> aData);
 
   void AddImage(wr::ImageKey aKey,
                 const ImageDescriptor& aDescriptor,
                 Range<uint8_t> aBytes);
 
   void AddBlobImage(wr::ImageKey aKey,
                     const ImageDescriptor& aDescriptor,
                     Range<uint8_t> aBytes);
@@ -126,19 +105,72 @@ public:
   void AddFontInstance(wr::FontInstanceKey aKey,
                        wr::FontKey aFontKey,
                        float aGlyphSize,
                        const wr::FontInstanceOptions* aOptions,
                        const wr::FontInstancePlatformOptions* aPlatformOptions);
 
   void DeleteFontInstance(wr::FontInstanceKey aKey);
 
+  void Clear();
+
+  // Try to avoid using this when possible.
+  wr::ResourceUpdates* Raw() { return mUpdates; }
+
+protected:
+  explicit ResourceUpdateQueue(wr::ResourceUpdates* aUpdates)
+  : mUpdates(aUpdates) {}
+
+  wr::ResourceUpdates* mUpdates;
+};
+
+class WebRenderAPI
+{
+  NS_INLINE_DECL_REFCOUNTING(WebRenderAPI);
+
+public:
+  /// This can be called on the compositor thread only.
+  static already_AddRefed<WebRenderAPI> Create(layers::CompositorBridgeParentBase* aBridge,
+                                               RefPtr<widget::CompositorWidget>&& aWidget,
+                                               LayoutDeviceIntSize aSize);
+
+  already_AddRefed<WebRenderAPI> Clone();
+
+  wr::WindowId GetId() const { return mId; }
+
+  void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
+                            const layers::FrameMetrics::ViewID& aScrollId,
+                            const wr::LayoutPoint& aScrollPosition);
+
+  void GenerateFrame();
+  void GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
+                     const nsTArray<wr::WrTransformProperty>& aTransformArray);
+
+  void SetWindowParameters(LayoutDeviceIntSize size);
+
+  void SetDisplayList(gfx::Color aBgColor,
+                      Epoch aEpoch,
+                      mozilla::LayerSize aViewportSize,
+                      wr::WrPipelineId pipeline_id,
+                      const wr::LayoutSize& content_size,
+                      wr::BuiltDisplayListDescriptor dl_descriptor,
+                      uint8_t *dl_data,
+                      size_t dl_size,
+                      ResourceUpdateQueue& aResources);
+
+  void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id);
+
+  void SetRootPipeline(wr::PipelineId aPipeline);
+
+  void UpdateResources(ResourceUpdateQueue& aUpdates);
+
   void SetFrameStartTime(const TimeStamp& aTime);
 
   void RunOnRenderThread(UniquePtr<RendererEvent> aEvent);
+
   void Readback(gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize);
 
   void Pause();
   bool Resume();
 
   wr::WrIdNamespace GetNamespace();
   uint32_t GetMaxTextureSize() const { return mMaxTextureSize; }
   bool GetUseANGLE() const { return mUseANGLE; }
@@ -330,32 +362,36 @@ public:
                      const wr::LayoutRect& aBoxBounds,
                      const wr::LayoutVector2D& aOffset,
                      const wr::ColorF& aColor,
                      const float& aBlurRadius,
                      const float& aSpreadRadius,
                      const float& aBorderRadius,
                      const wr::BoxShadowClipMode& aClipMode);
 
+  ResourceUpdateQueue& Resources() { return mResourceUpdates; }
+
   // Returns the clip id that was most recently pushed with PushClip and that
   // has not yet been popped with PopClip. Return Nothing() if the clip stack
   // is empty.
   Maybe<wr::WrClipId> TopmostClipId();
   // Same as TopmostClipId() but for scroll layers.
   layers::FrameMetrics::ViewID TopmostScrollId();
   // Returns the scroll id that was pushed just before the given scroll id. This
   // function returns Nothing() if the given scrollid has not been encountered,
   // or if it is the rootmost scroll id (and therefore has no ancestor).
   Maybe<layers::FrameMetrics::ViewID> ParentScrollIdFor(layers::FrameMetrics::ViewID aScrollId);
 
   // Try to avoid using this when possible.
   wr::WrState* Raw() { return mWrState; }
 protected:
   wr::WrState* mWrState;
 
+  ResourceUpdateQueue mResourceUpdates;
+
   // Track the stack of clip ids and scroll layer ids that have been pushed
   // (by PushClip and PushScrollLayer, respectively) and are still active.
   // This is helpful for knowing e.g. what the ancestor scroll id of a particular
   // scroll id is, and doing other "queries" of current state.
   std::vector<wr::WrClipId> mClipIdStack;
   std::vector<layers::FrameMetrics::ViewID> mScrollIdStack;
 
   // Track the parent scroll id of each scroll id that we encountered. A
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -582,16 +582,26 @@ struct ByteBuffer
       mOwned = true;
     } else {
       mOwned = false;
       mData = nullptr;
       mLength = 0;
     }
   }
 
+  ByteBuffer(ByteBuffer&& aFrom)
+  : mLength(aFrom.mLength)
+  , mData(aFrom.mData)
+  , mOwned(aFrom.mOwned)
+  {
+    aFrom.mLength = 0;
+    aFrom.mData = nullptr;
+    aFrom.mOwned = false;
+  }
+
   ByteBuffer()
     : mLength(0)
     , mData(nullptr)
     , mOwned(false)
   {}
 
   bool
   Allocate(size_t aLength)
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -10,16 +10,17 @@ use webrender::{ReadPixelsFormat, Render
 use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::DebugFlags;
 use webrender::{ApiRecordingReceiver, BinaryRecorder};
 use thread_profiler::register_thread_with_profiler;
 use moz2d_renderer::Moz2dImageRenderer;
 use app_units::Au;
 use rayon;
 use euclid::SideOffsets2D;
+use bincode;
 
 extern crate webrender_api;
 
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrExternalImageBufferType = ExternalImageType;
 
 /// cbindgen:field-names=[mHandle]
 /// cbindgen:derive-lt=true
@@ -644,126 +645,135 @@ pub unsafe extern "C" fn wr_api_delete(d
     let handle = Box::from_raw(dh);
     if handle.document_id.0 == handle.api.get_namespace_id() {
         handle.api.delete_document(handle.document_id);
         handle.api.shut_down();
     }
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_image(dh: &mut DocumentHandle,
-                                   image_key: WrImageKey,
-                                   descriptor: &WrImageDescriptor,
-                                   bytes: ByteSlice) {
-    assert!(unsafe { is_in_compositor_thread() });
+pub extern "C" fn wr_resource_updates_add_image(
+    resources: &mut ResourceUpdates,
+    image_key: WrImageKey,
+    descriptor: &WrImageDescriptor,
+    bytes: ByteSlice
+) {
     let copied_bytes = bytes.as_slice().to_owned();
-    let mut resources = ResourceUpdates::new();
-    resources.add_image(image_key,
-                        descriptor.into(),
-                        ImageData::new(copied_bytes),
-                        None);
-    dh.api.update_resources(resources);
+    resources.add_image(
+        image_key,
+        descriptor.into(),
+        ImageData::new(copied_bytes),
+        None
+    );
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_blob_image(dh: &mut DocumentHandle,
-                                        image_key: WrImageKey,
-                                        descriptor: &WrImageDescriptor,
-                                        bytes: ByteSlice) {
-    assert!(unsafe { is_in_compositor_thread() });
+pub extern "C" fn wr_resource_updates_add_blob_image(
+    resources: &mut ResourceUpdates,
+    image_key: WrImageKey,
+    descriptor: &WrImageDescriptor,
+    bytes: ByteSlice
+) {
     let copied_bytes = bytes.as_slice().to_owned();
-    let mut resources = ResourceUpdates::new();
-    resources.add_image(image_key,
-                        descriptor.into(),
-                        ImageData::new_blob_image(copied_bytes),
-                        None);
-    dh.api.update_resources(resources);
+    resources.add_image(
+        image_key,
+        descriptor.into(),
+        ImageData::new_blob_image(copied_bytes),
+        None
+    );
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_external_image(dh: &mut DocumentHandle,
-                                            image_key: WrImageKey,
-                                            descriptor: &WrImageDescriptor,
-                                            external_image_id: WrExternalImageId,
-                                            buffer_type: WrExternalImageBufferType,
-                                            channel_index: u8) {
-    assert!(unsafe { is_in_compositor_thread() });
-    let mut resources = ResourceUpdates::new();
-    resources.add_image(image_key,
-                        descriptor.into(),
-                        ImageData::External(ExternalImageData {
-                                             id: external_image_id.into(),
-                                             channel_index: channel_index,
-                                             image_type: buffer_type,
-                                         }),
-                        None);
-    dh.api.update_resources(resources);
+pub extern "C" fn wr_resource_updates_add_external_image(
+    resources: &mut ResourceUpdates,
+    image_key: WrImageKey,
+    descriptor: &WrImageDescriptor,
+    external_image_id: WrExternalImageId,
+    buffer_type: WrExternalImageBufferType,
+    channel_index: u8
+) {
+    resources.add_image(
+        image_key,
+        descriptor.into(),
+        ImageData::External(
+            ExternalImageData {
+                id: external_image_id.into(),
+                channel_index: channel_index,
+                image_type: buffer_type,
+            }
+        ),
+        None
+    );
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_update_image(dh: &mut DocumentHandle,
-                                      key: WrImageKey,
-                                      descriptor: &WrImageDescriptor,
-                                      bytes: ByteSlice) {
-    assert!(unsafe { is_in_compositor_thread() });
+pub extern "C" fn wr_resource_updates_update_image(
+    resources: &mut ResourceUpdates,
+    key: WrImageKey,
+    descriptor: &WrImageDescriptor,
+    bytes: ByteSlice
+) {
     let copied_bytes = bytes.as_slice().to_owned();
-
-    let mut resources = ResourceUpdates::new();
     resources.update_image(key, descriptor.into(), ImageData::new(copied_bytes), None);
-    dh.api.update_resources(resources);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_update_external_image(
-    dh: &mut DocumentHandle,
+pub extern "C" fn wr_resource_updates_update_external_image(
+    resources: &mut ResourceUpdates,
     key: WrImageKey,
     descriptor: &WrImageDescriptor,
     external_image_id: WrExternalImageId,
     image_type: WrExternalImageBufferType,
     channel_index: u8
 ) {
-    assert!(unsafe { is_in_compositor_thread() });
-
-    let data = ImageData::External(
-        ExternalImageData {
-            id: external_image_id.into(),
-            channel_index,
-            image_type,
-        }
+    resources.update_image(
+        key,
+        descriptor.into(),
+        ImageData::External(
+            ExternalImageData {
+                id: external_image_id.into(),
+                channel_index,
+                image_type,
+            }
+        ),
+        None
     );
-
-    let mut resources = ResourceUpdates::new();
-    resources.update_image(key, descriptor.into(), data, None);
-    dh.api.update_resources(resources);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_update_blob_image(dh: &mut DocumentHandle,
-                                           image_key: WrImageKey,
-                                           descriptor: &WrImageDescriptor,
-                                           bytes: ByteSlice) {
-    assert!(unsafe { is_in_compositor_thread() });
+pub extern "C" fn wr_resource_updates_update_blob_image(
+    resources: &mut ResourceUpdates,
+    image_key: WrImageKey,
+    descriptor: &WrImageDescriptor,
+    bytes: ByteSlice
+) {
     let copied_bytes = bytes.as_slice().to_owned();
-    let mut resources = ResourceUpdates::new();
     resources.update_image(
         image_key,
         descriptor.into(),
         ImageData::new_blob_image(copied_bytes),
         None
     );
-    dh.api.update_resources(resources);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_delete_image(dh: &mut DocumentHandle,
-                                      key: WrImageKey) {
-    assert!(unsafe { is_in_compositor_thread() });
-    let mut resources = ResourceUpdates::new();
+pub extern "C" fn wr_resource_updates_delete_image(
+    resources: &mut ResourceUpdates,
+    key: WrImageKey
+) {
     resources.delete_image(key);
-    dh.api.update_resources(resources);
+}
+
+#[no_mangle]
+pub extern "C" fn wr_api_update_resources(
+    dh: &mut DocumentHandle,
+    resources: &mut ResourceUpdates
+) {
+    let resource_updates = mem::replace(resources, ResourceUpdates::new());
+    dh.api.update_resources(resource_updates);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_set_root_pipeline(dh: &mut DocumentHandle,
                                            pipeline_id: WrPipelineId) {
     dh.api.set_root_pipeline(dh.document_id, pipeline_id);
 }
 
@@ -773,65 +783,74 @@ pub extern "C" fn wr_api_set_window_para
                                                height: i32) {
     let size = DeviceUintSize::new(width as u32, height as u32);
     dh.api.set_window_parameters(dh.document_id,
                                  size,
                                  DeviceUintRect::new(DeviceUintPoint::new(0, 0), size));
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_set_root_display_list(dh: &mut DocumentHandle,
-                                                      color: ColorF,
-                                                      epoch: WrEpoch,
-                                                      viewport_width: f32,
-                                                      viewport_height: f32,
-                                                      pipeline_id: WrPipelineId,
-                                                      content_size: LayoutSize,
-                                                      dl_descriptor: BuiltDisplayListDescriptor,
-                                                      dl_data: *mut u8,
-                                                      dl_size: usize) {
-    let color = if color.a == 0.0 {
-        None
-    } else {
-        Some(color)
-    };
+pub unsafe extern "C" fn wr_api_set_display_list(
+    dh: &mut DocumentHandle,
+    color: ColorF,
+    epoch: WrEpoch,
+    viewport_width: f32,
+    viewport_height: f32,
+    pipeline_id: WrPipelineId,
+    content_size: LayoutSize,
+    dl_descriptor: BuiltDisplayListDescriptor,
+    dl_data: *mut u8,
+    dl_size: usize,
+    resources: &mut ResourceUpdates,
+) {
+    let resource_updates = mem::replace(resources, ResourceUpdates::new());
+
+    let color = if color.a == 0.0 { None } else { Some(color) };
+
     // See the documentation of set_display_list in api.rs. I don't think
     // it makes a difference in gecko at the moment(until APZ is figured out)
     // but I suppose it is a good default.
     let preserve_frame_state = true;
 
     let dl_slice = make_slice(dl_data, dl_size);
     let mut dl_vec = Vec::new();
     // XXX: see if we can get rid of the copy here
     dl_vec.extend_from_slice(dl_slice);
     let dl = BuiltDisplayList::from_data(dl_vec, dl_descriptor);
 
-    dh.api.set_display_list(dh.document_id,
-                            epoch,
-                            color,
-                            LayoutSize::new(viewport_width, viewport_height),
-                            (pipeline_id, content_size, dl),
-                            preserve_frame_state,
-                            ResourceUpdates::new());
+    dh.api.set_display_list(
+        dh.document_id,
+        epoch,
+        color,
+        LayoutSize::new(viewport_width, viewport_height),
+        (pipeline_id, content_size, dl),
+        preserve_frame_state,
+        resource_updates
+    );
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_clear_root_display_list(dh: &mut DocumentHandle,
-                                                        epoch: WrEpoch,
-                                                        pipeline_id: WrPipelineId) {
+pub unsafe extern "C" fn wr_api_clear_display_list(
+    dh: &mut DocumentHandle,
+    epoch: WrEpoch,
+    pipeline_id: WrPipelineId,
+) {
     let preserve_frame_state = true;
     let frame_builder = WebRenderFrameBuilder::new(pipeline_id, LayoutSize::zero());
+    let resource_updates = ResourceUpdates::new();
 
-    dh.api.set_display_list(dh.document_id,
-                            epoch,
-                            None,
-                            LayoutSize::new(0.0, 0.0),
-                            frame_builder.dl_builder.finalize(),
-                            preserve_frame_state,
-                            ResourceUpdates::new());
+    dh.api.set_display_list(
+        dh.document_id,
+        epoch,
+        None,
+        LayoutSize::new(0.0, 0.0),
+        frame_builder.dl_builder.finalize(),
+        preserve_frame_state,
+        resource_updates
+    );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_generate_frame(dh: &mut DocumentHandle) {
     dh.api.generate_frame(dh.document_id, None);
 }
 
 #[no_mangle]
@@ -878,65 +897,97 @@ pub extern "C" fn wr_api_generate_frame_
 pub extern "C" fn wr_api_send_external_event(dh: &mut DocumentHandle,
                                              evt: usize) {
     assert!(unsafe { !is_in_render_thread() });
 
     dh.api.send_external_event(ExternalEvent::from_raw(evt));
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_raw_font(dh: &mut DocumentHandle,
-                                      key: WrFontKey,
-                                      font_buffer: *mut u8,
-                                      buffer_size: usize,
-                                      index: u32) {
-    assert!(unsafe { is_in_compositor_thread() });
-
+pub extern "C" fn wr_resource_updates_add_raw_font(
+    resources: &mut ResourceUpdates,
+    key: WrFontKey,
+    font_buffer: *mut u8,
+    buffer_size: usize,
+    index: u32
+) {
     let font_slice = make_slice(font_buffer, buffer_size);
     let mut font_vector = Vec::new();
     font_vector.extend_from_slice(font_slice);
 
-    let mut resources = ResourceUpdates::new();
     resources.add_raw_font(key, font_vector, index);
-    dh.api.update_resources(resources);
+}
+
+#[no_mangle]
+pub extern "C" fn wr_resource_updates_delete_font(
+    resources: &mut ResourceUpdates,
+    key: WrFontKey
+) {
+    resources.delete_font(key);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_delete_font(dh: &mut DocumentHandle,
-                                     key: WrFontKey) {
-    assert!(unsafe { is_in_compositor_thread() });
-    let mut resources = ResourceUpdates::new();
-    resources.delete_font(key);
-    dh.api.update_resources(resources);
+pub extern "C" fn wr_resource_updates_add_font_instance(
+    resources: &mut ResourceUpdates,
+    key: WrFontInstanceKey,
+    font_key: WrFontKey,
+    glyph_size: f32,
+    options: *const FontInstanceOptions,
+    platform_options: *const FontInstancePlatformOptions
+) {
+    resources.add_font_instance(
+        key,
+        font_key,
+        Au::from_f32_px(glyph_size),
+        unsafe { options.as_ref().cloned() },
+        unsafe { platform_options.as_ref().cloned() }
+    );
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_font_instance(dh: &mut DocumentHandle,
-                                           key: WrFontInstanceKey,
-                                           font_key: WrFontKey,
-                                           glyph_size: f32,
-                                           options: *const FontInstanceOptions,
-                                           platform_options: *const FontInstancePlatformOptions) {
-    assert!(unsafe { is_in_compositor_thread() });
-    let mut resources = ResourceUpdates::new();
-    resources.add_font_instance(key,
-                                font_key,
-                                Au::from_f32_px(glyph_size),
-                                unsafe { options.as_ref().cloned() },
-                                unsafe { platform_options.as_ref().cloned() });
-    dh.api.update_resources(resources);
+pub extern "C" fn wr_resource_updates_delete_font_instance(
+    resources: &mut ResourceUpdates,
+    key: WrFontInstanceKey
+) {
+    resources.delete_font_instance(key);
+}
+
+#[no_mangle]
+pub extern "C" fn wr_resource_updates_new() -> *mut ResourceUpdates {
+    let updates = Box::new(ResourceUpdates::new());
+    Box::into_raw(updates)
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_delete_font_instance(dh: &mut DocumentHandle,
-                                              key: WrFontInstanceKey) {
-    assert!(unsafe { is_in_compositor_thread() });
-    let mut resources = ResourceUpdates::new();
-    resources.delete_font_instance(key);
-    dh.api.update_resources(resources);
+pub extern "C" fn wr_resource_updates_clear(resources: &mut ResourceUpdates) {
+    resources.updates.clear();
+}
+
+/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
+#[no_mangle]
+pub extern "C" fn wr_resource_updates_delete(updates: *mut ResourceUpdates) {
+    unsafe {
+        Box::from_raw(updates);
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn wr_resource_updates_serialize(resources: &mut ResourceUpdates, into: &mut VecU8) {
+    let mut data = Vec::new();
+    bincode::serialize_into(&mut data, &resources.updates, bincode::Infinite).unwrap();
+    resources.updates.clear();
+    *into = data;
+}
+
+#[no_mangle]
+pub extern "C" fn wr_resource_updates_deserialize(data: ByteSlice) -> *mut ResourceUpdates {
+    let resources: Box<ResourceUpdates> = Box::new(
+        bincode::deserialize_from(&mut data.as_slice(), bincode::Infinite).expect("Invalid wr::ResourceUpdate serialization?")
+    );
+    Box::into_raw(resources)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn wr_api_get_namespace(dh: &mut DocumentHandle) -> WrIdNamespace {
     dh.api.get_namespace_id()
 }
 
 // RenderThread WIP notes:
--- a/gfx/webrender_bindings/src/lib.rs
+++ b/gfx/webrender_bindings/src/lib.rs
@@ -6,12 +6,13 @@
 
 extern crate webrender;
 extern crate webrender_api;
 extern crate euclid;
 extern crate app_units;
 extern crate gleam;
 extern crate rayon;
 extern crate thread_profiler;
+extern crate bincode;
 
 #[allow(non_snake_case)]
 pub mod bindings;
 pub mod moz2d_renderer;
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -170,135 +170,31 @@ enum class YuvColorSpace : uint32_t {
 struct Arc_VecU8;
 
 struct DocumentHandle;
 
 // The renderer is responsible for submitting to the GPU the work prepared by the
 // RenderBackend.
 struct Renderer;
 
+// The resource updates for a given transaction (they must be applied in the same frame).
+struct ResourceUpdates;
+
 struct Vec_u8;
 
 struct WrRenderedEpochs;
 
 struct WrState;
 
 struct WrThreadPool;
 
 typedef Vec_u8 VecU8;
 
 typedef Arc_VecU8 ArcVecU8;
 
-struct IdNamespace {
-  uint32_t mHandle;
-
-  bool operator==(const IdNamespace& aOther) const {
-    return mHandle == aOther.mHandle;
-  }
-  bool operator!=(const IdNamespace& aOther) const {
-    return mHandle != aOther.mHandle;
-  }
-  bool operator<(const IdNamespace& aOther) const {
-    return mHandle < aOther.mHandle;
-  }
-  bool operator<=(const IdNamespace& aOther) const {
-    return mHandle <= aOther.mHandle;
-  }
-};
-
-struct ImageKey {
-  IdNamespace mNamespace;
-  uint32_t mHandle;
-
-  bool operator==(const ImageKey& aOther) const {
-    return mNamespace == aOther.mNamespace &&
-           mHandle == aOther.mHandle;
-  }
-};
-
-typedef ImageKey WrImageKey;
-
-struct WrImageDescriptor {
-  ImageFormat format;
-  uint32_t width;
-  uint32_t height;
-  uint32_t stride;
-  bool is_opaque;
-
-  bool operator==(const WrImageDescriptor& aOther) const {
-    return format == aOther.format &&
-           width == aOther.width &&
-           height == aOther.height &&
-           stride == aOther.stride &&
-           is_opaque == aOther.is_opaque;
-  }
-};
-
-struct ByteSlice {
-  const uint8_t *buffer;
-  size_t len;
-
-  bool operator==(const ByteSlice& aOther) const {
-    return buffer == aOther.buffer &&
-           len == aOther.len;
-  }
-};
-
-struct WrExternalImageId {
-  uint64_t mHandle;
-
-  bool operator==(const WrExternalImageId& aOther) const {
-    return mHandle == aOther.mHandle;
-  }
-};
-
-typedef ExternalImageType WrExternalImageBufferType;
-
-struct FontInstanceKey {
-  IdNamespace mNamespace;
-  uint32_t mHandle;
-
-  bool operator==(const FontInstanceKey& aOther) const {
-    return mNamespace == aOther.mNamespace &&
-           mHandle == aOther.mHandle;
-  }
-};
-
-typedef FontInstanceKey WrFontInstanceKey;
-
-struct FontKey {
-  IdNamespace mNamespace;
-  uint32_t mHandle;
-
-  bool operator==(const FontKey& aOther) const {
-    return mNamespace == aOther.mNamespace &&
-           mHandle == aOther.mHandle;
-  }
-};
-
-typedef FontKey WrFontKey;
-
-struct FontInstanceOptions {
-  FontRenderMode render_mode;
-
-  bool operator==(const FontInstanceOptions& aOther) const {
-    return render_mode == aOther.render_mode;
-  }
-};
-
-struct FontInstancePlatformOptions {
-  bool use_embedded_bitmap;
-  bool force_gdi_rendering;
-
-  bool operator==(const FontInstancePlatformOptions& aOther) const {
-    return use_embedded_bitmap == aOther.use_embedded_bitmap &&
-           force_gdi_rendering == aOther.force_gdi_rendering;
-  }
-};
-
 struct Epoch {
   uint32_t mHandle;
 
   bool operator==(const Epoch& aOther) const {
     return mHandle == aOther.mHandle;
   }
   bool operator<(const Epoch& aOther) const {
     return mHandle < aOther.mHandle;
@@ -428,16 +324,33 @@ struct TypedTransform3D_f32__LayoutPixel
 
 typedef TypedTransform3D_f32__LayoutPixel__LayoutPixel LayoutTransform;
 
 struct WrTransformProperty {
   uint64_t id;
   LayoutTransform transform;
 };
 
+struct IdNamespace {
+  uint32_t mHandle;
+
+  bool operator==(const IdNamespace& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
+  bool operator!=(const IdNamespace& aOther) const {
+    return mHandle != aOther.mHandle;
+  }
+  bool operator<(const IdNamespace& aOther) const {
+    return mHandle < aOther.mHandle;
+  }
+  bool operator<=(const IdNamespace& aOther) const {
+    return mHandle <= aOther.mHandle;
+  }
+};
+
 typedef IdNamespace WrIdNamespace;
 
 // Represents RGBA screen colors with floating point numbers.
 // 
 // All components must be between 0.0 and 1.0.
 // An alpha value of 1.0 is opaque while 0.0 is fully transparent.
 struct ColorF {
   float r;
@@ -497,16 +410,28 @@ struct WrComplexClipRegion {
   BorderRadius radii;
 
   bool operator==(const WrComplexClipRegion& aOther) const {
     return rect == aOther.rect &&
            radii == aOther.radii;
   }
 };
 
+struct ImageKey {
+  IdNamespace mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const ImageKey& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+           mHandle == aOther.mHandle;
+  }
+};
+
+typedef ImageKey WrImageKey;
+
 struct WrImageMask {
   WrImageKey image;
   LayoutRect rect;
   bool repeat;
 
   bool operator==(const WrImageMask& aOther) const {
     return image == aOther.image &&
            rect == aOther.rect &&
@@ -613,16 +538,28 @@ struct WrFilterOp {
   float argument;
 
   bool operator==(const WrFilterOp& aOther) const {
     return filter_type == aOther.filter_type &&
            argument == aOther.argument;
   }
 };
 
+struct FontInstanceKey {
+  IdNamespace mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const FontInstanceKey& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+           mHandle == aOther.mHandle;
+  }
+};
+
+typedef FontInstanceKey WrFontInstanceKey;
+
 typedef uint32_t GlyphIndex;
 
 struct GlyphInstance {
   GlyphIndex index;
   LayoutPoint point;
 
   bool operator==(const GlyphInstance& aOther) const {
     return index == aOther.index &&
@@ -647,16 +584,26 @@ struct TextShadow {
     return offset == aOther.offset &&
            color == aOther.color &&
            blur_radius == aOther.blur_radius;
   }
 };
 
 typedef YuvColorSpace WrYuvColorSpace;
 
+struct ByteSlice {
+  const uint8_t *buffer;
+  size_t len;
+
+  bool operator==(const ByteSlice& aOther) const {
+    return buffer == aOther.buffer &&
+           len == aOther.len;
+  }
+};
+
 struct TypedPoint2D_u16__Tiles {
   uint16_t x;
   uint16_t y;
 
   bool operator==(const TypedPoint2D_u16__Tiles& aOther) const {
     return x == aOther.x &&
            y == aOther.y;
   }
@@ -713,32 +660,88 @@ struct WrExternalImage {
            v0 == aOther.v0 &&
            u1 == aOther.u1 &&
            v1 == aOther.v1 &&
            buff == aOther.buff &&
            size == aOther.size;
   }
 };
 
+struct WrExternalImageId {
+  uint64_t mHandle;
+
+  bool operator==(const WrExternalImageId& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
+};
+
 typedef WrExternalImage (*LockExternalImageCallback)(void*, WrExternalImageId, uint8_t);
 
 typedef void (*UnlockExternalImageCallback)(void*, WrExternalImageId, uint8_t);
 
 struct WrExternalImageHandler {
   void *external_image_obj;
   LockExternalImageCallback lock_func;
   UnlockExternalImageCallback unlock_func;
 
   bool operator==(const WrExternalImageHandler& aOther) const {
     return external_image_obj == aOther.external_image_obj &&
            lock_func == aOther.lock_func &&
            unlock_func == aOther.unlock_func;
   }
 };
 
+struct WrImageDescriptor {
+  ImageFormat format;
+  uint32_t width;
+  uint32_t height;
+  uint32_t stride;
+  bool is_opaque;
+
+  bool operator==(const WrImageDescriptor& aOther) const {
+    return format == aOther.format &&
+           width == aOther.width &&
+           height == aOther.height &&
+           stride == aOther.stride &&
+           is_opaque == aOther.is_opaque;
+  }
+};
+
+typedef ExternalImageType WrExternalImageBufferType;
+
+struct FontKey {
+  IdNamespace mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const FontKey& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+           mHandle == aOther.mHandle;
+  }
+};
+
+typedef FontKey WrFontKey;
+
+struct FontInstanceOptions {
+  FontRenderMode render_mode;
+
+  bool operator==(const FontInstanceOptions& aOther) const {
+    return render_mode == aOther.render_mode;
+  }
+};
+
+struct FontInstancePlatformOptions {
+  bool use_embedded_bitmap;
+  bool force_gdi_rendering;
+
+  bool operator==(const FontInstancePlatformOptions& aOther) const {
+    return use_embedded_bitmap == aOther.use_embedded_bitmap &&
+           force_gdi_rendering == aOther.force_gdi_rendering;
+  }
+};
+
 /* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
  * To generate this file:
  *   1. Get the latest cbindgen using `cargo install --force cbindgen`
  *      a. Alternatively, you can clone `https://github.com/rlhunt/cbindgen` and use a tagged release
  *   2. Run `rustup run nightly cbindgen toolkit/library/rust/ --crate webrender_bindings -o gfx/webrender_bindings/webrender_ffi_generated.h`
  */
 
 extern void gfx_critical_note(const char *aMsg);
@@ -753,86 +756,31 @@ extern bool is_in_main_thread();
 
 extern bool is_in_render_thread();
 
 WR_INLINE
 const VecU8 *wr_add_ref_arc(const ArcVecU8 *aArc)
 WR_FUNC;
 
 WR_INLINE
-void wr_api_add_blob_image(DocumentHandle *aDh,
-                           WrImageKey aImageKey,
-                           const WrImageDescriptor *aDescriptor,
-                           ByteSlice aBytes)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_add_external_image(DocumentHandle *aDh,
-                               WrImageKey aImageKey,
-                               const WrImageDescriptor *aDescriptor,
-                               WrExternalImageId aExternalImageId,
-                               WrExternalImageBufferType aBufferType,
-                               uint8_t aChannelIndex)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_add_font_instance(DocumentHandle *aDh,
-                              WrFontInstanceKey aKey,
-                              WrFontKey aFontKey,
-                              float aGlyphSize,
-                              const FontInstanceOptions *aOptions,
-                              const FontInstancePlatformOptions *aPlatformOptions)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_add_image(DocumentHandle *aDh,
-                      WrImageKey aImageKey,
-                      const WrImageDescriptor *aDescriptor,
-                      ByteSlice aBytes)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_add_raw_font(DocumentHandle *aDh,
-                         WrFontKey aKey,
-                         uint8_t *aFontBuffer,
-                         size_t aBufferSize,
-                         uint32_t aIndex)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_clear_root_display_list(DocumentHandle *aDh,
-                                    WrEpoch aEpoch,
-                                    WrPipelineId aPipelineId)
+void wr_api_clear_display_list(DocumentHandle *aDh,
+                               WrEpoch aEpoch,
+                               WrPipelineId aPipelineId)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_clone(DocumentHandle *aDh,
                   DocumentHandle **aOutHandle)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_delete(DocumentHandle *aDh)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE
-void wr_api_delete_font(DocumentHandle *aDh,
-                        WrFontKey aKey)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_delete_font_instance(DocumentHandle *aDh,
-                                 WrFontInstanceKey aKey)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_delete_image(DocumentHandle *aDh,
-                         WrImageKey aKey)
-WR_FUNC;
-
-WR_INLINE
 void wr_api_finalize_builder(WrState *aState,
                              LayoutSize *aContentSize,
                              BuiltDisplayListDescriptor *aDlDescriptor,
                              WrVecU8 *aDlData)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_generate_frame(DocumentHandle *aDh)
@@ -851,60 +799,43 @@ WrIdNamespace wr_api_get_namespace(Docum
 WR_FUNC;
 
 WR_INLINE
 void wr_api_send_external_event(DocumentHandle *aDh,
                                 size_t aEvt)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE
-void wr_api_set_root_display_list(DocumentHandle *aDh,
-                                  ColorF aColor,
-                                  WrEpoch aEpoch,
-                                  float aViewportWidth,
-                                  float aViewportHeight,
-                                  WrPipelineId aPipelineId,
-                                  LayoutSize aContentSize,
-                                  BuiltDisplayListDescriptor aDlDescriptor,
-                                  uint8_t *aDlData,
-                                  size_t aDlSize)
+void wr_api_set_display_list(DocumentHandle *aDh,
+                             ColorF aColor,
+                             WrEpoch aEpoch,
+                             float aViewportWidth,
+                             float aViewportHeight,
+                             WrPipelineId aPipelineId,
+                             LayoutSize aContentSize,
+                             BuiltDisplayListDescriptor aDlDescriptor,
+                             uint8_t *aDlData,
+                             size_t aDlSize,
+                             ResourceUpdates *aResources)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_set_root_pipeline(DocumentHandle *aDh,
                               WrPipelineId aPipelineId)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_set_window_parameters(DocumentHandle *aDh,
                                   int32_t aWidth,
                                   int32_t aHeight)
 WR_FUNC;
 
 WR_INLINE
-void wr_api_update_blob_image(DocumentHandle *aDh,
-                              WrImageKey aImageKey,
-                              const WrImageDescriptor *aDescriptor,
-                              ByteSlice aBytes)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_update_external_image(DocumentHandle *aDh,
-                                  WrImageKey aKey,
-                                  const WrImageDescriptor *aDescriptor,
-                                  WrExternalImageId aExternalImageId,
-                                  WrExternalImageBufferType aImageType,
-                                  uint8_t aChannelIndex)
-WR_FUNC;
-
-WR_INLINE
-void wr_api_update_image(DocumentHandle *aDh,
-                         WrImageKey aKey,
-                         const WrImageDescriptor *aDescriptor,
-                         ByteSlice aBytes)
+void wr_api_update_resources(DocumentHandle *aDh,
+                             ResourceUpdates *aResources)
 WR_FUNC;
 
 WR_INLINE
 void wr_dec_ref_arc(const VecU8 *aArc)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_begin(WrState *aState,
@@ -1229,16 +1160,115 @@ void wr_renderer_set_external_image_hand
                                             WrExternalImageHandler *aExternalImageHandler)
 WR_FUNC;
 
 WR_INLINE
 void wr_renderer_update(Renderer *aRenderer)
 WR_FUNC;
 
 WR_INLINE
+void wr_resource_updates_add_blob_image(ResourceUpdates *aResources,
+                                        WrImageKey aImageKey,
+                                        const WrImageDescriptor *aDescriptor,
+                                        ByteSlice aBytes)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_add_external_image(ResourceUpdates *aResources,
+                                            WrImageKey aImageKey,
+                                            const WrImageDescriptor *aDescriptor,
+                                            WrExternalImageId aExternalImageId,
+                                            WrExternalImageBufferType aBufferType,
+                                            uint8_t aChannelIndex)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_add_font_instance(ResourceUpdates *aResources,
+                                           WrFontInstanceKey aKey,
+                                           WrFontKey aFontKey,
+                                           float aGlyphSize,
+                                           const FontInstanceOptions *aOptions,
+                                           const FontInstancePlatformOptions *aPlatformOptions)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_add_image(ResourceUpdates *aResources,
+                                   WrImageKey aImageKey,
+                                   const WrImageDescriptor *aDescriptor,
+                                   ByteSlice aBytes)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_add_raw_font(ResourceUpdates *aResources,
+                                      WrFontKey aKey,
+                                      uint8_t *aFontBuffer,
+                                      size_t aBufferSize,
+                                      uint32_t aIndex)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_clear(ResourceUpdates *aResources)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_delete(ResourceUpdates *aUpdates)
+WR_DESTRUCTOR_SAFE_FUNC;
+
+WR_INLINE
+void wr_resource_updates_delete_font(ResourceUpdates *aResources,
+                                     WrFontKey aKey)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_delete_font_instance(ResourceUpdates *aResources,
+                                              WrFontInstanceKey aKey)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_delete_image(ResourceUpdates *aResources,
+                                      WrImageKey aKey)
+WR_FUNC;
+
+WR_INLINE
+ResourceUpdates *wr_resource_updates_deserialize(ByteSlice aData)
+WR_FUNC;
+
+WR_INLINE
+ResourceUpdates *wr_resource_updates_new()
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_serialize(ResourceUpdates *aResources,
+                                   VecU8 *aInto)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_update_blob_image(ResourceUpdates *aResources,
+                                           WrImageKey aImageKey,
+                                           const WrImageDescriptor *aDescriptor,
+                                           ByteSlice aBytes)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_update_external_image(ResourceUpdates *aResources,
+                                               WrImageKey aKey,
+                                               const WrImageDescriptor *aDescriptor,
+                                               WrExternalImageId aExternalImageId,
+                                               WrExternalImageBufferType aImageType,
+                                               uint8_t aChannelIndex)
+WR_FUNC;
+
+WR_INLINE
+void wr_resource_updates_update_image(ResourceUpdates *aResources,
+                                      WrImageKey aKey,
+                                      const WrImageDescriptor *aDescriptor,
+                                      ByteSlice aBytes)
+WR_FUNC;
+
+WR_INLINE
 void wr_scroll_layer_with_id(DocumentHandle *aDh,
                              WrPipelineId aPipelineId,
                              uint64_t aScrollId,
                              LayoutPoint aNewScrollOrigin)
 WR_FUNC;
 
 WR_INLINE
 void wr_state_delete(WrState *aState)
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -1022,19 +1022,19 @@ description = bug 1350634
 [PUiCompositorController::Pause]
 description =
 [PUiCompositorController::Resume]
 description =
 [PUiCompositorController::ResumeAndResize]
 description =
 [PWebRenderBridge::Create]
 description =
-[PWebRenderBridge::DPSyncEnd]
+[PWebRenderBridge::SetDisplayListSync]
 description =
-[PWebRenderBridge::DPGetSnapshot]
+[PWebRenderBridge::GetSnapshot]
 description =
 [PWebRenderBridge::SetTestSampleTime]
 description = test only
 [PWebRenderBridge::LeaveTestMode]
 description = test only
 [PWebRenderBridge::GetAnimationOpacity]
 description = test only
 [PWebRenderBridge::GetAnimationTransform]
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -320,17 +320,17 @@ function ModuleInstantiate()
             // This can happen due to OOM when appending to the stack.
             assert(error === "out of memory",
                    "Stack must contain module unless we hit OOM");
             RecordModuleError(module, error);
         }
 
         assert(module.status === MODULE_STATUS_ERRORED,
                "Bad module status after failed instantiation");
-        assert(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT) === error,
+        assert(SameValue(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT), error),
                "Module has different error set after failed instantiation");
 
         throw error;
     }
 
     // Step 6
     assert(module.status == MODULE_STATUS_INSTANTIATED ||
            module.status == MODULE_STATUS_EVALUATED,
@@ -545,17 +545,17 @@ function ModuleEvaluate()
             // This can happen due to OOM when appending to the stack.
             assert(error === "out of memory",
                   "Stack must contain module unless we hit OOM");
             RecordModuleError(module, error);
         }
 
         assert(module.status === MODULE_STATUS_ERRORED,
                "Bad module status after failed evaluation");
-        assert(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT) === error,
+        assert(SameValue(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT), error),
                "Module has different error set after failed evaluation");
 
         throw error;
     }
 
     assert(module.status == MODULE_STATUS_EVALUATED,
            "Bad module status after successful evaluation");
     assert(stack.length === 0,
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -273,17 +273,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
          * variable accesses in the script.
          */
         LazyFunction
     };
 
     const EmitterMode emitterMode;
 
     // The end location of a function body that is being emitted.
-    uint32_t functionBodyEndPos;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t functionBodyEndPos;
     // Whether functionBodyEndPos was set.
     bool functionBodyEndPosSet;
 
     /*
      * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
      * space above their tempMark points. This means that you cannot alloc from
      * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
      * destruction.
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -460,16 +460,32 @@ js::TenuringTracer::TenuringTracer(JSRun
   : JSTracer(rt, JSTracer::TracerKindTag::Tenuring, TraceWeakMapKeysValues)
   , nursery_(*nursery)
   , tenuredSize(0)
   , head(nullptr)
   , tail(&head)
 {
 }
 
+inline float
+js::Nursery::calcPromotionRate(bool *validForTenuring) const {
+    float used = float(previousGC.nurseryUsedBytes);
+    float capacity = float(previousGC.nurseryCapacity);
+    float tenured = float(previousGC.tenuredBytes);
+
+    if (validForTenuring) {
+        /*
+         * We can only use promotion rates if they're likely to be valid,
+         * they're only valid if the nursury was at least 90% full.
+         */
+        *validForTenuring = used > capacity * 0.9f;
+    }
+    return tenured / used;
+}
+
 void
 js::Nursery::renderProfileJSON(JSONPrinter& json) const
 {
     if (!isEnabled()) {
         json.beginObject();
         json.property("status", "nursery disabled");
         json.endObject();
         return;
@@ -485,18 +501,17 @@ js::Nursery::renderProfileJSON(JSONPrint
         json.endObject();
         return;
     }
 
     json.beginObject();
 
     json.property("reason", JS::gcreason::ExplainReason(previousGC.reason));
     json.property("bytes_tenured", previousGC.tenuredBytes);
-    json.floatProperty("promotion_rate",
-                       100.0 * previousGC.tenuredBytes / double(previousGC.nurseryUsedBytes), 2);
+    json.floatProperty("promotion_rate", calcPromotionRate(nullptr), 0);
     json.property("nursery_bytes", previousGC.nurseryUsedBytes);
     json.property("new_nursery_bytes", numChunks() * ChunkSize);
 
     json.beginObjectProperty("timings");
 
 #define EXTRACT_NAME(name, text) #name,
     static const char* names[] = {
 FOR_EACH_NURSERY_PROFILE_TIME(EXTRACT_NAME)
@@ -604,41 +619,49 @@ js::Nursery::collect(JS::gcreason::Reaso
     maybeClearProfileDurations();
     startProfile(ProfileKey::Total);
 
     // The hazard analysis thinks doCollection can invalidate pointers in
     // tenureCounts below.
     JS::AutoSuppressGCAnalysis nogc;
 
     TenureCountCache tenureCounts;
-    double promotionRate = 0;
     previousGC.reason = JS::gcreason::NO_REASON;
-    if (!isEmpty())
-        promotionRate = doCollection(reason, tenureCounts);
+    if (!isEmpty()) {
+        doCollection(reason, tenureCounts);
+    } else {
+        previousGC.nurseryUsedBytes = 0;
+        previousGC.nurseryCapacity = spaceToEnd();
+        previousGC.tenuredBytes = 0;
+    }
 
     // Resize the nursery.
     startProfile(ProfileKey::Resize);
-    maybeResizeNursery(reason, promotionRate);
+    maybeResizeNursery(reason);
     endProfile(ProfileKey::Resize);
 
     // If we are promoting the nursery, or exhausted the store buffer with
     // pointers to nursery things, which will force a collection well before
     // the nursery is full, look for object groups that are getting promoted
     // excessively and try to pretenure them.
     startProfile(ProfileKey::Pretenure);
+    bool validPromotionRate;
+    const float promotionRate = calcPromotionRate(&validPromotionRate);
     uint32_t pretenureCount = 0;
-    if (promotionRate > 0.8 || IsFullStoreBufferReason(reason)) {
-        JSContext* cx = TlsContext.get();
-        for (auto& entry : tenureCounts.entries) {
-            if (entry.count >= 3000) {
-                ObjectGroup* group = entry.group;
-                if (group->canPreTenure()) {
-                    AutoCompartment ac(cx, group);
-                    group->setShouldPreTenure(cx);
-                    pretenureCount++;
+    if (validPromotionRate) {
+        if (promotionRate > 0.8 || IsFullStoreBufferReason(reason)) {
+            JSContext* cx = TlsContext.get();
+            for (auto& entry : tenureCounts.entries) {
+                if (entry.count >= 3000) {
+                    ObjectGroup* group = entry.group;
+                    if (group->canPreTenure()) {
+                        AutoCompartment ac(cx, group);
+                        group->setShouldPreTenure(cx);
+                        pretenureCount++;
+                    }
                 }
             }
         }
     }
     endProfile(ProfileKey::Pretenure);
 
     // We ignore gcMaxBytes when allocating for minor collection. However, if we
     // overflowed, we disable the nursery. The next time we allocate, we'll fail
@@ -680,28 +703,29 @@ js::Nursery::collect(JS::gcreason::Reaso
                     fprintf(stderr, "  %d x ", entry.count);
                     entry.group->print();
                 }
             }
         }
     }
 }
 
-double
+void
 js::Nursery::doCollection(JS::gcreason::Reason reason,
                           TenureCountCache& tenureCounts)
 {
     JSRuntime* rt = runtime();
     AutoTraceSession session(rt, JS::HeapState::MinorCollecting);
     AutoSetThreadIsPerformingGC performingGC;
     AutoStopVerifyingBarriers av(rt, false);
     AutoDisableProxyCheck disableStrictProxyChecking;
     mozilla::DebugOnly<AutoEnterOOMUnsafeRegion> oomUnsafeRegion;
 
-    size_t initialNurserySize = spaceToEnd();
+    const size_t initialNurseryCapacity = spaceToEnd();
+    const size_t initialNurseryUsedBytes = initialNurseryCapacity - freeSpace();
 
     // Move objects pointed to by roots from the nursery to the major heap.
     TenuringTracer mover(rt, this);
 
     // Mark the store buffer. This must happen first.
     StoreBuffer& sb = runtime()->gc.storeBuffer();
 
     // The MIR graph only contains nursery pointers if cancelIonCompilations()
@@ -788,21 +812,19 @@ js::Nursery::doCollection(JS::gcreason::
     startProfile(ProfileKey::CheckHashTables);
 #ifdef JS_GC_ZEAL
     if (rt->hasZealMode(ZealMode::CheckHashTablesOnMinorGC))
         CheckHashTablesAfterMovingGC(rt);
 #endif
     endProfile(ProfileKey::CheckHashTables);
 
     previousGC.reason = reason;
-    previousGC.nurseryUsedBytes = initialNurserySize;
+    previousGC.nurseryCapacity = initialNurseryCapacity;
+    previousGC.nurseryUsedBytes = initialNurseryUsedBytes;
     previousGC.tenuredBytes = mover.tenuredSize;
-
-    // Calculate and return the promotion rate.
-    return mover.tenuredSize / double(initialNurserySize);
 }
 
 void
 js::Nursery::FreeMallocedBuffersTask::transferBuffersToFree(MallocedBuffersSet& buffersToFree,
                                                             const AutoLockHelperThreadState& lock)
 {
     // Transfer the contents of the source set to the task's buffers_ member by
     // swapping the sets, which also clears the source.
@@ -918,17 +940,17 @@ js::Nursery::setCurrentChunk(unsigned ch
 MOZ_ALWAYS_INLINE void
 js::Nursery::setStartPosition()
 {
     currentStartChunk_ = currentChunk_;
     currentStartPosition_ = position();
 }
 
 void
-js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason, double promotionRate)
+js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
 {
     static const double GrowThreshold   = 0.05;
     static const double ShrinkThreshold = 0.01;
     unsigned newMaxNurseryChunks;
 
     // Shrink the nursery to its minimum size of we ran out of memory or
     // received a memory pressure event.
     if (gc::IsOOMReason(reason)) {
@@ -937,30 +959,37 @@ js::Nursery::maybeResizeNursery(JS::gcre
     }
 
 #ifdef JS_GC_ZEAL
     // This zeal mode disabled nursery resizing.
     if (runtime()->hasZealMode(ZealMode::GenerationalGC))
         return;
 #endif
 
+    bool canUsePromotionRate;
+    const float promotionRate = calcPromotionRate(&canUsePromotionRate);
+
     newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift;
     if (newMaxNurseryChunks != maxNurseryChunks_) {
         maxNurseryChunks_ = newMaxNurseryChunks;
         /* The configured maximum nursery size is changing */
-        int extraChunks = numChunks() - newMaxNurseryChunks;
+        const int extraChunks = numChunks() - newMaxNurseryChunks;
         if (extraChunks > 0) {
             /* We need to shrink the nursery */
             shrinkAllocableSpace(extraChunks);
 
-            previousPromotionRate_ = promotionRate;
+            if (canUsePromotionRate)
+                previousPromotionRate_ = promotionRate;
             return;
         }
     }
 
+    if (!canUsePromotionRate)
+        return;
+
     if (promotionRate > GrowThreshold)
         growAllocableSpace();
     else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold)
         shrinkAllocableSpace(1);
 
     previousPromotionRate_ = promotionRate;
 }
 
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -311,17 +311,17 @@ class Nursery
 
     /* The index of the chunk that is currently being allocated from. */
     unsigned currentChunk_;
 
     /* Maximum number of chunks to allocate for the nursery. */
     unsigned maxNurseryChunks_;
 
     /* Promotion rate for the previous minor collection. */
-    double previousPromotionRate_;
+    float previousPromotionRate_;
 
     /* Report minor collections taking at least this long, if enabled. */
     mozilla::TimeDuration profileThreshold_;
     bool enableProfiling_;
 
     /* Report ObjectGroups with at lest this many instances tenured. */
     int64_t reportTenurings_;
 
@@ -348,23 +348,39 @@ class Nursery
     using ProfileDurations =
         mozilla::EnumeratedArray<ProfileKey, ProfileKey::KeyCount, mozilla::TimeDuration>;
 
     ProfileTimes startTimes_;
     ProfileDurations profileDurations_;
     ProfileDurations totalDurations_;
     uint64_t minorGcCount_;
 
+    /*
+     * This data is initialised only if the nursery is enabled and after at
+     * least one call to Nursery::collect()
+     */
     struct {
         JS::gcreason::Reason reason;
-        uint64_t nurseryUsedBytes;
-        uint64_t tenuredBytes;
+        size_t nurseryCapacity;
+        size_t nurseryUsedBytes;
+        size_t tenuredBytes;
     } previousGC;
 
     /*
+     * Calculate the promotion rate of the most recent minor GC.
+     * The valid_for_tenuring parameter is used to return whether this
+     * promotion rate is accurate enough (the nursery was full enough) to be
+     * used for tenuring and other decisions.
+     *
+     * Must only be called if the previousGC data is initialised.
+     */
+    float
+    calcPromotionRate(bool *validForTenuring) const;
+
+    /*
      * The set of externally malloced buffers potentially kept live by objects
      * stored in the nursery. Any external buffers that do not belong to a
      * tenured thing at the end of a minor GC must be freed.
      */
     typedef HashSet<void*, PointerHasher<void*>, SystemAllocPolicy> MallocedBuffersSet;
     MallocedBuffersSet mallocedBuffers;
 
     /* A task structure used to free the malloced bufers on a background thread. */
@@ -433,17 +449,17 @@ class Nursery
     JSRuntime* runtime() const { return runtime_; }
 
     /* Allocates a new GC thing from the tenured generation during minor GC. */
     gc::TenuredCell* allocateFromTenured(JS::Zone* zone, gc::AllocKind thingKind);
 
     /* Common internal allocator function. */
     void* allocate(size_t size);
 
-    double doCollection(JS::gcreason::Reason reason,
+    void doCollection(JS::gcreason::Reason reason,
                         gc::TenureCountCache& tenureCounts);
 
     /*
      * Move the object at |src| in the Nursery to an already-allocated cell
      * |dst| in Tenured.
      */
     void collectToFixedPoint(TenuringTracer& trc, gc::TenureCountCache& tenureCounts);
 
@@ -461,17 +477,17 @@ class Nursery
      * Frees all non-live nursery-allocated things at the end of a minor
      * collection.
      */
     void sweep();
 
     void sweepDictionaryModeObjects();
 
     /* Change the allocable space provided by the nursery. */
-    void maybeResizeNursery(JS::gcreason::Reason reason, double promotionRate);
+    void maybeResizeNursery(JS::gcreason::Reason reason);
     void growAllocableSpace();
     void shrinkAllocableSpace(unsigned removeNumChunks);
     void minimizeAllocableSpace();
 
     /* Profile recording and printing. */
     void maybeClearProfileDurations();
     void startProfile(ProfileKey key);
     void endProfile(ProfileKey key);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1394505.js
@@ -0,0 +1,13 @@
+if (helperThreadCount() === 0)
+    quit();
+if (!('oomTest' in this))
+    quit();
+
+for (let j = 0; j < 50; j++) {
+    if (j === 1)
+        oomTest(function() {});
+    evalInWorker(`
+        for (let i = 0; i < 30; i++)
+            relazifyFunctions();
+    `);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1394492.js
@@ -0,0 +1,6 @@
+// |jit-test| error: NaN
+let m = parseModule(`
+  throw i => { return 5; }, m-1;
+`);
+m.declarationInstantiation();
+m.evaluation();
--- a/js/src/jit-test/tests/wasm/integer.js
+++ b/js/src/jit-test/tests/wasm/integer.js
@@ -179,16 +179,17 @@ assertEq(testTrunc(13.37), 1);
     testBinary64('mul', "0x7fffffff", 2, "0xfffffffe");
     testBinary64('div_s', -40, 2, -20);
     testBinary64('div_s', -40, 8, -5);
     testBinary64('div_s', -40, 7, -5);
     testBinary64('div_s', 40, 8, 5);
     testBinary64('div_s', 40, 7, 5);
     testBinary64('div_s', "0x1234567887654321", 2, "0x91a2b3c43b2a190");
     testBinary64('div_s', "0x1234567887654321", "0x1000000000", "0x1234567");
+    testBinary64('div_s', -1, "0x100000000", 0);
     testBinary64('div_u', -40, 2, "0x7fffffffffffffec");
     testBinary64('div_u', "0x1234567887654321", 9, "0x205d0b80f0b4059");
     testBinary64('div_u', 40, 2, 20);
     testBinary64('div_u', 40, 8, 5);
     testBinary64('rem_s', 40, -3, 1);
     testBinary64('rem_s', 0, -3, 0);
     testBinary64('rem_s', 5, 2, 1);
     testBinary64('rem_s', 65, 64, 1);
--- a/js/src/jit/AtomicOperations.h
+++ b/js/src/jit/AtomicOperations.h
@@ -150,27 +150,32 @@ class AtomicOperations
     // Test lock-freedom for any int32 value.  This implements the
     // Atomics::isLockFree() operation in the ECMAScript Shared Memory and
     // Atomics specification, as follows:
     //
     // 4-byte accesses are always lock free (in the spec).
     // 1- and 2-byte accesses are always lock free (in SpiderMonkey).
     //
     // Lock-freedom for 8 bytes is determined by the platform's isLockfree8().
-    // However, the spec stipulates that isLockFree(8) is true only if there is
-    // an integer array that admits atomic operations whose BYTES_PER_ELEMENT=8;
-    // at the moment (August 2017) there are no such arrays.
+    // However, the ES spec stipulates that isLockFree(8) is true only if there
+    // is an integer array that admits atomic operations whose
+    // BYTES_PER_ELEMENT=8; at the moment (August 2017) there are no such
+    // arrays.
     //
-    // There is no lock-freedom for any other values on any platform.
+    // There is no lock-freedom for JS for any other values on any platform.
     static inline bool isLockfreeJS(int32_t n);
 
-    // If the return value is true then a call to the 64-bit (8-byte)
-    // routines below will work, otherwise those functions will assert in
-    // debug builds and may crash in release build.  (See the code in
-    // ../arm for an example.)  The value of this call does not change
+    // If the return value is true then the templated functions below are
+    // supported for int64_t and uint64_t.  If the return value is false then
+    // those functions will MOZ_CRASH.  The value of this call does not change
+    // during execution.
+    static inline bool hasAtomic8();
+
+    // If the return value is true then hasAtomic8() is true and the atomic
+    // operations are indeed lock-free.  The value of this call does not change
     // during execution.
     static inline bool isLockfree8();
 
     // Execute a full memory barrier (LoadLoad+LoadStore+StoreLoad+StoreStore).
     static inline void fenceSeqCst();
 
     // All clients should use the APIs that take SharedMem pointers.
     // See above for semantics and acceptable types.
--- a/js/src/jit/arm/AtomicOperations-arm.h
+++ b/js/src/jit/arm/AtomicOperations-arm.h
@@ -26,36 +26,42 @@
 // ordered operations, but these reorderings are not allowed by JS.  To do
 // better we will end up with inline assembler or JIT-generated code.
 
 #if !defined(__clang__) && !defined(__GNUC__)
 # error "This file only for gcc-compatible compilers"
 #endif
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    // This guard is really only for tier-2 and tier-3 systems: LDREXD and
+    // STREXD have been available since ARMv6K, and only ARMv7 and later are
+    // tier-1.
+    return HasLDSTREXBHD();
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     // The JIT and the C++ compiler must agree on whether to use atomics
     // for 64-bit accesses.  There are two ways to do this: either the
     // JIT defers to the C++ compiler (so if the C++ code is compiled
     // for ARMv6, say, and __atomic_always_lock_free(8) is false, then the
     // JIT ignores the fact that the program is running on ARMv7 or newer);
     // or the C++ code in this file calls out to run-time generated code
     // to do whatever the JIT does.
     //
     // For now, make the JIT defer to the C++ compiler when we know what
     // the C++ compiler will do, otherwise assume a lock is needed.
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
 
-    // This guard is really only for tier-2 and tier-3 systems: LDREXD and
-    // STREXD have been available since ARMv6K, and only ARMv7 and later are
-    // tier-1.
-    return HasLDSTREXBHD() && __atomic_always_lock_free(sizeof(int64_t), 0);
+    return hasAtomic8() && __atomic_always_lock_free(sizeof(int64_t), 0);
 }
 
 inline void
 js::jit::AtomicOperations::fenceSeqCst()
 {
     __atomic_thread_fence(__ATOMIC_SEQ_CST);
 }
 
--- a/js/src/jit/arm64/AtomicOperations-arm64.h
+++ b/js/src/jit/arm64/AtomicOperations-arm64.h
@@ -12,16 +12,22 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Types.h"
 
 #if !defined(__clang__) && !defined(__GNUC__)
 # error "This file only for gcc-compatible compilers"
 #endif
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
     return true;
 }
--- a/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
+++ b/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
@@ -29,18 +29,29 @@
 // compatible option for older compilers: enable this to use GCC's old
 // __sync functions instead of the newer __atomic functions.  This
 // will be required for GCC 4.6.x and earlier, and probably for Clang
 // 3.1, should we need to use those versions.
 
 //#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    // NOTE, change this when primitives below have been properly changed to
+    // support 8-byte atomics.
+    return false;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
+    if (!hasAtomic8())
+        return false;
+
 #ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     // NOTE, this condition is obsolete.  See comment above.
 # if _MIPS_SIM == _ABI64
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
 # endif
--- a/js/src/jit/none/AtomicOperations-feeling-lucky.h
+++ b/js/src/jit/none/AtomicOperations-feeling-lucky.h
@@ -87,16 +87,26 @@
 #  error "This combination of features is senseless, please fix"
 #endif
 
 // Try to avoid platform #ifdefs below this point.
 
 #ifdef GNUC_COMPATIBLE
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+#if defined(HAS_64BIT_ATOMICS)
+    return true;
+#else
+    return false;
+#endif
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
 #if defined(HAS_64BIT_LOCKFREE)
     return true;
 #else
     return false;
 #endif
 }
--- a/js/src/jit/x86-shared/AtomicOperations-x86-shared-gcc.h
+++ b/js/src/jit/x86-shared/AtomicOperations-x86-shared-gcc.h
@@ -57,123 +57,146 @@
 
 // For now, we require that the C++ compiler's atomics are lock free, even for
 // 64-bit accesses.
 
 // When compiling with Clang on 32-bit linux it will be necessary to link with
 // -latomic to get the proper 64-bit intrinsics.
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
     return true;
 }
 
 inline void
 js::jit::AtomicOperations::fenceSeqCst()
 {
     __atomic_thread_fence(__ATOMIC_SEQ_CST);
 }
 
 template<typename T>
+static bool
+IsAligned(const T* addr)
+{
+    return (uintptr_t(addr) & (sizeof(T) - 1)) == 0;
+}
+
+template<typename T>
 inline T
 js::jit::AtomicOperations::loadSeqCst(T* addr)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     T v;
     __atomic_load(addr, &v, __ATOMIC_SEQ_CST);
     return v;
 }
 
 template<typename T>
 inline void
 js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     __atomic_store(addr, &val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     T v;
     __atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST);
     return v;
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     __atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
     return oldval;
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST);
 }
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::loadSafeWhenRacy(T* addr)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     T v;
     __atomic_load(addr, &v, __ATOMIC_RELAXED);
     return v;
 }
 
 namespace js { namespace jit {
 
 template<>
@@ -188,16 +211,17 @@ js::jit::AtomicOperations::loadSafeWhenR
 } }
 
 template<typename T>
 inline void
 js::jit::AtomicOperations::storeSafeWhenRacy(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
     MOZ_ASSERT_IF(sizeof(T) == 8, isLockfree8());
+    MOZ_ASSERT(IsAligned(addr));
     __atomic_store(addr, &val, __ATOMIC_RELAXED);
 }
 
 namespace js { namespace jit {
 
 template<>
 inline void
 js::jit::AtomicOperations::storeSafeWhenRacy(uint8_clamped* addr, uint8_clamped val)
--- a/js/src/jit/x86-shared/AtomicOperations-x86-shared-msvc.h
+++ b/js/src/jit/x86-shared/AtomicOperations-x86-shared-msvc.h
@@ -29,16 +29,25 @@
 // higher level of function which uses the intrinsic when possible (8, 16, and
 // 32-bit operations, and 64-bit operations on 64-bit systems) and otherwise
 // falls back on CMPXCHG8B for 64-bit operations on 32-bit systems.  We could be
 // using those functions in many cases here (though not all).  I have not done
 // so because (a) I don't yet know how far back those functions are supported
 // and (b) I expect we'll end up dropping into assembler here eventually so as
 // to guarantee that the C++ compiler won't optimize the code.
 
+// Note, _InterlockedCompareExchange takes the *new* value as the second argument
+// and the *comparand* (expected old value) as the third argument.
+
+inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
 inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     // The MSDN docs suggest very strongly that if code is compiled for Pentium
     // or better the 64-bit primitives will be lock-free, see eg the "Remarks"
     // secion of the page for _InterlockedCompareExchange64, currently here:
     // https://msdn.microsoft.com/en-us/library/ttk2z1ws%28v=vs.85%29.aspx
     //
@@ -51,33 +60,42 @@ js::jit::AtomicOperations::isLockfree8()
 inline void
 js::jit::AtomicOperations::fenceSeqCst()
 {
     _ReadWriteBarrier();
     _mm_mfence();
 }
 
 template<typename T>
+static bool
+IsAligned(const T* addr)
+{
+    return (uintptr_t(addr) & (sizeof(T) - 1)) == 0;
+}
+
+template<typename T>
 inline T
 js::jit::AtomicOperations::loadSeqCst(T* addr)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
+    MOZ_ASSERT(IsAligned(addr));
     _ReadWriteBarrier();
     T v = *addr;
     _ReadWriteBarrier();
     return v;
 }
 
 #ifdef _M_IX86
 namespace js { namespace jit {
 
 # define MSC_LOADOP(T)                      \
     template<>                              \
     inline T                                \
     AtomicOperations::loadSeqCst(T* addr) { \
+        MOZ_ASSERT(IsAligned(addr));        \
         _ReadWriteBarrier();                \
         return (T)_InterlockedCompareExchange64((__int64 volatile*)addr, 0, 0); \
     }
 
 MSC_LOADOP(int64_t)
 MSC_LOADOP(uint64_t)
 
 # undef MSC_LOADOP
@@ -85,34 +103,36 @@ MSC_LOADOP(uint64_t)
 } }
 #endif // _M_IX86
 
 template<typename T>
 inline void
 js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
 {
     static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only");
+    MOZ_ASSERT(IsAligned(addr));
     _ReadWriteBarrier();
     *addr = val;
     fenceSeqCst();
 }
 
 #ifdef _M_IX86
 namespace js { namespace jit {
 
 # define MSC_STOREOP(T)                              \
     template<>                                      \
     inline void                                     \
     AtomicOperations::storeSeqCst(T* addr, T val) { \
+        MOZ_ASSERT(IsAligned(addr));                \
         _ReadWriteBarrier();                        \
         T oldval = *addr;                           \
         for (;;) {                                  \
             T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr, \
-                                                         (__int64)oldval,         \
-                                                         (__int64)val);           \
+                                                         (__int64)val,            \
+                                                         (__int64)oldval);        \
             if (nextval == oldval)                  \
                 break;                              \
             oldval = nextval;                       \
         }                                           \
         _ReadWriteBarrier();                        \
     }
 
 MSC_STOREOP(int64_t)
@@ -122,30 +142,32 @@ MSC_STOREOP(uint64_t)
 
 } }
 #endif // _M_IX86
 
 #define MSC_EXCHANGEOP(T, U, xchgop)                            \
     template<> inline T                                         \
     AtomicOperations::exchangeSeqCst(T* addr, T val) {          \
         static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only"); \
+        MOZ_ASSERT(IsAligned(addr));                            \
         return (T)xchgop((U volatile*)addr, (U)val);            \
     }
 
 #ifdef _M_IX86
 # define MSC_EXCHANGEOP_CAS(T)                                       \
     template<> inline T                                              \
     AtomicOperations::exchangeSeqCst(T* addr, T val) {               \
         static_assert(sizeof(T) == 8, "8-byte variant");             \
+        MOZ_ASSERT(IsAligned(addr));                                 \
         _ReadWriteBarrier();                                         \
         T oldval = *addr;                                            \
         for (;;) {                                                   \
             T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr, \
-                                                         (__int64)oldval,         \
-                                                         (__int64)val);           \
+                                                         (__int64)val,            \
+                                                         (__int64)oldval);        \
             if (nextval == oldval)                                   \
                 break;                                               \
             oldval = nextval;                                        \
         }                                                            \
         _ReadWriteBarrier();                                         \
         return oldval;                                               \
     }
 #endif // _M_IX86
@@ -171,16 +193,17 @@ MSC_EXCHANGEOP(uint64_t, __int64, _Inter
 
 #undef MSC_EXCHANGEOP
 #undef MSC_EXCHANGEOP_CAS
 
 #define MSC_CAS(T, U, cmpxchg)                                          \
     template<> inline T                                                 \
     AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval) { \
         static_assert(sizeof(T) <= 8, "atomics supported up to 8 bytes only"); \
+        MOZ_ASSERT(IsAligned(addr));                                    \
         return (T)cmpxchg((U volatile*)addr, (U)newval, (U)oldval);     \
     }
 
 namespace js { namespace jit {
 
 MSC_CAS(int8_t, char, _InterlockedCompareExchange8)
 MSC_CAS(uint8_t, char, _InterlockedCompareExchange8)
 MSC_CAS(int16_t, short, _InterlockedCompareExchange16)
@@ -194,36 +217,38 @@ MSC_CAS(uint64_t, __int64, _InterlockedC
 
 #undef MSC_CAS
 
 #define MSC_FETCHADDOP(T, U, xadd)                                      \
     template<> inline T                                                 \
     AtomicOperations::fetchAddSeqCst(T* addr, T val) {                  \
         static_assert(sizeof(T) <= 8,                                   \
                       "atomics supported up to 8 bytes only");          \
+        MOZ_ASSERT(IsAligned(addr));                                    \
         return (T)xadd((U volatile*)addr, (U)val);                      \
     }                                                                   \
 
 #define MSC_FETCHSUBOP(T)                                            \
     template<> inline T                                              \
     AtomicOperations::fetchSubSeqCst(T* addr, T val) {               \
         return fetchAddSeqCst(addr, (T)(0-val));                     \
     }
 
 #ifdef _M_IX86
 # define MSC_FETCHADDOP_CAS(T)                                       \
     template<> inline T                                              \
     AtomicOperations::fetchAddSeqCst(T* addr, T val) {               \
         static_assert(sizeof(T) == 8, "8-byte variant");             \
+        MOZ_ASSERT(IsAligned(addr));                                 \
         _ReadWriteBarrier();                                         \
         T oldval = *addr;                                            \
         for (;;) {                                                   \
             T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr, \
-                                                         (__int64)oldval, \
-                                                         (__int64)(oldval + val)); \
+                                                         (__int64)(oldval + val), \
+                                                         (__int64)oldval);        \
             if (nextval == oldval)                                   \
                 break;                                               \
             oldval = nextval;                                        \
         }                                                            \
         _ReadWriteBarrier();                                         \
         return oldval;                                               \
     }
 #endif // _M_IX86
@@ -260,38 +285,40 @@ MSC_FETCHSUBOP(uint64_t)
 #undef MSC_FETCHADDOP_CAS
 #undef MSC_FETCHSUBOP
 
 #define MSC_FETCHBITOPX(T, U, name, op)                                 \
     template<> inline T                                                 \
     AtomicOperations::name(T* addr, T val) {                            \
         static_assert(sizeof(T) <= 8,                                   \
                       "atomics supported up to 8 bytes only");          \
+        MOZ_ASSERT(IsAligned(addr));                                    \
         return (T)op((U volatile*)addr, (U)val);                        \
     }
 
 #define MSC_FETCHBITOP(T, U, andop, orop, xorop)                        \
     MSC_FETCHBITOPX(T, U, fetchAndSeqCst, andop)                        \
     MSC_FETCHBITOPX(T, U, fetchOrSeqCst, orop)                          \
     MSC_FETCHBITOPX(T, U, fetchXorSeqCst, xorop)
 
 #ifdef _M_IX86
 # define AND_OP &
 # define OR_OP |
 # define XOR_OP ^
 # define MSC_FETCHBITOPX_CAS(T, name, OP)                            \
     template<> inline T                                              \
     AtomicOperations::name(T* addr, T val) {                         \
         static_assert(sizeof(T) == 8, "8-byte variant");             \
+        MOZ_ASSERT(IsAligned(addr));                                 \
         _ReadWriteBarrier();                                         \
         T oldval = *addr;                                            \
         for (;;) {                                                   \
-            T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr, \
-                                                         (__int64)oldval, \
-                                                         (__int64)(oldval OP val)); \
+            T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr,  \
+                                                         (__int64)(oldval OP val), \
+                                                         (__int64)oldval);         \
             if (nextval == oldval)                                   \
                 break;                                               \
             oldval = nextval;                                        \
         }                                                            \
         _ReadWriteBarrier();                                         \
         return oldval;                                               \
     }
 
@@ -325,24 +352,26 @@ MSC_FETCHBITOP(uint64_t, __int64, _Inter
 #undef MSC_FETCHBITOPX
 #undef MSC_FETCHBITOP_CAS
 #undef MSC_FETCHBITOP
 
 template<typename T>
 inline T
 js::jit::AtomicOperations::loadSafeWhenRacy(T* addr)
 {
+    MOZ_ASSERT(IsAligned(addr));
     return *addr;
 }
 
 #ifdef _M_IX86
 # define MSC_RACYLOADOP(T)                        \
     template<>                                    \
     inline T                                      \
     AtomicOperations::loadSafeWhenRacy(T* addr) { \
+        MOZ_ASSERT(IsAligned(addr));              \
         return (T)_InterlockedCompareExchange64((__int64 volatile*)addr, 0, 0); \
     }
 
 namespace js { namespace jit {
 
 MSC_RACYLOADOP(int64_t)
 MSC_RACYLOADOP(uint64_t)
 
@@ -350,31 +379,33 @@ MSC_RACYLOADOP(uint64_t)
 
 # undef MSC_RACYLOADOP
 #endif // _M_IX86
 
 template<typename T>
 inline void
 js::jit::AtomicOperations::storeSafeWhenRacy(T* addr, T val)
 {
+    MOZ_ASSERT(IsAligned(addr));
     *addr = val;
 }
 
 #ifdef _M_IX86
 namespace js { namespace jit {
 
 # define MSC_RACYSTOREOP(T)                               \
     template<>                                            \
     inline void                                           \
     AtomicOperations::storeSafeWhenRacy(T* addr, T val) { \
+        MOZ_ASSERT(IsAligned(addr));                      \
         T oldval = *addr;                                 \
         for (;;) {                                        \
             T nextval = (T)_InterlockedCompareExchange64((__int64 volatile*)addr, \
-                                                         (__int64)oldval,         \
-                                                         (__int64)val);           \
+                                                         (__int64)val,            \
+                                                         (__int64)oldval);        \
             if (nextval == oldval)                        \
                 break;                                    \
             oldval = nextval;                             \
         }                                                 \
     }
 
 MSC_RACYSTOREOP(int64_t)
 MSC_RACYSTOREOP(uint64_t)
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/hidePointer.cpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+* vim: set ts=8 sts=4 et sw=4 tw=99:
+*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Atomics.h"
+
+// This is an attempt to hide pointer values from the C++ compiler.  This might
+// not stand up in the presence of PGO but that's probably not important.
+
+// g_hidden_pointer is public so that it's limited what the compiler can assume
+// about it, and atomic so that we don't run afoul of the compiler's UB
+// analysis.
+
+mozilla::Atomic<void*> g_hidden_pointer;
+
+// Call this to install a pointer into the global.
+
+MOZ_NEVER_INLINE void setHiddenPointer(void* p)
+{
+    g_hidden_pointer = p;
+}
+
+// Call this to retrieve the pointer.
+
+MOZ_NEVER_INLINE void* getHiddenPointer()
+{
+    return g_hidden_pointer;
+}
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -7,16 +7,17 @@
 GeckoProgram('jsapi-tests', linkage=None)
 
 UNIFIED_SOURCES += [
     'selfTest.cpp',
     'testAddPropertyPropcache.cpp',
     'testArgumentsObject.cpp',
     'testArrayBuffer.cpp',
     'testArrayBufferView.cpp',
+    'testAtomicOperations.cpp',
     'testBoundFunction.cpp',
     'testBug604087.cpp',
     'testCallArgs.cpp',
     'testCallNonGenericMethodOnProxy.cpp',
     'testChromeBuffer.cpp',
     'testCloneScript.cpp',
     'testDateToLocaleString.cpp',
     'testDebugger.cpp',
@@ -106,16 +107,21 @@ UNIFIED_SOURCES += [
     'testXDR.cpp',
 ]
 
 SOURCES += [
     # There are clashing definitions of js::jit::AssemblerBuffer.
     'testAssemblerBuffer.cpp',
 ]
 
+SOURCES += [
+    # We don't want this in the C++ files with the test cases.
+    'hidePointer.cpp',
+]
+
 if CONFIG['ENABLE_ION']:
     UNIFIED_SOURCES += [
         'testJitDCEinGVN.cpp',
         'testJitFoldsTo.cpp',
         'testJitGVN.cpp',
         'testJitMacroAssembler.cpp',
         'testJitMoveEmitterCycles-mips32.cpp',
         'testJitMoveEmitterCycles.cpp',
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/testAtomicOperations.cpp
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+* vim: set ts=8 sts=4 et sw=4 tw=99:
+*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Alignment.h"
+#include "mozilla/Assertions.h"
+
+#include "jit/AtomicOperations.h"
+#include "jsapi-tests/tests.h"
+#include "vm/SharedMem.h"
+#include "wasm/WasmJS.h"
+
+using namespace js;
+
+// Machinery to disguise pointer addresses to the C++ compiler -- quite possibly
+// not thread-safe.
+
+extern void setHiddenPointer(void* p);
+extern void* getHiddenPointer();
+
+void* hidePointerValue(void* p) {
+    setHiddenPointer(p);
+    return getHiddenPointer();
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Lock-freedom predicates
+
+BEGIN_TEST(testAtomicLockFree8)
+{
+    // isLockfree8() must not return true if there are no 8-byte atomics
+
+    CHECK(!jit::AtomicOperations::isLockfree8() || jit::AtomicOperations::hasAtomic8());
+
+    // We must have lock-free 8-byte atomics on every platform where we support
+    // wasm, but we don't care otherwise.
+
+    CHECK(!wasm::HasSupport(cx) || jit::AtomicOperations::isLockfree8());
+    return true;
+}
+END_TEST(testAtomicLockFree8)
+
+// The JS spec requires specific behavior for all but 1 and 2.
+
+BEGIN_TEST(testAtomicLockFreeJS)
+{
+    CHECK(jit::AtomicOperations::isLockfreeJS(1) == true);  // false is allowed by spec but not in SpiderMonkey
+    CHECK(jit::AtomicOperations::isLockfreeJS(2) == true);  // ditto
+    CHECK(jit::AtomicOperations::isLockfreeJS(3) == false); // required
+    CHECK(jit::AtomicOperations::isLockfreeJS(4) == true);  // required
+    CHECK(jit::AtomicOperations::isLockfreeJS(5) == false); // required
+    CHECK(jit::AtomicOperations::isLockfreeJS(6) == false); // required
+    CHECK(jit::AtomicOperations::isLockfreeJS(7) == false); // required
+    CHECK(jit::AtomicOperations::isLockfreeJS(8) == false); // required
+    return true;
+}
+END_TEST(testAtomicLockFreeJS)
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Fence
+
+// This only tests that fenceSeqCst is defined and that it doesn't crash if we
+// call it, but it has no return value and its effect is not observable here.
+
+BEGIN_TEST(testAtomicFence)
+{
+    jit::AtomicOperations::fenceSeqCst();
+    return true;
+}
+END_TEST(testAtomicFence)
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Memory access primitives
+
+// These tests for the atomic load and store primitives ascertain that the
+// primitives are defined and that they load and store the values they should,
+// but not that the primitives are actually atomic wrt to the memory subsystem.
+
+// Memory for testing atomics.  This must be aligned to the natural alignment of
+// the type we're testing; for now, use 8-byte alignment for all.
+
+MOZ_ALIGNED_DECL(static uint8_t atomicMem[8], 8);
+MOZ_ALIGNED_DECL(static uint8_t atomicMem2[8], 8);
+
+// T is the primitive type we're testing, and A and B are references to constant
+// bindings holding values of that type.
+//
+// No bytes of A and B should be 0 or FF.  A+B and A-B must not overflow.
+
+#define ATOMIC_TESTS(T, A, B) \
+    T* q = (T*)hidePointerValue((void*)atomicMem);                      \
+    *q = A;                                                             \
+    SharedMem<T*> p = SharedMem<T*>::shared((T*)hidePointerValue((T*)atomicMem)); \
+    CHECK(*q == A);                                                     \
+    CHECK(jit::AtomicOperations::loadSeqCst(p) == A);                   \
+    CHECK(*q == A);                                                     \
+    jit::AtomicOperations::storeSeqCst(p, B);                           \
+    CHECK(*q == B);                                                     \
+    CHECK(jit::AtomicOperations::exchangeSeqCst(p, A) == B);            \
+    CHECK(*q == A);                                                     \
+    CHECK(jit::AtomicOperations::compareExchangeSeqCst(p, (T)0, (T)1) == A); /*failure*/ \
+    CHECK(*q == A);                                                     \
+    CHECK(jit::AtomicOperations::compareExchangeSeqCst(p, A, B) == A);  /*success*/ \
+    CHECK(*q == B);                                                     \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::fetchAddSeqCst(p, B) == A);            \
+    CHECK(*q == A+B);                                                   \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::fetchSubSeqCst(p, B) == A);            \
+    CHECK(*q == A-B);                                                   \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::fetchAndSeqCst(p, B) == A);            \
+    CHECK(*q == (A&B));                                                 \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::fetchOrSeqCst(p, B) == A);             \
+    CHECK(*q == (A|B));                                                 \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::fetchXorSeqCst(p, B) == A);            \
+    CHECK(*q == (A^B));                                                 \
+    *q = A;                                                             \
+    CHECK(jit::AtomicOperations::loadSafeWhenRacy(p) == A);             \
+    jit::AtomicOperations::storeSafeWhenRacy(p, B);                     \
+    CHECK(*q == B);                                                     \
+    T* q2 = (T*)hidePointerValue((void*)atomicMem2);                    \
+    SharedMem<T*> p2 = SharedMem<T*>::shared((T*)hidePointerValue((void*)atomicMem2)); \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::memcpySafeWhenRacy(p2, p, sizeof(T));        \
+    CHECK(*q2 == A);                                                    \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::memcpySafeWhenRacy(p2, p.unwrap(), sizeof(T));\
+    CHECK(*q2 == A);                                                    \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::memcpySafeWhenRacy(p2.unwrap(), p, sizeof(T));\
+    CHECK(*q2 == A);                                                    \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::memmoveSafeWhenRacy(p2, p, sizeof(T));       \
+    CHECK(*q2 == A);                                                    \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::podCopySafeWhenRacy(p2, p, 1);               \
+    CHECK(*q2 == A);                                                    \
+    *q = A;                                                             \
+    *q2 = B;                                                            \
+    jit::AtomicOperations::podMoveSafeWhenRacy(p2, p, 1);               \
+    CHECK(*q2 == A);                                                    \
+    return true
+
+BEGIN_TEST(testAtomicOperationsU8)
+{
+    const uint8_t A = 0xab;
+    const uint8_t B = 0x37;
+    ATOMIC_TESTS(uint8_t, A, B);
+}
+END_TEST(testAtomicOperationsU8)
+
+BEGIN_TEST(testAtomicOperationsI8)
+{
+    const int8_t A = 0x3b;
+    const int8_t B = 0x27;
+    ATOMIC_TESTS(int8_t, A, B);
+}
+END_TEST(testAtomicOperationsI8)
+
+BEGIN_TEST(testAtomicOperationsU16)
+{
+    const uint16_t A = 0xabdc;
+    const uint16_t B = 0x3789;
+    ATOMIC_TESTS(uint16_t, A, B);
+}
+END_TEST(testAtomicOperationsU16)
+
+BEGIN_TEST(testAtomicOperationsI16)
+{
+    const int16_t A = 0x3bdc;
+    const int16_t B = 0x2737;
+    ATOMIC_TESTS(int16_t, A, B);
+}
+END_TEST(testAtomicOperationsI16)
+
+BEGIN_TEST(testAtomicOperationsU32)
+{
+    const uint32_t A = 0xabdc0588;
+    const uint32_t B = 0x37891942;
+    ATOMIC_TESTS(uint32_t, A, B);
+}
+END_TEST(testAtomicOperationsU32)
+
+BEGIN_TEST(testAtomicOperationsI32)
+{
+    const int32_t A = 0x3bdc0588;
+    const int32_t B = 0x27371843;
+    ATOMIC_TESTS(int32_t, A, B);
+}
+END_TEST(testAtomicOperationsI32)
+
+BEGIN_TEST(testAtomicOperationsU64)
+{
+    if (!jit::AtomicOperations::hasAtomic8())
+        return true;
+
+    const uint64_t A(0x9aadf00ddeadbeef);
+    const uint64_t B(0x4eedbead1337f001);
+    ATOMIC_TESTS(uint64_t, A, B);
+}
+END_TEST(testAtomicOperationsU64)
+
+BEGIN_TEST(testAtomicOperationsI64)
+{
+    if (!jit::AtomicOperations::hasAtomic8())
+        return true;
+
+    const int64_t A(0x2aadf00ddeadbeef);
+    const int64_t B(0x4eedbead1337f001);
+    ATOMIC_TESTS(int64_t, A, B);
+}
+END_TEST(testAtomicOperationsI64)
+
+#undef ATOMIC_TESTS
--- a/js/src/vm/CharacterEncoding.cpp
+++ b/js/src/vm/CharacterEncoding.cpp
@@ -498,28 +498,41 @@ JS::StringIsASCII(const char* s)
 }
 
 bool
 JS::StringIsUTF8(const uint8_t* s, uint32_t length)
 {
     const uint8_t* limit = s + length;
     while (s < limit) {
         uint32_t len;
-        if ((*s & 0x80) == 0)
+        uint32_t min;
+        uint32_t n = *s;
+        if ((n & 0x80) == 0) {
             len = 1;
-        else if ((*s & 0xE0) == 0xC0)
+            min = 0;
+        } else if ((n & 0xE0) == 0xC0) {
             len = 2;
-        else if ((*s & 0xF0) == 0xE0)
+            min = 0x80;
+            n &= 0x1F;
+        } else if ((n & 0xF0) == 0xE0) {
             len = 3;
-        else if ((*s & 0xF8) == 0xF0)
+            min = 0x800;
+            n &= 0x0F;
+        } else if ((n & 0xF8) == 0xF0) {
             len = 4;
-        else
+            min = 0x10000;
+            n &= 0x07;
+        } else {
             return false;
+        }
         if (s + len > limit)
             return false;
         for (uint32_t i = 1; i < len; i++) {
             if ((s[i] & 0xC0) != 0x80)
                 return false;
+            n = (n << 6) | (s[i] & 0x3F);
         }
+        if (n < min || (0xD800 <= n && n < 0xE000) || n >= 0x110000)
+            return false;
         s += len;
     }
     return true;
 }
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -301,17 +301,17 @@ CancelOffThreadIonCompileLocked(const Co
             HelperThreadState().wait(lock, GlobalHelperThreadState::CONSUMER);
     } while (cancelled);
 
     /* Cancel code generation for any completed entries. */
     GlobalHelperThreadState::IonBuilderVector& finished = HelperThreadState().ionFinishedList(lock);
     for (size_t i = 0; i < finished.length(); i++) {
         jit::IonBuilder* builder = finished[i];
         if (IonBuilderMatches(selector, builder)) {
-            builder->script()->zone()->group()->numFinishedBuilders--;
+            builder->script()->zoneFromAnyThread()->group()->numFinishedBuilders--;
             jit::FinishOffThreadBuilder(nullptr, builder, lock);
             HelperThreadState().remove(finished, &i);
         }
     }
 
     /* Cancel lazy linking for pending builders (attached to the ionScript). */
     if (discardLazyLinkList) {
         MOZ_ASSERT(!selector.is<AllCompilations>());
--- a/js/src/vm/Scope.h
+++ b/js/src/vm/Scope.h
@@ -1095,25 +1095,25 @@ class BindingIter
     //
     //            imports - name
     // positional formals - environment slot or name
     //      other formals - environment slot or name
     //    top-level funcs - environment slot or name
     //               vars - environment slot or name
     //               lets - environment slot or name
     //             consts - environment slot or name
-    uint32_t positionalFormalStart_;
-    uint32_t nonPositionalFormalStart_;
-    uint32_t topLevelFunctionStart_;
-    uint32_t varStart_;
-    uint32_t letStart_;
-    uint32_t constStart_;
-    uint32_t length_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t positionalFormalStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t nonPositionalFormalStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t topLevelFunctionStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t varStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t letStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t constStart_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
 
-    uint32_t index_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t index_;
 
     enum Flags : uint8_t {
         CannotHaveSlots = 0,
         CanHaveArgumentSlots = 1 << 0,
         CanHaveFrameSlots = 1 << 1,
         CanHaveEnvironmentSlots = 1 << 2,
 
         // See comment in settle below.
@@ -1121,22 +1121,22 @@ class BindingIter
         IgnoreDestructuredFormalParameters = 1 << 4,
 
         // Truly I hate named lambdas.
         IsNamedLambda = 1 << 5
     };
 
     static const uint8_t CanHaveSlotsMask = 0x7;
 
-    uint8_t flags_;
-    uint16_t argumentSlot_;
-    uint32_t frameSlot_;
-    uint32_t environmentSlot_;
+    MOZ_INIT_OUTSIDE_CTOR uint8_t flags_;
+    MOZ_INIT_OUTSIDE_CTOR uint16_t argumentSlot_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t frameSlot_;
+    MOZ_INIT_OUTSIDE_CTOR uint32_t environmentSlot_;
 
-    BindingName* names_;
+    MOZ_INIT_OUTSIDE_CTOR BindingName* names_;
 
     void init(uint32_t positionalFormalStart, uint32_t nonPositionalFormalStart,
               uint32_t topLevelFunctionStart, uint32_t varStart,
               uint32_t letStart, uint32_t constStart,
               uint8_t flags, uint32_t firstFrameSlot, uint32_t firstEnvironmentSlot,
               BindingName* names, uint32_t length)
     {
         positionalFormalStart_ = positionalFormalStart;
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -4254,17 +4254,17 @@ BaseCompiler::emitQuotientI64()
     int64_t c;
     uint_fast8_t power;
     if (popConstPositivePowerOfTwoI64(&c, &power, 0)) {
         if (power != 0) {
             RegI64 r = popI64();
             Label positive;
             masm.branchTest64(Assembler::NotSigned, r, r, Register::Invalid(),
                               &positive);
-            masm.add64(Imm32(c-1), r);
+            masm.add64(Imm64(c-1), r);
             masm.bind(&positive);
 
             masm.rshift64Arithmetic(Imm32(power & 63), r);
             pushI64(r);
         }
     } else {
         bool isConst = peekConstI64(&c);
         RegI64 r0, r1;
--- a/layout/reftests/bugs/481948-2-ref.html
+++ b/layout/reftests/bugs/481948-2-ref.html
@@ -1,14 +1,14 @@
 <html>
 <head>
 <style type="text/css">
 body {
   /* try for some likely fonts that might implement the "fi" ligature */
-  font-family: Times, Calibri, Palatino Linotype, DejaVu Serif, serif;
+  font-family: Times, Calibri, PalatinoLinotype, DejaVuSerif, serif;
   font-size: 40pt;
 }
 .R {
   color: #FF0000;
 }
 .G {
   color: #00FF00;
 }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/legacy-family-names-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8>
+<style>
+body { font-family: Avenir Next, serif; font-weight: 900; }
+</style>
+<body>
+Hello world
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/legacy-family-names-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8>
+<style>
+body { font-family: Avenir Next Heavy, serif; }
+</style>
+<body>
+Hello world
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/legacy-family-names-2-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8>
+<style>
+body { font-family: Arial, serif; font-weight: 900; }
+</style>
+<body>
+Hello world
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/legacy-family-names-2.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8>
+<style>
+body { font-family: Arial Black, serif; }
+</style>
+<body>
+Hello world
+</body>
--- a/layout/reftests/font-matching/reftest.list
+++ b/layout/reftests/font-matching/reftest.list
@@ -128,8 +128,14 @@ skip-if(!cocoaWidget) HTTP(..) != apple-
 # random-if(!OSX) == system-generic-fallback-1.html system-generic-fallback-1-ref.html
 # random-if(!OSX) == system-generic-fallback-2.html system-generic-fallback-2-ref.html
 # random-if(!OSX) == system-generic-fallback-3.html system-generic-fallback-3-ref.html
 # random-if(!OSX) == system-generic-fallback-4.html system-generic-fallback-4-ref.html
 # random-if(!OSX) != system-generic-fallback-ko.html system-generic-fallback-ja.html
 # random-if(!OSX) != system-generic-fallback-zh-tw.html system-generic-fallback-ja.html
 # random-if(!OSX) != system-generic-fallback-zh-cn.html system-generic-fallback-ja.html
 # random-if(!OSX) != system-generic-fallback-zh-tw.html system-generic-fallback-zh-cn.html
+
+# Tests for legacy font family name (GDI-model families) matching;
+# these depend on specific fonts that are available as standard on macOS and Windows,
+# and are not expected to pass on platforms that don't have those same fonts.
+skip-if(!cocoaWidget) == legacy-family-names-1.html legacy-family-names-1-ref.html
+skip-if(!winWidget) == legacy-family-names-2.html legacy-family-names-2-ref.html
--- a/mobile/android/components/extensions/ext-utils.js
+++ b/mobile/android/components/extensions/ext-utils.js
@@ -650,16 +650,22 @@ class Window extends WindowBase {
 
   * getTabs() {
     let {tabManager} = this.extension;
 
     for (let nativeTab of this.window.BrowserApp.tabs) {
       yield tabManager.getWrapper(nativeTab);
     }
   }
+
+  get activeTab() {
+    let {tabManager} = this.extension;
+
+    return tabManager.getWrapper(this.window.BrowserApp.selectedTab);
+  }
 }
 
 Object.assign(global, {Tab, TabContext, Window});
 
 class TabManager extends TabManagerBase {
   get(tabId, default_ = undefined) {
     let nativeTab = tabTracker.getTab(tabId, default_);
 
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -1269,32 +1269,35 @@ Http2Stream::UpdatePriorityDependency()
   // streams for folowers (images) depend on b
   // default streams (xhr, async js) depend on 5
   // explicit bg streams (beacon, etc..) depend on 7
   // spculative bg streams depend on 9
   // urgent-start streams depend on d
 
   mPriorityDependency = GetPriorityDependencyFromTransaction(trans);
 
-  if (mTransactionTabId != mCurrentForegroundTabOuterContentWindowId &&
+  if (gHttpHandler->ActiveTabPriority() &&
+      mTransactionTabId != mCurrentForegroundTabOuterContentWindowId &&
       mPriorityDependency != Http2Session::kUrgentStartGroupID) {
     LOG3(("Http2Stream::UpdatePriorityDependency %p "
           " depends on background group for trans %p\n",
           this, trans));
     mPriorityDependency = Http2Session::kBackgroundGroupID;
   }
 
   LOG3(("Http2Stream::UpdatePriorityDependency %p "
         "depends on stream 0x%X\n",
         this, mPriorityDependency));
 }
 
 void
 Http2Stream::TopLevelOuterContentWindowIdChanged(uint64_t windowId)
 {
+  MOZ_ASSERT(gHttpHandler->ActiveTabPriority());
+
   LOG3(("Http2Stream::TopLevelOuterContentWindowIdChanged "
         "%p windowId=%" PRIx64 "\n",
         this, windowId));
 
   mCurrentForegroundTabOuterContentWindowId = windowId;
 
   if (!mSession->UseH2Deps()) {
     return;
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3468,17 +3468,19 @@ nsHttpConnectionMgr::OnMsgUpdateCurrentT
     }
 
     bool activeTabWasLoading = mActiveTabTransactionsExist;
     bool activeTabIdChanged = mCurrentTopLevelOuterContentWindowId != winId;
 
     uint64_t previousWindowId = mCurrentTopLevelOuterContentWindowId;
     mCurrentTopLevelOuterContentWindowId = winId;
 
-    NotifyConnectionOfWindowIdChange(previousWindowId);
+    if (gHttpHandler->ActiveTabPriority()) {
+        NotifyConnectionOfWindowIdChange(previousWindowId);
+    }
 
     LOG(("nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId"
          " id=%" PRIx64 "\n",
          mCurrentTopLevelOuterContentWindowId));
 
     nsTArray<RefPtr<nsHttpTransaction>> *transactions = nullptr;
 
     if (activeTabIdChanged) {
--- a/parser/htmlparser/nsElementTable.cpp
+++ b/parser/htmlparser/nsElementTable.cpp
@@ -169,24 +169,33 @@ const nsHTMLElement gHTMLElements[] = {
   ELEM(instruction, kFlowEntity,                 false)
   ELEM(userdefined, (kFlowEntity|kHeadMisc),     false)
 };
 
 #undef ELEM
 
 /*********************************************************************************************/
 
-bool nsHTMLElement::IsContainer(eHTMLTags aChild)
+bool nsHTMLElement::IsMemberOf(int32_t aSet) const
 {
-  return !gHTMLElements[aChild].mLeaf;
+  return TestBits(aSet, mParentBits);
 }
 
-bool nsHTMLElement::IsMemberOf(int32_t aSet) const
+bool nsHTMLElement::IsContainer(eHTMLTags aId)
 {
-  return TestBits(aSet,mParentBits);
+  return !gHTMLElements[aId].mLeaf;
+}
+
+bool nsHTMLElement::IsBlock(eHTMLTags aId)
+{
+  return gHTMLElements[aId].IsMemberOf(kBlock)       ||
+         gHTMLElements[aId].IsMemberOf(kBlockEntity) ||
+         gHTMLElements[aId].IsMemberOf(kHeading)     ||
+         gHTMLElements[aId].IsMemberOf(kPreformatted)||
+         gHTMLElements[aId].IsMemberOf(kList);
 }
 
 #ifdef DEBUG
 void CheckElementTable()
 {
   for (eHTMLTags t = eHTMLTag_unknown; t <= eHTMLTag_userdefined; t = eHTMLTags(t + 1)) {
     NS_ASSERTION(gHTMLElements[t].mTagID == t, "gHTMLElements entries does match tag list.");
   }
--- a/parser/htmlparser/nsElementTable.h
+++ b/parser/htmlparser/nsElementTable.h
@@ -82,13 +82,14 @@ struct nsHTMLElement {
 
 #ifdef DEBUG
   eHTMLTags       mTagID;
 #endif
   int             mParentBits;        //defines groups that can contain this element
   bool            mLeaf;
 
   static  bool    IsContainer(eHTMLTags aTag);
+  static  bool    IsBlock(eHTMLTags aTag);
 };
 
 extern const nsHTMLElement gHTMLElements[];
 
 #endif
--- a/parser/htmlparser/nsParserService.cpp
+++ b/parser/htmlparser/nsParserService.cpp
@@ -45,21 +45,12 @@ nsParserService::IsContainer(int32_t aId
   aIsContainer = nsHTMLElement::IsContainer((eHTMLTags)aId);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsParserService::IsBlock(int32_t aId, bool& aIsBlock) const
 {
-  if((aId>eHTMLTag_unknown) && (aId<eHTMLTag_userdefined)) {
-    aIsBlock=((gHTMLElements[aId].IsMemberOf(kBlock))       ||
-              (gHTMLElements[aId].IsMemberOf(kBlockEntity)) ||
-              (gHTMLElements[aId].IsMemberOf(kHeading))     ||
-              (gHTMLElements[aId].IsMemberOf(kPreformatted))||
-              (gHTMLElements[aId].IsMemberOf(kList)));
-  }
-  else {
-    aIsBlock = false;
-  }
+  aIsBlock = nsHTMLElement::IsBlock((eHTMLTags)aId);
 
   return NS_OK;
 }
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1135,9 +1135,9 @@ static const TransportSecurityPreload kP
   { "za.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
   { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
 };
 
 // Pinning Preload List Length = 479;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1512927270423000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1513012774620000);
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -865,16 +865,19 @@ getKeaGroupName(uint32_t aKeaGroup)
 static nsCString
 getSignatureName(uint32_t aSignatureScheme)
 {
   nsCString signatureName;
   switch (aSignatureScheme) {
     case ssl_sig_none:
       signatureName = NS_LITERAL_CSTRING("none");
       break;
+    case ssl_sig_rsa_pkcs1_sha1:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA1");
+      break;
     case ssl_sig_rsa_pkcs1_sha256:
       signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA256");
       break;
     case ssl_sig_rsa_pkcs1_sha384:
       signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA384");
       break;
     case  ssl_sig_rsa_pkcs1_sha512:
       signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA512");
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -35,17 +35,16 @@ 126ium.moe: could not connect to host
 127011-networks.ch: could not connect to host
 12vpn.org: could not connect to host
 12vpnchina.com: could not connect to host
 1536.cf: could not connect to host
 163pwd.com: could not connect to host
 166166.com: could not connect to host
 16deza.com: did not receive HSTS header
 16packets.com: could not connect to host
-173vpn.cn: could not connect to host
 188betwarriors.co.uk: could not connect to host
 188trafalgar.ca: did not receive HSTS header
 195gm.com: could not connect to host
 1a-jva.de: could not connect to host
 1atic.com: could not connect to host
 1cover.com: could not connect to host
 1k8b.com: could not connect to host
 1password.com: did not receive HSTS header
@@ -61,17 +60,17 @@ 24sihu.com: could not connect to host
 25daysof.io: could not connect to host
 2859cc.com: could not connect to host
 2acbi-asso.fr: did not receive HSTS header
 2bizi.ru: could not connect to host
 2brokegirls.org: could not connect to host
 2carpros.com: did not receive HSTS header
 2intermediate.co.uk: did not receive HSTS header
 2or3.tk: could not connect to host
-2ss.jp: could not connect to host
+2ss.jp: did not receive HSTS header
 300651.ru: did not receive HSTS header
 300m.com: did not receive HSTS header
 300mbmovies4u.cc: could not connect to host
 301.website: could not connect to host
 302.nyc: could not connect to host
 314chan.org: could not connect to host
 32ph.com: could not connect to host
 33drugstore.com: did not receive HSTS header
@@ -79,17 +78,16 @@ 341.mg: could not connect to host
 3555aa.com: could not connect to host
 35792.de: could not connect to host
 360gradus.com: did not receive HSTS header
 365.or.jp: could not connect to host
 368mibn.com: could not connect to host
 3778xl.com: did not receive HSTS header
 38sihu.com: could not connect to host
 39sihu.com: could not connect to host
-3ags.de: did not receive HSTS header
 3chit.cf: could not connect to host
 3click-loan.com: could not connect to host
 3d-bastler.de: could not connect to host
 3dcart.com: did not receive HSTS header
 3delivered.com: could not connect to host
 3dproteinimaging.com: did not receive HSTS header
 3sreporting.com: did not receive HSTS header
 404.sh: max-age too low: 0
@@ -103,44 +101,44 @@ 4azino777.ru: could not connect to host
 4cclothing.com: could not connect to host
 4elements.com: did not receive HSTS header
 4eyes.ch: did not receive HSTS header
 4miners.net: could not connect to host
 4ourty2.org: did not receive HSTS header
 4sqsu.eu: could not connect to host
 4w-performers.link: could not connect to host
 50millionablaze.org: could not connect to host
-517vpn.cn: could not connect to host
 540.co: did not receive HSTS header
 54bf.com: could not connect to host
 56ct.com: could not connect to host
-5ece.de: could not connect to host
 5piecesofadvice.com: could not connect to host
 5w5.la: could not connect to host
 60ych.net: did not receive HSTS header
 6120.eu: did not receive HSTS header
 64616e.xyz: could not connect to host
 69square.com: could not connect to host
 6w6.la: could not connect to host
 721av.com: max-age too low: 2592000
 7777av.co: did not receive HSTS header
 7kovrikov.ru: did not receive HSTS header
 7nw.eu: could not connect to host
 7thheavenrestaurant.com: could not connect to host
+8.net.co: could not connect to host
 808.lv: did not receive HSTS header
 83i.net: could not connect to host
 88.to: could not connect to host
 888lu.co: could not connect to host
 89955.com: could not connect to host
 90smthng.com: could not connect to host
 911911.pw: could not connect to host
 922.be: could not connect to host
 960news.ca: could not connect to host
 9651678.ru: could not connect to host
 99511.fi: did not receive HSTS header
+99998522.com: did not receive HSTS header
 9point6.com: could not connect to host
 9tolife.be: did not receive HSTS header
 a-intel.com: could not connect to host
 a-plus.space: could not connect to host
 a-rickroll-n.pw: could not connect to host
 a-theme.com: could not connect to host
 a.ai: could not connect to host
 a1-autopartsglasgow.com: did not receive HSTS header
@@ -304,16 +302,21 @@ alenan.org: could not connect to host
 alessandro.pw: did not receive HSTS header
 alethearose.com: did not receive HSTS header
 alexandre.sh: did not receive HSTS header
 alexbaker.org: did not receive HSTS header
 alexberts.ch: did not receive HSTS header
 alexdaulby.com: could not connect to host
 alexei.su: could not connect to host
 alexisabarca.com: could not connect to host
+alexismeza.com: could not connect to host
+alexismeza.com.mx: could not connect to host
+alexismeza.dk: could not connect to host
+alexismeza.es: could not connect to host
+alexismeza.nl: could not connect to host
 alexvetter.de: could not connect to host
 alfa24.pro: could not connect to host
 alilialili.ga: could not connect to host
 alisync.com: could not connect to host
 alittlebitcheeky.com: did not receive HSTS header
 aljmz.com: did not receive HSTS header
 alkami.com: could not connect to host
 all-subtitles.com: could not connect to host
@@ -350,16 +353,21 @@ alzashop.com: did not receive HSTS heade
 am8888.top: could not connect to host
 amandaonishi.com: could not connect to host
 amavis.org: did not receive HSTS header
 amcvega.com: did not receive HSTS header
 amerhd.com: did not receive HSTS header
 american-truck-simulator.de: could not connect to host
 american-truck-simulator.net: could not connect to host
 americanworkwear.nl: did not receive HSTS header
+ameza.co.uk: could not connect to host
+ameza.com.mx: could not connect to host
+ameza.io: could not connect to host
+ameza.me: could not connect to host
+ameza.net: could not connect to host
 amigogeek.net: could not connect to host
 amilx.com: could not connect to host
 amilx.org: could not connect to host
 amimoto-ami.com: max-age too low: 3153600
 amishsecurity.com: could not connect to host
 amitse.com: did not receive HSTS header
 amitube.com: could not connect to host
 amlvfs.net: could not connect to host
@@ -367,17 +375,17 @@ ammoulianiapartments.com: did not receiv
 amo-entreprise-et-commerce.fr: could not connect to host
 amoory.com: could not connect to host
 amoozesh98.com: did not receive HSTS header
 amorimendes.com.br: did not receive HSTS header
 amri.nl: did not receive HSTS header
 anabol.nl: could not connect to host
 anadoluefessporkulubu.org: could not connect to host
 anagra.ms: could not connect to host
-analytic-s.ml: could not connect to host
+analytic-s.ml: did not receive HSTS header
 analyticsinmotion.net: could not connect to host
 ancientkarma.com: could not connect to host
 andere-gedanken.net: max-age too low: 10
 anderslind.dk: could not connect to host
 andiplusben.com: could not connect to host
 andre-ballensiefen.de: did not receive HSTS header
 andreasbreitenlohner.de: did not receive HSTS header
 andreasfritz-fotografie.de: could not connect to host
@@ -440,17 +448,16 @@ antscript.com: did not receive HSTS head
 anttitenhunen.com: could not connect to host
 anycoin.me: could not connect to host
 aocast.info: could not connect to host
 aojf.fr: could not connect to host
 aozora.moe: could not connect to host
 apachelounge.com: did not receive HSTS header
 apaginastore.com.br: did not receive HSTS header
 aparaatti.org: could not connect to host
-apartmanicg.me: did not receive HSTS header
 apeasternpower.com: could not connect to host
 api.mega.co.nz: could not connect to host
 apibot.de: could not connect to host
 apis.google.com: did not receive HSTS header (error ignored - included regardless)
 apis.world: could not connect to host
 apm.com.tw: did not receive HSTS header
 apmg-certified.com: did not receive HSTS header
 apmg-cyber.com: did not receive HSTS header
@@ -474,47 +481,47 @@ apps-for-fishing.com: could not connect 
 appsbystudio.co.uk: did not receive HSTS header
 appsdash.io: could not connect to host
 aqilacademy.com.au: could not connect to host
 aquaundine.net: could not connect to host
 aquilalab.com: could not connect to host
 arabdigitalexpression.org: did not receive HSTS header
 aradulconteaza.ro: could not connect to host
 aran.me.uk: could not connect to host
+arbeitslosenverwaltung.de: did not receive HSTS header
 arboineuropa.nl: did not receive HSTS header
 arboleda-hurtado.com: could not connect to host
 arbu.eu: max-age too low: 2419200
 arcbit.io: could not connect to host
 ardao.me: could not connect to host
 ardorlabs.se: could not connect to host
 arewedubstepyet.com: could not connect to host
 argennon.xyz: could not connect to host
-argh.io: could not connect to host
 arguggi.co.uk: could not connect to host
 ariacreations.net: did not receive HSTS header
 aristilabs.com: did not receive HSTS header
 arlen.io: could not connect to host
 arlen.se: could not connect to host
-arlet.click: could not connect to host
 armingrodon.de: max-age too low: 0
+arminpech.de: could not connect to host
 armor.com: did not receive HSTS header
 armored.ninja: could not connect to host
 armory.consulting: could not connect to host
 armory.supplies: could not connect to host
 armsday.com: could not connect to host
 armytricka.cz: did not receive HSTS header
+aromaclub.nl: did not receive HSTS header
 aroundme.org: did not receive HSTS header
 arpa.ph: did not receive HSTS header
 arpr.co: did not receive HSTS header
 arrayify.com: could not connect to host
 arrow-api.nl: did not receive HSTS header
 arrow-cloud.nl: could not connect to host
 arrowfunction.com: could not connect to host
 ars-design.net: could not connect to host
-art2web.net: could not connect to host
 artartefatos.com.br: did not receive HSTS header
 artesupra.com: did not receive HSTS header
 arthan.me: could not connect to host
 artifex21.com: could not connect to host
 artifex21.fr: could not connect to host
 artiming.com: could not connect to host
 artisavotins.com: could not connect to host
 artistnetwork.nl: did not receive HSTS header
@@ -602,16 +609,17 @@ auvernet.org: could not connect to host
 aux-arts-de-la-table.com: did not receive HSTS header
 auxetek.se: could not connect to host
 auxiliumincrementum.co.uk: could not connect to host
 av.de: did not receive HSTS header
 avantmfg.com: did not receive HSTS header
 avec-ou-sans-ordonnance.fr: could not connect to host
 avepol.cz: did not receive HSTS header
 avepol.eu: did not receive HSTS header
+avi9526.pp.ua: could not connect to host
 aviacao.pt: did not receive HSTS header
 aviodeals.com: could not connect to host
 avonlearningcampus.com: could not connect to host
 avqueen.cn: did not receive HSTS header
 avus-automobile.com: did not receive HSTS header
 awanderlustadventure.com: did not receive HSTS header
 awg-mode.de: did not receive HSTS header
 aww.moe: did not receive HSTS header
@@ -639,33 +647,34 @@ babysaying.me: could not connect to host
 bacchanallia.com: could not connect to host
 back-bone.nl: did not receive HSTS header
 backschues.net: did not receive HSTS header
 bad.show: could not connect to host
 badcronjob.com: could not connect to host
 badenhard.eu: could not connect to host
 badkamergigant.com: could not connect to host
 badlink.org: could not connect to host
-baff.lu: did not receive HSTS header
+baff.lu: could not connect to host
 bagiobella.com: max-age too low: 0
 baiduaccount.com: could not connect to host
 bailbondsaffordable.com: did not receive HSTS header
 bair.io: could not connect to host
 bakingstone.com: could not connect to host
 bakkerdesignandbuild.com: did not receive HSTS header
 balcan-underground.net: could not connect to host
 baldwinkoo.com: could not connect to host
 baleares.party: could not connect to host
 balloonphp.com: could not connect to host
 bambooforest.nl: could not connect to host
 bananabandy.com: could not connect to host
 banbanchs.com: could not connect to host
 banchethai.com: did not receive HSTS header
 bandb.xyz: could not connect to host
 bandrcrafts.com: did not receive HSTS header
+bangzafran.com: did not receive HSTS header
 banqingdiao.com: could not connect to host
 barely.sexy: did not receive HSTS header
 bariller.fr: could not connect to host
 barrelhead.org: could not connect to host
 barshout.co.uk: could not connect to host
 barss.io: could not connect to host
 barunisystems.com: could not connect to host
 bashcode.ninja: could not connect to host
@@ -719,17 +728,19 @@ beetleroadstories.com: could not connect
 befundup.com: could not connect to host
 behere.be: could not connect to host
 beholdthehurricane.com: could not connect to host
 beichtgenerator.de: did not receive HSTS header
 beier.io: could not connect to host
 beikeil.de: did not receive HSTS header
 belairsewvac.com: could not connect to host
 belegit.org: could not connect to host
+belewpictures.com: could not connect to host
 belize-firmengruendung.com: could not connect to host
+belliash.eu.org: did not receive HSTS header
 belltower.io: could not connect to host
 belmontprom.com: could not connect to host
 bemyvictim.com: max-age too low: 2678400
 bendechrai.com: did not receive HSTS header
 beneffy.com: did not receive HSTS header
 benjakesjohnson.com: could not connect to host
 benk.press: could not connect to host
 benny003.de: did not receive HSTS header
@@ -778,16 +789,17 @@ bezprawnik.pl: did not receive HSTS head
 bf.am: max-age too low: 0
 bfear.com: could not connect to host
 bfelob.gov: max-age too low: 86400
 bffm.biz: could not connect to host
 bgcparkstad.nl: did not receive HSTS header
 bgmn.net: max-age too low: 0
 bhatia.at: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 bi.search.yahoo.com: did not receive HSTS header
+biblerhymes.com: did not receive HSTS header
 bidon.ca: did not receive HSTS header
 bieberium.de: could not connect to host
 biego.cn: did not receive HSTS header
 bienenblog.cc: could not connect to host
 bierbringer.at: could not connect to host
 big-black.de: did not receive HSTS header
 bigbbqbrush.bid: could not connect to host
 bigbrownpromotions.com.au: did not receive HSTS header
@@ -799,18 +811,16 @@ bildiri.ci: did not receive HSTS header
 bildschirmflackern.de: did not receive HSTS header
 biletua.de: could not connect to host
 billin.net: did not receive HSTS header
 billkiss.com: could not connect to host
 billninja.com: did not receive HSTS header
 billrusling.com: could not connect to host
 bimbo.com: did not receive HSTS header
 binaryabstraction.com: could not connect to host
-binaryappdev.com: did not receive HSTS header
-binaryfigments.com: could not connect to host
 binderapp.net: could not connect to host
 biofam.ru: did not receive HSTS header
 bioknowme.com: did not receive HSTS header
 bionicspirit.com: could not connect to host
 biophysik-ssl.de: did not receive HSTS header
 biou.me: could not connect to host
 birkman.com: did not receive HSTS header
 bisterfeldt.com: could not connect to host
@@ -832,17 +842,16 @@ bitnet.io: did not receive HSTS header
 bitrage.de: could not connect to host
 bitraum.io: did not receive HSTS header
 bitsafe.systems: could not connect to host
 bitvigor.com: could not connect to host
 bitwrought.net: could not connect to host
 bivsi.com: could not connect to host
 bizcms.com: did not receive HSTS header
 bizon.sk: did not receive HSTS header
-biztok.eu: could not connect to host
 bkb-skandal.ch: could not connect to host
 black-armada.com: could not connect to host
 black-armada.com.pl: could not connect to host
 black-armada.pl: could not connect to host
 black-octopus.ru: did not receive HSTS header
 blackburn.link: could not connect to host
 blackdesertsp.com: could not connect to host
 blacklane.com: did not receive HSTS header
@@ -882,17 +891,16 @@ bluescloud.xyz: could not connect to hos
 bluetenmeer.com: did not receive HSTS header
 bluketing.com: did not receive HSTS header
 bluserv.net: could not connect to host
 blutroyal.de: could not connect to host
 bm-trading.nl: did not receive HSTS header
 bnhlibrary.com: did not receive HSTS header
 board-buy.ru: could not connect to host
 boardgamegeeks.de: could not connect to host
-boboolo.com: could not connect to host
 bodo-wolff.de: could not connect to host
 bodyblog.nl: did not receive HSTS header
 bodybuilding-legends.com: could not connect to host
 bodyweightsolution.com: could not connect to host
 boensou.com: did not receive HSTS header
 bogosity.se: could not connect to host
 bohan.life: could not connect to host
 boiadeirodeberna.com: could not connect to host
@@ -934,44 +942,42 @@ bran.cc: could not connect to host
 branchtrack.com: did not receive HSTS header
 brandnewdays.nl: could not connect to host
 brandon.so: could not connect to host
 brandred.net: could not connect to host
 brandspray.com: could not connect to host
 brasilmorar.com: did not receive HSTS header
 bratteng.xyz: could not connect to host
 bravz.de: could not connect to host
-brefy.com: did not receive HSTS header
 bregnedalsystems.dk: did not receive HSTS header
 bremensaki.com: max-age too low: 2592000
 brettabel.com: could not connect to host
 brickoo.com: could not connect to host
 brickyardbuffalo.com: did not receive HSTS header
 bridholm.se: could not connect to host
 brightstarkids.com.au: did not receive HSTS header
 brilliantbuilders.co.uk: did not receive HSTS header
 britzer-toner.de: did not receive HSTS header
 brks.xyz: could not connect to host
 broken-oak.com: could not connect to host
 brookechase.com: did not receive HSTS header
 browserid.org: could not connect to host
 brunix.net: did not receive HSTS header
-brunohenc.from.hr: could not connect to host
+brunohenc.from.hr: did not receive HSTS header
 brunoonline.co.uk: could not connect to host
 brunoramos.com: could not connect to host
 brunoramos.org: could not connect to host
 brunosouza.org: could not connect to host
 bryn.xyz: could not connect to host
 bsagan.fr: could not connect to host
 bsdtips.com: could not connect to host
 bsdug.org: could not connect to host
 bsociabl.com: could not connect to host
 btc-e.com: did not receive HSTS header
 btcdlc.com: could not connect to host
-buben.tech: could not connect to host
 bubulazi.com: did not receive HSTS header
 bubulazy.com: did not receive HSTS header
 buch-cuber.de: could not connect to host
 buchheld.at: did not receive HSTS header
 bucket.tk: could not connect to host
 budgetthostels.nl: did not receive HSTS header
 budskap.eu: could not connect to host
 buenosairesestetica.com.ar: could not connect to host
@@ -1096,38 +1102,35 @@ campbellsoftware.co.uk: could not connec
 campfire.co.il: did not receive HSTS header
 campusdrugprevention.gov: did not receive HSTS header
 camsanalytics.com: could not connect to host
 canadiangamblingchoice.com: did not receive HSTS header
 cancelmyprofile.com: did not receive HSTS header
 candicontrols.com: did not receive HSTS header
 candratech.com: could not connect to host
 candygirl.shop: could not connect to host
-candylion.rocks: could not connect to host
 cannyfoxx.me: could not connect to host
 canyonshoa.com: did not receive HSTS header
 capecycles.co.za: did not receive HSTS header
 capeyorkfire.com.au: did not receive HSTS header
 capitaltg.com: could not connect to host
 capsogusto.com: did not receive HSTS header
 captchatheprize.com: could not connect to host
 captianseb.de: could not connect to host
 captivatedbytabrett.com: could not connect to host
 capturethepen.co.uk: could not connect to host
 car-navi.ph: did not receive HSTS header
-car-shop.top: could not connect to host
 carano-service.de: did not receive HSTS header
 caraudio69.cz: could not connect to host
 card-toka.jp: did not receive HSTS header
 cardoni.net: did not receive HSTS header
 cardstream.com: did not receive HSTS header
 cardurl.com: did not receive HSTS header
 careerstuds.com: could not connect to host
 caringladies.org: could not connect to host
-carlandfaith.com: could not connect to host
 carlo.mx: did not receive HSTS header
 carlolly.co.uk: could not connect to host
 carlosalves.info: could not connect to host
 carloshmm.stream: could not connect to host
 carpliyz.com: could not connect to host
 carroarmato0.be: could not connect to host
 carsforbackpackers.com: could not connect to host
 carwashvapeur.be: could not connect to host
@@ -1146,34 +1149,34 @@ cata.ga: could not connect to host
 catarsisvr.com: could not connect to host
 catinmay.com: did not receive HSTS header
 catnapstudios.com: could not connect to host
 caulong-ao.net: could not connect to host
 cavaleria.ro: did not receive HSTS header
 caveclan.org: did not receive HSTS header
 cavedevs.de: could not connect to host
 cavedroid.xyz: could not connect to host
-cbdev.de: could not connect to host
 cbengineeringinc.com: did not receive HSTS header
 cbhq.net: could not connect to host
 ccblog.de: did not receive HSTS header
 cctech.ph: could not connect to host
 cd.search.yahoo.com: did not receive HSTS header
 cd0.us: could not connect to host
 cdcpartners.gov: could not connect to host
-cdlcenter.com: could not connect to host
 cdnb.co: could not connect to host
 cdndepo.com: could not connect to host
 cdreporting.co.uk: did not receive HSTS header
+cee.io: could not connect to host
 celeirorural.com.br: did not receive HSTS header
 celina-reads.de: did not receive HSTS header
 cellsites.nz: could not connect to host
 centralpoint.be: did not receive HSTS header
 centralpoint.nl: did not receive HSTS header
 centralvacsunlimited.net: could not connect to host
+centrationgame.com: could not connect to host
 centrepoint-community.com: could not connect to host
 centsforchange.net: did not receive HSTS header
 ceritamalam.net: could not connect to host
 cerize.love: could not connect to host
 cert.se: max-age too low: 2628001
 certifi.io: could not connect to host
 certmgr.org: could not connect to host
 cesal.net: could not connect to host
@@ -1192,16 +1195,17 @@ chainmonitor.com: could not connect to h
 championsofregnum.com: did not receive HSTS header
 chandlerredding.com: did not receive HSTS header
 changetip.com: did not receive HSTS header
 chaos.fail: did not receive HSTS header
 chaoswebs.net: did not receive HSTS header
 charge.co: could not connect to host
 charityclear.com: did not receive HSTS header
 charitystreet.co.uk: could not connect to host
+charlipopkids.com.au: could not connect to host
 charnleyhouse.co.uk: max-age too low: 604800
 charp.eu: could not connect to host
 chartpen.com: could not connect to host
 chartstoffarm.de: did not receive HSTS header
 chaska.co.za: did not receive HSTS header
 chat-porc.eu: did not receive HSTS header
 chatbot.me: did not receive HSTS header
 chateauconstellation.ch: did not receive HSTS header
@@ -1229,38 +1233,40 @@ chijiokeindustries.co.uk: could not conn
 childcaresolutionscny.org: did not receive HSTS header
 chinacdn.org: could not connect to host
 chinawhale.com: did not receive HSTS header
 chirgui.eu: could not connect to host
 chlouis.net: could not connect to host
 chm.vn: did not receive HSTS header
 chodobien.com: could not connect to host
 choiralberta.ca: could not connect to host
-chon.io: could not connect to host
+chonghe.org: did not receive HSTS header
 chontalpa.pw: could not connect to host
 choruscrowd.com: could not connect to host
+chosenplaintext.org: could not connect to host
 chotu.net: could not connect to host
 chris-web.info: could not connect to host
 chrisandsarahinasia.com: did not receive HSTS header
 chrisbrakebill.com: could not connect to host
+chrisbrown.id.au: could not connect to host
 chrisfaber.com: could not connect to host
 chriskirchner.de: could not connect to host
 chriskyrouac.com: could not connect to host
 chrisopperwall.com: could not connect to host
 christiaandruif.nl: could not connect to host
 christianbro.gq: could not connect to host
 christophercolumbusfoundation.gov: could not connect to host
 christophersole.com: could not connect to host
 christophheich.me: could not connect to host
 chrisupjohn.com: could not connect to host
+chromaryu.net: did not receive HSTS header
 chrome-devtools-frontend.appspot.com: did not receive HSTS header (error ignored - included regardless)
 chrome.google.com: did not receive HSTS header (error ignored - included regardless)
 chrst.ph: could not connect to host
 chua.cf: could not connect to host
-chua.family: could not connect to host
 chulado.com: did not receive HSTS header
 churchux.co: did not receive HSTS header
 cidr.ml: could not connect to host
 cigarblogs.net: could not connect to host
 cigi.site: could not connect to host
 ciicutini.ro: did not receive HSTS header
 cim2b.de: could not connect to host
 cimalando.eu: could not connect to host
@@ -1293,16 +1299,17 @@ clickandgo.com: did not receive HSTS hea
 clickandshoot.nl: did not receive HSTS header
 clickgram.biz: could not connect to host
 clicn.bio: could not connect to host
 clicnbio.com: did not receive HSTS header
 clintonbloodworth.com: could not connect to host
 clintonbloodworth.io: could not connect to host
 clintwilson.technology: max-age too low: 2592000
 clipped4u.com: could not connect to host
+closient.com: could not connect to host
 cloud-project.com: did not receive HSTS header
 cloud.wtf: could not connect to host
 cloudapi.vc: could not connect to host
 cloudbleed.info: could not connect to host
 cloudcert.org: did not receive HSTS header
 cloudcy.net: could not connect to host
 clouddesktop.co.nz: could not connect to host
 cloudey.net: did not receive HSTS header
@@ -1310,17 +1317,17 @@ cloudflare.com: did not receive HSTS hea
 cloudimag.es: could not connect to host
 cloudlink.club: could not connect to host
 cloudns.com.au: could not connect to host
 cloudspotterapp.com: did not receive HSTS header
 cloudstoragemaus.com: could not connect to host
 cloudstorm.me: could not connect to host
 cloudstrike.co: could not connect to host
 cloudwalk.io: did not receive HSTS header
-clovissantos.com: could not connect to host
+clovissantos.com: did not receive HSTS header
 clowde.in: could not connect to host
 clubmate.rocks: could not connect to host
 clubmix.co.kr: could not connect to host
 cluster.id: did not receive HSTS header
 clustermaze.net: could not connect to host
 clvrwebdesign.com: could not connect to host
 clywedogmaths.co.uk: could not connect to host
 cmc-versand.de: did not receive HSTS header
@@ -1410,16 +1417,17 @@ consciousbrand.org.au: could not connect
 consciousbranding.org.au: could not connect to host
 consciousbrands.net.au: could not connect to host
 console.python.org: did not receive HSTS header
 console.support: did not receive HSTS header
 contactbig.com: could not connect to host
 contactsingapore.sg: did not receive HSTS header
 containerstatistics.com: could not connect to host
 contarkos.xyz: could not connect to host
+contextplatform.com: could not connect to host
 continuumgaming.com: could not connect to host
 controlcenter.gigahost.dk: did not receive HSTS header
 convert.zone: did not receive HSTS header
 cooink.net: could not connect to host
 cooko.at: could not connect to host
 coolaj86.com: did not receive HSTS header
 coolchevy.org.ua: did not receive HSTS header
 coole-meister.de: could not connect to host
@@ -1446,49 +1454,51 @@ corruption-mc.net: could not connect to 
 corruption-rsps.net: could not connect to host
 corruption-server.net: could not connect to host
 costow.club: could not connect to host
 count.sh: could not connect to host
 couponcodeq.com: did not receive HSTS header
 couragewhispers.ca: could not connect to host
 coursdeprogrammation.com: could not connect to host
 coursella.com: did not receive HSTS header
+courtlistener.com: could not connect to host
 covenantbank.net: could not connect to host
 coverduck.ru: could not connect to host
 cpuvinf.eu.org: could not connect to host
 cr.search.yahoo.com: did not receive HSTS header
 cracking.org: did not receive HSTS header
 craftbeerbarn.co.uk: could not connect to host
 craftedge.xyz: could not connect to host
 craftmain.eu: could not connect to host
 cranems.com.ua: did not receive HSTS header
 cranioschule.com: did not receive HSTS header
 crate.io: did not receive HSTS header
 cravelyrics.com: could not connect to host
 crazifyngers.com: could not connect to host
 crazy-crawler.de: did not receive HSTS header
 crazycen.com: could not connect to host
+crazycraftland.de: could not connect to host
 crazycraftland.net: could not connect to host
 crazyhotseeds.com: did not receive HSTS header
 crbug.com: did not receive HSTS header (error ignored - included regardless)
 creaescola.com: did not receive HSTS header
 create-test-publish.co.uk: could not connect to host
 creativephysics.ml: could not connect to host
 creativeplayuk.com: did not receive HSTS header
 crecket.me: could not connect to host
 crendontech.com: could not connect to host
 crestoncottage.com: could not connect to host
 criena.net: did not receive HSTS header
 crimewatch.net.za: could not connect to host
+crisissurvivalspecialists.com: could not connect to host
 cristiandeluxe.com: did not receive HSTS header
 crizk.com: could not connect to host
 crockett.io: did not receive HSTS header
 croome.no-ip.org: could not connect to host
 crosbug.com: did not receive HSTS header (error ignored - included regardless)
-crosscom.ch: could not connect to host
 crosssec.com: did not receive HSTS header
 crow.tw: could not connect to host
 crowd.supply: did not receive HSTS header
 crowdcurity.com: did not receive HSTS header
 crowdjuris.com: could not connect to host
 crows.io: did not receive HSTS header
 crrev.com: did not receive HSTS header (error ignored - included regardless)
 crtvmgmt.com: could not connect to host
@@ -1534,17 +1544,16 @@ ctj.im: could not connect to host
 cubecart-demo.co.uk: did not receive HSTS header
 cubecart-hosting.co.uk: did not receive HSTS header
 cubecart.net: did not receive HSTS header
 cubela.tech: could not connect to host
 cubeserver.eu: could not connect to host
 cubewano.com: could not connect to host
 cucc.date: did not receive HSTS header
 cujanovic.com: did not receive HSTS header
-cujba.com: could not connect to host
 culinae.nl: could not connect to host
 culture-school.top: could not connect to host
 cumshots-video.ru: could not connect to host
 cunha.be: could not connect to host
 cuntflaps.me: could not connect to host
 cuongquach.com: did not receive HSTS header
 curlyroots.com: did not receive HSTS header
 curroapp.com: could not connect to host
@@ -1556,17 +1565,18 @@ cuvva.insure: did not receive HSTS heade
 cvtparking.co.uk: could not connect to host
 cwage.com: could not connect to host
 cyanogenmod.xxx: could not connect to host
 cyber.cafe: could not connect to host
 cyberlab.kiev.ua: did not receive HSTS header
 cyberpunk.ca: could not connect to host
 cybershambles.com: could not connect to host
 cybersmart.co.uk: did not receive HSTS header
-cycleluxembourg.lu: did not receive HSTS header
+cyclehackluxembourgcity.lu: could not connect to host
+cycleluxembourg.lu: could not connect to host
 cydia-search.io: could not connect to host
 cyhour.com: did not receive HSTS header
 cynoshair.com: could not connect to host
 cyphertite.com: could not connect to host
 cytadel.fr: did not receive HSTS header
 cyyzaid.cn: could not connect to host
 czbix.com: did not receive HSTS header
 d-rickroll-e.pw: could not connect to host
@@ -1604,17 +1614,16 @@ danijobs.com: could not connect to host
 danishenanigans.com: could not connect to host
 dankeblog.com: could not connect to host
 dankredues.com: could not connect to host
 dannycrichton.com: did not receive HSTS header
 danrl.de: could not connect to host
 danwillenberg.com: did not receive HSTS header
 daolerp.xyz: could not connect to host
 daplie.com: did not receive HSTS header
-daracokorilo.com: did not receive HSTS header
 dargasia.is: could not connect to host
 dario.im: could not connect to host
 dark-x.cf: could not connect to host
 darkanzali.pl: max-age too low: 0
 darkengine.io: could not connect to host
 darkfriday.ddns.net: could not connect to host
 darkhole.cn: did not receive HSTS header
 darkkeepers.dk: did not receive HSTS header
@@ -1657,17 +1666,16 @@ dbx.ovh: did not receive HSTS header
 dcaracing.nl: could not connect to host
 dccode.gov: could not connect to host
 dccraft.net: could not connect to host
 dcl.re: did not receive HSTS header
 dcuofriends.net: could not connect to host
 dcurt.is: did not receive HSTS header
 dcw.io: did not receive HSTS header
 ddatsh.com: could not connect to host
-ddepot.us: did not receive HSTS header
 debank.tv: did not receive HSTS header
 debatch.se: could not connect to host
 debian-vhost.de: did not receive HSTS header
 debiton.dk: could not connect to host
 debtkit.co.uk: did not receive HSTS header
 decafu.co: could not connect to host
 decesus.com: could not connect to host
 decibelios.li: could not connect to host
@@ -1719,16 +1727,20 @@ designgears.com: did not receive HSTS he
 designthinking.or.jp: did not receive HSTS header
 desserteagleselvenar.tk: could not connect to host
 destinationbijoux.fr: could not connect to host
 destom.be: could not connect to host
 detalhecomercio.com.br: did not receive HSTS header
 detector.exposed: could not connect to host
 detest.org: could not connect to host
 detutorial.com: max-age too low: 0
+deux.solutions: could not connect to host
+deuxsol.co: could not connect to host
+deuxsol.com: could not connect to host
+deuxsolutions.com: could not connect to host
 deuxvia.com: could not connect to host
 dev-aegon.azurewebsites.net: did not receive HSTS header
 devafterdark.com: could not connect to host
 devcu.com: could not connect to host
 devcu.net: could not connect to host
 develop.cool: could not connect to host
 develop.fitness: could not connect to host
 developersclub.website: could not connect to host
@@ -1748,17 +1760,16 @@ dhpcs.com: did not receive HSTS header
 dhpiggott.net: did not receive HSTS header
 diablotine.rocks: could not connect to host
 dianlujitao.com: did not receive HSTS header
 diannaobos.com: did not receive HSTS header
 dicando.com: max-age too low: 2592000
 dicelab.co.uk: could not connect to host
 dicgaming.net: could not connect to host
 dicionariofinanceiro.com: did not receive HSTS header
-dickieslife.com: could not connect to host
 didierlaumen.be: could not connect to host
 die-borts.ch: could not connect to host
 dierenkruiden.nl: could not connect to host
 diewebstube.de: could not connect to host
 diezel.com: could not connect to host
 diferenca.com: did not receive HSTS header
 digired.xyz: could not connect to host
 digitalbank.kz: could not connect to host
@@ -1798,16 +1809,17 @@ dl.google.com: did not receive HSTS head
 dlc.viasinc.com: could not connect to host
 dlemper.de: did not receive HSTS header
 dlscomputers.com.au: did not receive HSTS header
 dmcibulldog.com: did not receive HSTS header
 dmix.ca: could not connect to host
 dmtry.me: did not receive HSTS header
 dmwall.cn: could not connect to host
 dmz.ninja: could not connect to host
+dndtools.net: could not connect to host
 dns.google.com: did not receive HSTS header (error ignored - included regardless)
 dnsknowledge.com: did not receive HSTS header
 do-do.tk: could not connect to host
 do.search.yahoo.com: did not receive HSTS header
 dobet.in: could not connect to host
 docid.io: could not connect to host
 docket.news: could not connect to host
 docset.io: could not connect to host
@@ -1819,16 +1831,17 @@ dogbox.se: did not receive HSTS header
 dogespeed.ga: could not connect to host
 doggieholic.net: could not connect to host
 dogoodbehappyllc.com: could not connect to host
 dohosting.ru: could not connect to host
 dojin.nagoya: could not connect to host
 dokan.online: did not receive HSTS header
 doked.io: could not connect to host
 dolevik.com: could not connect to host
+doli.se: could not connect to host
 dollarstore24.com: could not connect to host
 dollywiki.co.uk: could not connect to host
 dolphin-cloud.com: could not connect to host
 dolphincorp.co.uk: did not receive HSTS header
 dolphinswithlasers.com: did not receive HSTS header
 domaine-aigoual-cevennes.com: did not receive HSTS header
 domaris.de: could not connect to host
 domenicocatelli.com: could not connect to host
@@ -1848,16 +1861,17 @@ doridian.com: could not connect to host
 doridian.de: could not connect to host
 doridian.org: could not connect to host
 dorkfarm.com: did not receive HSTS header
 dosenbierrepublik.com: did not receive HSTS header
 dot42.no: could not connect to host
 dotacni-parazit.cz: did not receive HSTS header
 dotadata.me: could not connect to host
 dotspaperie.com: could not connect to host
+dougferris.id.au: could not connect to host
 doujin.nagoya: could not connect to host
 dovecotadmin.org: could not connect to host
 doveholesband.co.uk: did not receive HSTS header
 dovetailnow.com: could not connect to host
 download.jitsi.org: did not receive HSTS header
 downsouthweddings.com.au: did not receive HSTS header
 doxcelerate.com: did not receive HSTS header
 doyoucheck.com: did not receive HSTS header
@@ -1976,16 +1990,17 @@ ecrimex.net: did not receive HSTS header
 edati.lv: could not connect to host
 edcphenix.tk: could not connect to host
 eddmixpanel.com: could not connect to host
 eddyn.net: did not receive HSTS header
 edelblack.ch: could not connect to host
 edelsteincosmetic.com: did not receive HSTS header
 eden-noel.at: could not connect to host
 edenaya.com: could not connect to host
+edgar.cloud: could not connect to host
 edgereinvent.com: did not receive HSTS header
 ediscomp.sk: did not receive HSTS header
 edissecurity.sk: did not receive HSTS header
 edix.ru: could not connect to host
 edk.com.tr: did not receive HSTS header
 edmodo.com: did not receive HSTS header
 educatio.tech: could not connect to host
 eduroam.no: did not receive HSTS header
@@ -2036,17 +2051,16 @@ electricianforum.co.uk: did not receive 
 electricoperaduo.com: could not connect to host
 electromc.com: could not connect to host
 elektronring.com: could not connect to host
 elemenx.com: did not receive HSTS header
 elemprendedor.com.ve: did not receive HSTS header
 elenag.ga: could not connect to host
 elenoon.ir: did not receive HSTS header
 elgacien.de: could not connect to host
-elhall.ru: did not receive HSTS header
 elimdengelen.com: did not receive HSTS header
 elite-porno.ru: could not connect to host
 elitefishtank.com: could not connect to host
 elnutricionista.es: did not receive HSTS header
 elohna.ch: did not receive HSTS header
 elonbase.com: could not connect to host
 elpo.xyz: could not connect to host
 elsamakhin.com: could not connect to host
@@ -2081,16 +2095,17 @@ end.pp.ua: could not connect to host
 endlessdark.net: max-age too low: 600
 endlesshorizon.net: could not connect to host
 endlesstone.com: did not receive HSTS header
 endohaus.ca: could not connect to host
 endohaus.com: could not connect to host
 endohaus.eu: could not connect to host
 enefan.jp: could not connect to host
 engelwerbung.com: did not receive HSTS header
+engg.ca: could not connect to host
 enginsight.com: did not receive HSTS header
 englishyamal.ru: did not receive HSTS header
 enigmacpt.com: did not receive HSTS header
 enigmail.net: did not receive HSTS header
 enjen.net: did not receive HSTS header
 enjoymayfield.com: max-age too low: 0
 enlightenment.org: did not receive HSTS header
 enskat.de: could not connect to host
@@ -2166,17 +2181,17 @@ etdonline.co.uk: could not connect to ho
 eternitylove.us: could not connect to host
 eth-faucet.net: did not receive HSTS header
 eth9.net: could not connect to host
 ethanfaust.com: could not connect to host
 etheria-software.tk: did not receive HSTS header
 ethicalexploiting.com: could not connect to host
 ethicall.org.uk: did not receive HSTS header
 ethil-faer.fr: could not connect to host
-ethlan.fr: max-age too low: 0
+ethlan.fr: could not connect to host
 etk2000.com: did not receive HSTS header
 etmirror.top: could not connect to host
 etmirror.xyz: could not connect to host
 etproxy.tech: could not connect to host
 etrker.com: did not receive HSTS header
 ets2mp.de: did not receive HSTS header
 etsysecure.com: could not connect to host
 etula.ga: could not connect to host
@@ -2263,16 +2278,17 @@ fallenangelspirits.uk: could not connect
 fam-weyer.de: did not receive HSTS header
 fame-agency.net: could not connect to host
 familie-sprink.de: could not connect to host
 familie-zimmermann.at: could not connect to host
 famio.cn: could not connect to host
 fantasyfootballpundit.com: did not receive HSTS header
 fanyl.cn: could not connect to host
 farces.com: did not receive HSTS header
+farhadexchange.com: did not receive HSTS header
 farhood.org: did not receive HSTS header
 fashion.net: did not receive HSTS header
 fashioncare.cz: did not receive HSTS header
 fasset.jp: could not connect to host
 fastcomcorp.com: did not receive HSTS header
 fastcomcorp.net: did not receive HSTS header
 fastconfirm.com: could not connect to host
 fastograph.com: could not connect to host
@@ -2423,36 +2439,34 @@ forplanetsake.com: could not connect to 
 forus.be: could not connect to host
 fotiu.com: could not connect to host
 fotocerita.net: could not connect to host
 fotogiraffe.ru: could not connect to host
 fotografosexpertos.com: did not receive HSTS header
 fotopasja.info: could not connect to host
 fourchin.net: could not connect to host
 fourwheelpartloanssimple.com: did not receive HSTS header
-foxdev.io: could not connect to host
+foxdev.io: did not receive HSTS header
 foxley-farm.co.uk: did not receive HSTS header
 foxley-seeds.co.uk: did not receive HSTS header
 foxleyseeds.co.uk: could not connect to host
 foxtrot.pw: could not connect to host
 fr33d0m.link: could not connect to host
 fragilesolar.cf: could not connect to host
 fralef.me: did not receive HSTS header
 francevpn.xyz: could not connect to host
 frangor.info: did not receive HSTS header
 frankwei.xyz: did not receive HSTS header
 franta.biz: did not receive HSTS header
 franta.email: did not receive HSTS header
 franzt.de: could not connect to host
-franzt.ovh: could not connect to host
 frasesdeamizade.pt: could not connect to host
 frasys.io: could not connect to host
 frau-inge.de: could not connect to host
 fraudempire.com: could not connect to host
-frebib.net: could not connect to host
 freeflow.tv: could not connect to host
 freelanced.co.za: could not connect to host
 freelo.cz: did not receive HSTS header
 freematthale.net: did not receive HSTS header
 freenetproject.org: did not receive HSTS header
 freesoftwaredriver.com: did not receive HSTS header
 freethought.org.au: could not connect to host
 freeutopia.org: did not receive HSTS header
@@ -2493,16 +2507,17 @@ furnation.com: could not connect to host
 furry.be: did not receive HSTS header
 fusedrops.com: could not connect to host
 fusionmate.com: could not connect to host
 futbol11.com: did not receive HSTS header
 futurestarsusa.org: did not receive HSTS header
 futuretechnologi.es: could not connect to host
 futureyouhealth.com: did not receive HSTS header
 fuwafuwa.moe: could not connect to host
+fuxwerk.de: could not connect to host
 fwei.tk: could not connect to host
 fwest.ovh: did not receive HSTS header
 fwest98.ovh: did not receive HSTS header
 fws.gov: did not receive HSTS header
 fx-rk.com: did not receive HSTS header
 fysiohaenraets.nl: did not receive HSTS header
 fzn.io: could not connect to host
 fzslm.me: could not connect to host
@@ -2623,17 +2638,19 @@ getpake.com: could not connect to host
 getremembrall.com: could not connect to host
 getronics.care: could not connect to host
 getsello.com: could not connect to host
 getspeaker.com: did not receive HSTS header
 getwashdaddy.com: could not connect to host
 gfm.tech: could not connect to host
 gfournier.ca: could not connect to host
 gfwsb.ml: could not connect to host
+gglks.com: did not receive HSTS header
 ggss.ml: could not connect to host
+ggx.us: could not connect to host
 gh16.com.ar: could not connect to host
 gheorghe-sarcov.ga: could not connect to host
 gheorghesarcov.ga: could not connect to host
 gheorghesarcov.tk: could not connect to host
 ghostcir.com: could not connect to host
 giakki.eu: could not connect to host
 gianlucapartengo.photography: did not receive HSTS header
 gibraltar-firma.com: did not receive HSTS header
@@ -2652,16 +2669,17 @@ gingali.de: did not receive HSTS header
 gintenreiter-photography.com: did not receive HSTS header
 giogadesign.com: did not receive HSTS header
 gipsamsfashion.com: could not connect to host
 gipsic.com: did not receive HSTS header
 gis3m.org: did not receive HSTS header
 gistfy.com: could not connect to host
 git-stuff.tk: could not connect to host
 github.party: did not receive HSTS header
+gitstuff.tk: could not connect to host
 givemyanswer.com: could not connect to host
 gizzo.sk: could not connect to host
 gl.search.yahoo.com: did not receive HSTS header
 glass.google.com: did not receive HSTS header (error ignored - included regardless)
 glasslikes.com: did not receive HSTS header
 glentakahashi.com: max-age too low: 0
 glitzmirror.com: could not connect to host
 global-adult-webcams.com: did not receive HSTS header
@@ -2677,27 +2695,28 @@ glotter.com: did not receive HSTS header
 gloucesterphotographer.com: did not receive HSTS header
 glubbforum.de: did not receive HSTS header
 glws.org: did not receive HSTS header
 gm-assicurazioni.it: could not connect to host
 gm.search.yahoo.com: did not receive HSTS header
 gmail.com: did not receive HSTS header (error ignored - included regardless)
 gmat.ovh: could not connect to host
 gmoes.at: max-age too low: 600000
-gnilebein.de: could not connect to host
 go.ax: did not receive HSTS header
 go2sh.de: did not receive HSTS header
 goabonga.com: could not connect to host
 goalsetup.com: did not receive HSTS header
 goaltree.ch: did not receive HSTS header
 goarmy.eu: could not connect to host
 goat.chat: did not receive HSTS header
 goat.xyz: max-age too low: 86400
 goben.ch: could not connect to host
 goblins.net: did not receive HSTS header
+godsofhell.com: did not receive HSTS header
+godsofhell.de: did not receive HSTS header
 goedeke.ml: could not connect to host
 goerner.me: did not receive HSTS header
 goge.site: could not connect to host
 gogenenglish.com: could not connect to host
 gogetssl.com: did not receive HSTS header
 goggs.eu: could not connect to host
 gogold-g.com: could not connect to host
 gokhankesici.com: could not connect to host
@@ -2705,29 +2724,29 @@ gold24.in: did not receive HSTS header
 goldegg-training.com: did not receive HSTS header
 goldendata.io: could not connect to host
 goldminer.ga: could not connect to host
 goldpros.com: did not receive HSTS header
 golocal-media.de: could not connect to host
 gong8.win: could not connect to host
 gonzalosanchez.mx: did not receive HSTS header
 goodenough.nz: did not receive HSTS header
-goodmengroup.de: could not connect to host
 goodtech.com.br: could not connect to host
 goodwin43.ru: could not connect to host
 google: could not connect to host (error ignored - included regardless)
 googlemail.com: did not receive HSTS header (error ignored - included regardless)
 googleplex.com: did not receive HSTS header (error ignored - included regardless)
 goolok.com: could not connect to host
 gootlijsten.nl: did not receive HSTS header
 goozz.nl: did not receive HSTS header
 gopay.cz: did not receive HSTS header
 gopokego.cz: could not connect to host
 gorilla-gym.site: could not connect to host
-gorillow.com: did not receive HSTS header
+gorillow.com: could not connect to host
+gorn.ch: could not connect to host
 goshop.cz: did not receive HSTS header
 gotgenes.com: could not connect to host
 goto.google.com: did not receive HSTS header (error ignored - included regardless)
 gotocloud.ru: could not connect to host
 gotowned.org: max-age too low: 0
 gotspot.com: could not connect to host
 gottcode.org: did not receive HSTS header
 gov.ax: could not connect to host
@@ -2757,16 +2776,18 @@ greatnet.de: did not receive HSTS header
 greatsong.net: did not receive HSTS header
 greencardtalent.com: could not connect to host
 greenesting.ch: could not connect to host
 greenesting.com: could not connect to host
 greenhillantiques.co.uk: did not receive HSTS header
 greenvines.com.tw: did not receive HSTS header
 greenvpn.ltd: could not connect to host
 greg.red: could not connect to host
+gregmilton.com: could not connect to host
+gregmilton.org: could not connect to host
 gregorytlee.me: could not connect to host
 gremots.com: could not connect to host
 greplin.com: could not connect to host
 gresb.com: did not receive HSTS header
 gretchelizartistry.com: did not receive HSTS header
 grevesgarten.de: could not connect to host
 greyline.se: could not connect to host
 gribani.com: could not connect to host
@@ -2931,39 +2952,38 @@ hcs-company.com: did not receive HSTS he
 hcs-company.nl: did not receive HSTS header
 hd-offensive.at: could not connect to host
 hdrboundless.com: could not connect to host
 hdsmigrationtool.com: could not connect to host
 hduin.xyz: could not connect to host
 hdwallpapers.net: did not receive HSTS header
 head-shop.lt: could not connect to host
 head-shop.lv: could not connect to host
+headmates.xyz: could not connect to host
 healthycod.in: could not connect to host
 healtious.com: could not connect to host
 heart.ge: did not receive HSTS header
 heartlandrentals.com: did not receive HSTS header
 hearty.blog: could not connect to host
 hearty.space: could not connect to host
 hearty.tw: did not receive HSTS header
 heartyme.net: could not connect to host
 heathmanners.com: could not connect to host
 heavystresser.com: could not connect to host
 hebaus.com: could not connect to host
 hebriff.com: could not connect to host
 heidilein.info: did not receive HSTS header
 heijblok.com: could not connect to host
 heimnetze.org: could not connect to host
 helencrump.co.uk: did not receive HSTS header
-hellofilters.com: did not receive HSTS header
 helloworldhost.com: did not receive HSTS header
 helpadmin.net: could not connect to host
 helpium.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 helpmebuild.com: did not receive HSTS header
 helpmij.cf: did not receive HSTS header
-helup.com: did not receive HSTS header
 hemdal.se: could not connect to host
 hencagon.com: could not connect to host
 henriknoerr.com: could not connect to host
 hepteract.us: did not receive HSTS header
 herbandpat.org: could not connect to host
 herbertmouwen.nl: could not connect to host
 heritagedentistry.ca: did not receive HSTS header
 herpaderp.net: could not connect to host
@@ -2997,34 +3017,34 @@ hipercultura.com: did not receive HSTS h
 hiphopconvention.nl: could not connect to host
 hipi.jp: could not connect to host
 hirefitness.co.uk: did not receive HSTS header
 hititgunesi-tr.com: did not receive HSTS header
 hitoy.org: did not receive HSTS header
 hittipps.com: did not receive HSTS header
 hiv.gov: did not receive HSTS header
 hjw-kunstwerk.de: could not connect to host
-hloe0xff.ru: could not connect to host
+hloe0xff.ru: did not receive HSTS header
 hlyue.com: did not receive HSTS header
 hm1ch.ovh: could not connect to host
 hmm.nyc: could not connect to host
 hn.search.yahoo.com: did not receive HSTS header
 hobaugh.social: could not connect to host
 hodne.io: could not connect to host
 hoekwoningverkopen.nl: could not connect to host
 hoerbuecher-und-hoerspiele.de: could not connect to host
 hofiprojekt.cz: did not receive HSTS header
 hogar123.es: could not connect to host
 hoiku-map.tokyo: could not connect to host
-hoikuen-now.top: could not connect to host
 holgerlehner.com: could not connect to host
 holifestival-freyung.de: could not connect to host
 holymoly.lu: could not connect to host
 homa.website: could not connect to host
 homads.com: did not receive HSTS header
+homeandyarddetailing.com: could not connect to host
 homeclouding.de: could not connect to host
 homedna.com: did not receive HSTS header
 homeexx.com: could not connect to host
 hometownmall.com: did not receive HSTS header
 hongyd.online: could not connect to host
 hongzhaxiaofendui.com: could not connect to host
 honoo.com: could not connect to host
 hookandloom.com: did not receive HSTS header
@@ -3112,17 +3132,16 @@ iamreubin.co.uk: did not receive HSTS he
 iamveto.com: could not connect to host
 iapws.com: could not connect to host
 iban.is: could not connect to host
 ibarf.nl: did not receive HSTS header
 ibnuwebhost.com: could not connect to host
 icabanken.se: did not receive HSTS header
 icaforsakring.se: did not receive HSTS header
 ice.yt: could not connect to host
-icebat.dyndns.org: could not connect to host
 icepink.com.br: did not receive HSTS header
 icfl.com.br: could not connect to host
 ich-find-den-g.net: could not connect to host
 ich-mach-druck.eu: did not receive HSTS header
 ichnichtskaufmann.de: could not connect to host
 ichoosebtec.com: did not receive HSTS header
 icity.ly: did not receive HSTS header
 icloud.net: could not connect to host
@@ -3135,17 +3154,16 @@ ideal-envelopes.co.uk: did not receive H
 idealmykonos.com: did not receive HSTS header
 ideaplus.me: did not receive HSTS header
 ideasmeetingpoint.com: could not connect to host
 ideation-inc.co.jp: could not connect to host
 idecode.net: could not connect to host
 idedr.com: could not connect to host
 identitylabs.uk: could not connect to host
 idgsupply.com: did not receive HSTS header
-idinby.dk: did not receive HSTS header
 idisplay.es: did not receive HSTS header
 idlekernel.com: could not connect to host
 idontexist.me: did not receive HSTS header
 ie.search.yahoo.com: did not receive HSTS header
 ieji.de: could not connect to host
 ierna.com: did not receive HSTS header
 ies-italia.it: did not receive HSTS header
 ies.id.lv: could not connect to host
@@ -3166,17 +3184,16 @@ ihsbsd.me: could not connect to host
 ihsbsd.tk: could not connect to host
 iispeed.com: did not receive HSTS header
 ikon.name: did not receive HSTS header
 ikwilguidobellen.nl: could not connect to host
 ilbuongiorno.it: did not receive HSTS header
 ilgi.work: could not connect to host
 ilikerainbows.co: could not connect to host
 ilikerainbows.co.uk: could not connect to host
-ilikfreshweedstores.com: could not connect to host
 ilmconpm.de: did not receive HSTS header
 ilona.graphics: did not receive HSTS header
 iluvscotland.co.uk: max-age too low: 7776000
 imakepoems.net: could not connect to host
 imanolbarba.net: could not connect to host
 ime.moe: could not connect to host
 imim.pw: could not connect to host
 imjiangtao.com: could not connect to host
@@ -3233,47 +3250,47 @@ informaticapremium.com: did not receive 
 infosec.rip: could not connect to host
 infosoph.org: did not receive HSTS header
 infotics.es: did not receive HSTS header
 infura.co.th: could not connect to host
 ingeeibach.de: could not connect to host
 ingesol.fr: did not receive HSTS header
 injertoshorticolas.com: did not receive HSTS header
 injigo.com: did not receive HSTS header
-injust.cf: did not receive HSTS header
-injust.ga: did not receive HSTS header
-injust.gq: did not receive HSTS header
+injust.cf: could not connect to host
+injust.ga: could not connect to host
+injust.gq: could not connect to host
 injust.ml: could not connect to host
-injust.tk: did not receive HSTS header
+injust.tk: could not connect to host
 inkable.com.au: did not receive HSTS header
 inked-guy.de: could not connect to host
 inkedguy.de: could not connect to host
 inkstory.gr: did not receive HSTS header
 inksupply.com: did not receive HSTS header
 inleaked.com: could not connect to host
 inme.ga: could not connect to host
 inmyarea.com: max-age too low: 0
 innophate-security.nl: could not connect to host
 innovation.gov: could not connect to host
 innovativeideaz.org: did not receive HSTS header
+inoa8.com: did not receive HSTS header
 inquisitive.io: did not receive HSTS header
 insane-bullets.com: could not connect to host
 insane.zone: could not connect to host
 insite-feedback.com: did not receive HSTS header
 inspire-av.com: did not receive HSTS header
 inspiroinc.com: could not connect to host
 instacart.com: did not receive HSTS header
 installgentoo.net: could not connect to host
 instant-hack.com: did not receive HSTS header
 instantdev.io: could not connect to host
 instinctiveads.com: did not receive HSTS header
 institutoflordelavida.com: could not connect to host
 instruktor.io: could not connect to host
 intarweb.ca: could not connect to host
-integraelchen.de: could not connect to host
 intel.li: could not connect to host
 interboursegeneva.ch: did not receive HSTS header
 interference.io: could not connect to host
 interhosts.co.za: could not connect to host
 interim-cto.de: could not connect to host
 interleucina.org: did not receive HSTS header
 interlocal.co.uk: could not connect to host
 interlun.com: could not connect to host
@@ -3351,17 +3368,16 @@ isogram.nl: could not connect to host
 israkurort.com: did not receive HSTS header
 istanbultravelguide.info: could not connect to host
 istaspirtslietas.lv: did not receive HSTS header
 it-go.net: did not receive HSTS header
 it-schwerin.de: could not connect to host
 itechgeek.com: max-age too low: 0
 iteha.de: could not connect to host
 items.lv: did not receive HSTS header
-itemton.com: did not receive HSTS header
 ithakama.com: did not receive HSTS header
 ithakama.cz: did not receive HSTS header
 itinsight.hu: did not receive HSTS header
 itos.asia: did not receive HSTS header
 itos.pl: did not receive HSTS header
 itpros.ru: could not connect to host
 itriskltd.com: could not connect to host
 itsadog.co.uk: did not receive HSTS header
@@ -3467,17 +3483,17 @@ jessicah.org: could not connect to host
 jesuisformidable.nl: could not connect to host
 jet-code.com: could not connect to host
 jetaprices.com: could not connect to host
 jetsetcharge.com: could not connect to host
 jetsetpay.com: could not connect to host
 jettshome.org: could not connect to host
 jeugdkans.nl: did not receive HSTS header
 jewellerydesignstore.com: could not connect to host
-jfmel.com: did not receive HSTS header
+jfmel.com: could not connect to host
 jfx.space: did not receive HSTS header
 jh-media.eu: could not connect to host
 jhburton.uk: could not connect to host
 jhejderup.me: could not connect to host
 jia1hao.com: could not connect to host
 jiaidu.com: could not connect to host
 jiangzm.com: could not connect to host
 jief.me: could not connect to host
@@ -3518,26 +3534,26 @@ johnverkerk.com: could not connect to ho
 jointoweb.com: could not connect to host
 jonas-keidel.de: did not receive HSTS header
 jonasgroth.se: did not receive HSTS header
 jonathan.ir: could not connect to host
 jonfor.net: could not connect to host
 jongha.me: could not connect to host
 jonn.me: could not connect to host
 jonnichols.info: did not receive HSTS header
+jonnybarnes.uk: did not receive HSTS header
 jonsno.ws: could not connect to host
 joostbovee.nl: did not receive HSTS header
 jordanhamilton.me: could not connect to host
 jordanstrustcompany.cn: could not connect to host
 jordanstrustcompany.ru: could not connect to host
 jorgemesa.me: could not connect to host
 josahrens.me: could not connect to host
 josecage.com: could not connect to host
 joshi.su: could not connect to host
-joshschmelzle.com: could not connect to host
 joshstroup.me: could not connect to host
 jotpics.com: could not connect to host
 jottit.com: could not connect to host
 jpaglier.com: could not connect to host
 jpbike.cz: could not connect to host
 jpeaches.xyz: could not connect to host
 jrc9.ca: did not receive HSTS header
 jrgold.me: could not connect to host
@@ -3634,16 +3650,17 @@ keepcoalintheground.org: could not conne
 kenvix.com: could not connect to host
 kerangalam.com: did not receive HSTS header
 kerksanders.nl: did not receive HSTS header
 kermadec.blog: could not connect to host
 kermadec.com: could not connect to host
 kermadec.net: could not connect to host
 kernl.us: did not receive HSTS header
 keskeces.com: did not receive HSTS header
+kevinmeijer.nl: could not connect to host
 keymaster.lookout.com: did not receive HSTS header
 kfbrussels.be: could not connect to host
 kg-rating.com: could not connect to host
 kgxtech.com: max-age too low: 2592000
 khaganat.net: did not receive HSTS header
 ki-on.net: did not receive HSTS header
 kialo.com: did not receive HSTS header
 kickass-proxies.org: could not connect to host
@@ -3683,16 +3700,17 @@ kitchenchaos.de: could not connect to ho
 kitk.at: could not connect to host
 kitsostech.com: could not connect to host
 kitsta.com: could not connect to host
 kiwiirc.com: max-age too low: 5256000
 kiyo.space: could not connect to host
 kizil.net: could not connect to host
 kjaermaxi.me: did not receive HSTS header
 kjg-bachrain.de: could not connect to host
+klangnok.de: could not connect to host
 klauwd.com: did not receive HSTS header
 klaxn.org: could not connect to host
 kleertjesvoordelig.nl: could not connect to host
 kleinerarchitekturfuehrer.de: could not connect to host
 kleppe.co: could not connect to host
 kletterkater.com: did not receive HSTS header
 klicktojob.de: could not connect to host
 klunkergarten.org: could not connect to host
@@ -3705,35 +3723,36 @@ knowledgesnap.com: could not connect to 
 knowledgesnapsites.com: could not connect to host
 kodexplorer.ml: could not connect to host
 kodiaklabs.org: could not connect to host
 kodokushi.fr: could not connect to host
 koelbli.ch: did not receive HSTS header
 koen.io: did not receive HSTS header
 koenrouwhorst.nl: did not receive HSTS header
 koenvdheuvel.me: did not receive HSTS header
+koerperimpuls.ch: did not receive HSTS header
 koha.be: could not connect to host
 koik.io: could not connect to host
 kojima-life.co.jp: max-age too low: 0
 kokenmetaanbiedingen.nl: did not receive HSTS header
 kola-entertainments.de: did not receive HSTS header
 kolaykaydet.com: did not receive HSTS header
 kolozsvaricsuhe.hu: did not receive HSTS header
 komikito.com: could not connect to host
+kominfo.go.id: could not connect to host
 kompetenzwerft.de: did not receive HSTS header
 konata.us: could not connect to host
 kontaxis.network: could not connect to host
 kontorhaus-schlachte.de: could not connect to host
 koopjesnel.nl: could not connect to host
 koordinate.net: could not connect to host
 kori.ml: did not receive HSTS header
 koriyoukai.net: did not receive HSTS header
 korni22.org: did not receive HSTS header
 korsanparti.org: could not connect to host
-koryfi.com: could not connect to host
 kostuumstore.nl: could not connect to host
 kotonehoko.net: could not connect to host
 kotovstyle.ru: could not connect to host
 koukni.cz: did not receive HSTS header
 kourpe.online: could not connect to host
 kprog.net: could not connect to host
 kr.search.yahoo.com: did not receive HSTS header
 kraftfleisch.de: did not receive HSTS header
@@ -3761,33 +3780,33 @@ kryptomech.com: could not connect to hos
 ksfh-mail.de: could not connect to host
 kstan.me: could not connect to host
 kswriter.com: could not connect to host
 kucom.it: did not receive HSTS header
 kuechenplan.online: could not connect to host
 kueulangtahunanak.net: could not connect to host
 kum.com: could not connect to host
 kummerlaender.eu: did not receive HSTS header
-kuoruan.com: could not connect to host
 kupelne-ptacek.sk: did not receive HSTS header
 kuppingercole.com: did not receive HSTS header
 kura.io: could not connect to host
 kurehun.org: could not connect to host
 kuro346.moe: could not connect to host
 kurrietv.nl: did not receive HSTS header
 kurtmclester.com: did not receive HSTS header
 kurz.pw: could not connect to host
 kweddingplanning.com: did not receive HSTS header
 kwok.tv: could not connect to host
 kwondratsch.com: could not connect to host
 kxind.cn: could not connect to host
 kyanite.co: could not connect to host
 kylapps.com: did not receive HSTS header
 kylinj.com: could not connect to host
 kyochon.fr: could not connect to host
+kyusyu.org: did not receive HSTS header
 kz.search.yahoo.com: did not receive HSTS header
 kzjnet.com: could not connect to host
 l-rickroll-i.pw: could not connect to host
 la-flora-negra.de: could not connect to host
 la-grande-jaugue.fr: did not receive HSTS header
 la-retraite-info.com: could not connect to host
 labaia.info: could not connect to host
 labina.com.tr: did not receive HSTS header
@@ -3826,17 +3845,16 @@ langendries.eu: could not connect to hos
 langhun.me: did not receive HSTS header
 laniakean.com: could not connect to host
 lanzainc.xyz: could not connect to host
 lanzarote-online.info: could not connect to host
 laobox.fr: could not connect to host
 laospage.com: did not receive HSTS header
 laplaceduvillage.net: could not connect to host
 laquack.com: could not connect to host
-laracode.eu: could not connect to host
 laredsemanario.com: could not connect to host
 lasercloud.ml: could not connect to host
 laserfuchs.de: did not receive HSTS header
 lashstuff.com: did not receive HSTS header
 lastpass.com: did not receive HSTS header
 latelierdekathy.com: could not connect to host
 latinred.com: could not connect to host
 latus.xyz: could not connect to host
@@ -3861,17 +3879,16 @@ learnedovo.com: did not receive HSTS hea
 learnfrenchfluently.com: did not receive HSTS header
 learningorder.com: could not connect to host
 lebrun.org: could not connect to host
 leddruckalarm.de: did not receive HSTS header
 ledgerscope.net: could not connect to host
 leen.io: did not receive HSTS header
 legarage.org: could not connect to host
 legavenue.com.br: did not receive HSTS header
-lehighmathcircle.org: could not connect to host
 leinir.dk: did not receive HSTS header
 leitner.com.au: did not receive HSTS header
 leiyun.me: did not receive HSTS header
 lellyboi.ml: could not connect to host
 lelongbank.com: did not receive HSTS header
 lemp.io: did not receive HSTS header
 lenagroben.de: could not connect to host
 lennarth.com: did not receive HSTS header
@@ -3894,16 +3911,17 @@ lesperlesdunet.fr: could not connect to 
 lesquerda.cat: did not receive HSTS header
 letitfly.me: could not connect to host
 letras.mus.br: did not receive HSTS header
 letsmultiplayerplay.com: did not receive HSTS header
 letstox.com: could not connect to host
 letustravel.tk: could not connect to host
 levatc.tk: could not connect to host
 level-10.net: did not receive HSTS header
+levelcheat.com: did not receive HSTS header
 levelum.com: did not receive HSTS header
 levert.ch: could not connect to host
 lexpierce.social: could not connect to host
 lez-cuties.com: could not connect to host
 lfullerdesign.com: did not receive HSTS header
 lg21.co: could not connect to host
 lgiswa.com.au: did not receive HSTS header
 lgrs.com.au: did not receive HSTS header
@@ -3922,16 +3940,17 @@ lianye5.cc: could not connect to host
 lianye6.cc: could not connect to host
 lianyexiuchang.in: could not connect to host
 liaoshuma.com: could not connect to host
 libanco.com: could not connect to host
 libertyrp.org: could not connect to host
 library.linode.com: did not receive HSTS header
 librechan.net: could not connect to host
 libreduca.com: could not connect to host
+librends.org: could not connect to host
 lichess4545.com: did not receive HSTS header
 lichess4545.tv: did not receive HSTS header
 lidl-selection.at: could not connect to host
 liemen.net: did not receive HSTS header
 lifecoach.tw: did not receive HSTS header
 lifecoachproviders.com: did not receive HSTS header
 lifeguard.aecom.com: did not receive HSTS header
 lifeinitsownway.com: could not connect to host
@@ -3974,17 +3993,18 @@ liquorsanthe.in: could not connect to ho
 lisaco.de: could not connect to host
 lisbongold.com: did not receive HSTS header
 listafirmelor.com: could not connect to host
 listage.ovh: did not receive HSTS header
 litespeed.io: could not connect to host
 little.pw: did not receive HSTS header
 littlefreelibrary.org: did not receive HSTS header
 littleqiu.net: could not connect to host
-liudon.org: could not connect to host
+litz.ca: could not connect to host
+litzenberger.ca: could not connect to host
 livedemo.io: could not connect to host
 livej.am: could not connect to host
 livi.co: did not receive HSTS header
 liviababynet.com.br: did not receive HSTS header
 lixiang.one: could not connect to host
 lkp111138.me: could not connect to host
 loacg.com: did not receive HSTS header
 loadingdeck.com: did not receive HSTS header
@@ -4054,16 +4074,17 @@ lu.search.yahoo.com: did not receive HST
 lucas-garte.com: did not receive HSTS header
 lucaterzini.com: could not connect to host
 luclu7.pw: did not receive HSTS header
 ludwig.click: did not receive HSTS header
 ludwiggrill.de: could not connect to host
 luelistan.net: could not connect to host
 lufthansaexperts.com: max-age too low: 2592000
 luis-checa.com: could not connect to host
+lukeistschuld.de: did not receive HSTS header
 lukeng.me: could not connect to host
 lukonet.com: did not receive HSTS header
 luludapomerania.com: could not connect to host
 lumd.me: could not connect to host
 lumi.do: did not receive HSTS header
 lumi.pw: could not connect to host
 lunarift.com: could not connect to host
 lunarlog.com: could not connect to host
@@ -4090,31 +4111,33 @@ m-ali.xyz: could not connect to host
 m-rickroll-v.pw: could not connect to host
 m.gparent.org: could not connect to host
 m.nu: did not receive HSTS header
 m0wef.uk: could not connect to host
 m2tc.fr: could not connect to host
 m3-gmbh.de: did not receive HSTS header
 m82labs.com: did not receive HSTS header
 maarten.nyc: could not connect to host
+maartenterpstra.xyz: could not connect to host
 mac-torrents.me: did not receive HSTS header
 macbolo.com: could not connect to host
 macchaberrycream.com: could not connect to host
 macchedil.com: did not receive HSTS header
 macdj.tk: could not connect to host
 macgeneral.de: did not receive HSTS header
 machbach.net: could not connect to host
 macsandcheesedreams.com: could not connect to host
 madars.org: did not receive HSTS header
 maddin.ga: could not connect to host
 madebymagnitude.com: did not receive HSTS header
 maderwin.com: did not receive HSTS header
 madesoftware.com.br: could not connect to host
 mafamane.com: could not connect to host
 maff.scot: could not connect to host
+mafiaforum.de: did not receive HSTS header
 mafiareturns.com: max-age too low: 2592000
 magenx.com: did not receive HSTS header
 magi.systems: could not connect to host
 magia360.com: did not receive HSTS header
 mahamed91.pw: could not connect to host
 mahfouzadedimeji.com: did not receive HSTS header
 mail-settings.google.com: did not receive HSTS header (error ignored - included regardless)
 mail.google.com: did not receive HSTS header (error ignored - included regardless)
@@ -4125,17 +4148,16 @@ mailhost.it: could not connect to host
 mailing-femprendedores.com: did not receive HSTS header
 mailing-jbgg.com: did not receive HSTS header
 main-street-seo.com: did not receive HSTS header
 maintainerheaven.ch: could not connect to host
 majesnix.org: did not receive HSTS header
 make-pizza.info: could not connect to host
 makeitdynamic.com: could not connect to host
 makerstuff.net: did not receive HSTS header
-makeyourlaws.org: could not connect to host
 malena.com.ua: did not receive HSTS header
 malerversand.de: did not receive HSTS header
 malfait.nl: could not connect to host
 maljaars-media.nl: could not connect to host
 mallner.me: could not connect to host
 malmstroms-co.se: could not connect to host
 maltes.website: could not connect to host
 malwaretips.com: did not receive HSTS header
@@ -4157,16 +4179,17 @@ manageprojects.com: did not receive HSTS
 manantial.mx: did not receive HSTS header
 maniadeprazer.com.br: could not connect to host
 manifestbin.com: did not receive HSTS header
 manitasicily.com: did not receive HSTS header
 manningbrothers.com: did not receive HSTS header
 manshop24.com: could not connect to host
 mansion-note.com: did not receive HSTS header
 maomaofuli.vip: could not connect to host
+maozedong.red: did not receive HSTS header
 maple5.com: did not receive HSTS header
 marcelparra.com: could not connect to host
 marchagen.nl: did not receive HSTS header
 marcianoandtopazio.com: could not connect to host
 marco01809.net: could not connect to host
 marcoececilia.it: did not receive HSTS header
 marcofinke.de: could not connect to host
 marcontrol.com: did not receive HSTS header
@@ -4262,34 +4285,31 @@ mcga.media: could not connect to host
 mclab.su: could not connect to host
 mclist.it: could not connect to host
 mctherealm.net: could not connect to host
 mdfnet.se: did not receive HSTS header
 mdosch.de: did not receive HSTS header
 mdscomp.net: did not receive HSTS header
 meadowfen.farm: could not connect to host
 meadowfenfarm.com: could not connect to host
-meadowviewfarms.org: could not connect to host
 meamod.com: max-age too low: 0
 meat-education.com: could not connect to host
 mebio.us: did not receive HSTS header
 mecenat-cassous.com: did not receive HSTS header
 mechmk1.me: did not receive HSTS header
 medallia.io: could not connect to host
 mediacru.sh: could not connect to host
-mediaexpert.fr: could not connect to host
 mediafinancelab.org: did not receive HSTS header
 mediamag.am: max-age too low: 0
 mediastorm.us: could not connect to host
 mediawikicn.org: could not connect to host
 medicalwikis.cz: did not receive HSTS header
 medienservice-fritz.de: did not receive HSTS header
 medirich.co: could not connect to host
 meditek-dv.ru: could not connect to host
-medlineplus.gov: did not receive HSTS header
 medm-test.com: could not connect to host
 medzinenews.com: did not receive HSTS header
 meedoennoordkop.nl: did not receive HSTS header
 meedoenzaanstad.nl: did not receive HSTS header
 meetfinch.com: could not connect to host
 meetings2.com: did not receive HSTS header
 meetscompany.jp: did not receive HSTS header
 megakiste.de: could not connect to host
@@ -4327,26 +4347,28 @@ mesmoque.com: did not receive HSTS heade
 metagrader.com: could not connect to host
 metasyntactic.xyz: could not connect to host
 metebalci.com: did not receive HSTS header
 meteosherbrooke.com: could not connect to host
 meteosky.net: could not connect to host
 meter.md: could not connect to host
 metin2blog.de: did not receive HSTS header
 metis.pw: could not connect to host
+metrans-spedition.de: could not connect to host
 metricaid.com: did not receive HSTS header
 metzgerei-birkenhof.de: could not connect to host
 meuemail.pro: could not connect to host
 mexbt.com: could not connect to host
 mexicanbusinessweb.mx: did not receive HSTS header
 mexicansbook.ru: could not connect to host
 mfcatalin.com: could not connect to host
 mfedderke.com: could not connect to host
 mgdigital.fr: did not receive HSTS header
 mh-bloemen.co.jp: could not connect to host
+mhalfter.de: did not receive HSTS header
 mhdsyarif.com: did not receive HSTS header
 mhealthdemocamp.com: could not connect to host
 mhertel.com: did not receive HSTS header
 mhict.nl: could not connect to host
 mhjuma.com: could not connect to host
 mht-travel.com: could not connect to host
 mhx.pw: could not connect to host
 mi80.com: could not connect to host
@@ -4413,17 +4435,16 @@ minecraft-forums.gq: could not connect t
 minecraftforum.ch: could not connect to host
 minecraftforums.cf: could not connect to host
 minecraftforums.gq: could not connect to host
 minecraftforums.ml: could not connect to host
 minecraftserverz.com: could not connect to host
 minecraftvoter.com: could not connect to host
 mineover.es: could not connect to host
 minesouls.fr: did not receive HSTS header
-mingy.ddns.net: could not connect to host
 minh.at: could not connect to host
 mini-piraten.de: did not receive HSTS header
 minikneet.nl: could not connect to host
 minimoo.se: could not connect to host
 minimvc.com: did not receive HSTS header
 minnesotadata.com: could not connect to host
 minora.io: could not connect to host
 minoris.se: could not connect to host
@@ -4433,17 +4454,16 @@ mironized.com: did not receive HSTS head
 mirrorx.com: did not receive HSTS header
 misiondelosangeles-mailing.com: did not receive HSTS header
 missrain.tw: could not connect to host
 mist.ink: could not connect to host
 mister.hosting: could not connect to host
 misterl.net: did not receive HSTS header
 mitarbeiter-pc.de: did not receive HSTS header
 mitchellrenouf.ca: could not connect to host
-mitsu-szene.de: did not receive HSTS header
 mittenhacks.com: could not connect to host
 mivcon.net: could not connect to host
 mizd.at: could not connect to host
 mizi.name: could not connect to host
 mk-dizajn.com: did not receive HSTS header
 mkasu.org: did not receive HSTS header
 mkw.st: could not connect to host
 mlcdn.co: could not connect to host
@@ -4474,16 +4494,17 @@ mochanstore.com: did not receive HSTS he
 mockmyapp.com: could not connect to host
 mocloud.eu: could not connect to host
 mocsuite.club: could not connect to host
 mocurio.com: could not connect to host
 modded-minecraft-server-list.com: could not connect to host
 moddedark.com: could not connect to host
 mode-marine.com: could not connect to host
 model9.io: did not receive HSTS header
+modelsclub.org.ua: could not connect to host
 modemagazines.co.uk: could not connect to host
 moderatoren.org: did not receive HSTS header
 moderatortv.de: did not receive HSTS header
 modx.by: max-age too low: 31536
 modydev.club: could not connect to host
 moe4sale.in: did not receive HSTS header
 moebel-nagel.de: did not receive HSTS header
 moellers.it: could not connect to host
@@ -4503,16 +4524,17 @@ mona.lu: did not receive HSTS header
 monarca.systems: could not connect to host
 monasterialis.eu: could not connect to host
 mondar.io: could not connect to host
 mondopoint.com: did not receive HSTS header
 mondwandler.de: could not connect to host
 monika-sokol.de: did not receive HSTS header
 monitaure.io: could not connect to host
 monitman.com: did not receive HSTS header
+monpc-pro.fr: did not receive HSTS header
 monsieurbureau.com: did not receive HSTS header
 montanacures.org: could not connect to host
 montenero.pl: could not connect to host
 montonicms.com: could not connect to host
 moobo.xyz: could not connect to host
 moon.lc: could not connect to host
 moonless.net: could not connect to host
 moonloupe.com: could not connect to host
@@ -4544,16 +4566,17 @@ motocyklovedily.cz: did not receive HSTS
 mottvd.com: could not connect to host
 moudicat.com: could not connect to host
 moula.com.au: did not receive HSTS header
 mountainmusicpromotions.com: did not receive HSTS header
 moviedollars.com: did not receive HSTS header
 moviesabout.net: could not connect to host
 moy-gorod.od.ua: did not receive HSTS header
 mp3juices.is: could not connect to host
+mpe.org: could not connect to host
 mqas.net: could not connect to host
 mr-hosting.com: could not connect to host
 mrawe.com: could not connect to host
 mrdani.net: could not connect to host
 mredsanders.net: could not connect to host
 mrettich.org: did not receive HSTS header
 mrhack.cz: did not receive HSTS header
 mrning.com: did not receive HSTS header
@@ -4670,16 +4693,17 @@ namorico.me: could not connect to host
 nan.zone: could not connect to host
 nandex.org: could not connect to host
 naniki.co.uk: did not receive HSTS header
 nanogeneinc.com: could not connect to host
 nanokamo.com: did not receive HSTS header
 nansay.cn: could not connect to host
 nanto.eu: could not connect to host
 narada.com.ua: could not connect to host
+nartuk.com.ua: did not receive HSTS header
 nashira.cz: did not receive HSTS header
 natalia-fadeeva.ru: could not connect to host
 natalia.io: could not connect to host
 natalieandjoshua.com: could not connect to host
 nataliedawnhanson.com: could not connect to host
 natalt.org: did not receive HSTS header
 nathanmfarrugia.com: did not receive HSTS header
 nationwidevehiclecontracts.co.uk: did not receive HSTS header
@@ -4696,57 +4720,55 @@ ncc60205.info: could not connect to host
 ncpc.gov: could not connect to host
 nct.org.uk: did not receive HSTS header
 nctx.co.uk: did not receive HSTS header
 ndtmarket.place: could not connect to host
 near.st: did not receive HSTS header
 nebra.io: could not connect to host
 nebulousenhanced.com: could not connect to host
 nedzad.me: could not connect to host
-neer.io: could not connect to host
 neftaly.com: did not receive HSTS header
 negativecurvature.net: could not connect to host
 neilgreen.net: did not receive HSTS header
 neko-life.com: did not receive HSTS header
 neko-system.com: did not receive HSTS header
 nemno.de: could not connect to host
 nemovement.org: could not connect to host
 neoani.me: could not connect to host
 neofelhz.space: did not receive HSTS header
 neonisi.com: could not connect to host
-neonnuke.tech: did not receive HSTS header
+neonnuke.tech: could not connect to host
 neosolution.ca: did not receive HSTS header
 nephos.xyz: did not receive HSTS header
 nepustil.net: did not receive HSTS header
 nerd42.de: could not connect to host
-nerdhouse.io: could not connect to host
 neris.io: could not connect to host
 nestedquotes.ca: could not connect to host
 net-navi.cc: did not receive HSTS header
 netba.net: could not connect to host
 netbox.cc: could not connect to host
 netherwind.eu: did not receive HSTS header
 nethruster.com: did not receive HSTS header
 netlilo.com: could not connect to host
 netloanusa.com: could not connect to host
-netlocal.ru: could not connect to host
 netmagik.com: did not receive HSTS header
 netprofile.com.au: did not receive HSTS header
 netresourcedesign.com: could not connect to host
 nettefoundation.com: could not connect to host
 networx-online.de: could not connect to host
 netzbit.de: could not connect to host
 netzpolitik.org: max-age too low: 2592000
 netztest.at: did not receive HSTS header
 netzvieh.de: could not connect to host
 netzzwerg4u.de: could not connect to host
 neueonlinecasino2016.com: could not connect to host
 neuralgic.net: could not connect to host
 neuro-plus-100.com: could not connect to host
 neuronfactor.com: max-age too low: 1000
+neurotransmitter.net: could not connect to host
 never-afk.de: did not receive HSTS header
 neveta.com: could not connect to host
 newbieboss.com: did not receive HSTS header
 newcitygas.ca: did not receive HSTS header
 newedivideo.it: could not connect to host
 newgenerationplus.org: could not connect to host
 newhdmovies.io: could not connect to host
 newkaliningrad.ru: did not receive HSTS header
@@ -4760,16 +4782,17 @@ nexgeneration-solutions.com: could not c
 next176.sk: did not receive HSTS header
 nextcloud.org: could not connect to host
 nexth.de: could not connect to host
 nexth.net: could not connect to host
 nexth.us: could not connect to host
 nextpages.de: could not connect to host
 nextproject.us: could not connect to host
 nfo.so: could not connect to host
+nfz.moe: did not receive HSTS header
 ng-security.com: could not connect to host
 ngine.ch: did not receive HSTS header
 nginxnudes.com: could not connect to host
 nglr.org: could not connect to host
 ngt-service.ru: did not receive HSTS header
 ni.search.yahoo.com: did not receive HSTS header
 niagarafalls.ca: did not receive HSTS header
 nibiisclaim.com: could not connect to host
@@ -4785,25 +4808,23 @@ nien.chat: could not connect to host
 nien.org: did not receive HSTS header
 nigger.racing: could not connect to host
 nightsnack.cf: could not connect to host
 nightwinds.tk: could not connect to host
 niho.jp: did not receive HSTS header
 nikcub.com: could not connect to host
 niklas.pw: did not receive HSTS header
 niklaslindblad.se: did not receive HSTS header
-nikolasbradshaw.com: did not receive HSTS header
 ninchisho-online.com: did not receive HSTS header
 ninhs.org: could not connect to host
 ninjaspiders.com: could not connect to host
 nippler.org: did not receive HSTS header
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
 nirudo.me: did not receive HSTS header
-niva.synology.me: could not connect to host
 nixmag.net: did not receive HSTS header
 nkp-media.de: could not connect to host
 nll.fi: could not connect to host
 nmadda.com: did not receive HSTS header
 nmctest.net: could not connect to host
 nmueller.at: could not connect to host
 nnya.cat: could not connect to host
 no-ip.cz: did not receive HSTS header
@@ -4826,29 +4847,28 @@ nopex.no: could not connect to host
 nopol.de: could not connect to host
 norandom.com: could not connect to host
 norb.at: could not connect to host
 nordlicht.photography: did not receive HSTS header
 noref.tk: could not connect to host
 northcutt.com: did not receive HSTS header
 nosecretshop.com: could not connect to host
 notadd.com: did not receive HSTS header
-notarankastojkovic.me: did not receive HSTS header
 notenoughtime.de: could not connect to host
 nothing.net.nz: max-age too low: 7776000
 nothing.org.uk: did not receive HSTS header
 noticia.do: did not receive HSTS header
+notify.moe: could not connect to host
 notjustbitchy.com: did not receive HSTS header
 nottheonion.net: did not receive HSTS header
 nou.si: could not connect to host
 nouvelle-vague-saint-cast.fr: did not receive HSTS header
 nova-elearning.com: did not receive HSTS header
 novaco.in: max-age too low: 3600
 novacoast.com: did not receive HSTS header
-novascan.net: could not connect to host
 novatrucking.de: could not connect to host
 novavoidhowl.com: did not receive HSTS header
 novelabs.de: could not connect to host
 novurania.com: did not receive HSTS header
 nowak.ninja: did not receive HSTS header
 noworrywp.com: could not connect to host
 nozoe.jp: could not connect to host
 np.search.yahoo.com: did not receive HSTS header
@@ -4918,17 +4938,17 @@ offenedialoge.de: max-age too low: 25920
 officeclub.com.mx: did not receive HSTS header
 offshore-firma.org: could not connect to host
 offshore-unternehmen.com: could not connect to host
 offshorefirma-gruenden.com: could not connect to host
 offshoremarineparts.com: did not receive HSTS header
 ofo2.com: could not connect to host
 oganek.ie: could not connect to host
 ogogoshop.com: could not connect to host
-ohai.su: did not receive HSTS header
+ohai.su: could not connect to host
 ohling.org: could not connect to host
 ohyooo.com: could not connect to host
 oiepoie.nl: could not connect to host
 oishioffice.com: did not receive HSTS header
 ojls.co: could not connect to host
 okane.love: could not connect to host
 okok-rent.com: could not connect to host
 okok.rent: could not connect to host
@@ -4936,16 +4956,17 @@ okutama.in.th: could not connect to host
 olanderflorist.com: could not connect to host
 olcso-vps-szerver.hu: could not connect to host
 oldchaphome.nl: did not receive HSTS header
 oldoakflorist.com: could not connect to host
 oliverdunk.com: did not receive HSTS header
 ollehbizev.co.kr: could not connect to host
 olswangtrainees.com: could not connect to host
 omacostudio.com: could not connect to host
+omarh.net: could not connect to host
 omgaanmetidealen.com: could not connect to host
 ominto.com: max-age too low: 0
 omniscimus.net: could not connect to host
 omniti.com: max-age too low: 1
 omquote.gq: could not connect to host
 omskit.ru: did not receive HSTS header
 onearth.one: did not receive HSTS header
 oneb4nk.com: could not connect to host
@@ -5011,16 +5032,17 @@ openquery.com.au: did not receive HSTS h
 openshift.redhat.com: did not receive HSTS header
 opensourcehouse.net: could not connect to host
 opensrd.com: could not connect to host
 openssf.org: could not connect to host
 openxmpp.com: could not connect to host
 opim.ca: did not receive HSTS header
 opoleo.com: could not connect to host
 opperwall.net: could not connect to host
+oprechtgezegd.nl: could not connect to host
 opsafewinter.net: could not connect to host
 opsbears.com: did not receive HSTS header
 opstacks.com: did not receive HSTS header
 optenhoefel.de: could not connect to host
 optimista.soy: could not connect to host
 optometriepunt.nl: did not receive HSTS header
 optumrxhealthstore.com: could not connect to host
 oracaodocredo.com.br: could not connect to host
@@ -5132,19 +5154,16 @@ parpaing-paillette.net: could not connec
 particonpsplus.it: did not receive HSTS header
 partirkyoto.jp: did not receive HSTS header
 partyhaus.ovh: did not receive HSTS header
 partyvan.eu: could not connect to host
 partyvan.it: could not connect to host
 partyvan.moe: could not connect to host
 partyvan.nl: could not connect to host
 partyvan.se: could not connect to host
-pascalmathis.com: did not receive HSTS header
-pascalmathis.me: did not receive HSTS header
-pascalmathis.net: did not receive HSTS header
 passumpsicbank.com: did not receive HSTS header
 passwd.io: could not connect to host
 passwordbox.com: did not receive HSTS header
 passwordrevelator.net: did not receive HSTS header
 pastaf.com: could not connect to host
 pastdream.xyz: could not connect to host
 paste.linode.com: could not connect to host
 pastebin.linode.com: could not connect to host
@@ -5154,17 +5173,17 @@ patadanabouca.pw: could not connect to h
 pataua.kiwi: could not connect to host
 paternitydnatest.com: could not connect to host
 paterno-gaming.com: could not connect to host
 patfs.com: did not receive HSTS header
 patientinsight.net: did not receive HSTS header
 patt.us: could not connect to host
 patterson.mp: could not connect to host
 paul-kerebel.pro: could not connect to host
-paulbramhall.uk: could not connect to host
+paulbramhall.uk: did not receive HSTS header
 paulbunyanmls.com: did not receive HSTS header
 paulproell.at: could not connect to host
 paulshir.com: could not connect to host
 paulyang.cn: did not receive HSTS header
 pavelfojt.cz: did not receive HSTS header
 paxwinkel.nl: did not receive HSTS header
 pay.gigahost.dk: did not receive HSTS header
 paybro.eu: did not receive HSTS header
@@ -5214,17 +5233,16 @@ perlwork.nl: [Exception... "Component re
 pernatie.ru: could not connect to host
 perplex.nl: did not receive HSTS header
 perroud.pro: did not receive HSTS header
 personalcommunicationsecurity.com: could not connect to host
 personaldatabasen.no: could not connect to host
 personalinjurylist.com: could not connect to host
 personalizedtouch.co: could not connect to host
 perthdevicelab.com: did not receive HSTS header
-pervacio.hu: could not connect to host
 pet-nsk.ru: could not connect to host
 petchart.net: could not connect to host
 peterdavehello.org: did not receive HSTS header
 petersmark.com: could not connect to host
 pethub.com: did not receive HSTS header
 petit.site: could not connect to host
 petplum.com: could not connect to host
 petravdbos.nl: did not receive HSTS header
@@ -5276,17 +5294,17 @@ pinpayments.com: did not receive HSTS he
 pippen.io: could not connect to host
 pirata.ga: could not connect to host
 piratebit.tech: could not connect to host
 piratedb.com: could not connect to host
 piratedot.com: could not connect to host
 piratelist.online: could not connect to host
 piratenlogin.de: could not connect to host
 pirateproxy.pe: could not connect to host
-pirateproxy.sx: did not receive HSTS header
+pirateproxy.sx: could not connect to host
 pirateproxy.vip: could not connect to host
 pirati.cz: did not receive HSTS header
 piratte.net: did not receive HSTS header
 pirlitu.com: did not receive HSTS header
 pisexy.me: did not receive HSTS header
 pisidia.de: could not connect to host
 pitchup.com: did not receive HSTS header
 pitonarms.com: could not connect to host
@@ -5379,28 +5397,26 @@ poussinooz.fr: could not connect to host
 povitria.net: could not connect to host
 powdersnow.top: could not connect to host
 power-of-interest.com: could not connect to host
 power99press.com: did not receive HSTS header
 poweroff.win: could not connect to host
 powerplannerapp.com: did not receive HSTS header
 powershift.ne.jp: did not receive HSTS header
 powerxequality.com: could not connect to host
-ppmathis.ch: did not receive HSTS header
-ppmathis.com: did not receive HSTS header
 ppr-truby.ru: could not connect to host
 ppuu.org: did not receive HSTS header
 ppy3.com: did not receive HSTS header
 pr.search.yahoo.com: did not receive HSTS header
 pr2studio.com: could not connect to host
 practicallabs.com: could not connect to host
+practodev.com: did not receive HSTS header
 pratinav.xyz: could not connect to host
 prattpokemon.com: could not connect to host
 praxis-research.info: did not receive HSTS header
-prc.gov: did not receive HSTS header
 prediksisydney.com: could not connect to host
 preezzie.com: could not connect to host
 prefis.com: did not receive HSTS header
 prefontaine.name: could not connect to host
 prego-shop.de: did not receive HSTS header
 preissler.co.uk: could not connect to host
 prelist.org: did not receive HSTS header
 prenger.co: could not connect to host
@@ -5411,16 +5427,17 @@ presidentials2016.com: could not connect
 press-anime-nenkan.com: did not receive HSTS header
 pressfreedomfoundation.org: did not receive HSTS header
 prettygrouse.com: did not receive HSTS header
 pretzlaff.info: did not receive HSTS header
 preworkout.me: could not connect to host
 prezola.com: did not receive HSTS header
 prgslab.net: could not connect to host
 pridoc.se: did not receive HSTS header
+prielwurmjaeger.de: did not receive HSTS header
 printerest.io: could not connect to host
 printexpress.cloud: did not receive HSTS header
 printfn.com: could not connect to host
 priolkar.com: did not receive HSTS header
 privacylabs.io: did not receive HSTS header
 privacyrup.net: could not connect to host
 privateideas.de: could not connect to host
 privytime.com: could not connect to host
@@ -5446,17 +5463,16 @@ projectascension.io: could not connect t
 projectdp.net: could not connect to host
 projectmercury.space: could not connect to host
 projetoresecia.com: did not receive HSTS header
 promecon-gmbh.de: did not receive HSTS header