Merge inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Wed, 17 Jan 2018 11:46:53 +0200
changeset 721495 4e429d313fd2e0f9202271ee8f3fb798817ec3e7
parent 721456 5a130721f8ea9793e201453caf4bc56d5b3ae53f (current diff)
parent 721494 c8137f45cf3aea65921a8bc7ae8061cc14f9e93f (diff)
child 721496 06b7afe876c2026b944ad8f84b6fd1e5b83a72bf
child 721500 4fe5c71008b470f4c8b15f05e903d50d5c6e9303
child 721514 4bf1fe5b99dca6cf7f41f633857b2d0c302070a3
child 721527 7eaf34a4efa6768d94a9b7c4ceeabbde1e6910eb
child 721548 ddfb55d1367fde0b4abefb09b804b879ebb3e79d
child 721559 0a32242ee02ef54cf8f06c7dcd2977333e90905b
child 721567 82bdc08c16fe6538e362b09bb6e53a0741e8f6b8
child 721570 2e45e00dc9ae1564b37d9454b4bd855ee26af9db
child 721573 0ac9b67599d749fb273bf60ece999965f40578c1
child 721583 7e2e0484a193cc4823e0e7f73174469d93ce2917
child 721585 fca51cb43951784007d9997d0c95da5269053dd5
child 721586 29496d12f023c52e20466000c2e679c9cf67351c
child 721589 724dfb33df76b4f7835f6e34614a7f6a65b5051a
child 721590 e07dd380a84614a3e6b8a9000883af092197b021
child 721591 81bce4779be2feca70ace6a1a616b0c7dc042e6b
child 721592 41145d09cad5c4ca21539df9cb2c22f6f568e985
child 721593 1f632ddd3175cb83f8a8c61d5bd7d013d9679d9c
child 721603 9a7540b8bae28961cde48c655d51281910640daf
child 721604 e1e80d86539c0f40e003ce645d2167234a1854d0
child 721605 90550adae012e1bf9df8bc75f4c4b94265ebad8d
child 721608 8fb58e31a85046380fac21692e84ea5730db1348
child 721610 1a4c5f3d7b9a3ef320aa5e07145dcfd6084465ce
child 721611 105d3c0fbf506f87bb9e774eb6ff36d61874d031
child 721613 17f8fc886c940d47d0bfab902257428704cfe3f5
child 721628 cc4d53871cb65e2ec3aa52cfb65e03c24824d67f
child 721632 e0bd7c82e78083292b3138ed1fb761df8dfb3acf
child 721633 32c292a473754b4962f0049006b81aa813cb6770
child 721643 6c19c5aaabe48de438b593287ddd32317b8b8c7c
child 721644 4895709f80a262bde251cd6435b7de87eb3ef6df
child 721655 0aa633408a7009be49dddcff6861ef1ab3935311
child 721662 7c4e72e62dc0b85de0a30c49d17be1ef202603ef
child 721665 872c8e63b7cf17848823e6413ffc108ea0ea3404
child 721666 8baa204f7a336a21f9ae9d3e7e836450874571fd
child 721667 6282958680171e93630d2cd975788b5d2ff96c74
child 721668 5bd64855cf8ca17d31b1b565c2ae73677cf956e4
child 721670 10190b2d356fde01e62237b383002468efe8ffca
child 721686 375242c390603892d79d85c5dd6d425b615e4e97
child 721690 11086759cb56e51300d79e05bc3d06f5da7a67f9
child 721697 fc5a32e73bd39d64788e7cd4a2e376b482a2d5d6
child 721701 9d089d54c9f4f3bf04aee0b83bd6007047415740
child 721707 b851fdb9ce4ce7738b40294f18a2711d27512fb4
child 721721 3eeb832ace97ae24cfeb3db0cbcdbc3390b1f304
child 721793 44be96dbd0ff93274ca60619dfad9fbba32a8cfd
child 721797 0f33ff3a72ee0518dd09085cb04324e06f24df7c
child 721852 5239a35d4a16173a539cae22a605835402facb2a
child 721860 7a4efcf50e63a69c8f9709157d2b43a1582264f4
child 721863 28b8352ec09919ef5e67a283a3b0c23a5e8a4fe8
child 721864 8d33e73c7eca08edf3795972e8f76e59e535694e
child 721873 5cbd8b28ea8c17580209c2aa7f66af1b5e5f6483
child 721881 7561fa4b78299072f646a0f8329226de7cf1e08f
child 721901 a960d10c4f00ef9141c3792a343e0408baddeb26
child 722014 3dd345ed962ee97f8ff8dca9b0475b016cfa9051
child 722028 8b778c1585b0348de1696b8b176de27356a171e0
child 722100 72deae1db6620e8f38c9aa1116fb0636f2b08b53
child 722166 690c5303fce7fa448811344769d20d784262daab
child 722172 c5fcd80205aa45ca060457c9cc748fbcb086a558
child 722174 d97c7e1786b18ad83a7bf9dbde73569fb88a4099
child 722176 3933deea05640559c3dc00c6d4d8211af0e71965
child 722177 ce1202cae13c717c9c6a6755e96c9afec8b29444
child 722230 97ae122f745bc49063ff1a0c1b1f9da3dc930407
child 722281 6139a9353b536bdfc69faf7545be4ea35de724f0
child 722293 7d3345b311101e03652461cd336e0dd748706744
child 722302 bd9bda3b524b15acda79be2ce08b3a374a2e7dbe
child 722589 a3aa6f70d2b909ecbec78aab79a88d53ebe8eb31
child 722676 294c01149b7dff72326beebb705fe3cb8940202f
child 722678 c31307843debb8d66e203f0d024434412b748a5d
child 722682 076e3f557fb13b81f5695dec2033ad3c0aa3124f
child 723243 16dfec69b8b0e4c70f3438db5043dcd0b7bc97f0
child 723322 c391076899cb2f78713bca6369ab20392e84fe80
child 723325 43027ebec000840331246a455c9cbd6703ce9f81
child 723327 3110915d15ffe9ea1916a6bd4957911bac0493fb
child 723833 3749b48a015938ec25b0bafbb615ecb710caf9ec
child 724064 9b6b809ee3d4b782a9708d369ab765e2839a92fd
push id95847
push userbmo:oriol-bugzilla@hotmail.com
push dateWed, 17 Jan 2018 10:32:58 +0000
reviewersmerge
milestone59.0a1
Merge inbound to mozilla-central. a=merge
browser/config/mozconfigs/win32/debug-searchfox
dom/base/nsContentUtils.cpp
dom/canvas/test/webgl-mochitest/mochitest.ini
dom/ipc/ContentParent.cpp
dom/ipc/PContent.ipdl
modules/libpref/init/all.js
taskcluster/ci/searchfox/kind.yml
taskcluster/taskgraph/transforms/docker_image.py
taskcluster/taskgraph/transforms/task.py
testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_searchfox_debug.py
toolkit/components/backgroundhangmonitor/HangStack.cpp
toolkit/components/backgroundhangmonitor/HangStack.h
--- a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
+++ b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
@@ -70,10 +70,16 @@ add_task(async function() {
 
   // This is sync in non-e10s, but in e10s we need to wait for this, so yield anyway.
   // Note that the switchTab promise doesn't actually guarantee anything about *which*
   // tab ends up as selected when its event fires, so using that here wouldn't work.
   await openedTabSelectedPromise;
   // should be switched back
   ok(openedTab.selected, "Ta-dah, the other tab should now be selected again!");
 
+  // In e10s, with the conformant promise scheduling, we have to wait for next tick
+  // to ensure that the prompt is open before removing the opened tab, because the
+  // promise callback of 'openedTabSelectedPromise' could be done at the middle of
+  // RemotePrompt.openTabPrompt() while 'DOMModalDialogClosed' event is fired.
+  await TestUtils.waitForTick();
+
   await BrowserTestUtils.removeTab(openedTab);
 });
rename from browser/config/mozconfigs/win32/debug-searchfox
rename to browser/config/mozconfigs/win64/debug-searchfox
--- a/browser/config/mozconfigs/win32/debug-searchfox
+++ b/browser/config/mozconfigs/win64/debug-searchfox
@@ -1,17 +1,18 @@
 MOZ_AUTOMATION_BUILD_SYMBOLS=0
 MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/mozconfig.win-common"
 . "$topsrcdir/browser/config/mozconfigs/common"
+. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 
 ac_add_options --enable-optimize
 ac_add_options --enable-debug
 
 ac_add_options --enable-clang-plugin
 ac_add_options --enable-mozsearch-plugin
 
-. $topsrcdir/build/win32/mozconfig.vs-latest
+. $topsrcdir/build/win64/mozconfig.vs-latest
 
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.clang-cl"
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm
@@ -274,16 +274,32 @@ this.TestRunner = {
       } else {
         bounds = bounds.union(rect);
       }
     }
 
     return {bounds, rects};
   },
 
+  _do_skip(reason, combo, config, func) {
+    const { todo } = reason;
+    if (todo) {
+      this.mochitestScope.todo(
+        false,
+        `Skipped configuration ` +
+        `[ ${combo.map((e) => e.name).join(", ")} ] for failure in ` +
+        `${config.name}.${func}: ${todo}`);
+    } else {
+      this.mochitestScope.info(
+        `\tSkipped configuration ` +
+        `[ ${combo.map((e) => e.name).join(", ")} ] ` +
+        `for "${reason}" in  ${config.name}.${func}`);
+    }
+  },
+
   async _performCombo(combo) {
     let paddedComboIndex = padLeft(this.currentComboIndex + 1, String(this.combos.length).length);
     this.mochitestScope.info(
       `Combination ${paddedComboIndex}/${this.combos.length}: ${this._comboName(combo).substring(1)}`
     );
 
     // Notice that this does need to be a closure, not a function, as otherwise
     // "this" gets replaced and we lose access to this.mochitestScope.
@@ -293,30 +309,34 @@ this.TestRunner = {
       let applyPromise = Promise.resolve(config.applyConfig());
       let timeoutPromise = new Promise((resolve, reject) => {
         setTimeout(reject, APPLY_CONFIG_TIMEOUT_MS, "Timed out");
       });
 
       this.mochitestScope.info("called " + config.name);
       // Add a default timeout of 500ms to avoid conflicts when configurations
       // try to apply at the same time. e.g WindowSize and TabsInTitlebar
-      return Promise.race([applyPromise, timeoutPromise]).then(() => {
+      return Promise.race([applyPromise, timeoutPromise]).then(result => {
         return new Promise((resolve) => {
-          setTimeout(resolve, 500);
+          setTimeout(() => resolve(result), 500);
         });
       });
     };
 
     try {
       // First go through and actually apply all of the configs
       for (let i = 0; i < combo.length; i++) {
         let config = combo[i];
         if (!this._lastCombo || config !== this._lastCombo[i]) {
           this.mochitestScope.info(`promising ${config.name}`);
-          await changeConfig(config);
+          const reason = await changeConfig(config);
+          if (reason) {
+            this._do_skip(reason, combo, config, "applyConfig");
+            return;
+          }
         }
       }
 
       // Update the lastCombo since it's now been applied regardless of whether it's accepted below.
       this.mochitestScope.info("fulfilled all applyConfig so setting lastCombo.");
       this._lastCombo = combo;
 
       // Then ask configs if the current setup is valid. We can't can do this in
@@ -325,28 +345,32 @@ this.TestRunner = {
       for (let i = 0; i < combo.length; i++) {
         let config = combo[i];
         // A configuration can specify an optional verifyConfig method to indicate
         // if the current config is valid for a screenshot. This gets called even
         // if the this config was used in the lastCombo since another config may
         // have invalidated it.
         if (config.verifyConfig) {
           this.mochitestScope.info(`checking if the combo is valid with ${config.name}`);
-          await config.verifyConfig();
+          const reason = await config.verifyConfig();
+          if (reason) {
+            this._do_skip(reason, combo, config, "applyConfig");
+            return;
+          }
         }
       }
     } catch (ex) {
-      this.mochitestScope.info(`\tskipped configuration [ ${combo.map((e) => e.name).join(", ")} ]`);
-      this.mochitestScope.info(`\treason: ${ex.toString()}`);
-      // Don't set lastCombo here so that we properly know which configurations
-      // need to be applied since the last screenshot
-
-      // Return so we don't take a screenshot.
+      this.mochitestScope.ok(false, `Unexpected exception in [ ${combo.map(({ name }) => name).join(", ")} ]: ${ex.toString()}`);
+      this.mochitestScope.info(`\t${ex}`);
+      if (ex.stack) {
+        this.mochitestScope.info(`\t${ex.stack}`);
+      }
       return;
     }
+    this.mochitestScope.info(`Configured UI for [ ${combo.map(({ name }) => name).join(", ")} ] successfully`);
 
     // Collect selectors from combo configs for cropping region
     let windowType;
     const finalSelectors = [];
     for (const obj of combo) {
       if (!windowType) {
         windowType = obj.windowType;
       } else if (windowType !== obj.windowType) {
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/AppMenu.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/AppMenu.jsm
@@ -30,57 +30,57 @@ this.AppMenu = {
         let promise = browserWindow.PanelUI.show();
         browserWindow.PanelUI.showMainView();
         return promise;
       },
     },
 
     appMenuHistorySubview: {
       selectors: ["#appMenu-popup"],
-      applyConfig() {
+      async applyConfig() {
         // History has a footer
         if (isCustomizing()) {
-          return Promise.reject("Can't show subviews while customizing");
+          return "Can't show subviews while customizing";
         }
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
-        let promise = browserWindow.PanelUI.show();
-        return promise.then(() => {
-          browserWindow.PanelUI.showMainView();
-          browserWindow.document.getElementById("history-panelmenu").click();
-        });
+        await browserWindow.PanelUI.show();
+        browserWindow.PanelUI.showMainView();
+        browserWindow.document.getElementById("history-panelmenu").click();
+
+        return undefined;
       },
 
       verifyConfig: verifyConfigHelper,
     },
 
     appMenuHelpSubview: {
       selectors: ["#appMenu-popup"],
-      applyConfig() {
+      async applyConfig() {
         if (isCustomizing()) {
-          return Promise.reject("Can't show subviews while customizing");
+          return "Can't show subviews while customizing";
         }
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
-        let promise = browserWindow.PanelUI.show();
-        return promise.then(() => {
-          browserWindow.PanelUI.showMainView();
-          browserWindow.document.getElementById("PanelUI-help").click();
-        });
+        await browserWindow.PanelUI.show();
+        browserWindow.PanelUI.showMainView();
+        browserWindow.document.getElementById("PanelUI-help").click();
+
+        return undefined;
       },
 
       verifyConfig: verifyConfigHelper,
     },
 
   },
 };
 
 function verifyConfigHelper() {
   if (isCustomizing()) {
-    return Promise.reject("AppMenu verifyConfigHelper");
+    return "navigator:browser has the customizing attribute";
   }
-  return Promise.resolve("AppMenu verifyConfigHelper");
+  return undefined;
 }
 
 function isCustomizing() {
   let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
   if (browserWindow.document.documentElement.hasAttribute("customizing")) {
     return true;
   }
   return false;
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Buttons.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Buttons.jsm
@@ -33,37 +33,37 @@ this.Buttons = {
     },
 
     menuPanelButtons: {
       selectors: ["#widget-overflow"],
       applyConfig: async () => {
         CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
       },
 
-      verifyConfig() {
+      async verifyConfig() {
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
         if (browserWindow.PanelUI.panel.state == "closed") {
-          return Promise.reject("The button isn't shown when the panel isn't open.");
+          return "The button isn't shown when the panel isn't open.";
         }
-        return Promise.resolve("menuPanelButtons.verifyConfig");
+        return undefined;
       },
     },
 
     custPaletteButtons: {
       selectors: ["#customization-palette"],
       applyConfig: async () => {
         CustomizableUI.removeWidgetFromArea("screenshot-widget");
       },
 
-      verifyConfig() {
+      async verifyConfig() {
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
         if (browserWindow.document.documentElement.getAttribute("customizing") != "true") {
-          return Promise.reject("The button isn't shown when we're not in customize mode.");
+          return "The button isn't shown when we're not in customize mode.";
         }
-        return Promise.resolve("custPaletteButtons.verifyConfig");
+        return undefined;
       },
     },
   },
 };
 
 function createWidget() {
   let id = "screenshot-widget";
   let spec = {
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/ControlCenter.jsm
@@ -50,17 +50,17 @@ this.ControlCenter = {
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
         let gBrowser = browserWindow.gBrowser;
         BrowserTestUtils.loadURI(gBrowser.selectedBrowser, channel.file.path);
         await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
         await openIdentityPopup();
       },
 
       async verifyConfig() {
-        return Promise.reject("Bug 1373563: intermittent controlCenter_localFile on Taskcluster");
+        return { todo: "Bug 1373563: intermittent controlCenter_localFile on Taskcluster" };
       },
     },
 
     http: {
       selectors: ["#identity-popup"],
       async applyConfig() {
         await loadPage(HTTP_PAGE);
         await openIdentityPopup();
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/PermissionPrompts.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/PermissionPrompts.jsm
@@ -107,18 +107,20 @@ this.PermissionPrompts = {
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
         let notification = browserWindow.document.getElementById("addon-install-confirmation-notification");
 
         await closeLastTab();
         await clickOn("#addons");
 
         // We want to skip the progress-notification, so we wait for
         // the install-confirmation screen to be "not hidden" = shown.
-        await BrowserTestUtils.waitForCondition(() => !notification.hasAttribute("hidden"),
-                                                "addon install confirmation did not show", 200);
+        return BrowserTestUtils.waitForCondition(() => !notification.hasAttribute("hidden"),
+                                                "addon install confirmation did not show", 200).catch((msg) => {
+                                                  return Promise.resolve({todo: msg});
+                                                });
       },
     },
   },
 };
 
 async function closeLastTab() {
   if (!lastTab) {
     return;
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Preferences.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Preferences.jsm
@@ -31,30 +31,38 @@ this.Preferences = {
 
     for (let [primary, customFn] of panes) {
       let configName = primary.replace(/^pane/, "prefs");
       if (customFn) {
         configName += "-" + customFn.name;
       }
       this.configurations[configName] = {};
       this.configurations[configName].selectors = ["#browser"];
-      this.configurations[configName].applyConfig = prefHelper.bind(null, primary, customFn);
+      if (primary == "panePrivacy" && customFn) {
+        this.configurations[configName].applyConfig = async () => {
+          return {todo: `${configName} times out on the try server`};
+        };
+      } else {
+        this.configurations[configName].applyConfig = prefHelper.bind(null, primary, customFn);
+      }
     }
   },
 
   configurations: {},
 };
 
 let prefHelper = async function(primary, customFn = null) {
   let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
   let selectedBrowser = browserWindow.gBrowser.selectedBrowser;
 
   // close any dialog that might still be open
   await ContentTask.spawn(selectedBrowser, null, async function() {
-    if (!content.window.gSubDialog) {
+    // Check that gSubDialog is defined on the content window
+    // and that there is an open dialog to close
+    if (!content.window.gSubDialog || !content.window.gSubDialog._topDialog) {
       return;
     }
     content.window.gSubDialog.close();
   });
 
   let readyPromise = null;
   if (selectedBrowser.currentURI.specIgnoringRef == "about:preferences") {
     if (selectedBrowser.currentURI.spec == "about:preferences#" + primary.replace(/^pane/, "")) {
@@ -68,19 +76,21 @@ let prefHelper = async function(primary,
   }
 
   browserWindow.openPreferences(primary, {origin: "mozscreenshots"});
 
   await readyPromise;
 
   if (customFn) {
     let customPaintPromise = paintPromise(browserWindow);
-    await customFn(selectedBrowser);
+    let result = await customFn(selectedBrowser);
     await customPaintPromise;
+    return result;
   }
+  return undefined;
 };
 
 function paintPromise(browserWindow) {
   return new Promise((resolve) => {
     browserWindow.addEventListener("MozAfterPaint", function() {
       resolve();
     }, {once: true});
   });
@@ -94,18 +104,23 @@ async function browsingGroup(aBrowser) {
 
 async function cacheGroup(aBrowser) {
   await ContentTask.spawn(aBrowser, null, async function() {
     content.document.getElementById("cacheGroup").scrollIntoView();
   });
 }
 
 async function DNTDialog(aBrowser) {
-  await ContentTask.spawn(aBrowser, null, async function() {
-    content.document.getElementById("doNotTrackSettings").click();
+  return ContentTask.spawn(aBrowser, null, async function() {
+    const button = content.document.getElementById("doNotTrackSettings");
+    if (!button) {
+      return {todo: "The dialog may have exited before we could click the button"};
+    }
+    button.click();
+    return undefined;
   });
 }
 
 async function connectionDialog(aBrowser) {
   await ContentTask.spawn(aBrowser, null, async function() {
     content.document.getElementById("connectionSettings").click();
   });
 }
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
@@ -48,17 +48,17 @@ this.Tabs = {
         tab = browserWindow.gBrowser.addTab("about:privatebrowsing");
         browserWindow.gBrowser.pinTab(tab);
         tab = browserWindow.gBrowser.addTab("about:home");
         browserWindow.gBrowser.pinTab(tab);
         browserWindow.gBrowser.selectTabAtIndex(5);
         hoverTab(browserWindow.gBrowser.tabs[2]);
         // also hover the new tab button
         let newTabButton = browserWindow.document.getAnonymousElementByAttribute(browserWindow.
-                           gBrowser.tabContainer, "class", "tabs-newtab-button");
+                           gBrowser.tabContainer, "anonid", "tabs-newtab-button");
         hoverTab(newTabButton);
         browserWindow.gBrowser.tabs[browserWindow.gBrowser.tabs.length - 1].
                       setAttribute("beforehovered", true);
 
         await new Promise((resolve, reject) => {
           setTimeout(resolve, 3000);
         });
         await allTabTitlesDisplayed(browserWindow);
@@ -129,16 +129,17 @@ this.Tabs = {
 
 /* helpers */
 
 async function allTabTitlesDisplayed(browserWindow) {
   let specToTitleMap = {
     "about:home": "New Tab",
     "about:newtab": "New Tab",
     "about:addons": "Add-ons Manager",
+    "about:privatebrowsing": "Open a private window?"
   };
   specToTitleMap[PREFS_TAB] = "browser/skin/settings.svg";
   specToTitleMap[CUST_TAB] = "browser/skin/customize.svg";
   specToTitleMap[DEFAULT_FAVICON_TAB] = "No favicon";
 
   let tabTitlePromises = [];
   for (let tab of browserWindow.gBrowser.tabs) {
     function tabTitleLoaded(spec) {
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/TabsInTitlebar.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/TabsInTitlebar.jsm
@@ -16,17 +16,17 @@ this.TabsInTitlebar = {
 
   init(libDir) {},
 
   configurations: {
     tabsInTitlebar: {
       selectors: ["#navigator-toolbox"],
       async applyConfig() {
         if (Services.appinfo.OS == "Linux") {
-          return Promise.reject("TabsInTitlebar isn't supported on Linux");
+          return "TabsInTitlebar isn't supported on Linux";
         }
         Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, true);
         return undefined;
       },
     },
 
     tabsOutsideTitlebar: {
       selectors: ["#navigator-toolbox"].concat(Services.appinfo.OS == "Linux" ? [] : ["#titlebar"]),
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Toolbars.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Toolbars.jsm
@@ -31,17 +31,17 @@ this.Toolbars = {
         let personalToolbar = browserWindow.document.getElementById("PersonalToolbar");
         browserWindow.setToolbarVisibility(personalToolbar, true);
         toggleMenubarIfNecessary(true);
       },
 
       async verifyConfig() {
         let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
         if (browserWindow.fullScreen) {
-          return Promise.reject("The bookmark toolbar and menubar are not shown in fullscreen.");
+          return "The bookmark toolbar and menubar are not shown in fullscreen.";
         }
         return undefined;
       },
     },
 
   },
 };
 
--- a/browser/tools/mozscreenshots/primaryUI/browser_primaryUI.js
+++ b/browser/tools/mozscreenshots/primaryUI/browser_primaryUI.js
@@ -6,11 +6,15 @@
 
 "use strict";
 
 add_task(async function capture() {
   if (!shouldCapture()) {
     return;
   }
 
+  if (AppConstants.platform == "macosx") {
+    // Bug 1425394 - Generate output so mozprocess knows we're still alive for the long session.
+    SimpleTest.requestCompleteLog();
+  }
   let sets = ["TabsInTitlebar", "Tabs", "WindowSize", "Toolbars", "LightweightThemes", "UIDensities"];
   await TestRunner.start(sets, "primaryUI");
 });
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 8.0
-commit https://github.com/devtools-html/debugger.html/commit/9be8e9d9e7a70730bc02e50ae019028f1f06b14e
-comparison https://github.com/devtools-html/debugger.html/compare/release-7...release-8
+Version 9.0
+commit: https://github.com/devtools-html/debugger.html/commit/0de8d3f673ee0f0030d666f1827380e17bef8036
+comparison: https://github.com/devtools-html/debugger.html/compare/release-8...release-9
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.0
 - babel-preset-react @6.24.1
 - react @15.6.2
 - react-dom @15.6.2
 - webpack @3.10.0
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -1563,44 +1563,48 @@ html[dir="rtl"] .managed-tree .tree .nod
   padding: 0.5em;
   user-select: none;
   font-size: 12px;
 }
 
 .outline-list {
   list-style-type: none;
   width: 100%;
-  padding: 10px;
+  padding: 10px 0px;
   margin: 0;
 }
 
 .outline-list__class-list {
   list-style: none;
   margin: 0;
   padding: 0;
 }
 
 .outline-list h2 {
   font-weight: normal;
   font-size: 1em;
-  margin: 10px 0;
+  margin: 10px 0 10px 10px;
   color: var(--theme-body-color);
 }
 
 .outline-list__element {
   padding-bottom: 0.5rem;
   padding-right: 0.5rem;
   padding-top: 0.2rem;
   cursor: default;
   white-space: nowrap;
 }
 
 .outline-list__element:hover {
   background: var(--theme-toolbar-background-hover);
 }
+
+.outline-list__element .function {
+  padding-left: 10px;
+}
 /* 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/>. */
 
 .function-signature {
   align-self: center;
 }
 
@@ -2844,26 +2848,50 @@ html .breakpoints-list .breakpoint.pause
 
 .breakpoint:hover .close {
   visibility: visible;
 }
 /* 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/>. */
 
+.expression-input-form {
+  width: 100%;
+}
+
 .input-expression {
   width: 100%;
-  margin: 0px;
+  margin: 0;
   border: 1px;
   background-color: var(--theme-sidebar-background);
   font-size: 12px;
-  padding: 0px 20px;
+  padding: 0.5em 2.16em;
   color: var(--theme-body-color);
 }
 
+@keyframes shake {
+  0%,
+  100% {
+    transform: translateX(0);
+  }
+  20%,
+  60% {
+    transform: translateX(-10px);
+  }
+  40%,
+  80% {
+    transform: translateX(10px);
+  }
+}
+
+.input-expression.error {
+  border: 1px solid red;
+  animation: 150ms cubic-bezier(0.07, 0.95, 0, 1) shake;
+}
+
 .input-expression::placeholder {
   text-align: center;
   font-style: italic;
   color: var(--theme-comment-alt);
   opacity: 1;
 }
 
 .input-expression:focus {
@@ -2872,17 +2900,16 @@ html .breakpoints-list .breakpoint.pause
 }
 
 .expressions-list {
   /* TODO: add normalize */
   margin: 0;
   padding: 0;
 }
 .expression-input-container {
-  padding: 0.5em;
   display: flex;
 }
 
 .expression-container {
   border: 1px;
   padding: 0.25em 1em 0.25em 0.5em;
   width: 100%;
   color: var(--theme-body-color);
@@ -3362,25 +3389,28 @@ img.resume {
 html[dir="rtl"] .dropdown {
   right: calc((var(--width) - 11px) * (-1));
 }
 
 .dropdown-block {
   padding: 0px 2px;
   position: relative;
   align-self: center;
+  height: 100%;
 }
 
 .dropdown-button {
   color: var(--theme-content-color3);
   background: none;
   border: none;
   padding: 0;
   font-weight: 100;
   font-size: 14px;
+  height: 100%;
+  width: 24px;
 }
 
 .dropdown li {
   transition: all 0.25s ease;
   padding: 2px 10px 10px 5px;
   overflow: hidden;
   height: 30px;
   text-overflow: ellipsis;
@@ -3391,16 +3421,17 @@ html[dir="rtl"] .dropdown {
   background-color: var(--search-overlays-semitransparent);
 }
 
 .dropdown-icon {
   width: var(--icon-size);
   height: var(--icon-size);
   margin-right: 5px;
   vertical-align: middle;
+  display: inline-block;
 }
 
 .dropdown-icon.prettyPrint {
   mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
   mask-size: 100%;
   background: var(--theme-highlight-blue);
 }
 
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -10240,19 +10240,19 @@ if (isDevelopment()) {
   pref("devtools.debugger.features.wasm", true);
   pref("devtools.debugger.features.shortcuts", true);
   pref("devtools.debugger.features.root", true);
   pref("devtools.debugger.features.column-breakpoints", false);
   pref("devtools.debugger.features.chrome-scopes", false);
   pref("devtools.debugger.features.map-scopes", true);
   pref("devtools.debugger.features.breakpoints-dropdown", true);
   pref("devtools.debugger.features.remove-command-bar-options", true);
-  pref("devtools.debugger.features.code-coverage", true);
-  pref("devtools.debugger.features.event-listeners", true);
-  pref("devtools.debugger.features.code-folding", true);
+  pref("devtools.debugger.features.code-coverage", false);
+  pref("devtools.debugger.features.event-listeners", false);
+  pref("devtools.debugger.features.code-folding", false);
   pref("devtools.debugger.features.outline", true);
   pref("devtools.debugger.features.column-breakpoints", true);
 }
 
 const prefs = new PrefsHelper("devtools", {
   autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"],
   clientSourceMapsEnabled: ["Bool", "source-map.client-service.enabled"],
   pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"],
@@ -10286,17 +10286,18 @@ const features = new PrefsHelper("devtoo
   columnBreakpoints: ["Bool", "column-breakpoints"],
   chromeScopes: ["Bool", "chrome-scopes"],
   mapScopes: ["Bool", "map-scopes"],
   breakpointsDropdown: ["Bool", "breakpoints-dropdown"],
   removeCommandBarOptions: ["Bool", "remove-command-bar-options"],
   workers: ["Bool", "workers"],
   codeCoverage: ["Bool", "code-coverage"],
   eventListeners: ["Bool", "event-listeners"],
-  outline: ["Bool", "outline"]
+  outline: ["Bool", "outline"],
+  codeFolding: ["Bool", "code-folding"]
 });
 /* harmony export (immutable) */ __webpack_exports__["features"] = features;
 
 
 if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
   // clear pending Breakpoints
   prefs.pendingBreakpoints = {};
   prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
@@ -14131,17 +14132,17 @@ module.exports = "<!-- This Source Code 
 /* 955 */,
 /* 956 */,
 /* 957 */,
 /* 958 */,
 /* 959 */,
 /* 960 */
 /***/ (function(module, exports) {
 
-module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUri2): This is the text that appears in the\n# context menu to copy the source URI of file open.\ncopySourceUri2=Copy source URI\ncopySourceUri2.accesskey=u\n\n# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the\n# context menu to set a directory as root directory\nsetDirectoryRoot.label=Set directory root\nsetDirectoryRoot.accesskey=r\n\n# LOCALIZATION NOTE (copyFunction): This is the text that appears in the\n# context menu to copy the function the user selected\ncopyFunction.label=Copy function\ncopyFunction.accesskey=F\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy stack trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step in %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step out %S\n\n# LOCALIZATION NOTE (pauseButtonItem): The label that is displayed for the dropdown pause\n# list item when the debugger is in a running state.\npauseButtonItem=Pause on Next Statement\n\n# LOCALIZATION NOTE (ignoreExceptionsItem): The pause on exceptions button description\n# when the debugger will not pause on exceptions.\nignoreExceptionsItem=Ignore exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptionsItem): The pause on exceptions dropdown\n# item shown when a user is adding a new breakpoint.\npauseOnUncaughtExceptionsItem=Pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptionsItem): The pause on exceptions button description\n# when the debugger will pause on all exceptions.\npauseOnExceptionsItem=Pause on all exceptions\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display.\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle\n# breakpoints.\ntoggleBreakpoint.key=CmdOrCtrl+B\n\n# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle\n# the conditional breakpoint panel.\ntoggleCondPanel.key=CmdOrCtrl+Shift+B\n\n# LOCALIZATION NOTE (stepOut.key): A key shortcut to\n# step out.\nstepOut.key=Shift+F11\n\n# LOCALIZATION NOTE (shortcuts.header.editor): Sections header in\n# the shortcuts modal for keyboard shortcuts related to editing.\nshortcuts.header.editor=Editor\n\n# LOCALIZATION NOTE (shortcuts.header.stepping): Sections header in\n# the shortcuts modal for keyboard shortcuts related to stepping.\nshortcuts.header.stepping=Stepping\n\n# LOCALIZATION NOTE (shortcuts.header.search): Sections header in\n# the shortcuts modal for keyboard shortcuts related to search.\nshortcuts.header.search=Search\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search\n# message when the query did not match any text of all files in a project.\nprojectTextSearch.noResults=No results found\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf2.label=Enable\nbreakpointMenuItem.enableSelf2.accesskey=E\nbreakpointMenuItem.disableSelf2.label=Disable\nbreakpointMenuItem.disableSelf2.accesskey=D\nbreakpointMenuItem.deleteSelf2.label=Remove\nbreakpointMenuItem.deleteSelf2.accesskey=R\nbreakpointMenuItem.enableOthers2.label=Enable others\nbreakpointMenuItem.enableOthers2.accesskey=o\nbreakpointMenuItem.disableOthers2.label=Disable others\nbreakpointMenuItem.disableOthers2.accesskey=s\nbreakpointMenuItem.deleteOthers2.label=Remove others\nbreakpointMenuItem.deleteOthers2.accesskey=h\nbreakpointMenuItem.enableAll2.label=Enable all\nbreakpointMenuItem.enableAll2.accesskey=b\nbreakpointMenuItem.disableAll2.label=Disable all\nbreakpointMenuItem.disableAll2.accesskey=k\nbreakpointMenuItem.deleteAll2.label=Remove all\nbreakpointMenuItem.deleteAll2.accesskey=a\nbreakpointMenuItem.removeCondition2.label=Remove condition\nbreakpointMenuItem.removeCondition2.accesskey=c\nbreakpointMenuItem.addCondition2.label=Add condition\nbreakpointMenuItem.addCondition2.accesskey=A\nbreakpointMenuItem.editCondition2.label=Edit condition\nbreakpointMenuItem.editCondition2.accesskey=n\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\nbreakpointMenuItem.removeCondition.label=Remove breakpoint condition\nbreakpointMenuItem.removeCondition.accesskey=c\nbreakpointMenuItem.editCondition.label=Edit breakpoint condition\nbreakpointMenuItem.editCondition.accesskey=n\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (editor.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=No results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context\n# menu item for jumping to a new paused location\neditor.continueToHere.label=Continue to here\neditor.continueToHere.accesskey=H\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable breakpoint\neditor.disableBreakpoint.accesskey=D\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add conditional breakpoint\neditor.addConditionalBreakpoint.accesskey=c\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.close): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\neditor.jumpToMappedLocation1.accesskey=m\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable framework grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable framework grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add watch expression\nexpressions.label=Add watch expression\nexpressions.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close other tabs\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty print source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed source\n\n# LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated\n# with a mapped source. %S is replaced by the source map origin.\nsourceFooter.mappedSource=(From %S)\n\n# LOCALIZATION NOTE (sourceFooter.mappedSourceTooltip): Tooltip text associated\n# with a mapped source. %S is replaced by the source map origin.\nsourceFooter.mappedSourceTooltip=(Source mapped from %S)\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display\noutline.noFunctions=No functions\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults2): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText3): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText3=Error loading this URI: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesDomNodeValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(gotoLineModal.placeholder): The placeholder\n# text displayed when the user searches for specific lines in a file\ngotoLineModal.placeholder=Go to line…\ngotoLineModal.key=CmdOrCtrl+Shift+;\ngotoLineModal.title=Go to a line number in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\nsymbolSearch.search.functionsPlaceholder.title=Search for a function in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\nsymbolSearch.search.variablesPlaceholder.title=Search for a variable in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n\n# LOCALIZATION NOTE (anonymous): The text that is displayed when the\n# display name is null.\nanonymous=(anonymous)\n\n# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing\n# keyboard shortcut action for toggling breakpoint\nshortcuts.toggleBreakpoint=Toggle Breakpoint\nshortcuts.toggleBreakpoint.accesskey=B\n\n# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing\n# keyboard shortcut action for toggling conditional panel keyboard\nshortcuts.toggleCondPanel=Toggle Conditional Panel\n\n# LOCALIZATION NOTE (shortcuts.pauseOrResume): text describing\n# keyboard shortcut action for pause of resume\nshortcuts.pauseOrResume=Pause/Resume\n\n# LOCALIZATION NOTE (shortcuts.stepOver): text describing\n# keyboard shortcut action for stepping over\nshortcuts.stepOver=Step Over\n\n# LOCALIZATION NOTE (shortcuts.stepIn): text describing\n# keyboard shortcut action for stepping in\nshortcuts.stepIn=Step In\n\n# LOCALIZATION NOTE (shortcuts.stepOut): text describing\n# keyboard shortcut action for stepping out\nshortcuts.stepOut=Step Out\n\n# LOCALIZATION NOTE (shortcuts.fileSearch): text describing\n# keyboard shortcut action for source file search\nshortcuts.fileSearch=Source File Search\n\n# LOCALIZATION NOTE (shortcuts.searchAgain): text describing\n# keyboard shortcut action for searching again\nshortcuts.searchAgain=Search Again\n\n# LOCALIZATION NOTE (shortcuts.projectSearch): text describing\n# keyboard shortcut action for full project search\nshortcuts.projectSearch=Full Project Search\n\n# LOCALIZATION NOTE (shortcuts.functionSearch): text describing\n# keyboard shortcut action for function search\nshortcuts.functionSearch=Function Search\n\n# LOCALIZATION NOTE (shortcuts.buttonName): text describing\n# keyboard shortcut button text\nshortcuts.buttonName=Keyboard shortcuts\n"
+module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUri2): This is the text that appears in the\n# context menu to copy the source URI of file open.\ncopySourceUri2=Copy source URI\ncopySourceUri2.accesskey=u\n\n# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the\n# context menu to set a directory as root directory\nsetDirectoryRoot.label=Set directory root\nsetDirectoryRoot.accesskey=r\n\n# LOCALIZATION NOTE (copyFunction): This is the text that appears in the\n# context menu to copy the function the user selected\ncopyFunction.label=Copy function\ncopyFunction.accesskey=F\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy stack trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step in %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step out %S\n\n# LOCALIZATION NOTE (pauseButtonItem): The label that is displayed for the dropdown pause\n# list item when the debugger is in a running state.\npauseButtonItem=Pause on Next Statement\n\n# LOCALIZATION NOTE (ignoreExceptionsItem): The pause on exceptions button description\n# when the debugger will not pause on exceptions.\nignoreExceptionsItem=Ignore exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptionsItem): The pause on exceptions dropdown\n# item shown when a user is adding a new breakpoint.\npauseOnUncaughtExceptionsItem=Pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptionsItem): The pause on exceptions button description\n# when the debugger will pause on all exceptions.\npauseOnExceptionsItem=Pause on all exceptions\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display.\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle\n# breakpoints.\ntoggleBreakpoint.key=CmdOrCtrl+B\n\n# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle\n# the conditional breakpoint panel.\ntoggleCondPanel.key=CmdOrCtrl+Shift+B\n\n# LOCALIZATION NOTE (stepOut.key): A key shortcut to\n# step out.\nstepOut.key=Shift+F11\n\n# LOCALIZATION NOTE (shortcuts.header.editor): Sections header in\n# the shortcuts modal for keyboard shortcuts related to editing.\nshortcuts.header.editor=Editor\n\n# LOCALIZATION NOTE (shortcuts.header.stepping): Sections header in\n# the shortcuts modal for keyboard shortcuts related to stepping.\nshortcuts.header.stepping=Stepping\n\n# LOCALIZATION NOTE (shortcuts.header.search): Sections header in\n# the shortcuts modal for keyboard shortcuts related to search.\nshortcuts.header.search=Search\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search\n# message when the query did not match any text of all files in a project.\nprojectTextSearch.noResults=No results found\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf2.label=Enable\nbreakpointMenuItem.enableSelf2.accesskey=E\nbreakpointMenuItem.disableSelf2.label=Disable\nbreakpointMenuItem.disableSelf2.accesskey=D\nbreakpointMenuItem.deleteSelf2.label=Remove\nbreakpointMenuItem.deleteSelf2.accesskey=R\nbreakpointMenuItem.enableOthers2.label=Enable others\nbreakpointMenuItem.enableOthers2.accesskey=o\nbreakpointMenuItem.disableOthers2.label=Disable others\nbreakpointMenuItem.disableOthers2.accesskey=s\nbreakpointMenuItem.deleteOthers2.label=Remove others\nbreakpointMenuItem.deleteOthers2.accesskey=h\nbreakpointMenuItem.enableAll2.label=Enable all\nbreakpointMenuItem.enableAll2.accesskey=b\nbreakpointMenuItem.disableAll2.label=Disable all\nbreakpointMenuItem.disableAll2.accesskey=k\nbreakpointMenuItem.deleteAll2.label=Remove all\nbreakpointMenuItem.deleteAll2.accesskey=a\nbreakpointMenuItem.removeCondition2.label=Remove condition\nbreakpointMenuItem.removeCondition2.accesskey=c\nbreakpointMenuItem.addCondition2.label=Add condition\nbreakpointMenuItem.addCondition2.accesskey=A\nbreakpointMenuItem.editCondition2.label=Edit condition\nbreakpointMenuItem.editCondition2.accesskey=n\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\nbreakpointMenuItem.removeCondition.label=Remove breakpoint condition\nbreakpointMenuItem.removeCondition.accesskey=c\nbreakpointMenuItem.editCondition.label=Edit breakpoint condition\nbreakpointMenuItem.editCondition.accesskey=n\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (editor.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=No results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context\n# menu item for jumping to a new paused location\neditor.continueToHere.label=Continue to here\neditor.continueToHere.accesskey=H\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable breakpoint\neditor.disableBreakpoint.accesskey=D\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add conditional breakpoint\neditor.addConditionalBreakpoint.accesskey=c\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.close): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\neditor.jumpToMappedLocation1.accesskey=m\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable framework grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable framework grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add watch expression\n# LOCALIZATION NOTE (expressions.errorMsg): Error text for expression\n# input element\nexpressions.errorMsg=Invalid expression…\nexpressions.label=Add watch expression\nexpressions.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close other tabs\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty print source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed source\n\n# LOCALIZATION NOTE (sourceFooter.mappedSource): Text associated\n# with a mapped source. %S is replaced by the source map origin.\nsourceFooter.mappedSource=(From %S)\n\n# LOCALIZATION NOTE (sourceFooter.mappedSourceTooltip): Tooltip text associated\n# with a mapped source. %S is replaced by the source map origin.\nsourceFooter.mappedSourceTooltip=(Source mapped from %S)\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display\noutline.noFunctions=No functions\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults2): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText3): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText3=Error loading this URI: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesDomNodeValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(gotoLineModal.placeholder): The placeholder\n# text displayed when the user searches for specific lines in a file\ngotoLineModal.placeholder=Go to line…\ngotoLineModal.key=CmdOrCtrl+Shift+;\ngotoLineModal.title=Go to a line number in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\nsymbolSearch.search.functionsPlaceholder.title=Search for a function in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\nsymbolSearch.search.variablesPlaceholder.title=Search for a variable in a file\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n\n# LOCALIZATION NOTE (anonymous): The text that is displayed when the\n# display name is null.\nanonymous=(anonymous)\n\n# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing\n# keyboard shortcut action for toggling breakpoint\nshortcuts.toggleBreakpoint=Toggle Breakpoint\nshortcuts.toggleBreakpoint.accesskey=B\n\n# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing\n# keyboard shortcut action for toggling conditional panel keyboard\nshortcuts.toggleCondPanel=Toggle Conditional Panel\n\n# LOCALIZATION NOTE (shortcuts.pauseOrResume): text describing\n# keyboard shortcut action for pause of resume\nshortcuts.pauseOrResume=Pause/Resume\n\n# LOCALIZATION NOTE (shortcuts.stepOver): text describing\n# keyboard shortcut action for stepping over\nshortcuts.stepOver=Step Over\n\n# LOCALIZATION NOTE (shortcuts.stepIn): text describing\n# keyboard shortcut action for stepping in\nshortcuts.stepIn=Step In\n\n# LOCALIZATION NOTE (shortcuts.stepOut): text describing\n# keyboard shortcut action for stepping out\nshortcuts.stepOut=Step Out\n\n# LOCALIZATION NOTE (shortcuts.fileSearch): text describing\n# keyboard shortcut action for source file search\nshortcuts.fileSearch=Source File Search\n\n# LOCALIZATION NOTE (shortcuts.searchAgain): text describing\n# keyboard shortcut action for searching again\nshortcuts.searchAgain=Search Again\n\n# LOCALIZATION NOTE (shortcuts.projectSearch): text describing\n# keyboard shortcut action for full project search\nshortcuts.projectSearch=Full Project Search\n\n# LOCALIZATION NOTE (shortcuts.functionSearch): text describing\n# keyboard shortcut action for function search\nshortcuts.functionSearch=Function Search\n\n# LOCALIZATION NOTE (shortcuts.buttonName): text describing\n# keyboard shortcut button text\nshortcuts.buttonName=Keyboard shortcuts\n"
 
 /***/ }),
 /* 961 */,
 /* 962 */,
 /* 963 */,
 /* 964 */,
 /* 965 */
 /***/ (function(module, exports) {
@@ -21330,16 +21331,17 @@ async function getGeneratedLocation(stat
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.addExpression = addExpression;
+exports.clearExpressionError = clearExpressionError;
 exports.updateExpression = updateExpression;
 exports.deleteExpression = deleteExpression;
 exports.evaluateExpressions = evaluateExpressions;
 exports.getMappedExpression = getMappedExpression;
 
 var _selectors = __webpack_require__(1352);
 
 var _promise = __webpack_require__(1653);
@@ -21368,38 +21370,44 @@ function addExpression(input) {
       return;
     }
 
     const expression = (0, _selectors.getExpression)(getState(), input);
     if (expression) {
       return dispatch(evaluateExpression(expression));
     }
 
-    dispatch({
-      type: "ADD_EXPRESSION",
-      input
-    });
+    const expressionError = await parser.hasSyntaxError(input);
+    dispatch({ type: "ADD_EXPRESSION", input, expressionError });
 
     const newExpression = (0, _selectors.getExpression)(getState(), input);
-    dispatch(evaluateExpression(newExpression));
+    if (newExpression) {
+      return dispatch(evaluateExpression(newExpression));
+    }
   };
 } /* 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/>. */
 
+function clearExpressionError() {
+  return { type: "CLEAR_EXPRESSION_ERROR" };
+}
+
 function updateExpression(input, expression) {
-  return ({ dispatch, getState }) => {
+  return async ({ dispatch, getState }) => {
     if (!input || input == expression.input) {
       return;
     }
 
+    const expressionError = await parser.hasSyntaxError(input);
     dispatch({
       type: "UPDATE_EXPRESSION",
       expression,
-      input: input
+      input: expressionError ? expression.input : input,
+      expressionError
     });
 
     dispatch(evaluateExpressions());
   };
 }
 
 /**
  *
@@ -21435,25 +21443,16 @@ function evaluateExpressions() {
 function evaluateExpression(expression) {
   return async function ({ dispatch, getState, client, sourceMaps }) {
     if (!expression.input) {
       console.warn("Expressions should not be empty");
       return;
     }
 
     let input = expression.input;
-    const error = await parser.hasSyntaxError(input);
-    if (error) {
-      return dispatch({
-        type: "EVALUATE_EXPRESSION",
-        input: expression.input,
-        value: { input: expression.input, result: error }
-      });
-    }
-
     const frame = (0, _selectors.getSelectedFrame)(getState());
 
     if (frame) {
       const { location, generatedLocation } = frame;
       const source = (0, _selectors.getSource)(getState(), location.sourceId);
       const sourceId = source.get("id");
 
       if (!(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
@@ -23057,17 +23056,17 @@ async function findScopeByName(source, n
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.getExpressions = exports.State = undefined;
+exports.getExpressionError = exports.getExpressions = exports.State = undefined;
 exports.getExpression = getExpression;
 
 var _makeRecord = __webpack_require__(1361);
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
 
 var _immutable = __webpack_require__(146);
 
@@ -23075,49 +23074,55 @@ var _lodash = __webpack_require__(2);
 
 var _reselect = __webpack_require__(993);
 
 var _prefs = __webpack_require__(226);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const State = exports.State = (0, _makeRecord2.default)({
-  expressions: (0, _immutable.List)(restoreExpressions())
+  expressions: (0, _immutable.List)(restoreExpressions()),
+  expressionError: false
 }); /* 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/>. */
 
 /**
  * Expressions reducer
  * @module reducers/expressions
  */
 
 function update(state = State(), action) {
   switch (action.type) {
     case "ADD_EXPRESSION":
+      if (action.expressionError) {
+        return state.set("expressionError", !!action.expressionError);
+      }
       return appendToList(state, ["expressions"], {
         input: action.input,
         value: null,
         updating: true
       });
     case "UPDATE_EXPRESSION":
       const key = action.expression.input;
       return updateItemInList(state, ["expressions"], key, {
         input: action.input,
         value: null,
         updating: true
-      });
+      }).set("expressionError", !!action.expressionError);
     case "EVALUATE_EXPRESSION":
       return updateItemInList(state, ["expressions"], action.input, {
         input: action.input,
         value: action.value,
         updating: false
       });
     case "DELETE_EXPRESSION":
       return deleteExpression(state, action.input);
+    case "CLEAR_EXPRESSION_ERROR":
+      return state.set("expressionError", false);
   }
 
   return state;
 }
 
 function restoreExpressions() {
   const exprs = _prefs.prefs.expressions;
   if (exprs.length == 0) {
@@ -23160,16 +23165,18 @@ function deleteExpression(state, input) 
 const getExpressionsWrapper = state => state.expressions;
 
 const getExpressions = exports.getExpressions = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.get("expressions"));
 
 function getExpression(state, input) {
   return getExpressions(state).find(exp => exp.input == input);
 }
 
+const getExpressionError = exports.getExpressionError = (0, _reselect.createSelector)(getExpressionsWrapper, expressions => expressions.get("expressionError"));
+
 exports.default = update;
 
 /***/ }),
 /* 1418 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -30388,17 +30395,17 @@ async function paused(_, packet) {
     return;
   }
 
   // Eagerly fetch the frames
   const response = await threadClient.getFrames(0, CALL_STACK_PAGE_SIZE);
 
   if (why.type != "alreadyPaused") {
     const pause = (0, _create.createPause)(packet, response);
-    _sourceQueue2.default.flush();
+    await _sourceQueue2.default.flush();
     actions.paused(pause);
   }
 }
 
 function resumed(_, packet) {
   // NOTE: the client suppresses resumed events while interrupted
   // to prevent unintentional behavior.
   // see [client docs](../README.md#interrupted) for more information.
@@ -31937,23 +31944,23 @@ function willNavigate(_, event) {
   return async function ({ dispatch, getState, client, sourceMaps }) {
     await sourceMaps.clearSourceMaps();
     (0, _wasm.clearWasmStates)();
     (0, _editor.clearDocuments)();
     (0, _parser.clearSymbols)();
     (0, _parser.clearASTs)();
     (0, _parser.clearScopes)();
     (0, _parser.clearSources)();
-    _sourceQueue2.default.clear();
-
     dispatch(navigate(event.url));
   };
 }
 
 function navigate(url) {
+  _sourceQueue2.default.clear();
+
   return {
     type: "NAVIGATE",
     url
   };
 }
 
 function connect(url) {
   return async function ({ dispatch }) {
@@ -32998,23 +33005,17 @@ class TextSearch extends _react.Componen
         getChildren: file => file.matches || [],
         itemHeight: 24,
         autoExpand: 1,
         autoExpandDepth: 1,
         getParent: item => null,
         getPath: getFilePath,
         renderItem: renderItem
       });
-    } else if (status === _projectTextSearch.statusType.fetching) {
-      return _react2.default.createElement(
-        "div",
-        { className: "no-result-msg absolute-center" },
-        "Loading..."
-      );
-    } else if (this.props.query && !results.length) {
+    } else if (this.props.query && !results.length || status === _projectTextSearch.statusType.fetching) {
       return _react2.default.createElement(
         "div",
         { className: "no-result-msg absolute-center" },
         L10N.getStr("projectTextSearch.noResults")
       );
     }
   }
 
@@ -40909,111 +40910,132 @@ Object.defineProperty(exports, "__esModu
 });
 
 var _react = __webpack_require__(0);
 
 var _react2 = _interopRequireDefault(_react);
 
 var _reactRedux = __webpack_require__(1189);
 
-var _redux = __webpack_require__(3);
+var _classnames = __webpack_require__(175);
+
+var _classnames2 = _interopRequireDefault(_classnames);
+
+var _devtoolsReps = __webpack_require__(1408);
 
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
 var _selectors = __webpack_require__(1352);
 
 var _expressions = __webpack_require__(1437);
 
 var _Close = __webpack_require__(1374);
 
 var _Close2 = _interopRequireDefault(_Close);
 
-var _devtoolsReps = __webpack_require__(1408);
-
 __webpack_require__(1335);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class Expressions extends _react.PureComponent {
 
-  constructor(...args) {
-    super(...args);
-
-    this.state = {
-      editing: null
-    };
-
+  constructor(props) {
+    super(props);
+
+    this.clear = () => {
+      this.setState(() => {
+        this.props.clearExpressionError();
+        return { editing: false, editIndex: -1, inputValue: "" };
+      });
+    };
+
+    this.handleChange = e => {
+      this.setState({ inputValue: e.target.value });
+    };
+
+    this.handleKeyDown = e => {
+      if (e.key === "Escape") {
+        this.clear();
+      }
+    };
+
+    this.handleExistingSubmit = async (e, expression) => {
+      e.preventDefault();
+      e.stopPropagation();
+      this.props.updateExpression(this.state.inputValue, expression);
+    };
+
+    this.handleNewSubmit = async e => {
+      e.preventDefault();
+      e.stopPropagation();
+      this.props.addExpression(this.state.inputValue);
+      this.setState({ editing: false, editIndex: -1, inputValue: "" });
+    };
+
+    this.state = { editing: false, editIndex: -1, inputValue: "" };
     this.renderExpression = this.renderExpression.bind(this);
   }
 
   componentDidMount() {
     const { expressions, evaluateExpressions } = this.props;
     if (expressions.size > 0) {
       evaluateExpressions();
     }
   }
 
+  componentWillReceiveProps(nextProps) {
+    if (this.state.editing && !nextProps.expressionError) {
+      this.clear();
+    }
+  }
+
   shouldComponentUpdate(nextProps, nextState) {
-    const { editing } = this.state;
-    const { expressions, loadedObjects } = this.props;
-    return expressions !== nextProps.expressions || loadedObjects !== nextProps.loadedObjects || editing !== nextState.editing;
-  }
-
-  editExpression(expression, { depth }) {
+    const { editing, inputValue } = this.state;
+    const { expressions, expressionError, loadedObjects } = this.props;
+    return expressions !== nextProps.expressions || expressionError !== nextProps.expressionError || loadedObjects !== nextProps.loadedObjects || editing !== nextState.editing || inputValue !== nextState.inputValue;
+  }
+
+  componentDidUpdate() {
+    if (this._input) {
+      const input = this._input;
+      input.setSelectionRange(input.value.length + 1, input.value.length + 1);
+      input.focus();
+    }
+  }
+
+  editExpression(expression, index, { depth }) {
     if (depth > 0) {
       return;
     }
-
-    this.setState({ editing: expression.input });
+    this.setState({
+      inputValue: expression.input,
+      editing: true,
+      editIndex: index
+    });
   }
 
   deleteExpression(e, expression) {
     e.stopPropagation();
     const { deleteExpression } = this.props;
     deleteExpression(expression);
   }
 
-  inputKeyPress(e, expression) {
-    if (e.key !== "Enter") {
-      return;
-    }
-
-    const value = e.target.value;
-    if (value == "") {
-      return;
-    }
-
-    this.setState({ editing: null });
-    e.target.value = "";
-    this.props.updateExpression(value, expression);
-  }
-
-  renderExpressionEditInput(expression) {
-    return _react2.default.createElement(
-      "span",
-      { className: "expression-input-container", key: expression.input },
-      _react2.default.createElement("input", {
-        className: "input-expression",
-        type: "text",
-        onKeyPress: e => this.inputKeyPress(e, expression),
-        onBlur: () => this.setState({ editing: null }),
-        defaultValue: expression.input,
-        ref: c => this._input = c
-      })
-    );
-  }
-
-  renderExpression(expression) {
-    const { loadObjectProperties, loadedObjects, openLink } = this.props;
-    const { editing } = this.state;
+  renderExpression(expression, index) {
+    const {
+      expressionError,
+      loadObjectProperties,
+      loadedObjects,
+      openLink
+    } = this.props;
+    const { editing, editIndex } = this.state;
     const { input, updating } = expression;
-
-    if (editing == input) {
+    const isEditingExpr = editing && editIndex === index;
+    if (isEditingExpr || isEditingExpr && expressionError) {
       return this.renderExpressionEditInput(expression);
     }
 
     if (updating) {
       return;
     }
 
     const { value } = (0, _expressions.getValue)(expression);
@@ -41030,17 +41052,17 @@ class Expressions extends _react.PureCom
       _react2.default.createElement(
         "div",
         { className: "expression-content" },
         _react2.default.createElement(_devtoolsReps.ObjectInspector, {
           roots: [root],
           autoExpandDepth: 0,
           disableWrap: true,
           disabledFocus: true,
-          onDoubleClick: (items, options) => this.editExpression(expression, options),
+          onDoubleClick: (items, options) => this.editExpression(expression, index, options),
           openLink: openLink,
           getObjectProperties: id => loadedObjects[id],
           loadObjectProperties: loadObjectProperties
           // TODO: See https://github.com/devtools-html/debugger.html/issues/3555.
           , getObjectEntries: actor => {},
           loadObjectEntries: grip => {}
         }),
         _react2.default.createElement(
@@ -41049,48 +41071,65 @@ class Expressions extends _react.PureCom
           _react2.default.createElement(_Close2.default, {
             handleClick: e => this.deleteExpression(e, expression)
           })
         )
       )
     );
   }
 
-  componentDidUpdate() {
-    if (this._input) {
-      this._input.focus();
-    }
-  }
-
   renderNewExpressionInput() {
-    const onKeyPress = e => {
-      if (e.key !== "Enter") {
-        return;
-      }
-
-      const value = e.target.value;
-      if (value == "") {
-        return;
-      }
-
-      e.stopPropagation();
-      e.target.value = "";
-      this.props.addExpression(value);
-    };
-
+    const { expressionError } = this.props;
+    const { editing, inputValue } = this.state;
+    const error = editing === false && expressionError === true;
+    const placeholder = error ? L10N.getStr("expressions.errorMsg") : L10N.getStr("expressions.placeholder");
     return _react2.default.createElement(
       "li",
       { className: "expression-input-container" },
-      _react2.default.createElement("input", {
-        className: "input-expression",
-        type: "text",
-        placeholder: L10N.getStr("expressions.placeholder"),
-        onBlur: e => e.target.value = "",
-        onKeyPress: onKeyPress
-      })
+      _react2.default.createElement(
+        "form",
+        { className: "expression-input-form", onSubmit: this.handleNewSubmit },
+        _react2.default.createElement("input", {
+          className: (0, _classnames2.default)("input-expression", { error }),
+          type: "text",
+          placeholder: placeholder,
+          onChange: this.handleChange,
+          onBlur: this.clear,
+          onKeyDown: this.handleKeyDown,
+          value: !editing ? inputValue : ""
+        }),
+        _react2.default.createElement("input", { type: "submit", style: { display: "none" } })
+      )
+    );
+  }
+
+  renderExpressionEditInput(expression) {
+    const { expressionError } = this.props;
+    const { inputValue, editing } = this.state;
+    const error = editing === true && expressionError === true;
+    return _react2.default.createElement(
+      "span",
+      { className: "expression-input-container", key: expression.input },
+      _react2.default.createElement(
+        "form",
+        {
+          className: "expression-input-form",
+          onSubmit: e => this.handleExistingSubmit(e, expression)
+        },
+        _react2.default.createElement("input", {
+          className: (0, _classnames2.default)("input-expression", { error }),
+          type: "text",
+          onChange: this.handleChange,
+          onBlur: this.clear,
+          onKeyDown: this.handleKeyDown,
+          value: editing ? inputValue : expression.input,
+          ref: c => this._input = c
+        }),
+        _react2.default.createElement("input", { type: "submit", style: { display: "none" } })
+      )
     );
   }
 
   render() {
     const { expressions } = this.props;
     return _react2.default.createElement(
       "ul",
       { className: "pane expressions-list" },
@@ -41099,18 +41138,19 @@ class Expressions extends _react.PureCom
     );
   }
 } /* 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/>. */
 
 exports.default = (0, _reactRedux.connect)(state => ({
   expressions: (0, _selectors.getExpressions)(state),
+  expressionError: (0, _selectors.getExpressionError)(state),
   loadedObjects: (0, _selectors.getLoadedObjects)(state)
-}), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(Expressions);
+}), _actions2.default)(Expressions);
 
 /***/ }),
 /* 1602 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
@@ -48666,28 +48706,27 @@ function getScope(scope, selectedFrame, 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 
 var _lodash = __webpack_require__(2);
 
 let newSources;
 let createSource;
+let supportsWasm = false;
 let queuedSources;
-let supportsWasm = false;
-
-const queue = (0, _lodash.throttle)(() => {
-  if (!newSources || !createSource) {
-    return;
-  }
-  newSources(queuedSources.map(source => {
-    return createSource(source, { supportsWasm });
-  }));
+
+async function dispatchNewSources() {
+  const sources = queuedSources;
   queuedSources = [];
-}, 100);
+
+  await newSources(sources.map(source => createSource(source, { supportsWasm })));
+}
+
+const queue = (0, _lodash.throttle)(dispatchNewSources, 100);
 
 exports.default = {
   initialize: options => {
     newSources = options.actions.newSources;
     createSource = options.createSource;
     supportsWasm = options.supportsWasm;
     queuedSources = [];
   },
@@ -49700,35 +49739,35 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.createEditor = createEditor;
 
 var _sourceEditor = __webpack_require__(197);
 
 var _sourceEditor2 = _interopRequireDefault(_sourceEditor);
 
-var _devtoolsConfig = __webpack_require__(1355);
+var _prefs = __webpack_require__(226);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 /* 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/>. */
 
 function createEditor() {
   const gutters = ["breakpoints", "hit-markers", "CodeMirror-linenumbers"];
 
-  if ((0, _devtoolsConfig.isEnabled)("codeFolding")) {
+  if (_prefs.features.codeFolding) {
     gutters.push("CodeMirror-foldgutter");
   }
 
   return new _sourceEditor2.default({
     mode: "javascript",
-    foldGutter: (0, _devtoolsConfig.isEnabled)("codeFolding"),
-    enableCodeFolding: (0, _devtoolsConfig.isEnabled)("codeFolding"),
+    foldGutter: _prefs.features.codeFolding,
+    enableCodeFolding: _prefs.features.codeFolding,
     readOnly: true,
     lineNumbers: true,
     theme: "mozilla",
     styleActiveLine: false,
     lineWrapping: false,
     matchBrackets: true,
     showAnnotationRuler: true,
     gutters,
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reloading.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps-reloading.js
@@ -22,24 +22,28 @@ add_task(async function() {
   // should not move anywhere.
   await addBreakpoint(dbg, entrySrc, 13);
   is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
   ok(
     getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
     "Breakpoint has correct line"
   );
 
+  await addBreakpoint(dbg, entrySrc, 5);
   await addBreakpoint(dbg, entrySrc, 15);
   await disableBreakpoint(dbg, entrySrc, 15);
 
   // Test reloading the debugger
   await reload(dbg, "opts.js");
   await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
 
-  is(getBreakpoints(getState()).size, 2, "One breakpoint exists");
+  await waitForPaused(dbg);
+  assertPausedLocation(dbg);
+
+  is(getBreakpoints(getState()).size, 3, "Three breakpoints exist");
 
   ok(
     getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
     "Breakpoint has correct line"
   );
 
   ok(
     getBreakpoint(getState(), {
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -434,16 +434,19 @@ framework.enableGrouping.accesskey=u
 generated=generated
 
 # LOCALIZATION NOTE (original): Source Map term for a debugger UI source location
 original=original
 
 # LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
 # input element
 expressions.placeholder=Add watch expression
+# LOCALIZATION NOTE (expressions.errorMsg): Error text for expression
+# input element
+expressions.errorMsg=Invalid expression…
 expressions.label=Add watch expression
 expressions.accesskey=e
 
 # LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
 # for closing the selected tab below the mouse.
 sourceTabs.closeTab=Close tab
 sourceTabs.closeTab.accesskey=c
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -5268,42 +5268,47 @@ nsContentUtils::SetNodeTextContent(nsICo
   }
 
   // Might as well stick a batch around this since we're performing several
   // mutations.
   mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(),
     UPDATE_CONTENT_MODEL, true);
   nsAutoMutationBatch mb;
 
-  uint32_t childCount = aContent->GetChildCount();
-
   if (aTryReuse && !aValue.IsEmpty()) {
-    uint32_t removeIndex = 0;
-
-    for (uint32_t i = 0; i < childCount; ++i) {
-      nsIContent* child = aContent->GetChildAt_Deprecated(removeIndex);
-      if (removeIndex == 0 && child && child->IsNodeOfType(nsINode::eTEXT)) {
-        nsresult rv = child->SetText(aValue, true);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        removeIndex = 1;
+    // Let's remove nodes until we find a eTEXT.
+    while (aContent->HasChildren()) {
+      nsIContent* child = aContent->GetFirstChild();
+      if (child->IsNodeOfType(nsINode::eTEXT)) {
+        break;
       }
-      else {
-        aContent->RemoveChildAt_Deprecated(removeIndex, true);
+      aContent->RemoveChildNode(child, true);
+    }
+
+    // If we have a node, it must be a eTEXT and we reuse it.
+    if (aContent->HasChildren()) {
+      nsIContent* child = aContent->GetFirstChild();
+      MOZ_ASSERT(child->IsNodeOfType(nsINode::eTEXT));
+      nsresult rv = child->SetText(aValue, true);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // All the following nodes, if they exist, must be deleted.
+      while (nsIContent* nextChild = child->GetNextSibling()) {
+        aContent->RemoveChildNode(nextChild, true);
       }
     }
 
-    if (removeIndex == 1) {
+    if (aContent->HasChildren()) {
       return NS_OK;
     }
   }
   else {
     mb.Init(aContent, true, false);
-    for (uint32_t i = 0; i < childCount; ++i) {
-      aContent->RemoveChildAt_Deprecated(0, true);
+    while (aContent->HasChildren()) {
+      aContent->RemoveChildNode(aContent->GetFirstChild(), true);
     }
   }
   mb.RemovalDone();
 
   if (aValue.IsEmpty()) {
     return NS_OK;
   }
 
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -799,29 +799,19 @@ WebGLContext::AssertCachedGlobalState() 
     ////////////////
 
     // Draw state
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
     MOZ_ASSERT_IF(IsWebGL2(),
                   gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
 
-    GLfloat colorClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-    gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
-    const bool ok = IsCacheCorrect(mColorClearValue[0], colorClearValue[0]) &&
-               IsCacheCorrect(mColorClearValue[1], colorClearValue[1]) &&
-               IsCacheCorrect(mColorClearValue[2], colorClearValue[2]) &&
-               IsCacheCorrect(mColorClearValue[3], colorClearValue[3]);
-    if (!ok) {
-        gfxCriticalNote << mColorClearValue[0] << " - " << colorClearValue[0] << " = " << (mColorClearValue[0] - colorClearValue[0]) << "\n"
-                        << mColorClearValue[1] << " - " << colorClearValue[1] << " = " << (mColorClearValue[1] - colorClearValue[1]) << "\n"
-                        << mColorClearValue[2] << " - " << colorClearValue[2] << " = " << (mColorClearValue[2] - colorClearValue[2]) << "\n"
-                        << mColorClearValue[3] << " - " << colorClearValue[3] << " = " << (mColorClearValue[3] - colorClearValue[3]);
-    }
-    MOZ_ASSERT(ok);
+    // Cannot trivially check COLOR_CLEAR_VALUE, since in old GL versions glGet may clamp
+    // based on whether the current framebuffer is floating-point or not.
+    // This also means COLOR_CLEAR_VALUE save+restore is dangerous!
 
     realGLboolean depthWriteMask = 0;
     gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
     MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
 
     GLfloat depthClearValue = 0.0f;
     gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
     MOZ_ASSERT(IsCacheCorrect(mDepthClearValue, depthClearValue));
--- a/dom/canvas/WebGLExtensionColorBufferFloat.cpp
+++ b/dom/canvas/WebGLExtensionColorBufferFloat.cpp
@@ -29,37 +29,16 @@ WebGLExtensionColorBufferFloat::WebGLExt
     };
 
 #define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
 
     // The extension doesn't actually add RGB32F; only RGBA32F.
     FOO(RGBA32F);
 
 #undef FOO
-
-#ifdef DEBUG
-    const auto gl = webgl->gl;
-    float was[4] = {};
-    gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, was);
-
-    const float test[4] = {-1.0, 0, 2.0, 255.0};
-    gl->fClearColor(test[0], test[1], test[2], test[3]);
-
-    float now[4] = {};
-    gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, now);
-    const bool ok = now[0] == test[0] && now[1] == test[1] &&
-                    now[2] == test[2] && now[3] == test[3];
-    if (!ok) {
-        printf_stderr("COLOR_CLEAR_VALUE: now{%f,%f,%f,%f} != test{%f,%f,%f,%f}\n",
-                      test[0], test[1], test[2], test[3],
-                      now[0], now[1], now[2], now[3]);
-        MOZ_ASSERT(false);
-    }
-    gl->fClearColor(was[0], was[1], was[2], was[3]);
-#endif
 }
 
 WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
 {
 }
 
 bool
 WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl)
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -7591,17 +7591,17 @@ fail-if = (os == 'android')
 [generated/test_conformance__extensions__oes-texture-half-float-with-image-data.html]
 skip-if = (os == 'win' && os_version == '6.1')
 fail-if = (os == 'android')
 [generated/test_conformance__extensions__oes-texture-half-float-with-image.html]
 fail-if = (os == 'android')
 [generated/test_conformance__extensions__oes-texture-half-float-with-video.html]
 fail-if = (os == 'mac') || (os == 'android') || (os == 'linux') || (os == 'win')
 [generated/test_conformance__extensions__oes-texture-half-float.html]
-fail-if = (os == 'mac') || (os == 'win') || (os == 'android')
+fail-if = (os == 'mac') || (os == 'win') || (os == 'android') || (os == 'linux')
 [generated/test_conformance__extensions__oes-vertex-array-object-bufferData.html]
 [generated/test_conformance__extensions__oes-vertex-array-object.html]
 skip-if = (os == 'mac' && os_version == '10.6')
 fail-if = (os == 'mac') || (os == 'linux') || (os == 'win')
 [generated/test_conformance__extensions__webgl-compressed-texture-atc.html]
 [generated/test_conformance__extensions__webgl-compressed-texture-etc.html]
 [generated/test_conformance__extensions__webgl-compressed-texture-pvrtc.html]
 [generated/test_conformance__extensions__webgl-compressed-texture-s3tc-srgb.html]
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -127,17 +127,17 @@ fail-if = (os == 'mac') || (os == 'linux
 skip-if = (os == 'mac' && os_version == '10.6')
 [generated/test_conformance__textures__misc__texture-size.html]
 # application crashed [@ mozilla::gl::GLContext::AfterGLCall]
 skip-if = (os == 'android') || (os == 'win')
 
 [generated/test_2_conformance2__vertex_arrays__vertex-array-object.html]
 fail-if = (os == 'mac') || (os == 'win')
 [generated/test_conformance__extensions__oes-texture-half-float.html]
-fail-if = (os == 'mac') || (os == 'win') || (os == 'android')
+fail-if = (os == 'mac') || (os == 'win') || (os == 'android') || (os == 'linux')
 [generated/test_conformance__attribs__gl-vertexattribpointer.html]
 fail-if = (os == 'android')
 [generated/test_conformance__ogles__GL__biuDepthRange__biuDepthRange_001_to_002.html]
 fail-if = (os == 'android')
 [generated/test_conformance__ogles__GL__gl_FragCoord__gl_FragCoord_001_to_003.html]
 fail-if = (os == 'android')
 
 [generated/test_conformance__textures__misc__texture-size-limit.html]
--- a/dom/canvas/test/webgl-mochitest/mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest/mochitest.ini
@@ -12,31 +12,31 @@ support-files =
   red-green.webmvp8.webm
   red-green.webmvp9.webm
 
 [ensure-exts/test_ANGLE_instanced_arrays.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
 [ensure-exts/test_EXT_blend_minmax.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_color_buffer_half_float.html]
-fail-if = (os == 'android') || (os == 'linux')
+fail-if = (os == 'android')
 [ensure-exts/test_EXT_disjoint_timer_query.html]
 fail-if = (os == 'android') || (os == 'win' && os_version == '5.1')
 [ensure-exts/test_EXT_frag_depth.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_sRGB.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
 [ensure-exts/test_EXT_shader_texture_lod.html]
 fail-if = (os == 'android')
 [ensure-exts/test_EXT_texture_filter_anisotropic.html]
 fail-if = (os == 'android') || (os == 'linux')
 [ensure-exts/test_OES_standard_derivatives.html]
 fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_color_buffer_float.html]
-fail-if = (os == 'android') || (os == 'linux')
+fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_compressed_texture_atc.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_es3.html]
 fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_etc1.html]
 fail-if = (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_pvrtc.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -68,16 +68,17 @@
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
+#include "mozilla/HangDetails.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
 #include "NullPrincipal.h"
 
 #if !defined(XP_WIN)
 #include "mozilla/Omnijar.h"
 #endif
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -95,16 +95,17 @@
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/WebBrowserPersistDocumentParent.h"
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/Unused.h"
+#include "mozilla/HangDetails.h"
 #include "nsAnonymousTemporaryFile.h"
 #include "nsAppRunner.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsCExternalHandlerService.h"
 #include "nsCOMPtr.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsConsoleMessage.h"
 #include "nsConsoleService.h"
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -55,16 +55,17 @@ include URIParams;
 include PluginTypes;
 include ProtocolTypes;
 include PBackgroundSharedTypes;
 include PContentPermission;
 include ServiceWorkerConfiguration;
 include GraphicsMessages;
 include MemoryReportTypes;
 include ClientIPCTypes;
+include HangTypes;
 
 // Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
 // are put into different UnifiedProtocolsXX.cpp files.
 // XXX Remove this once bug 1069073 is fixed
 include "mozilla/dom/PContentBridgeParent.h";
 
 using GeoPosition from "nsGeoPositionIPCSerialiser.h";
 using AlertNotificationType from "mozilla/AlertNotificationIPCSerializer.h";
@@ -93,17 +94,16 @@ using mozilla::layers::CompositorOptions
 using mozilla::Telemetry::HistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedHistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DynamicScalarDefinition from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
-using mozilla::HangDetails from "mozilla/HangDetails.h";
 
 union ChromeRegistryItem
 {
     ChromePackage;
     OverrideMapping;
     SubstitutionMapping;
 };
 
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -68,17 +68,17 @@ namespace mozilla {
 namespace {
 
 #ifdef MOZ_CUBEB_REMOTING
 ////////////////////////////////////////////////////////////////////////////////
 // Cubeb Sound Server Thread
 void* sServerHandle = nullptr;
 
 // Initialized during early startup, protected by sMutex.
-ipc::FileDescriptor sIPCConnection;
+StaticAutoPtr<ipc::FileDescriptor> sIPCConnection;
 
 static bool
 StartSoundServer()
 {
   sServerHandle = audioipc_server_start();
   return sServerHandle != nullptr;
 }
 
@@ -199,16 +199,17 @@ cubeb_channel_layout sPreferredChannelLa
 
 } // namespace
 
 static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
 // Consevative default that can work on all platforms.
 static const uint32_t CUBEB_NORMAL_LATENCY_FRAMES = 1024;
 
 namespace CubebUtils {
+cubeb* GetCubebContextUnlocked();
 
 void PrefChanged(const char* aPref, void* aClosure)
 {
   if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) {
     nsAutoCString value;
     Preferences::GetCString(aPref, value);
     StaticMutexAutoLock lock(sMutex);
     if (value.IsEmpty()) {
@@ -400,22 +401,22 @@ void InitBrandName()
 }
 
 #ifdef MOZ_CUBEB_REMOTING
 void InitAudioIPCConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
   auto contentChild = dom::ContentChild::GetSingleton();
   auto promise = contentChild->SendCreateAudioIPCConnection();
-  promise->Then(AbstractThread::GetCurrent(),
+  promise->Then(AbstractThread::MainThread(),
                 __func__,
                 [](ipc::FileDescriptor aFD) {
                   StaticMutexAutoLock lock(sMutex);
-                  MOZ_ASSERT(!sIPCConnection.IsValid());
-                  sIPCConnection = aFD;
+                  MOZ_ASSERT(!sIPCConnection);
+                  sIPCConnection = new ipc::FileDescriptor(aFD);
                 },
                 [](mozilla::ipc::ResponseRejectReason aReason) {
                   MOZ_LOG(gCubebLog, LogLevel::Error, ("SendCreateAudioIPCConnection failed: %d",
                                                        int(aReason)));
                 });
 }
 #endif
 
@@ -447,29 +448,30 @@ cubeb* GetCubebContextUnlocked()
     NS_WARNING_ASSERTION(
       sBrandName, "Did not initialize sbrandName, and not on the main thread?");
   }
 
 #ifdef MOZ_CUBEB_REMOTING
   if (sCubebSandbox) {
     if (XRE_IsParentProcess()) {
       // TODO: Don't use audio IPC when within the same process.
-      MOZ_ASSERT(!sIPCConnection.IsValid());
-      sIPCConnection = CreateAudioIPCConnection();
+      MOZ_ASSERT(!sIPCConnection);
+      sIPCConnection = new ipc::FileDescriptor(CreateAudioIPCConnection());
     } else {
-      MOZ_DIAGNOSTIC_ASSERT(sIPCConnection.IsValid());
+      MOZ_DIAGNOSTIC_ASSERT(sIPCConnection);
     }
   }
 
   MOZ_LOG(gCubebLog, LogLevel::Info, ("%s: %s", PREF_CUBEB_SANDBOX, sCubebSandbox ? "true" : "false"));
 
   int rv = sCubebSandbox
     ? audioipc_client_init(&sCubebContext, sBrandName,
-                           sIPCConnection.ClonePlatformHandle().release())
+                           sIPCConnection->ClonePlatformHandle().release())
     : cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
+  sIPCConnection = nullptr;
 #else // !MOZ_CUBEB_REMOTING
   int rv = cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
 #endif // MOZ_CUBEB_REMOTING
   NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
   sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Uninitialized;
 
   if (MOZ_LOG_TEST(gCubebLog, LogLevel::Verbose)) {
     cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback);
@@ -554,18 +556,17 @@ void InitLibrary()
   // calling this callback on init would immediately re-disble the logging.
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LOGGING_LEVEL);
 #ifndef MOZ_WIDGET_ANDROID
   AbstractThread::MainThread()->Dispatch(
     NS_NewRunnableFunction("CubebUtils::InitLibrary", &InitBrandName));
 #endif
 #ifdef MOZ_CUBEB_REMOTING
   if (sCubebSandbox && XRE_IsContentProcess()) {
-    AbstractThread::MainThread()->Dispatch(
-      NS_NewRunnableFunction("CubebUtils::InitLibrary", &InitAudioIPCConnection));
+    InitAudioIPCConnection();
   }
 #endif
 }
 
 void ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_SANDBOX);
@@ -580,17 +581,17 @@ void ShutdownLibrary()
     sCubebContext = nullptr;
   }
   sBrandName = nullptr;
   sCubebBackendName = nullptr;
   // This will ensure we don't try to re-create a context.
   sCubebState = CubebState::Shutdown;
 
 #ifdef MOZ_CUBEB_REMOTING
-  sIPCConnection = ipc::FileDescriptor();
+  sIPCConnection = nullptr;
   ShutdownSoundServer();
 #endif
 }
 
 uint32_t MaxNumberOfChannels()
 {
   cubeb* cubebContext = GetCubebContext();
   uint32_t maxNumberOfChannels;
--- a/dom/media/CubebUtils.h
+++ b/dom/media/CubebUtils.h
@@ -33,21 +33,19 @@ uint32_t PreferredSampleRate();
 // Get the bit mask of the connected audio device's preferred layout.
 uint32_t PreferredChannelMap(uint32_t aChannels);
 
 enum Side {
   Input,
   Output
 };
 
-void PrefChanged(const char* aPref, void* aClosure);
 double GetVolumeScale();
 bool GetFirstStream();
 cubeb* GetCubebContext();
-cubeb* GetCubebContextUnlocked();
 void ReportCubebStreamInitFailure(bool aIsFirstStream);
 void ReportCubebBackendUsed();
 uint32_t GetCubebPlaybackLatencyInMilliseconds();
 Maybe<uint32_t> GetCubebMSGLatencyInFrames();
 bool CubebLatencyPrefSet();
 cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap);
 void GetCurrentBackend(nsAString& aBackend);
 void GetPreferredChannelLayout(nsAString& aLayout);
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -48,21 +48,16 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngine)
 
   static const int DEFAULT_VIDEO_FPS = 30;
   static const int DEFAULT_43_VIDEO_WIDTH = 640;
   static const int DEFAULT_43_VIDEO_HEIGHT = 480;
   static const int DEFAULT_169_VIDEO_WIDTH = 1280;
   static const int DEFAULT_169_VIDEO_HEIGHT = 720;
 
-  // This allows using whatever rate the graph is using for the
-  // MediaStreamTrack. This is useful for microphone data, we know it's already
-  // at the correct rate for insertion in the MSG.
-  static const int USE_GRAPH_RATE = -1;
-
   /* Populate an array of video sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
                                      nsTArray<RefPtr<MediaEngineVideoSource> >*) = 0;
 
   /* Populate an array of audio sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -538,17 +538,16 @@ private:
   bool mDelayAgnostic;
   bool mExtendedFilter;
   MOZ_INIT_OUTSIDE_CTOR TrackID mTrackID;
   bool mStarted;
 
   nsString mDeviceName;
   nsCString mDeviceUUID;
 
-  int32_t mSampleFrequency;
   uint64_t mTotalFrames;
   uint64_t mLastLogFrames;
 
   // mSkipProcessing is true if none of the processing passes are enabled,
   // because of prefs or constraints. This allows simply copying the audio into
   // the MSG, skipping resampling and the whole webrtc.org code.
   // This is read and written to only on the MSG thread.
   bool mSkipProcessing;
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -65,17 +65,16 @@ MediaEngineWebRTCMicrophoneSource::Media
   , mAudioInput(aAudioInput)
   , mAudioProcessing(AudioProcessing::Create())
   , mMonitor("WebRTCMic.Monitor")
   , mCapIndex(aIndex)
   , mDelayAgnostic(aDelayAgnostic)
   , mExtendedFilter(aExtendedFilter)
   , mTrackID(TRACK_NONE)
   , mStarted(false)
-  , mSampleFrequency(MediaEngine::USE_GRAPH_RATE)
   , mTotalFrames(0)
   , mLastLogFrames(0)
   , mSkipProcessing(false)
   , mInputDownmixBuffer(MAX_SAMPLING_FREQ * MAX_CHANNELS / 100)
 {
   MOZ_ASSERT(aAudioInput);
   mDeviceName.Assign(NS_ConvertUTF8toUTF16(name));
   mDeviceUUID.Assign(uuid);
@@ -476,19 +475,17 @@ MediaEngineWebRTCMicrophoneSource::Start
   {
     MonitorAutoLock lock(mMonitor);
     mSources.AppendElement(aStream);
     mPrincipalHandles.AppendElement(aPrincipalHandle);
     MOZ_ASSERT(mSources.Length() == mPrincipalHandles.Length());
   }
 
   AudioSegment* segment = new AudioSegment();
-  if (mSampleFrequency == MediaEngine::USE_GRAPH_RATE) {
-    mSampleFrequency = aStream->GraphRate();
-  }
+
   aStream->AddAudioTrack(aID, aStream->GraphRate(), 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
 
   // XXX Make this based on the pref.
   aStream->RegisterForAudioMixing();
   LOG(("Start audio for stream %p", aStream));
 
   if (!mListener) {
     mListener = new mozilla::WebRTCAudioDataListener(this);
@@ -768,17 +765,17 @@ MediaEngineWebRTCMicrophoneSource::Inser
 {
   MonitorAutoLock lock(mMonitor);
   if (mState != kStarted) {
     return;
   }
 
   if (MOZ_LOG_TEST(AudioLogModule(), LogLevel::Debug)) {
     mTotalFrames += aFrames;
-    if (mTotalFrames > mLastLogFrames + mSampleFrequency) { // ~ 1 second
+    if (mTotalFrames > mLastLogFrames + mSources[0]->GraphRate()) { // ~ 1 second
       MOZ_LOG(AudioLogModule(), LogLevel::Debug,
               ("%p: Inserting %zu samples into graph, total frames = %" PRIu64,
                (void*)this, aFrames, mTotalFrames));
       mLastLogFrames = mTotalFrames;
     }
   }
 
   size_t len = mSources.Length();
@@ -889,19 +886,16 @@ MediaEngineWebRTCMicrophoneSource::FreeC
     MOZ_ASSERT(sChannelsOpen > 0);
     --sChannelsOpen;
   }
 }
 
 bool
 MediaEngineWebRTCMicrophoneSource::AllocChannel()
 {
-  mSampleFrequency = MediaEngine::USE_GRAPH_RATE;
-  LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
-
   mState = kAllocated;
   sChannelsOpen++;
   return true;
 }
 
 void
 MediaEngineWebRTCMicrophoneSource::Shutdown()
 {
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -20,67 +20,67 @@
 // ];
 //
 // See createInterfaceMap() below for a complete list of properties.
 
 // IMPORTANT: Do not change this list without review from
 //            a JavaScript Engine peer!
 var ecmaGlobals =
   [
-    "Array",
-    "ArrayBuffer",
-    {name: "Atomics", disabled: true},
-    "Boolean",
-    {name: "ByteLengthQueuingStrategy", disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
-    {name: "CountQueuingStrategy", disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
-    "DataView",
-    "Date",
-    "Error",
-    "EvalError",
-    "Float32Array",
-    "Float64Array",
-    "Function",
+    {name: "Array", insecureContext: true},
+    {name: "ArrayBuffer", insecureContext: true},
+    {name: "Atomics", insecureContext: true, disabled: true},
+    {name: "Boolean", insecureContext: true},
+    {name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
+    {name: "CountQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
+    {name: "DataView", insecureContext: true},
+    {name: "Date", insecureContext: true},
+    {name: "Error", insecureContext: true},
+    {name: "EvalError", insecureContext: true},
+    {name: "Float32Array", insecureContext: true},
+    {name: "Float64Array", insecureContext: true},
+    {name: "Function", insecureContext: true},
     // NB: We haven't bothered to resolve constants like Infinity and NaN on
     // Xrayed windows (which are seen from the XBL scope). We could support
     // this if needed with some refactoring.
-    {name: "Infinity", xbl: false},
-    "Int16Array",
-    "Int32Array",
-    "Int8Array",
-    "InternalError",
-    "Intl",
-    "JSON",
-    "Map",
-    "Math",
-    {name: "NaN", xbl: false},
-    "Number",
-    "Object",
-    "Promise",
-    "Proxy",
-    "RangeError",
-    {name: "ReadableStream", disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
-    "ReferenceError",
-    "Reflect",
-    "RegExp",
-    "Set",
-    {name: "SharedArrayBuffer", disabled: true},
-    {name: "SIMD", nightly: true},
-    "String",
-    "Symbol",
-    "SyntaxError",
-    {name: "TypedObject", nightly: true},
-    "TypeError",
-    "Uint16Array",
-    "Uint32Array",
-    "Uint8Array",
-    "Uint8ClampedArray",
-    "URIError",
-    "WeakMap",
-    "WeakSet",
-    {name: "WebAssembly", disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()}
+    {name: "Infinity", insecureContext: true, xbl: false},
+    {name: "Int16Array", insecureContext: true},
+    {name: "Int32Array", insecureContext: true},
+    {name: "Int8Array", insecureContext: true},
+    {name: "InternalError", insecureContext: true},
+    {name: "Intl", insecureContext: true},
+    {name: "JSON", insecureContext: true},
+    {name: "Map", insecureContext: true},
+    {name: "Math", insecureContext: true},
+    {name: "NaN", insecureContext: true, xbl: false},
+    {name: "Number", insecureContext: true},
+    {name: "Object", insecureContext: true},
+    {name: "Promise", insecureContext: true},
+    {name: "Proxy", insecureContext: true},
+    {name: "RangeError", insecureContext: true},
+    {name: "ReadableStream", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
+    {name: "ReferenceError", insecureContext: true},
+    {name: "Reflect", insecureContext: true},
+    {name: "RegExp", insecureContext: true},
+    {name: "Set", insecureContext: true},
+    {name: "SharedArrayBuffer", insecureContext: true, disabled: true},
+    {name: "SIMD", insecureContext: true, nightly: true},
+    {name: "String", insecureContext: true},
+    {name: "Symbol", insecureContext: true},
+    {name: "SyntaxError", insecureContext: true},
+    {name: "TypedObject", insecureContext: true, nightly: true},
+    {name: "TypeError", insecureContext: true},
+    {name: "Uint16Array", insecureContext: true},
+    {name: "Uint32Array", insecureContext: true},
+    {name: "Uint8Array", insecureContext: true},
+    {name: "Uint8ClampedArray", insecureContext: true},
+    {name: "URIError", insecureContext: true},
+    {name: "WeakMap", insecureContext: true},
+    {name: "WeakSet", insecureContext: true},
+    {name: "WebAssembly", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()}
   ];
 // IMPORTANT: Do not change the list above without review from
 //            a JavaScript Engine peer!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer,
 //            except to remove items from it!
 //
 // This is a list of interfaces that were prefixed with 'moz' instead of 'Moz'.
@@ -96,1236 +96,1241 @@ var legacyMozPrefixedInterfaces =
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer,
 //            except to remove items from it!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AbortController",
+    {name: "AbortController", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AbortSignal",
+    {name: "AbortSignal", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AnalyserNode",
+    {name: "AnalyserNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "Animation"},
+    {name: "Animation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AnimationEffectReadOnly", release: false},
+    {name: "AnimationEffectReadOnly", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AnimationEffectTiming", release: false},
+    {name: "AnimationEffectTiming", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AnimationEffectTimingReadOnly", release: false},
+    {name: "AnimationEffectTimingReadOnly", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AnimationEvent",
+    {name: "AnimationEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AnimationPlaybackEvent", release: false},
+    {name: "AnimationPlaybackEvent", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AnimationTimeline", release: false},
+    {name: "AnimationTimeline", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Attr",
+    {name: "Attr", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Audio",
+    {name: "Audio", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioBuffer",
+    {name: "AudioBuffer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioContext",
+    {name: "AudioContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioBufferSourceNode",
+    {name: "AudioBufferSourceNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioDestinationNode",
+    {name: "AudioDestinationNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioListener",
+    {name: "AudioListener", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioNode",
+    {name: "AudioNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioParam",
+    {name: "AudioParam", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioProcessingEvent",
+    {name: "AudioProcessingEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioScheduledSourceNode",
+    {name: "AudioScheduledSourceNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AudioStreamTrack",
+    {name: "AudioStreamTrack", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AuthenticatorAssertionResponse", isSecureContext:true, nightly: true},
+    {name: "AuthenticatorAssertionResponse", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AuthenticatorAttestationResponse", isSecureContext:true, nightly: true},
+    {name: "AuthenticatorAttestationResponse", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AuthenticatorResponse", isSecureContext:true, nightly: true},
+    {name: "AuthenticatorResponse", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BarProp",
+    {name: "BarProp", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BaseAudioContext",
+    {name: "BaseAudioContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BatteryManager",
+    {name: "BatteryManager", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BeforeUnloadEvent",
+    {name: "BeforeUnloadEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BiquadFilterNode",
+    {name: "BiquadFilterNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Blob",
+    {name: "Blob", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BlobEvent",
+    {name: "BlobEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BoxObject", xbl: true},
+    {name: "BoxObject", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BroadcastChannel",
+    {name: "BroadcastChannel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Cache",
+    {name: "Cache", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CacheStorage",
+    {name: "CacheStorage", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CanvasCaptureMediaStream",
+    {name: "CanvasCaptureMediaStream", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CanvasGradient",
+    {name: "CanvasGradient", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CanvasPattern",
+    {name: "CanvasPattern", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CanvasRenderingContext2D",
+    {name: "CanvasRenderingContext2D", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CaretPosition",
+    {name: "CaretPosition", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CDATASection",
+    {name: "CDATASection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ChannelMergerNode",
+    {name: "ChannelMergerNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ChannelSplitterNode",
+    {name: "ChannelSplitterNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CharacterData",
+    {name: "CharacterData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ChromeNodeList", xbl: true},
+    {name: "ChromeNodeList", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ClipboardEvent",
+    {name: "ClipboardEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CloseEvent",
+    {name: "CloseEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CommandEvent", xbl: true},
+    {name: "CommandEvent", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Comment",
+    {name: "Comment", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CompositionEvent",
+    {name: "CompositionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ConstantSourceNode",
+    {name: "ConstantSourceNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ConvolverNode",
+    {name: "ConvolverNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "Credential", isSecureContext:true, nightly: true},
+    {name: "Credential", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CredentialsContainer", isSecureContext:true, nightly: true},
+    {name: "CredentialsContainer", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Crypto",
+    {name: "Crypto", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CryptoKey",
+    {name: "CryptoKey", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSS",
+    {name: "CSS", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSS2Properties",
+    {name: "CSS2Properties", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CSSAnimation", release: false},
+    {name: "CSSAnimation", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSConditionRule",
+    {name: "CSSConditionRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSCounterStyleRule",
+    {name: "CSSCounterStyleRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSFontFaceRule",
+    {name: "CSSFontFaceRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSFontFeatureValuesRule",
+    {name: "CSSFontFeatureValuesRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSGroupingRule",
+    {name: "CSSGroupingRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSImportRule",
+    {name: "CSSImportRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSKeyframeRule",
+    {name: "CSSKeyframeRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSKeyframesRule",
+    {name: "CSSKeyframesRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSMediaRule",
+    {name: "CSSMediaRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSMozDocumentRule",
+    {name: "CSSMozDocumentRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSNamespaceRule",
+    {name: "CSSNamespaceRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSPageRule",
+    {name: "CSSPageRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSPrimitiveValue",
+    {name: "CSSPrimitiveValue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CSSPseudoElement", release: false},
+    {name: "CSSPseudoElement", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSRule",
+    {name: "CSSRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSRuleList",
+    {name: "CSSRuleList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSStyleDeclaration",
+    {name: "CSSStyleDeclaration", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSStyleRule",
+    {name: "CSSStyleRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSStyleSheet",
+    {name: "CSSStyleSheet", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSSupportsRule",
+    {name: "CSSSupportsRule", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CSSTransition", release: false},
+    {name: "CSSTransition", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSValue",
+    {name: "CSSValue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CSSValueList",
+    {name: "CSSValueList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CustomElementRegistry",
+    {name: "CustomElementRegistry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CustomEvent",
+    {name: "CustomEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataChannel",
+    {name: "DataChannel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataTransfer",
+    {name: "DataTransfer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataTransferItem",
+    {name: "DataTransferItem", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DataTransferItemList",
+    {name: "DataTransferItemList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DelayNode",
+    {name: "DelayNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DeviceLightEvent",
+    {name: "DeviceLightEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DeviceMotionEvent",
+    {name: "DeviceMotionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DeviceOrientationEvent",
+    {name: "DeviceOrientationEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DeviceProximityEvent",
+    {name: "DeviceProximityEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Directory",
+    {name: "Directory", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Document",
+    {name: "Document", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DocumentFragment",
+    {name: "DocumentFragment", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DocumentTimeline", release: false},
+    {name: "DocumentTimeline", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DocumentType",
+    {name: "DocumentType", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DOMConstructor", xbl: true},
+    {name: "DOMConstructor", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMCursor",
+    {name: "DOMCursor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMError",
+    {name: "DOMError", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMException",
+    {name: "DOMException", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMImplementation",
+    {name: "DOMImplementation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMMatrix",
+    {name: "DOMMatrix", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMMatrixReadOnly",
+    {name: "DOMMatrixReadOnly", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMParser",
+    {name: "DOMParser", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMPoint",
+    {name: "DOMPoint", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMPointReadOnly",
+    {name: "DOMPointReadOnly", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMQuad",
+    {name: "DOMQuad", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMRect",
+    {name: "DOMRect", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMRectList",
+    {name: "DOMRectList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMRectReadOnly",
+    {name: "DOMRectReadOnly", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMRequest",
+    {name: "DOMRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMStringList",
+    {name: "DOMStringList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMStringMap",
+    {name: "DOMStringMap", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMTokenList",
+    {name: "DOMTokenList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DragEvent",
+    {name: "DragEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DynamicsCompressorNode",
+    {name: "DynamicsCompressorNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Element",
+    {name: "Element", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ErrorEvent",
+    {name: "ErrorEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Event",
+    {name: "Event", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "EventSource",
+    {name: "EventSource", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "EventTarget",
+    {name: "EventTarget", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "File",
+    {name: "File", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileList",
+    {name: "FileList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileReader",
+    {name: "FileReader", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileSystem",
+    {name: "FileSystem", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileSystemDirectoryEntry",
+    {name: "FileSystemDirectoryEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileSystemDirectoryReader",
+    {name: "FileSystemDirectoryReader", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileSystemEntry",
+    {name: "FileSystemEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileSystemFileEntry",
+    {name: "FileSystemFileEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FocusEvent",
+    {name: "FocusEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FormData",
+    {name: "FormData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FontFace",
+    {name: "FontFace", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FontFaceSet",
+    {name: "FontFaceSet", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FontFaceSetLoadEvent",
+    {name: "FontFaceSetLoadEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GainNode",
+    {name: "GainNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Gamepad",
+    {name: "Gamepad", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadAxisMoveEvent",
+    {name: "GamepadAxisMoveEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadButtonEvent",
+    {name: "GamepadButtonEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadButton",
+    {name: "GamepadButton", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadEvent",
+    {name: "GamepadEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadHapticActuator",
+    {name: "GamepadHapticActuator", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "GamepadPose",
+    {name: "GamepadPose", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HashChangeEvent",
+    {name: "HashChangeEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Headers",
+    {name: "Headers", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "History",
+    {name: "History", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLAllCollection",
+    {name: "HTMLAllCollection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLAnchorElement",
+    {name: "HTMLAnchorElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLAreaElement",
+    {name: "HTMLAreaElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLAudioElement",
+    {name: "HTMLAudioElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLBaseElement",
+    {name: "HTMLBaseElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLBodyElement",
+    {name: "HTMLBodyElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLBRElement",
+    {name: "HTMLBRElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLButtonElement",
+    {name: "HTMLButtonElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLCanvasElement",
+    {name: "HTMLCanvasElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLCollection",
+    {name: "HTMLCollection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDataElement",
+    {name: "HTMLDataElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDataListElement",
+    {name: "HTMLDataListElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDetailsElement",
+    {name: "HTMLDetailsElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "HTMLDialogElement", disabled: true},
+    {name: "HTMLDialogElement", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDirectoryElement",
+    {name: "HTMLDirectoryElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDivElement",
+    {name: "HTMLDivElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDListElement",
+    {name: "HTMLDListElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLDocument",
+    {name: "HTMLDocument", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLElement",
+    {name: "HTMLElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLEmbedElement",
+    {name: "HTMLEmbedElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFieldSetElement",
+    {name: "HTMLFieldSetElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFontElement",
+    {name: "HTMLFontElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFormControlsCollection",
+    {name: "HTMLFormControlsCollection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFormElement",
+    {name: "HTMLFormElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFrameElement",
+    {name: "HTMLFrameElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLFrameSetElement",
+    {name: "HTMLFrameSetElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLHeadElement",
+    {name: "HTMLHeadElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLHeadingElement",
+    {name: "HTMLHeadingElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLHRElement",
+    {name: "HTMLHRElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLHtmlElement",
+    {name: "HTMLHtmlElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLIFrameElement",
+    {name: "HTMLIFrameElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLImageElement",
+    {name: "HTMLImageElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLInputElement",
+    {name: "HTMLInputElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLLabelElement",
+    {name: "HTMLLabelElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLLegendElement",
+    {name: "HTMLLegendElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLLIElement",
+    {name: "HTMLLIElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLLinkElement",
+    {name: "HTMLLinkElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMapElement",
+    {name: "HTMLMapElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMediaElement",
+    {name: "HTMLMediaElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMenuElement",
+    {name: "HTMLMenuElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMenuItemElement",
+    {name: "HTMLMenuItemElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMetaElement",
+    {name: "HTMLMetaElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLMeterElement",
+    {name: "HTMLMeterElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLModElement",
+    {name: "HTMLModElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLObjectElement",
+    {name: "HTMLObjectElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLOListElement",
+    {name: "HTMLOListElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLOptGroupElement",
+    {name: "HTMLOptGroupElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLOptionElement",
+    {name: "HTMLOptionElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLOptionsCollection",
+    {name: "HTMLOptionsCollection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLOutputElement",
+    {name: "HTMLOutputElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLParagraphElement",
+    {name: "HTMLParagraphElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLParamElement",
+    {name: "HTMLParamElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLPreElement",
+    {name: "HTMLPreElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLPictureElement",
+    {name: "HTMLPictureElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLProgressElement",
+    {name: "HTMLProgressElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLQuoteElement",
+    {name: "HTMLQuoteElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLScriptElement",
+    {name: "HTMLScriptElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLSelectElement",
+    {name: "HTMLSelectElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "HTMLSlotElement", disabled: true},
+    {name: "HTMLSlotElement", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLSourceElement",
+    {name: "HTMLSourceElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLSpanElement",
+    {name: "HTMLSpanElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLStyleElement",
+    {name: "HTMLStyleElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableCaptionElement",
+    {name: "HTMLTableCaptionElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableCellElement",
+    {name: "HTMLTableCellElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableColElement",
+    {name: "HTMLTableColElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableElement",
+    {name: "HTMLTableElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableRowElement",
+    {name: "HTMLTableRowElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTableSectionElement",
+    {name: "HTMLTableSectionElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTemplateElement",
+    {name: "HTMLTemplateElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTextAreaElement",
+    {name: "HTMLTextAreaElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTimeElement",
+    {name: "HTMLTimeElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTitleElement",
+    {name: "HTMLTitleElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLTrackElement",
+    {name: "HTMLTrackElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLUListElement",
+    {name: "HTMLUListElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLUnknownElement",
+    {name: "HTMLUnknownElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "HTMLVideoElement",
+    {name: "HTMLVideoElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "IdleDeadline"},
+    {name: "IdleDeadline", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBCursor",
+    {name: "IDBCursor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBCursorWithValue",
+    {name: "IDBCursorWithValue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBDatabase",
+    {name: "IDBDatabase", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBFactory",
+    {name: "IDBFactory", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBFileHandle",
+    {name: "IDBFileHandle", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBFileRequest",
+    {name: "IDBFileRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBIndex",
+    {name: "IDBIndex", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBKeyRange",
+    {name: "IDBKeyRange", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBMutableFile",
+    {name: "IDBMutableFile", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBObjectStore",
+    {name: "IDBObjectStore", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBOpenDBRequest",
+    {name: "IDBOpenDBRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBRequest",
+    {name: "IDBRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBTransaction",
+    {name: "IDBTransaction", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBVersionChangeEvent",
+    {name: "IDBVersionChangeEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IIRFilterNode",
+    {name: "IIRFilterNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Image",
+    {name: "Image", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageBitmap",
+    {name: "ImageBitmap", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageBitmapRenderingContext",
+    {name: "ImageBitmapRenderingContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ImageCapture", disabled: true},
+    {name: "ImageCapture", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ImageCaptureErrorEvent", disabled: true},
+    {name: "ImageCaptureErrorEvent", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageData",
+    {name: "ImageData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "InputEvent",
+    {name: "InputEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "InstallTrigger",
+    {name: "InstallTrigger", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IntersectionObserver",
+    {name: "IntersectionObserver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IntersectionObserverEntry",
+    {name: "IntersectionObserverEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "KeyEvent",
+    {name: "KeyEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "KeyboardEvent",
+    {name: "KeyboardEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "KeyframeEffectReadOnly", release: false},
+    {name: "KeyframeEffectReadOnly", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "KeyframeEffect", release: false},
+    {name: "KeyframeEffect", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "LocalMediaStream",
+    {name: "LocalMediaStream", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Location",
+    {name: "Location", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaDeviceInfo",
+    {name: "MediaDeviceInfo", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaDevices",
+    {name: "MediaDevices", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaElementAudioSourceNode",
+    {name: "MediaElementAudioSourceNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaError",
+    {name: "MediaError", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeyError",
+    {name: "MediaKeyError", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaEncryptedEvent",
+    {name: "MediaEncryptedEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeys",
+    {name: "MediaKeys", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeySession",
+    {name: "MediaKeySession", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeySystemAccess",
+    {name: "MediaKeySystemAccess", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeyMessageEvent",
+    {name: "MediaKeyMessageEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaKeyStatusMap",
+    {name: "MediaKeyStatusMap", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaList",
+    {name: "MediaList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaQueryList",
+    {name: "MediaQueryList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaQueryListEvent",
+    {name: "MediaQueryListEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaRecorder",
+    {name: "MediaRecorder", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaRecorderErrorEvent",
+    {name: "MediaRecorderErrorEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaSource",
+    {name: "MediaSource", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStream",
+    {name: "MediaStream", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStreamAudioDestinationNode",
+    {name: "MediaStreamAudioDestinationNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStreamAudioSourceNode",
+    {name: "MediaStreamAudioSourceNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStreamEvent",
+    {name: "MediaStreamEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStreamTrackEvent",
+    {name: "MediaStreamTrackEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MediaStreamTrack",
+    {name: "MediaStreamTrack", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MenuBoxObject", xbl: true},
+    {name: "MenuBoxObject", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessageChannel",
+    {name: "MessageChannel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessageEvent",
+    {name: "MessageEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessagePort",
+    {name: "MessagePort", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MimeType",
+    {name: "MimeType", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MimeTypeArray",
+    {name: "MimeTypeArray", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MouseEvent",
+    {name: "MouseEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MouseScrollEvent",
+    {name: "MouseScrollEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "mozRTCIceCandidate",
+    {name: "mozRTCIceCandidate", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "mozRTCPeerConnection",
+    {name: "mozRTCPeerConnection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "mozRTCSessionDescription",
+    {name: "mozRTCSessionDescription", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MutationEvent",
+    {name: "MutationEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MutationObserver",
+    {name: "MutationObserver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MutationRecord",
+    {name: "MutationRecord", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "NamedNodeMap",
+    {name: "NamedNodeMap", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Navigator",
+    {name: "Navigator", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "NetworkInformation", desktop: false},
+    {name: "NetworkInformation", insecureContext: true, desktop: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Node",
+    {name: "Node", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "NodeFilter",
+    {name: "NodeFilter", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "NodeIterator",
+    {name: "NodeIterator", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "NodeList",
+    {name: "NodeList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Notification",
+    {name: "Notification", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "OffscreenCanvas", disabled: true},
+    {name: "OffscreenCanvas", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "OfflineAudioCompletionEvent",
+    {name: "OfflineAudioCompletionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "OfflineAudioContext",
+    {name: "OfflineAudioContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "OfflineResourceList",
+    {name: "OfflineResourceList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Option",
+    {name: "Option", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "OscillatorNode",
+    {name: "OscillatorNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PageTransitionEvent",
+    {name: "PageTransitionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PaintRequest",
+    {name: "PaintRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PaintRequestList",
+    {name: "PaintRequestList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PannerNode",
+    {name: "PannerNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Path2D",
+    {name: "Path2D", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Performance",
+    {name: "Performance", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceEntry",
+    {name: "PerformanceEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceMark",
+    {name: "PerformanceMark", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceMeasure",
+    {name: "PerformanceMeasure", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceNavigation",
+    {name: "PerformanceNavigation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceNavigationTiming",
+    {name: "PerformanceNavigationTiming", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceObserver",
+    {name: "PerformanceObserver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceObserverEntryList",
+    {name: "PerformanceObserverEntryList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceResourceTiming",
+    {name: "PerformanceResourceTiming", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceTiming",
+    {name: "PerformanceTiming", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PeriodicWave",
+    {name: "PeriodicWave", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Permissions",
+    {name: "Permissions", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PermissionStatus",
+    {name: "PermissionStatus", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Plugin",
+    {name: "Plugin", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PluginArray",
+    {name: "PluginArray", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PointerEvent", android: false},
+    {name: "PointerEvent", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PopStateEvent",
+    {name: "PopStateEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PopupBlockedEvent",
+    {name: "PopupBlockedEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PopupBoxObject", xbl: true},
+    {name: "PopupBoxObject", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "Presentation", desktop: false, release: false },
+    {name: "Presentation", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationAvailability", desktop: false, release: false },
+    {name: "PresentationAvailability", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationConnection", desktop: false, release: false},
+    {name: "PresentationConnection", insecureContext: true, desktop: false, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationConnectionAvailableEvent", desktop: false, release: false },
+    {name: "PresentationConnectionAvailableEvent", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationConnectionCloseEvent", desktop: false, release: false },
+    {name: "PresentationConnectionCloseEvent", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationConnectionList", desktop: false, release: false },
+    {name: "PresentationConnectionList", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationReceiver", desktop: false, release: false },
+    {name: "PresentationReceiver", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PresentationRequest", desktop: false, release: false },
+    {name: "PresentationRequest", insecureContext: true, desktop: false, release: false },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ProcessingInstruction",
+    {name: "ProcessingInstruction", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ProgressEvent",
+    {name: "ProgressEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PublicKeyCredential", isSecureContext:true, nightly: true},
+    {name: "PublicKeyCredential", nightly: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushManager",
+    {name: "PushManager", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushSubscription",
+    {name: "PushSubscription", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushSubscriptionOptions",
+    {name: "PushSubscriptionOptions", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RadioNodeList",
+    {name: "RadioNodeList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Range",
+    {name: "Range", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Rect",
+    {name: "Rect", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Request",
+    {name: "Request", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Response",
+    {name: "Response", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RGBColor",
+    {name: "RGBColor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCCertificate",
+    {name: "RTCCertificate", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCDataChannelEvent",
+    {name: "RTCDataChannelEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCDTMFSender",
+    {name: "RTCDTMFSender", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCDTMFToneChangeEvent",
+    {name: "RTCDTMFToneChangeEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCIceCandidate",
+    {name: "RTCIceCandidate", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCPeerConnection",
+    {name: "RTCPeerConnection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCPeerConnectionIceEvent",
+    {name: "RTCPeerConnectionIceEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCRtpReceiver",
+    {name: "RTCRtpReceiver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCRtpSender",
+    {name: "RTCRtpSender", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCRtpTransceiver",
+    {name: "RTCRtpTransceiver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCSessionDescription",
+    {name: "RTCSessionDescription", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCStatsReport",
+    {name: "RTCStatsReport", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "RTCTrackEvent",
+    {name: "RTCTrackEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Screen",
+    {name: "Screen", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ScreenOrientation",
+    {name: "ScreenOrientation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ScriptProcessorNode",
+    {name: "ScriptProcessorNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ScrollAreaEvent",
+    {name: "ScrollAreaEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SecurityPolicyViolationEvent", release: false},
+    {name: "SecurityPolicyViolationEvent", insecureContext: true, release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Selection",
+    {name: "Selection", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ServiceWorker",
+    {name: "ServiceWorker", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ServiceWorkerContainer",
+    {name: "ServiceWorkerContainer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ServiceWorkerRegistration",
+    {name: "ServiceWorkerRegistration", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ScopedCredential", disabled: true},
+    {name: "ScopedCredential", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ScopedCredentialInfo", disabled: true},
+    {name: "ScopedCredentialInfo", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ShadowRoot", disabled: true},
+    {name: "ShadowRoot", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SharedWorker",
+    {name: "SharedWorker", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SimpleGestureEvent", xbl: true},
+    {name: "SimpleGestureEvent", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SimpleTest", xbl: false},
+    {name: "SimpleTest", insecureContext: true, xbl: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SourceBuffer",
+    {name: "SourceBuffer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SourceBufferList",
+    {name: "SourceBufferList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpeechSynthesisErrorEvent", android: false},
+    {name: "SpeechSynthesisErrorEvent", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpeechSynthesisEvent", android: false},
+    {name: "SpeechSynthesisEvent", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpeechSynthesis", android: false},
+    {name: "SpeechSynthesis", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpeechSynthesisUtterance", android: false},
+    {name: "SpeechSynthesisUtterance", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpeechSynthesisVoice", android: false},
+    {name: "SpeechSynthesisVoice", insecureContext: true, android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SpecialPowers", xbl: false},
+    {name: "SpecialPowers", insecureContext: true, xbl: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "StereoPannerNode",
+    {name: "StereoPannerNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Storage",
+    {name: "Storage", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "StorageEvent",
+    {name: "StorageEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "StorageManager", isSecureContext: true, android: false},
+    {name: "StorageManager", android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "StyleSheet",
+    {name: "StyleSheet", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "StyleSheetList",
+    {name: "StyleSheetList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SubtleCrypto",
+    {name: "SubtleCrypto", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAElement",
+    {name: "SVGAElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAngle",
+    {name: "SVGAngle", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedAngle",
+    {name: "SVGAnimatedAngle", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedBoolean",
+    {name: "SVGAnimatedBoolean", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedEnumeration",
+    {name: "SVGAnimatedEnumeration", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedInteger",
+    {name: "SVGAnimatedInteger", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedLength",
+    {name: "SVGAnimatedLength", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedLengthList",
+    {name: "SVGAnimatedLengthList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedNumber",
+    {name: "SVGAnimatedNumber", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedNumberList",
+    {name: "SVGAnimatedNumberList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedPreserveAspectRatio",
+    {name: "SVGAnimatedPreserveAspectRatio", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedRect",
+    {name: "SVGAnimatedRect", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedString",
+    {name: "SVGAnimatedString", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimatedTransformList",
+    {name: "SVGAnimatedTransformList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimateElement",
+    {name: "SVGAnimateElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimateMotionElement",
+    {name: "SVGAnimateMotionElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimateTransformElement",
+    {name: "SVGAnimateTransformElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGAnimationElement",
+    {name: "SVGAnimationElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGCircleElement",
+    {name: "SVGCircleElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGClipPathElement",
+    {name: "SVGClipPathElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGComponentTransferFunctionElement",
+    {name: "SVGComponentTransferFunctionElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGDefsElement",
+    {name: "SVGDefsElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGDescElement",
+    {name: "SVGDescElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGElement",
+    {name: "SVGElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGEllipseElement",
+    {name: "SVGEllipseElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEBlendElement",
+    {name: "SVGFEBlendElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEColorMatrixElement",
+    {name: "SVGFEColorMatrixElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEComponentTransferElement",
+    {name: "SVGFEComponentTransferElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFECompositeElement",
+    {name: "SVGFECompositeElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEConvolveMatrixElement",
+    {name: "SVGFEConvolveMatrixElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEDiffuseLightingElement",
+    {name: "SVGFEDiffuseLightingElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEDisplacementMapElement",
+    {name: "SVGFEDisplacementMapElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEDistantLightElement",
+    {name: "SVGFEDistantLightElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEDropShadowElement",
+    {name: "SVGFEDropShadowElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEFloodElement",
+    {name: "SVGFEFloodElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEFuncAElement",
+    {name: "SVGFEFuncAElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEFuncBElement",
+    {name: "SVGFEFuncBElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEFuncGElement",
+    {name: "SVGFEFuncGElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEFuncRElement",
+    {name: "SVGFEFuncRElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEGaussianBlurElement",
+    {name: "SVGFEGaussianBlurElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEImageElement",
+    {name: "SVGFEImageElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEMergeElement",
+    {name: "SVGFEMergeElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEMergeNodeElement",
+    {name: "SVGFEMergeNodeElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEMorphologyElement",
+    {name: "SVGFEMorphologyElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEOffsetElement",
+    {name: "SVGFEOffsetElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFEPointLightElement",
+    {name: "SVGFEPointLightElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFESpecularLightingElement",
+    {name: "SVGFESpecularLightingElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFESpotLightElement",
+    {name: "SVGFESpotLightElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFETileElement",
+    {name: "SVGFETileElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFETurbulenceElement",
+    {name: "SVGFETurbulenceElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGFilterElement",
+    {name: "SVGFilterElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGForeignObjectElement",
+    {name: "SVGForeignObjectElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGGElement",
+    {name: "SVGGElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGGeometryElement",
+    {name: "SVGGeometryElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGGradientElement",
+    {name: "SVGGradientElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGGraphicsElement",
+    {name: "SVGGraphicsElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGImageElement",
+    {name: "SVGImageElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGLength",
+    {name: "SVGLength", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGLengthList",
+    {name: "SVGLengthList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGLinearGradientElement",
+    {name: "SVGLinearGradientElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGLineElement",
+    {name: "SVGLineElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGMarkerElement",
+    {name: "SVGMarkerElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGMaskElement",
+    {name: "SVGMaskElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGMatrix",
+    {name: "SVGMatrix", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGMetadataElement",
+    {name: "SVGMetadataElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGMPathElement",
+    {name: "SVGMPathElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGNumber",
+    {name: "SVGNumber", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGNumberList",
+    {name: "SVGNumberList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathElement",
+    {name: "SVGPathElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSeg",
+    {name: "SVGPathSeg", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegArcAbs",
+    {name: "SVGPathSegArcAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegArcRel",
+    {name: "SVGPathSegArcRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegClosePath",
+    {name: "SVGPathSegClosePath", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoCubicAbs",
+    {name: "SVGPathSegCurvetoCubicAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoCubicRel",
+    {name: "SVGPathSegCurvetoCubicRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoCubicSmoothAbs",
+    {name: "SVGPathSegCurvetoCubicSmoothAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoCubicSmoothRel",
+    {name: "SVGPathSegCurvetoCubicSmoothRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoQuadraticAbs",
+    {name: "SVGPathSegCurvetoQuadraticAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoQuadraticRel",
+    {name: "SVGPathSegCurvetoQuadraticRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoQuadraticSmoothAbs",
+    {name: "SVGPathSegCurvetoQuadraticSmoothAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegCurvetoQuadraticSmoothRel",
+    {name: "SVGPathSegCurvetoQuadraticSmoothRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoAbs",
+    {name: "SVGPathSegLinetoAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoHorizontalAbs",
+    {name: "SVGPathSegLinetoHorizontalAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoHorizontalRel",
+    {name: "SVGPathSegLinetoHorizontalRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoRel",
+    {name: "SVGPathSegLinetoRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoVerticalAbs",
+    {name: "SVGPathSegLinetoVerticalAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegLinetoVerticalRel",
+    {name: "SVGPathSegLinetoVerticalRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegList",
+    {name: "SVGPathSegList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegMovetoAbs",
+    {name: "SVGPathSegMovetoAbs", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPathSegMovetoRel",
+    {name: "SVGPathSegMovetoRel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPatternElement",
+    {name: "SVGPatternElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPoint",
+    {name: "SVGPoint", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPointList",
+    {name: "SVGPointList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPolygonElement",
+    {name: "SVGPolygonElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPolylineElement",
+    {name: "SVGPolylineElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGPreserveAspectRatio",
+    {name: "SVGPreserveAspectRatio", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGRadialGradientElement",
+    {name: "SVGRadialGradientElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGRect",
+    {name: "SVGRect", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGRectElement",
+    {name: "SVGRectElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGScriptElement",
+    {name: "SVGScriptElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGSetElement",
+    {name: "SVGSetElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGStopElement",
+    {name: "SVGStopElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGStringList",
+    {name: "SVGStringList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGStyleElement",
+    {name: "SVGStyleElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGSVGElement",
+    {name: "SVGSVGElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGSwitchElement",
+    {name: "SVGSwitchElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGSymbolElement",
+    {name: "SVGSymbolElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTextContentElement",
+    {name: "SVGTextContentElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTextElement",
+    {name: "SVGTextElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTextPathElement",
+    {name: "SVGTextPathElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTextPositioningElement",
+    {name: "SVGTextPositioningElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTitleElement",
+    {name: "SVGTitleElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTransform",
+    {name: "SVGTransform", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTransformList",
+    {name: "SVGTransformList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGTSpanElement",
+    {name: "SVGTSpanElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGUnitTypes",
+    {name: "SVGUnitTypes", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGUseElement",
+    {name: "SVGUseElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGViewElement",
+    {name: "SVGViewElement", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SVGZoomAndPan",
+    {name: "SVGZoomAndPan", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Text",
+    {name: "Text", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextDecoder",
+    {name: "TextDecoder", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextEncoder",
+    {name: "TextEncoder", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextMetrics",
+    {name: "TextMetrics", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextTrack",
+    {name: "TextTrack", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextTrackCue",
+    {name: "TextTrackCue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextTrackCueList",
+    {name: "TextTrackCueList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextTrackList",
+    {name: "TextTrackList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TimeEvent",
+    {name: "TimeEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TimeRanges",
+    {name: "TimeRanges", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Touch",
+    {name: "Touch", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TouchEvent",
+    {name: "TouchEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TouchList",
+    {name: "TouchList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TrackEvent",
+    {name: "TrackEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TransitionEvent",
+    {name: "TransitionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TreeColumn", xbl: true},
+    {name: "TreeColumn", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TreeColumns", xbl: true},
+    {name: "TreeColumns", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TreeContentView", xbl: true},
+    {name: "TreeContentView", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TreeWalker",
+    {name: "TreeWalker", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "U2F", disabled: true},
+    {name: "U2F", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "UIEvent",
+    {name: "UIEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "URL",
+    {name: "URL", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "URLSearchParams",
+    {name: "URLSearchParams", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "UserProximityEvent",
+    {name: "UserProximityEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ValidityState",
+    {name: "ValidityState", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "VideoPlaybackQuality",
+    {name: "VideoPlaybackQuality", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "VideoStreamTrack",
+    {name: "VideoStreamTrack", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRDisplay", releaseNonWindows: false},
+    {name: "VRDisplay", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRDisplayCapabilities", releaseNonWindows: false},
+    {name: "VRDisplayCapabilities", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRDisplayEvent", releaseNonWindows: false},
+    {name: "VRDisplayEvent", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VREyeParameters", releaseNonWindows: false},
+    {name: "VREyeParameters", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRFieldOfView", releaseNonWindows: false},
+    {name: "VRFieldOfView", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRFrameData", releaseNonWindows: false},
+    {name: "VRFrameData", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRPose", releaseNonWindows: false},
+    {name: "VRPose", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRStageParameters", releaseNonWindows: false},
+    {name: "VRStageParameters", insecureContext: true, releaseNonWindows: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "VTTCue",
+    {name: "VTTCue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "VTTRegion",
+    {name: "VTTRegion", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WaveShaperNode",
+    {name: "WaveShaperNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "WebAuthnAssertion", disabled: true},
+    {name: "WebAuthnAssertion", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "WebAuthnAttestation", disabled: true},
+    {name: "WebAuthnAttestation", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "WebAuthentication", disabled: true},
+    {name: "WebAuthentication", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLActiveInfo",
+    {name: "WebGLActiveInfo", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLBuffer",
+    {name: "WebGLBuffer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLContextEvent",
+    {name: "WebGLContextEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLFramebuffer",
+    {name: "WebGLFramebuffer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLProgram",
+    {name: "WebGLProgram", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLQuery",
+    {name: "WebGLQuery", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLRenderbuffer",
+    {name: "WebGLRenderbuffer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLRenderingContext",
+    {name: "WebGLRenderingContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGL2RenderingContext",
+    {name: "WebGL2RenderingContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLSampler",
+    {name: "WebGLSampler", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLShader",
+    {name: "WebGLShader", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLShaderPrecisionFormat",
+    {name: "WebGLShaderPrecisionFormat", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLSync",
+    {name: "WebGLSync", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLTexture",
+    {name: "WebGLTexture", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLTransformFeedback",
+    {name: "WebGLTransformFeedback", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLUniformLocation",
+    {name: "WebGLUniformLocation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebGLVertexArrayObject",
+    {name: "WebGLVertexArrayObject", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebKitCSSMatrix",
+    {name: "WebKitCSSMatrix", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebSocket",
+    {name: "WebSocket", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WheelEvent",
+    {name: "WheelEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Window",
+    {name: "Window", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Worker",
+    {name: "Worker", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLDocument",
+    {name: "XMLDocument", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequest",
+    {name: "XMLHttpRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequestEventTarget",
+    {name: "XMLHttpRequestEventTarget", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequestUpload",
+    {name: "XMLHttpRequestUpload", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLSerializer",
+    {name: "XMLSerializer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLStylesheetProcessingInstruction",
+    {name: "XMLStylesheetProcessingInstruction", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XPathEvaluator",
+    {name: "XPathEvaluator", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XPathExpression",
+    {name: "XPathExpression", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XPathResult",
+    {name: "XPathResult", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XSLTProcessor",
+    {name: "XSLTProcessor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULButtonElement", xbl: true},
+    {name: "XULButtonElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULCheckboxElement", xbl: true},
+    {name: "XULCheckboxElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULCommandEvent", xbl: true},
+    {name: "XULCommandEvent", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULControlElement", xbl: true},
+    {name: "XULControlElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULDocument", xbl: true},
+    {name: "XULDocument", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULElement", xbl: true},
+    {name: "XULElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULLabeledControlElement", xbl: true},
+    {name: "XULLabeledControlElement", insecureContext: true, xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
   var isMac = /Mac OS/.test(navigator.oscpu);
   var isWindows = /Windows/.test(navigator.oscpu);
   var isAndroid = navigator.userAgent.includes("Android");
   var isLinux = /Linux/.test(navigator.oscpu) && !isAndroid;
-  var isSecureContext = window.isSecureContext;
+  var isInsecureContext = !window.isSecureContext;
 
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
   {
     for (var entry of interfaces) {
       if (typeof(entry) === "string") {
-        interfaceMap[entry] = true;
+        interfaceMap[entry] = !isInsecureContext;
       } else {
         ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
         if ((entry.nightly === !isNightly) ||
             (entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
             (entry.xbl === !isXBLScope) ||
             (entry.desktop === !isDesktop) ||
             (entry.windows === !isWindows) ||
             (entry.mac === !isMac) ||
             (entry.linux === !isLinux) ||
             (entry.android === !isAndroid && !entry.nightlyAndroid) ||
             (entry.release === !isRelease) ||
             (entry.releaseNonWindows === !(isRelease && !isWindows)) ||
-            (entry.isSecureContext === !isSecureContext) ||
+	    // The insecureContext test is very purposefully converting
+	    // entry.insecureContext to boolean, so undefined will convert to
+	    // false.  That way entries without an insecureContext annotation
+	    // will get treated as "insecureContext: false", which means exposed
+	    // only in secure contexts.
+            (isInsecureContext && !Boolean(entry.insecureContext)) ||
             entry.disabled) {
           interfaceMap[entry.name] = false;
         } else {
           interfaceMap[entry.name] = true;
         }
       }
     }
   }
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -4,278 +4,284 @@
 
 // This file lists global interfaces we want exposed and verifies they
 // are what we intend. Each entry in the arrays below can either be a
 // simple string with the interface name, or an object with a 'name'
 // property giving the interface name as a string, and additional
 // properties which qualify the exposure of that interface. For example:
 //
 // [
-//   "AGlobalInterface",
+//   "AGlobalInterface", // secure context only
 //   { name: "ExperimentalThing", release: false },
 //   { name: "ReallyExperimentalThing", nightly: true },
 //   { name: "DesktopOnlyThing", desktop: true },
 //   { name: "FancyControl", xbl: true },
 //   { name: "DisabledEverywhere", disabled: true },
 // ];
 //
 // See createInterfaceMap() below for a complete list of properties.
 
 // IMPORTANT: Do not change this list without review from
 //            a JavaScript Engine peer!
 var ecmaGlobals =
   [
-    "Array",
-    "ArrayBuffer",
-    {name: "Atomics", disabled: true},
-    "Boolean",
-    {name: "ByteLengthQueuingStrategy", optional: true},
-    {name: "CountQueuingStrategy", optional: true},
-    "DataView",
-    "Date",
-    "Error",
-    "EvalError",
-    "Float32Array",
-    "Float64Array",
-    "Function",
-    "Infinity",
-    "Int16Array",
-    "Int32Array",
-    "Int8Array",
-    "InternalError",
-    "Intl",
-    "JSON",
-    "Map",
-    "Math",
-    "NaN",
-    "Number",
-    "Object",
-    "Promise",
-    "Proxy",
-    "RangeError",
-    {name: "ReadableStream", optional: true},
-    "ReferenceError",
-    "Reflect",
-    "RegExp",
-    "Set",
-    {name: "SharedArrayBuffer", disabled: true},
-    {name: "SIMD", nightly: true},
-    "String",
-    "Symbol",
-    "SyntaxError",
-    {name: "TypedObject", nightly: true},
-    "TypeError",
-    "Uint16Array",
-    "Uint32Array",
-    "Uint8Array",
-    "Uint8ClampedArray",
-    "URIError",
-    "WeakMap",
-    "WeakSet",
-    {name: "WebAssembly", optional: true}
+    {name: "Array", insecureContext: true},
+    {name: "ArrayBuffer", insecureContext: true},
+    {name: "Atomics", insecureContext: true, disabled: true},
+    {name: "Boolean", insecureContext: true},
+    {name: "ByteLengthQueuingStrategy", insecureContext: true, optional: true},
+    {name: "CountQueuingStrategy", insecureContext: true, optional: true},
+    {name: "DataView", insecureContext: true},
+    {name: "Date", insecureContext: true},
+    {name: "Error", insecureContext: true},
+    {name: "EvalError", insecureContext: true},
+    {name: "Float32Array", insecureContext: true},
+    {name: "Float64Array", insecureContext: true},
+    {name: "Function", insecureContext: true},
+    {name: "Infinity", insecureContext: true},
+    {name: "Int16Array", insecureContext: true},
+    {name: "Int32Array", insecureContext: true},
+    {name: "Int8Array", insecureContext: true},
+    {name: "InternalError", insecureContext: true},
+    {name: "Intl", insecureContext: true},
+    {name: "JSON", insecureContext: true},
+    {name: "Map", insecureContext: true},
+    {name: "Math", insecureContext: true},
+    {name: "NaN", insecureContext: true},
+    {name: "Number", insecureContext: true},
+    {name: "Object", insecureContext: true},
+    {name: "Promise", insecureContext: true},
+    {name: "Proxy", insecureContext: true},
+    {name: "RangeError", insecureContext: true},
+    {name: "ReadableStream", insecureContext: true, optional: true},
+    {name: "ReferenceError", insecureContext: true},
+    {name: "Reflect", insecureContext: true},
+    {name: "RegExp", insecureContext: true},
+    {name: "Set", insecureContext: true},
+    {name: "SharedArrayBuffer", insecureContext: true, disabled: true},
+    {name: "SIMD", insecureContext: true, nightly: true},
+    {name: "String", insecureContext: true},
+    {name: "Symbol", insecureContext: true},
+    {name: "SyntaxError", insecureContext: true},
+    {name: "TypedObject", insecureContext: true, nightly: true},
+    {name: "TypeError", insecureContext: true},
+    {name: "Uint16Array", insecureContext: true},
+    {name: "Uint32Array", insecureContext: true},
+    {name: "Uint8Array", insecureContext: true},
+    {name: "Uint8ClampedArray", insecureContext: true},
+    {name: "URIError", insecureContext: true},
+    {name: "WeakMap", insecureContext: true},
+    {name: "WeakSet", insecureContext: true},
+    {name: "WebAssembly", insecureContext: true, optional: true}
   ];
 // IMPORTANT: Do not change the list above without review from
 //            a JavaScript Engine peer!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AbortController",
+    {name: "AbortController", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "AbortSignal",
+    {name: "AbortSignal", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Blob",
+    {name: "Blob", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "BroadcastChannel",
+    {name: "BroadcastChannel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Cache",
+    {name: "Cache", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CacheStorage",
+    {name: "CacheStorage", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CloseEvent",
+    {name: "CloseEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Crypto",
+    {name: "Crypto", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "CustomEvent",
+    {name: "CustomEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DedicatedWorkerGlobalScope",
+    {name: "DedicatedWorkerGlobalScope", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Directory",
+    {name: "Directory", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMCursor",
+    {name: "DOMCursor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMError",
+    {name: "DOMError", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMException",
+    {name: "DOMException", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMRequest",
+    {name: "DOMRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DOMStringList",
+    {name: "DOMStringList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ErrorEvent",
+    {name: "ErrorEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Event",
+    {name: "Event", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "EventSource",
+    {name: "EventSource", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "EventTarget",
+    {name: "EventTarget", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "File",
+    {name: "File", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileList",
+    {name: "FileList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileReader",
+    {name: "FileReader", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FileReaderSync",
+    {name: "FileReaderSync", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "FormData",
+    {name: "FormData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Headers",
+    {name: "Headers", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBCursor",
+    {name: "IDBCursor", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBCursorWithValue",
+    {name: "IDBCursorWithValue", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBDatabase",
+    {name: "IDBDatabase", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBFactory",
+    {name: "IDBFactory", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBIndex",
+    {name: "IDBIndex", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBKeyRange",
+    {name: "IDBKeyRange", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBObjectStore",
+    {name: "IDBObjectStore", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBOpenDBRequest",
+    {name: "IDBOpenDBRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBRequest",
+    {name: "IDBRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBTransaction",
+    {name: "IDBTransaction", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "IDBVersionChangeEvent",
+    {name: "IDBVersionChangeEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageBitmap",
+    {name: "ImageBitmap", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageBitmapRenderingContext",
+    {name: "ImageBitmapRenderingContext", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ImageData",
+    {name: "ImageData", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessageChannel",
+    {name: "MessageChannel", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessageEvent",
+    {name: "MessageEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "MessagePort",
+    {name: "MessagePort", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "NetworkInformation", android: true },
+    { name: "NetworkInformation", insecureContext: true, android: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Notification",
+    {name: "Notification", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "OffscreenCanvas", disabled: true },
+    { name: "OffscreenCanvas", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Performance",
+    {name: "Performance", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceEntry",
+    {name: "PerformanceEntry", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceMark",
+    {name: "PerformanceMark", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceMeasure",
+    {name: "PerformanceMeasure", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceObserver",
+    {name: "PerformanceObserver", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PerformanceObserverEntryList",
+    {name: "PerformanceObserverEntryList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ProgressEvent",
+    {name: "ProgressEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushManager",
+    {name: "PushManager", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushSubscription",
+    {name: "PushSubscription", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "PushSubscriptionOptions",
+    {name: "PushSubscriptionOptions", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Request",
+    {name: "Request", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Response",
+    {name: "Response", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "ServiceWorkerRegistration",
+    {name: "ServiceWorkerRegistration", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "StorageManager", isSecureContext: true, android: false},
+    {name: "StorageManager", android: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "SubtleCrypto",
+    {name: "SubtleCrypto", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextDecoder",
+    {name: "TextDecoder", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "TextEncoder",
+    {name: "TextEncoder", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequest",
+    {name: "XMLHttpRequest", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequestEventTarget",
+    {name: "XMLHttpRequestEventTarget", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "XMLHttpRequestUpload",
+    {name: "XMLHttpRequestUpload", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "URL",
+    {name: "URL", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "URLSearchParams",
+    {name: "URLSearchParams", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLActiveInfo", disabled: true },
+    { name: "WebGLActiveInfo", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLBuffer", disabled: true },
+    { name: "WebGLBuffer", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLContextEvent", disabled: true },
+    { name: "WebGLContextEvent", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLFramebuffer", disabled: true },
+    { name: "WebGLFramebuffer", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLProgram", disabled: true },
+    { name: "WebGLProgram", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLRenderbuffer", disabled: true },
+    { name: "WebGLRenderbuffer", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLRenderingContext", disabled: true },
+    { name: "WebGLRenderingContext", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLShader", disabled: true },
+    { name: "WebGLShader", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLShaderPrecisionFormat", disabled: true },
+    { name: "WebGLShaderPrecisionFormat", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLTexture", disabled: true },
+    { name: "WebGLTexture", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLUniformLocation", disabled: true },
+    { name: "WebGLUniformLocation", insecureContext: true, disabled: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WebSocket",
+    {name: "WebSocket", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "Worker",
+    {name: "Worker", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WorkerGlobalScope",
+    {name: "WorkerGlobalScope", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WorkerLocation",
+    {name: "WorkerLocation", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "WorkerNavigator",
+    {name: "WorkerNavigator", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(version, userAgent) {
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(userAgent);
   var isAndroid = !!navigator.userAgent.includes("Android");
+  var isInsecureContext = !self.isSecureContext;
 
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
   {
     for (var entry of interfaces) {
       if (typeof(entry) === "string") {
-        interfaceMap[entry] = true;
+        interfaceMap[entry] = !isInsecureContext;
       } else {
         ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
         if ((entry.nightly === !isNightly) ||
             (entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
             (entry.desktop === !isDesktop) ||
             (entry.android === !isAndroid && !entry.nightlyAndroid) ||
             (entry.release === !isRelease) ||
-            (entry.isSecureContext === !isSecureContext) ||
+	    // The insecureContext test is very purposefully converting
+	    // entry.insecureContext to boolean, so undefined will convert to
+	    // false.  That way entries without an insecureContext annotation
+	    // will get treated as "insecureContext: false", which means exposed
+	    // only in secure contexts.
+            (isInsecureContext && !Boolean(entry.insecureContext)) ||
             entry.disabled) {
           interfaceMap[entry.name] = false;
         } else if (entry.optional) {
           interfaceMap[entry.name] = "optional";
         } else {
           interfaceMap[entry.name] = true;
         }
       }
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -620,41 +620,40 @@ txMozillaXMLOutput::createTxWrapper()
     nsresult rv = nsContentUtils::NameSpaceManager()->
         RegisterNameSpace(NS_LITERAL_STRING(kTXNameSpaceURI), namespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<Element> wrapper =
       mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
                             nsGkAtoms::transformiix, namespaceID);
 
-    uint32_t j = 0;
 #ifdef DEBUG
     // Keep track of the location of the current documentElement, if there is
     // one, so we can verify later
-    uint32_t rootLocation = 0;
+    uint32_t j = 0, rootLocation = 0;
 #endif
     for (nsCOMPtr<nsIContent> childContent = mDocument->GetFirstChild();
          childContent; childContent = childContent->GetNextSibling()) {
 #ifdef DEBUG
         if (childContent->IsElement()) {
             rootLocation = j;
         }
 #endif
 
         if (childContent->NodeInfo()->NameAtom() == nsGkAtoms::documentTypeNodeName) {
 #ifdef DEBUG
             // The new documentElement should go after the document type.
             // This is needed for cases when there is no existing
             // documentElement in the document.
             rootLocation = std::max(rootLocation, j + 1);
+            ++j;
 #endif
-            ++j;
         }
         else {
-            mDocument->RemoveChildAt_Deprecated(j, true);
+            mDocument->RemoveChildNode(childContent, true);
 
             rv = wrapper->AppendChildTo(childContent, true);
             NS_ENSURE_SUCCESS(rv, rv);
             break;
         }
     }
 
     if (!mCurrentNodeStack.AppendObject(wrapper)) {
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -749,40 +749,16 @@ GLContext::InitWithPrefixImpl(const char
         // this has been fixed in Mac OS X 10.9. See 907946
         // and it also works in 10.8.3 and higher.  See 1094338.
         if (Vendor() == gl::GLVendor::NVIDIA &&
             !nsCocoaFeatures::IsAtLeastVersion(10,8,3))
         {
             MarkUnsupported(GLFeature::depth_texture);
         }
 #endif
-        if (IsSupported(GLFeature::frag_color_float)) {
-            float was[4] = {};
-            fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, was);
-
-            const float test[4] = {-1.0, 0, 2.0, 255.0};
-            fClearColor(test[0], test[1], test[2], test[3]);
-
-            float now[4] = {};
-            fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, now);
-
-            fClearColor(was[0], was[1], was[2], was[3]);
-
-            const bool unclamped = now[0] == test[0] && now[1] == test[1] &&
-                                   now[2] == test[2] && now[3] == test[3];
-            if (!unclamped) {
-                printf_stderr("COLOR_CLEAR_VALUE: now{%f,%f,%f,%f} != test{%f,%f,%f,%f}\n",
-                              test[0], test[1], test[2], test[3],
-                              now[0], now[1], now[2], now[3]);
-                gfxCriticalNote << "GLFeature::frag_color_float failed support probe,"
-                                << " disabling. (RENDERER: "
-                                << (const char*)fGetString(LOCAL_GL_RENDERER) << ")";
-                MarkUnsupported(GLFeature::frag_color_float);
-            }
-        }
     }
 
     if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
         MOZ_ASSERT((mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
                    "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
                    " being available!");
     }
 
@@ -2066,96 +2042,16 @@ GLContext::AssembleOffscreenFBs(const GL
         *readFB_out = readFB;
     } else if (readFB) {
         MOZ_CRASH("readFB created when not requested!");
     }
 
     return isComplete;
 }
 
-
-void
-GLContext::ClearSafely()
-{
-    // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
-    // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
-    //
-    // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
-    // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
-    // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
-    // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
-    // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
-
-    realGLboolean scissorTestEnabled;
-    realGLboolean ditherEnabled;
-    realGLboolean colorWriteMask[4];
-    realGLboolean depthWriteMask;
-    GLint stencilWriteMaskFront, stencilWriteMaskBack;
-    GLfloat colorClearValue[4];
-    GLfloat depthClearValue;
-    GLint stencilClearValue;
-
-    // save current GL state
-    fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
-    fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
-    fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
-    fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
-    fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
-    fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
-    fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
-    fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
-    fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
-
-    // prepare GL state for clearing
-    fDisable(LOCAL_GL_SCISSOR_TEST);
-    fDisable(LOCAL_GL_DITHER);
-
-    fColorMask(1, 1, 1, 1);
-    fClearColor(0.f, 0.f, 0.f, 0.f);
-
-    fDepthMask(1);
-    fClearDepth(1.0f);
-
-    fStencilMask(0xffffffff);
-    fClearStencil(0);
-
-    // do clear
-    fClear(LOCAL_GL_COLOR_BUFFER_BIT |
-           LOCAL_GL_DEPTH_BUFFER_BIT |
-           LOCAL_GL_STENCIL_BUFFER_BIT);
-
-    // restore GL state after clearing
-    fColorMask(colorWriteMask[0],
-               colorWriteMask[1],
-               colorWriteMask[2],
-               colorWriteMask[3]);
-    fClearColor(colorClearValue[0],
-                colorClearValue[1],
-                colorClearValue[2],
-                colorClearValue[3]);
-
-    fDepthMask(depthWriteMask);
-    fClearDepth(depthClearValue);
-
-    fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
-    fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
-    fClearStencil(stencilClearValue);
-
-    if (ditherEnabled)
-        fEnable(LOCAL_GL_DITHER);
-    else
-        fDisable(LOCAL_GL_DITHER);
-
-    if (scissorTestEnabled)
-        fEnable(LOCAL_GL_SCISSOR_TEST);
-    else
-        fDisable(LOCAL_GL_SCISSOR_TEST);
-
-}
-
 void
 GLContext::MarkDestroyed()
 {
     if (IsDestroyed())
         return;
 
     // Null these before they're naturally nulled after dtor, as we want GLContext to
     // still be alive in *their* dtors.
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -3571,22 +3571,16 @@ public:
     bool IsOffscreen() const {
         return mIsOffscreen;
     }
 
     GLScreenBuffer* Screen() const {
         return mScreen.get();
     }
 
-    /* Clear to transparent black, with 0 depth and stencil,
-     * while preserving current ClearColor etc. values.
-     * Useful for resizing offscreen buffers.
-     */
-    void ClearSafely();
-
     bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
 
     bool IsDrawingToDefaultFramebuffer();
 
     bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const;
 
 protected:
     bool InitWithPrefix(const char* prefix, bool trygl);
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -14,16 +14,17 @@
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/gfx/gfxVars.h"
 #if defined(XP_WIN)
 # include "mozilla/gfx/DeviceManagerDx.h"
 #endif
 #include "mozilla/ipc/CrashReporterHost.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
 #include "mozilla/Unused.h"
+#include "mozilla/HangDetails.h"
 #include "nsIObserverService.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #include "ProfilerParent.h"
 #endif
 
 namespace mozilla {
 namespace gfx {
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -27,16 +27,17 @@
 #include "mozilla/layers/CompositorManagerParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
 #include "mozilla/layers/UiCompositorControllerParent.h"
 #include "mozilla/layers/MemoryReportingMLGPU.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/webrender/WebRenderAPI.h"
+#include "mozilla/HangDetails.h"
 #include "nsDebugImpl.h"
 #include "nsThreadManager.h"
 #include "prenv.h"
 #include "ProcessUtils.h"
 #include "VRManager.h"
 #include "VRManagerParent.h"
 #include "VRThread.h"
 #include "VsyncBridgeParent.h"
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 GraphicsMessages;
 include MemoryReportTypes;
+include HangTypes;
 include protocol PCompositorManager;
 include protocol PImageBridge;
 include protocol PProfiler;
 include protocol PVRManager;
 include protocol PVsyncBridge;
 include protocol PUiCompositorController;
 include protocol PVideoDecoderManager;
 
@@ -18,17 +19,16 @@ using mozilla::dom::NativeThreadId from 
 using mozilla::Telemetry::HistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedHistogramAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using mozilla::gfx::Feature from "gfxFeature.h";
 using mozilla::gfx::Fallback from "gfxFallback.h";
-using mozilla::HangDetails from "mozilla/HangDetails.h";
 
 namespace mozilla {
 namespace gfx {
 
 union GfxPrefValue {
   bool;
   int32_t;
   uint32_t;
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -50,16 +50,20 @@ public:
     MOZ_COUNT_DTOR(NewRenderer);
   }
 
   virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override
   {
     layers::AutoCompleteTask complete(mTask);
 
     UniquePtr<RenderCompositor> compositor = RenderCompositor::Create(Move(mCompositorWidget));
+    if (!compositor) {
+      // RenderCompositor::Create puts a message into gfxCriticalNote if it is nullptr
+      return;
+    }
 
     *mUseANGLE = compositor->UseANGLE();
 
     wr::Renderer* wrRenderer = nullptr;
     if (!wr_window_new(aWindowId, mSize.width, mSize.height, compositor->gl(),
                        aRenderThread.ThreadPool().Raw(),
                        mDocHandle, &wrRenderer,
                        mMaxTextureSize)) {
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -301,16 +301,18 @@ private:
 #ifdef NS_PRINTING
   // Called when the DocViewer is notified that the state
   // of Printing or PP has changed
   void SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
                                    bool                 aIsPrintingOrPP,
                                    bool                 aStartAtTop);
 #endif // NS_PRINTING
 
+  void ReturnToGalleyPresentation();
+
   // Whether we should attach to the top level widget. This is true if we
   // are sharing/recycling a single base widget and not creating multiple
   // child widgets.
   bool ShouldAttachToTopLevel();
 
 protected:
   // These return the current shell/prescontext etc.
   nsIPresShell* GetPresShell();
@@ -351,17 +353,17 @@ protected:
   // mTextZoom/mPageZoom record the textzoom/pagezoom of the first (galley)
   // presshell only.
   float mTextZoom;      // Text zoom, defaults to 1.0
   float mPageZoom;
   float mOverrideDPPX;  // DPPX overrided, defaults to 0.0
   int mMinFontSize;
 
   int16_t mNumURLStarts;
-  int16_t mDestroyRefCount;    // a second "refcount" for the document viewer's "destroy"
+  int16_t mDestroyBlockedCount;
 
   unsigned      mStopped : 1;
   unsigned      mLoaded : 1;
   unsigned      mDeferredWindowClose : 1;
   // document management data
   //   these items are specific to markup documents (html and xml)
   //   may consider splitting these out into a subclass
   unsigned      mIsSticky : 1;
@@ -497,17 +499,17 @@ void nsDocumentViewer::PrepareToStartLoa
 nsDocumentViewer::nsDocumentViewer()
   : mParentWidget(nullptr),
     mAttachedToParent(false),
     mTextZoom(1.0),
     mPageZoom(1.0),
     mOverrideDPPX(0.0),
     mMinFontSize(0),
     mNumURLStarts(0),
-    mDestroyRefCount(0),
+    mDestroyBlockedCount(0),
     mStopped(false),
     mLoaded(false),
     mDeferredWindowClose(false),
     mIsSticky(true),
     mInPermitUnload(false),
     mInPermitUnloadPrompt(false),
 #ifdef NS_PRINTING
     mClosingWhilePrinting(false),
@@ -549,17 +551,17 @@ nsDocumentViewer::~nsDocumentViewer()
     mDocument->Destroy();
   }
 
   if (mPrintJob) {
     mPrintJob->Destroy();
     mPrintJob = nullptr;
   }
 
-  MOZ_RELEASE_ASSERT(mDestroyRefCount == 0);
+  MOZ_RELEASE_ASSERT(mDestroyBlockedCount == 0);
   NS_ASSERTION(!mPresShell && !mPresContext,
                "User did not call nsIContentViewer::Destroy");
   if (mPresShell || mPresContext) {
     // Make sure we don't hand out a reference to the content viewer to
     // the SHEntry!
     mSHEntry = nullptr;
 
     Destroy();
@@ -1648,16 +1650,24 @@ DetachContainerRecurse(nsIDocShell *aShe
   }
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Destroy()
 {
   NS_ASSERTION(mDocument, "No document in Destroy()!");
 
+  // Don't let the document get unloaded while we are printing.
+  // this could happen if we hit the back button during printing.
+  // We also keep the viewer from being cached in session history, since
+  // we require all documents there to be sanitized.
+  if (mDestroyBlockedCount != 0) {
+    return NS_OK;
+  }
+
 #ifdef NS_PRINTING
   // Here is where we check to see if the document was still being prepared
   // for printing when it was asked to be destroy from someone externally
   // This usually happens if the document is unloaded while the user is in the
   // Print Dialog
   //
   // So we flip the bool to remember that the document is going away
   // and we can clean up and abort later after returning from the Print Dialog
@@ -1665,24 +1675,16 @@ nsDocumentViewer::Destroy()
     if (mPrintJob->CheckBeforeDestroy()) {
       return NS_OK;
     }
   }
   // Dispatch the 'afterprint' event now, if pending:
   mAutoBeforeAndAfterPrint = nullptr;
 #endif
 
-  // Don't let the document get unloaded while we are printing.
-  // this could happen if we hit the back button during printing.
-  // We also keep the viewer from being cached in session history, since
-  // we require all documents there to be sanitized.
-  if (mDestroyRefCount != 0) {
-    return NS_OK;
-  }
-
   // If we were told to put ourselves into session history instead of destroy
   // the presentation, do that now.
   if (mSHEntry) {
     if (mPresShell)
       mPresShell->Freeze();
 
     // Make sure the presentation isn't torn down by Hide().
     mSHEntry->SetSticky(mIsSticky);
@@ -4461,25 +4463,25 @@ nsDocumentViewer::SetIsPrintPreview(bool
 }
 
 //----------------------------------------------------------------------------------
 // nsIDocumentViewerPrint IFace
 //----------------------------------------------------------------------------------
 
 //------------------------------------------------------------
 void
-nsDocumentViewer::IncrementDestroyRefCount()
+nsDocumentViewer::IncrementDestroyBlockedCount()
 {
-  ++mDestroyRefCount;
+  ++mDestroyBlockedCount;
 }
 
 void
-nsDocumentViewer::DecrementDestroyRefCount()
+nsDocumentViewer::DecrementDestroyBlockedCount()
 {
-  --mDestroyRefCount;
+  --mDestroyBlockedCount;
 }
 
 //------------------------------------------------------------
 
 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
 //------------------------------------------------------------
 // Reset ESM focus for all descendent doc shells.
 static void
--- a/layout/base/nsIDocumentViewerPrint.h
+++ b/layout/base/nsIDocumentViewerPrint.h
@@ -36,20 +36,23 @@ public:
   virtual void SetIsPrintPreview(bool aIsPrintPreview) = 0;
   virtual bool GetIsPrintPreview() = 0;
 
   // The style set returned by CreateStyleSet is in the middle of an
   // update batch so that the caller can add sheets to it if needed.
   // Callers should call EndUpdate() on it when ready to use.
   virtual mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) = 0;
 
-  virtual void IncrementDestroyRefCount() = 0;
-  virtual void DecrementDestroyRefCount() = 0;
-
-  virtual void ReturnToGalleyPresentation() = 0;
+  /**
+   * This is used by nsPagePrintTimer to make nsDocumentViewer::Destroy()
+   * a no-op until printing is finished.  That prevents the nsDocumentViewer
+   * and its document, presshell and prescontext from going away.
+   */
+  virtual void IncrementDestroyBlockedCount() = 0;
+  virtual void DecrementDestroyBlockedCount() = 0;
 
   virtual void OnDonePrinting() = 0;
 
   /**
    * Returns true is InitializeForPrintPreview() has been called.
    */
   virtual bool IsInitializedForPrintPreview() = 0;
 
@@ -71,19 +74,18 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumen
 
 /* Use this macro when declaring classes that implement this interface. */
 #define NS_DECL_NSIDOCUMENTVIEWERPRINT \
   void SetIsPrinting(bool aIsPrinting) override; \
   bool GetIsPrinting() override; \
   void SetIsPrintPreview(bool aIsPrintPreview) override; \
   bool GetIsPrintPreview() override; \
   mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) override; \
-  void IncrementDestroyRefCount() override; \
-  void DecrementDestroyRefCount() override; \
-  void ReturnToGalleyPresentation() override; \
+  void IncrementDestroyBlockedCount() override; \
+  void DecrementDestroyBlockedCount() override; \
   void OnDonePrinting() override; \
   bool IsInitializedForPrintPreview() override; \
   void InitializeForPrintPreview() override; \
   void SetPrintPreviewPresentation(nsViewManager* aViewManager, \
                                    nsPresContext* aPresContext, \
                                    nsIPresShell* aPresShell) override;
 
 #endif /* nsIDocumentViewerPrint_h___ */
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -301,53 +301,88 @@ void UpdateASR(nsDisplayItem* aItem,
                                      aContainerASR.value()));
 }
 
 /**
  * Takes two display lists and merges them into an output list.
  *
  * The basic algorithm is:
  *
- * For-each item in the new list:
+ * For-each item i in the new list:
  *     If the item has a matching item in the old list:
- *         Remove items from the bottom of the old list until we reach the matching item:
+ *         Remove items from the start of the old list up until we reach an item that also exists in the new list (leaving the matched item in place):
  *             Add valid items to the merged list, destroy invalid items.
- *         Destroy the matching item from the old list.
- *     Add the item from the new list into the merged list.
- * Add all remaining valid items from the old list into the merged list.
+ *     Add i into the merged list.
+ *     If the start of the old list matches i, remove and destroy it, otherwise mark the old version of i as used.
+ * Add all remaining valid items from the old list into the merged list, skipping over (and destroying) any that are marked as used.
  *
  * If any item has a child display list, then we recurse into the merge
  * algorithm once we match up the new/old versions (if present).
  *
  * Example 1:
  *
  * Old List: A,B,C,D
- * New List: A,D
+ * Modified List: A,D
  * Invalidations: C,D
  *
  * We first match the A items, and add the new one to the merged list.
  * We then match the D items, copy B into the merged list, but not C
  * (since it's invalid). We then add the new D to the list and we're
  * finished.
  *
  * Merged List: A,B,D
  *
- * Example 2:
+ * Example 2 (layout/reftests/retained-dl-zindex-1.html):
  *
  * Old List: A, B
- * New List, B, A
+ * Modified List: B, A
+ * Invalidations: A
+ *
+ * In this example A has been explicitly moved to the back.
+ *
+ * We match the B items, but don't copy A since it's invalid, and then add the
+ * new B into the merged list. We then add A, and we're done.
+ *
+ * Merged List: B, A
+ *
+ * Example 3:
+ *
+ * Old List: A, B
+ * Modified List: B, A
  * Invalidations: -
  *
  * This can happen because a prior merge might have changed the ordering
  * for non-intersecting items.
  *
  * We match the B items, but don't copy A since it's also present in the new list
  * and then add the new B into the merged list. We then add A, and we're done.
  *
  * Merged List: B, A
+ *
+ * Example 4 (layout/reftests/retained-dl-zindex-2.html):
+ *
+ * Element A has two elements covering it (B and C), that don't intersect each
+ * other. We then move C to the back.
+ *
+ * The correct initial ordering has B and C after A, in any order.
+ *
+ * Old List: A, B, C
+ * Modified List: C, A
+ * Invalidations: C
+ *
+ * We match the C items, but don't add anything from the old list because A is present
+ * in both lists. We add C to the merged list, and mark the old version of C as reused.
+ *
+ * We then match A, add the new version the merged list and delete the old version.
+ *
+ * We then process the remainder of the old list, B is added (since it is valid,
+ * and hasn't been mark as reused), C is destroyed since it's marked as reused and
+ * is already present in the merged list.
+ *
+ * Merged List: C, A, B
  */
 void
 RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
                                               nsDisplayList* aOldList,
                                               nsDisplayList* aOutList,
                                               Maybe<const ActiveScrolledRoot*>& aOutContainerASR)
 {
   nsDisplayList merged;
@@ -402,49 +437,59 @@ RetainedDisplayListBuilder::MergeDisplay
     newListLookup.Put({ i->Frame(), i->GetPerFrameKey() }, i);
   }
 
   while (nsDisplayItem* newItem = aNewList->RemoveBottom()) {
     if (nsDisplayItem* oldItem = oldListLookup.Get({ newItem->Frame(), newItem->GetPerFrameKey() })) {
       // The new item has a matching counterpart in the old list that we haven't yet reached,
       // so copy all valid items from the old list into the merged list until we get to the
       // matched item.
-      if (!oldItem->IsReused()) {
-        nsDisplayItem* old = nullptr;
-        while ((old = aOldList->RemoveBottom()) && !IsSameItem(newItem, old)) {
-          if (IsAnyAncestorModified(old->FrameForInvalidation())) {
-            // The old item is invalid, discard it.
-            oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
-            old->Destroy(&mBuilder);
-          } else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
-            // The old item is also in the new list, but we haven't got to it yet.
-            // Mark that we've found it, and we'll deal with it when we get to the new
-            // entry.
-            old->SetReused(true);
-          } else {
-            // Recurse into the child list (without a matching new list) to
-            // ensure that we find and remove any invalidated items.
-            if (old->GetChildren()) {
-              nsDisplayList empty;
-              Maybe<const ActiveScrolledRoot*> containerASRForChildren;
-              MergeDisplayLists(&empty, old->GetChildren(),
-                                old->GetChildren(), containerASRForChildren);
-              UpdateASR(old, containerASRForChildren);
-              old->UpdateBounds(&mBuilder);
-            }
-            ReuseItem(old);
+      nsDisplayItem* old = nullptr;
+      while ((old = aOldList->GetBottom()) && old != oldItem) {
+        if (IsAnyAncestorModified(old->FrameForInvalidation())) {
+          // The old item is invalid, discard it.
+          oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
+          aOldList->RemoveBottom();
+          old->Destroy(&mBuilder);
+        } else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
+          // This old item is also in the new list, but we haven't got to it yet.
+          // Stop now, and we'll deal with it when we get to the new entry.
+          break;
+        } else {
+          // Recurse into the child list (without a matching new list) to
+          // ensure that we find and remove any invalidated items.
+          if (old->GetChildren()) {
+            nsDisplayList empty;
+            Maybe<const ActiveScrolledRoot*> containerASRForChildren;
+            MergeDisplayLists(&empty, old->GetChildren(),
+                              old->GetChildren(), containerASRForChildren);
+            UpdateASR(old, containerASRForChildren);
+            old->UpdateBounds(&mBuilder);
           }
+          aOldList->RemoveBottom();
+          ReuseItem(old);
         }
-        MOZ_ASSERT(old && IsSameItem(newItem, old));
-        MOZ_ASSERT(old == oldItem);
+      }
+      bool destroy = false;
+      if (old == oldItem) {
+        // If we advanced the old list until the matching item then we can pop
+        // the matching item off the old list and make sure we clean it up.
+        aOldList->RemoveBottom();
+        destroy = true;
+      } else {
+        // If we didn't get to the matching item, then mark the old item
+        // as being reused (since we're adding the new version to the new
+        // list now) so that we don't add it twice at the end.
+        oldItem->SetReused(true);
       }
 
       // Recursively merge any child lists, destroy the old item and add
       // the new one to the list.
-      if (oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
+      if (!destroy &&
+          oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
           !IsAnyAncestorModified(oldItem->FrameForInvalidation())) {
         // Event regions items don't have anything interesting other than
         // the lists of regions and frames, so we have no need to use the
         // newer item. Always use the old item instead since we assume it's
         // likely to have the bigger lists and merging will be quicker.
         MergeLayerEventRegions(oldItem, newItem);
         ReuseItem(oldItem);
         newItem->Destroy(&mBuilder);
@@ -454,29 +499,32 @@ RetainedDisplayListBuilder::MergeDisplay
           MOZ_ASSERT(newItem->GetChildren());
           Maybe<const ActiveScrolledRoot*> containerASRForChildren;
           MergeDisplayLists(newItem->GetChildren(), oldItem->GetChildren(),
                             newItem->GetChildren(), containerASRForChildren);
           UpdateASR(newItem, containerASRForChildren);
           newItem->UpdateBounds(&mBuilder);
         }
 
-        oldItem->Destroy(&mBuilder);
+        if (destroy) {
+          oldItem->Destroy(&mBuilder);
+        }
         UseItem(newItem);
       }
     } else {
       // If there was no matching item in the old list, then we only need to
       // add the new item to the merged list.
       UseItem(newItem);
     }
   }
 
   // Reuse the remaining valid items from the old display list.
   while (nsDisplayItem* old = aOldList->RemoveBottom()) {
-    if (!IsAnyAncestorModified(old->FrameForInvalidation())) {
+    if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
+        !old->IsReused()) {
       if (old->GetChildren()) {
         // We are calling MergeDisplayLists() to ensure that the display items
         // with modified or deleted children will be correctly handled.
         // Passing an empty new display list as an argument skips the merging
         // loop above and jumps back here.
         nsDisplayList empty;
         Maybe<const ActiveScrolledRoot*> containerASRForChildren;
 
@@ -545,26 +593,27 @@ SubDocEnumCb(nsIDocument* aDocument, voi
     // of the subdoc, and the view for the nsSubDocumentFrame.
     nsView* innerView = rootView->GetParent();
     MOZ_ASSERT(innerView);
 
     nsView* subDocView = innerView->GetParent();
     MOZ_ASSERT(subDocView);
 
     nsIFrame* subDocFrame = subDocView->GetFrame();
-    MOZ_ASSERT(subDocFrame);
-    nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(subDocFrame);
-    MOZ_ASSERT(subdocumentFrame);
+    if (subDocFrame) {
+      nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(subDocFrame);
+      MOZ_ASSERT(subdocumentFrame);
 
-    presShell = subdocumentFrame->GetSubdocumentPresShellForPainting(
-      data->builder->IsIgnoringPaintSuppression() ? nsSubDocumentFrame::IGNORE_PAINT_SUPPRESSION : 0);
-    nsIFrame* rootFrame = presShell ? presShell->GetRootFrame() : nullptr;
+      presShell = subdocumentFrame->GetSubdocumentPresShellForPainting(
+        data->builder->IsIgnoringPaintSuppression() ? nsSubDocumentFrame::IGNORE_PAINT_SUPPRESSION : 0);
+      nsIFrame* rootFrame = presShell ? presShell->GetRootFrame() : nullptr;
 
-    if (rootFrame) {
-      TakeAndAddModifiedFramesFromRootFrame(data->modifiedFrames, rootFrame);
+      if (rootFrame) {
+        TakeAndAddModifiedFramesFromRootFrame(data->modifiedFrames, rootFrame);
+      }
     }
   }
 
   aDocument->EnumerateSubDocuments(SubDocEnumCb, aData);
   return true;
 }
 
 static nsTArray<nsIFrame*>
--- a/layout/printing/nsPagePrintTimer.cpp
+++ b/layout/printing/nsPagePrintTimer.cpp
@@ -12,18 +12,18 @@
 #include "nsPrintJob.h"
 
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, mozilla::Runnable, nsITimerCallback)
 
 nsPagePrintTimer::~nsPagePrintTimer()
 {
-  // This matches the IncrementDestroyRefCount call in the constructor.
-  mDocViewerPrint->DecrementDestroyRefCount();
+  // This matches the IncrementDestroyBlockedCount call in the constructor.
+  mDocViewerPrint->DecrementDestroyBlockedCount();
 }
 
 nsresult
 nsPagePrintTimer::StartTimer(bool aUseDelay)
 {
   uint32_t delay = 0;
   if (aUseDelay) {
     if (mFiringCount < 10) {
@@ -135,34 +135,32 @@ nsPagePrintTimer::Notify(nsITimer *timer
   } else if (timer == mWatchDogTimer) {
     mWatchDogCount++;
     if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
       Fail();
       return NS_OK;
     }
   }
 
-  if (mDocViewerPrint) {
-    bool donePrePrint = true;
-    // Don't start to pre-print if we're waiting on the parent still.
-    if (mPrintJob && !mWaitingForRemotePrint) {
-      donePrePrint = mPrintJob->PrePrintPage();
-    }
+  bool donePrePrint = true;
+  // Don't start to pre-print if we're waiting on the parent still.
+  if (mPrintJob && !mWaitingForRemotePrint) {
+    donePrePrint = mPrintJob->PrePrintPage();
+  }
 
-    if (donePrePrint && !mWaitingForRemotePrint) {
-      StopWatchDogTimer();
-      // Pass nullptr here since name already was set in constructor.
-      mDocument->Dispatch(TaskCategory::Other, do_AddRef(this));
-    } else {
-      // Start the watch dog if we're waiting for preprint to ensure that if any
-      // mozPrintCallbacks take to long we error out.
-      StartWatchDogTimer();
-    }
+  if (donePrePrint && !mWaitingForRemotePrint) {
+    StopWatchDogTimer();
+    // Pass nullptr here since name already was set in constructor.
+    mDocument->Dispatch(TaskCategory::Other, do_AddRef(this));
+  } else {
+    // Start the watch dog if we're waiting for preprint to ensure that if any
+    // mozPrintCallbacks take to long we error out.
+    StartWatchDogTimer();
+  }
 
-  }
   return NS_OK;
 }
 
 
 void
 nsPagePrintTimer::WaitForRemotePrint()
 {
   mWaitingForRemotePrint = NS_NewTimer();
--- a/layout/printing/nsPagePrintTimer.h
+++ b/layout/printing/nsPagePrintTimer.h
@@ -7,16 +7,17 @@
 #define nsPagePrintTimer_h___
 
 // Timer Includes
 #include "nsITimer.h"
 
 #include "nsIDocumentViewerPrint.h"
 #include "nsPrintObject.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/OwningNonNull.h"
 #include "nsThreadUtils.h"
 
 class nsPrintJob;
 class nsIDocument;
 
 //---------------------------------------------------
 //-- Page Timer Class
 //---------------------------------------------------
@@ -28,26 +29,26 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   nsPagePrintTimer(nsPrintJob* aPrintJob,
                    nsIDocumentViewerPrint* aDocViewerPrint,
                    nsIDocument* aDocument,
                    uint32_t aDelay)
     : Runnable("nsPagePrintTimer")
     , mPrintJob(aPrintJob)
-    , mDocViewerPrint(aDocViewerPrint)
+    , mDocViewerPrint(*aDocViewerPrint)
     , mDocument(aDocument)
     , mDelay(aDelay)
     , mFiringCount(0)
     , mPrintObj(nullptr)
     , mWatchDogCount(0)
     , mDone(false)
   {
-    MOZ_ASSERT(aDocument);
-    mDocViewerPrint->IncrementDestroyRefCount();
+    MOZ_ASSERT(aDocViewerPrint && aDocument);
+    mDocViewerPrint->IncrementDestroyBlockedCount();
   }
 
   NS_DECL_NSITIMERCALLBACK
 
   nsresult Start(nsPrintObject* aPO);
 
   NS_IMETHOD Run() override;
 
@@ -66,17 +67,17 @@ private:
   ~nsPagePrintTimer();
 
   nsresult StartTimer(bool aUseDelay);
   nsresult StartWatchDogTimer();
   void     StopWatchDogTimer();
   void     Fail();
 
   nsPrintJob*                mPrintJob;
-  nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
+  const mozilla::OwningNonNull<nsIDocumentViewerPrint> mDocViewerPrint;
   nsCOMPtr<nsIDocument>      mDocument;
   nsCOMPtr<nsITimer>         mTimer;
   nsCOMPtr<nsITimer>         mWatchDogTimer;
   nsCOMPtr<nsITimer>         mWaitingForRemotePrint;
   uint32_t                   mDelay;
   uint32_t                   mFiringCount;
   nsPrintObject *            mPrintObj;
   uint32_t                   mWatchDogCount;
--- a/layout/printing/nsPrintData.cpp
+++ b/layout/printing/nsPrintData.cpp
@@ -33,17 +33,16 @@ nsPrintData::nsPrintData(ePrintDataType 
   , mIsAborted(false)
   , mPreparingForPrint(false)
   , mDocWasToBeDestroyed(false)
   , mShrinkToFit(false)
   , mPrintFrameType(nsIPrintSettings::kFramesAsIs)
   , mNumPrintablePages(0)
   , mNumPagesPrinted(0)
   , mShrinkRatio(1.0)
-  , mOrigDCScale(1.0)
   , mPPEventListeners(nullptr)
 {
   nsCOMPtr<nsIStringBundle> brandBundle;
   nsCOMPtr<nsIStringBundleService> svc =
     mozilla::services::GetStringBundleService();
   if (svc) {
     svc->CreateBundle( "chrome://branding/locale/brand.properties", getter_AddRefs( brandBundle ) );
     if (brandBundle) {
--- a/layout/printing/nsPrintData.h
+++ b/layout/printing/nsPrintData.h
@@ -77,17 +77,16 @@ public:
   bool                        mIsAborted;           // tells us the document is being aborted
   bool                        mPreparingForPrint;   // see comments above
   bool                        mDocWasToBeDestroyed; // see comments above
   bool                        mShrinkToFit;
   int16_t                     mPrintFrameType;
   int32_t                     mNumPrintablePages;
   int32_t                     mNumPagesPrinted;
   float                       mShrinkRatio;
-  float                       mOrigDCScale;
 
   nsCOMPtr<nsIPrintSettings>  mPrintSettings;
   nsPrintPreviewListener*     mPPEventListeners;
 
   nsString                    mBrandName; //  needed as a substitute name for a document
 
 private:
   nsPrintData() = delete;
--- a/layout/reftests/display-list/reftest.list
+++ b/layout/reftests/display-list/reftest.list
@@ -3,12 +3,14 @@ skip-if(!retainedDisplayList) == retaine
 skip-if(!retainedDisplayList) == retained-dl-frame-created-1.html retained-dl-style-change-1-ref.html
 skip-if(!retainedDisplayList) == retained-dl-style-change-stacking-context-1.html retained-dl-style-change-stacking-context-1-ref.html
 skip-if(!retainedDisplayList||!asyncPan) == retained-dl-async-scrolled-1.html retained-dl-async-scrolled-1-ref.html
 skip-if(!retainedDisplayList) == retained-dl-remove-for-ancestor-change-1.html retained-dl-remove-for-ancestor-change-1-ref.html
 skip-if(!retainedDisplayList) == retained-dl-scroll-out-of-view-1.html retained-dl-scroll-out-of-view-1-ref.html
 skip-if(!retainedDisplayList) == retained-dl-displayport-1.html retained-dl-displayport-1-ref.html
 skip-if(!retainedDisplayList) == retained-dl-prerender-transform-1.html retained-dl-prerender-transform-1-ref.html
 == retained-dl-wrap-list.html retained-dl-wrap-list-ref.html
+== retained-dl-zindex-1.html retained-dl-zindex-1-ref.html
+== retained-dl-zindex-2.html retained-dl-zindex-2-ref.html
 fuzzy(1,235200) == 1413073.html 1413073-ref.html
 == 1416291.html 1416291-ref.html
 == 1417601-1.html 1417601-1-ref.html
 == 1418945-1.html 1418945-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-zindex-1-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+  width: 200px;
+  height: 200px;
+  position:relative;
+  will-change: transform;
+}
+#one {
+  top:120px;
+  background-color:blue;
+}
+#two {
+  top: -200px;
+  left: 100px;
+  background-color:green;
+  z-index: -1;
+}
+</style>
+</head>
+<body>
+  <div id="one"></div>
+  <div id="two"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-zindex-1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<style>
+div {
+  width: 200px;
+  height: 200px;
+  position:relative;
+  will-change: transform;
+}
+#one {
+  top:120px;
+  background-color:blue;
+}
+#two {
+  top: -200px;
+  left: 100px;
+  background-color:green;
+  z-index: 1;
+}
+</style>
+</head>
+<body>
+  <div id="one"></div>
+  <div id="two"></div>
+</body>
+<script>
+function doTest() {
+  document.getElementById("two").style.zIndex = -1;
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-zindex-2-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+  width: 200px;
+  height: 200px;
+  position:relative;
+  will-change:transform;
+}
+#one {
+  top:120px;
+  background-color:blue;
+}
+#two {
+  top: -200px;
+  left: 100px;
+  background-color:green;
+}
+#three {
+  top: -180px;
+  left: 100px;
+  background-color:red;
+  z-index: -1;
+}
+</style>
+</head>
+<body>
+  <div id="one"></div>
+  <div id="two"></div>
+  <div id="three"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-zindex-2.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<style>
+div {
+  width: 200px;
+  height: 200px;
+  position:relative;
+  will-change:transform;
+}
+#one {
+  top:120px;
+  background-color:blue;
+}
+#two {
+  top: -200px;
+  left: 100px;
+  background-color:green;
+}
+#three {
+  top: -180px;
+  left: 100px;
+  background-color:red;
+  z-index: 1;
+}
+</style>
+</head>
+<body>
+  <div id="one"></div>
+  <div id="two"></div>
+  <div id="three"></div>
+</body>
+<script>
+function doTest() {
+  document.getElementById("three").style.zIndex = -1;
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -626,18 +626,22 @@ pref("media.decoder.recycle.enabled", fa
 pref("media.decoder.skip-to-next-key-frame.enabled", true);
 
 // Log level for cubeb, the audio input/output system. Valid values are
 // "verbose", "normal" and "" (log disabled).
 pref("media.cubeb.logging_level", "");
 
 #ifdef NIGHTLY_BUILD
 // Cubeb sandbox (remoting) control
+#ifdef XP_MACOSX
+pref("media.cubeb.sandbox", false);
+#else
 pref("media.cubeb.sandbox", true);
 #endif
+#endif
 
 // Set to true to force demux/decode warnings to be treated as errors.
 pref("media.playback.warnings-as-errors", false);
 
 // Weather we allow AMD switchable graphics
 pref("layers.amd-switchable-gfx.enabled", true);
 
 // Whether to use async panning and zooming
--- a/taskcluster/ci/searchfox/kind.yml
+++ b/taskcluster/ci/searchfox/kind.yml
@@ -74,29 +74,32 @@ jobs:
             - linux64-clang
             - linux64-hfsplus
             - linux64-libdmg
             - linux64-llvm-dsymutil
             - linux64-rust-macos
 
     # NOTE: Windows Searchfox jobs aren't working quite yet (bug 1418415).
 
-    win32-searchfox/debug:
-        description: "Win32 Searchfox Debug (clang-cl)"
+    win64-searchfox/debug:
+        description: "Win64 Searchfox Debug (clang-cl)"
         index:
             product: firefox
-            job-name: win32-searchfox-debug
+            job-name: win64-searchfox-debug
         treeherder:
-            platform: windows2012-32/debug
+            platform: windows2012-64/debug
         worker-type: aws-provisioner-v1/gecko-{level}-b-win2012
         worker:
             max-run-time: 7200
             env:
-                TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest"
+                TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win64/releng.manifest"
         run:
             using: mozharness
+            options: [append-env-variables-from-configs]
             script: mozharness/scripts/fx_desktop_build.py
             config:
                 - builds/releng_base_firefox.py
-                - builds/taskcluster_firefox_win32_clang_searchfox_debug.py
+                - builds/taskcluster_base_windows.py
+                - builds/taskcluster_base_win64.py
+                - builds/taskcluster_sub_win64/searchfox_debug.py
         toolchains:
-            - win32-clang-cl
-            - win32-rust
+            - win64-clang-cl
+            - win64-rust
--- a/taskcluster/taskgraph/actions/registry.py
+++ b/taskcluster/taskgraph/actions/registry.py
@@ -161,17 +161,19 @@ def register_callback_action(name, title
     function
         To be used as decorator for the callback function.
     """
     mem = {"registered": False}  # workaround nonlocal missing in 2.x
 
     def register_callback(cb):
         assert isinstance(cb, FunctionType), 'callback must be a function'
         assert isinstance(symbol, basestring), 'symbol must be a string'
-        assert 1 <= len(symbol) <= 25, 'symbol must be between 1 and 25 characters'
+        # Allow for json-e > 25 chars in the symbol.
+        if '$' not in symbol:
+            assert 1 <= len(symbol) <= 25, 'symbol must be between 1 and 25 characters'
         assert not mem['registered'], 'register_callback_action must be used as decorator'
         assert cb.__name__ not in callbacks, 'callback name {} is not unique'.format(cb.__name__)
 
         @register_task_action(name, title, description, order, context, schema)
         def build_callback_action_task(parameters):
             if not available(parameters):
                 return None
 
--- a/taskcluster/taskgraph/actions/release_promotion.py
+++ b/taskcluster/taskgraph/actions/release_promotion.py
@@ -84,17 +84,17 @@ VALID_DESKTOP_RELEASE_TYPES = (
 
 def is_release_promotion_available(parameters):
     return parameters['project'] in RELEASE_PROMOTION_PROJECTS
 
 
 @register_callback_action(
     name='release-promotion',
     title='Release Promotion',
-    symbol='Relpro',
+    symbol='${input.release_promotion_flavor}',
     description="Promote a release.",
     order=10000,
     context=[],
     available=is_release_promotion_available,
     schema={
         'type': 'object',
         'properties': {
             'build_number': {
--- a/taskcluster/taskgraph/parameters.py
+++ b/taskcluster/taskgraph/parameters.py
@@ -115,16 +115,41 @@ class Parameters(ReadOnlyDict):
     def __getitem__(self, k):
         if not (k in PARAMETERS.keys() or k in COMM_PARAMETERS.keys()):
             raise KeyError("no such parameter {!r}".format(k))
         try:
             return super(Parameters, self).__getitem__(k)
         except KeyError:
             raise KeyError("taskgraph parameter {!r} not found".format(k))
 
+    def is_try(self):
+        """
+        Determine whether this graph is being built on a try project.
+        """
+        return 'try' in self['project']
+
+    def file_url(self, path):
+        """
+        Determine the VCS URL for viewing a file in the tree, suitable for
+        viewing by a human.
+
+        :param basestring path: The path, relative to the root of the repository.
+
+        :return basestring: The URL displaying the given path.
+        """
+        if path.startswith('comm/'):
+            path = path[len('comm/'):]
+            repo = self['comm_head_repository']
+            rev = self['comm_head_rev']
+        else:
+            repo = self['head_repository']
+            rev = self['head_rev']
+
+        return '{}/file/{}/{}'.format(repo, rev, path)
+
 
 def load_parameters_file(filename, strict=True):
     """
     Load parameters from a path, url, decision task-id or project.
 
     Examples:
         task-id=fdtgsD5DQUmAQZEaGMvQ4Q
         project=mozilla-central
--- a/taskcluster/taskgraph/transforms/docker_image.py
+++ b/taskcluster/taskgraph/transforms/docker_image.py
@@ -108,17 +108,17 @@ def fill_template(config, tasks):
         zstd_level = '3' if int(config.params['level']) == 1 else '10'
 
         # include some information that is useful in reconstructing this task
         # from JSON
         taskdesc = {
             'label': 'build-docker-image-' + image_name,
             'description': description,
             'attributes': {'image_name': image_name},
-            'expires-after': '28 days' if config.params['project'] == 'try' else '1 year',
+            'expires-after': '28 days' if config.params.is_try() else '1 year',
             'scopes': ['secrets:get:project/taskcluster/gecko/hgfingerprint'],
             'treeherder': {
                 'symbol': job_symbol,
                 'platform': 'taskcluster-images/opt',
                 'kind': 'other',
                 'tier': 1,
             },
             'run-on-projects': [],
--- a/taskcluster/taskgraph/transforms/job/mozharness.py
+++ b/taskcluster/taskgraph/transforms/job/mozharness.py
@@ -169,17 +169,17 @@ def mozharness_on_docker_worker_setup(co
         env['MH_CUSTOM_BUILD_VARIANT_CFG'] = run['custom-build-variant-cfg']
 
     if 'extra-config' in run:
         env['EXTRA_MOZHARNESS_CONFIG'] = json.dumps(run['extra-config'])
 
     if 'job-script' in run:
         env['JOB_SCRIPT'] = run['job-script']
 
-    if 'try' in config.params['project']:
+    if config.params.is_try():
         env['TRY_COMMIT_MSG'] = config.params['message']
 
     # if we're not keeping artifacts, set some env variables to empty values
     # that will cause the build process to skip copying the results to the
     # artifacts directory.  This will have no effect for operations that are
     # not builds.
     if not run['keep-artifacts']:
         env['DIST_TARGET_UPLOADS'] = ''
@@ -252,17 +252,17 @@ def mozharness_on_generic_worker(config,
 
     if 'extra-config' in run:
         env['EXTRA_MOZHARNESS_CONFIG'] = json.dumps(run['extra-config'])
 
     # The windows generic worker uses batch files to pass environment variables
     # to commands.  Setting a variable to empty in a batch file unsets, so if
     # there is no `TRY_COMMIT_MESSAGE`, pass a space instead, so that
     # mozharness doesn't try to find the commit message on its own.
-    if 'try' in config.params['project']:
+    if config.params.is_try():
         env['TRY_COMMIT_MSG'] = config.params['message'] or 'no commit message'
 
     if not job['attributes']['build_platform'].startswith('win'):
         raise Exception(
             "Task generation for mozharness build jobs currently only supported on Windows"
         )
 
     mh_command = [r'c:\mozilla-build\python\python.exe']
--- a/taskcluster/taskgraph/transforms/job/mozharness_test.py
+++ b/taskcluster/taskgraph/transforms/job/mozharness_test.py
@@ -142,17 +142,17 @@ def mozharness_test_on_docker(config, jo
         env['MOCHITEST_FLAVOR'] = mozharness['mochitest-flavor']
 
     if mozharness['set-moz-node-path']:
         env['MOZ_NODE_PATH'] = '/usr/local/bin/node'
 
     if 'actions' in mozharness:
         env['MOZHARNESS_ACTIONS'] = ' '.join(mozharness['actions'])
 
-    if 'try' in config.params['project']:
+    if config.params.is_try():
         env['TRY_COMMIT_MSG'] = config.params['message']
 
     # handle some of the mozharness-specific options
 
     if mozharness['tooltool-downloads']:
         docker_worker_add_tooltool(config, job, taskdesc, internal=True)
 
     if test['reboot']:
@@ -310,17 +310,17 @@ def mozharness_test_on_generic_worker(co
             mh_command.append('--total-chunk={}'.format(test['chunks']))
             mh_command.append('--this-chunk={}'.format(test['this-chunk']))
         elif mozharness['chunking-args'] == 'test-suite-suffix':
             suffix = mozharness['chunk-suffix'].replace('<CHUNK>', str(test['this-chunk']))
             for i, c in enumerate(mh_command):
                 if isinstance(c, basestring) and c.startswith('--test-suite'):
                     mh_command[i] += suffix
 
-    if 'try' in config.params['project']:
+    if config.params.is_try():
         env['TRY_COMMIT_MSG'] = config.params['message']
 
     worker['mounts'] = [{
         'directory': '.',
         'content': {
             'artifact': 'public/build/mozharness.zip',
             'task-id': {
                 'task-reference': '<build>'
--- a/taskcluster/taskgraph/transforms/task.py
+++ b/taskcluster/taskgraph/transforms/task.py
@@ -870,17 +870,17 @@ def build_docker_worker_payload(config, 
 
             if out_of_tree_image:
                 name_hash = hashlib.sha256(out_of_tree_image).hexdigest()
                 suffix += name_hash[0:12]
 
         else:
             suffix = ''
 
-        skip_untrusted = config.params['project'] == 'try' or level == 1
+        skip_untrusted = config.params.is_try() or level == 1
 
         for cache in worker['caches']:
             # Some caches aren't enabled in environments where we can't
             # guarantee certain behavior. Filter those out.
             if cache.get('skip-untrusted') and skip_untrusted:
                 continue
 
             name = '%s%s' % (cache['name'], suffix)
@@ -1449,20 +1449,17 @@ def build_task(config, tasks):
             'created': {'relative-datestamp': '0 seconds'},
             'deadline': {'relative-datestamp': task['deadline-after']},
             'expires': {'relative-datestamp': task['expires-after']},
             'scopes': scopes,
             'metadata': {
                 'description': task['description'],
                 'name': task['label'],
                 'owner': config.params['owner'],
-                'source': '{}/file/{}/{}'.format(
-                    config.params['head_repository'],
-                    config.params['head_rev'],
-                    config.path),
+                'source': config.params.file_url(config.path),
             },
             'extra': extra,
             'tags': tags,
             'priority': task['priority'],
         }
 
         if task.get('requires', None):
             task_def['requires'] = task['requires']
--- a/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py
+++ b/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py
@@ -23,17 +23,17 @@ import time
 from SocketServer import ThreadingMixIn
 
 
 class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
     allow_reuse_address = True
     acceptable_errors = (errno.EPIPE, errno.ECONNABORTED)
 
     def handle_error(self, request, client_address):
-        error = sys.exc_value
+        error = sys.exc_info()[1]
 
         if ((isinstance(error, socket.error) and
              isinstance(error.args, tuple) and
              error.args[0] in self.acceptable_errors)
             or
             (isinstance(error, IOError) and
              error.errno in self.acceptable_errors)):
             pass  # remote hang up before the result is sent
--- a/testing/mozharness/configs/builds/releng_sub_android_configs/64_geckoview_docs.py
+++ b/testing/mozharness/configs/builds/releng_sub_android_configs/64_geckoview_docs.py
@@ -8,13 +8,14 @@ config = {
     'disable_package_metrics': True,
     'postflight_build_mach_commands': [
         ['android',
          'geckoview-docs',
          '--archive',
          '--upload', 'mozilla/geckoview',
          '--upload-branch', 'gh-pages/javadoc/{project}',
          '--upload-message', 'Update {project} javadoc to rev {revision}',
+         '--variant', 'officialWithGeckoBinariesNoMinApiRelease',
         ],
     ],
     'artifact_flag_build_variant_in_try': None, # There's no artifact equivalent.
     'max_build_output_timeout': 0,
 }
deleted file mode 100644
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_searchfox_debug.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import os
-import sys
-
-config = {
-    #########################################################################
-    ######## WINDOWS GENERIC CONFIG KEYS/VAlUES
-    # if you are updating this with custom 32 bit keys/values please add them
-    # below under the '32 bit specific' code block otherwise, update in this
-    # code block and also make sure this is synced between:
-    # - taskcluster_firefox_win32_debug
-    # - taskcluster_firefox_win32_opt
-    # - taskcluster_firefox_win64_debug
-    # - taskcluster_firefox_win64_opt
-    # - taskcluster_firefox_win32_clang
-    # - taskcluster_firefox_win32_clang_debug
-    # - taskcluster_firefox_win64_clang
-    # - taskcluster_firefox_win64_clang_debug
-
-    'default_actions': [
-        'clone-tools',
-        'build',
-        'check-test',
-    ],
-    'app_ini_path': '%(obj_dir)s/dist/bin/application.ini',
-    # decides whether we want to use moz_sign_cmd in env
-    'enable_signing': True,
-    'vcs_share_base': os.path.join('y:', os.sep, 'hg-shared'),
-    'tooltool_script': [
-      sys.executable,
-      os.path.join(os.environ['MOZILLABUILD'], 'tooltool.py')
-    ],
-    'tooltool_bootstrap': 'setup.sh',
-    'enable_count_ctors': False,
-    'max_build_output_timeout': 60 * 80,
-    'perfherder_extra_options': ['static-analysis'],
-    #########################################################################
-
-
-     #########################################################################
-     ###### 32 bit specific ######
-    'base_name': 'WINNT_5.2_%(branch)s',
-    'platform': 'win32',
-    'stage_platform': 'win32-st-an-debug',
-    'debug_build': True,
-    'publish_nightly_en_US_routes': True,
-    'env': {
-        'BINSCOPE': os.path.join(
-            os.environ['ProgramFiles(x86)'], 'Microsoft', 'SDL BinScope', 'BinScope.exe'
-        ),
-        'HG_SHARE_BASE_DIR': os.path.join('y:', os.sep, 'hg-shared'),
-        'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
-        'MOZ_CRASHREPORTER_NO_REPORT': '1',
-        'MOZ_OBJDIR': '%(abs_obj_dir)s',
-        'PDBSTR_PATH': 'C:/Program Files (x86)/Windows Kits/10/Debuggers/x86/srcsrv/pdbstr.exe',
-        'TINDERBOX_OUTPUT': '1',
-        'TOOLTOOL_CACHE': 'c:/builds/tooltool_cache',
-        'TOOLTOOL_HOME': '/c/builds',
-        'XPCOM_DEBUG_BREAK': 'stack-and-abort',
-        'MSYSTEM': 'MINGW32',
-        # Disable sccache because otherwise we won't index the files that
-        # sccache optimizes away compilation for
-        'SCCACHE_DISABLE': '1',
-    },
-    'upload_env': {
-        'UPLOAD_HOST': 'localhost',
-        'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
-    },
-    "check_test_env": {
-        'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
-    },
-    'mozconfig_platform': 'win32',
-    'mozconfig_variant': 'debug-searchfox',
-    'artifact_flag_build_variant_in_try': None,
-    #########################################################################
-}
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/builds/taskcluster_sub_win64/searchfox_debug.py
@@ -0,0 +1,13 @@
+config = {
+    'perfherder_extra_options': ['static-analysis'],
+    'stage_platform': 'win64-st-an-debug',
+    'debug_build': True,
+    'env': {
+        'XPCOM_DEBUG_BREAK': 'stack-and-abort',
+        # Disable sccache because otherwise we won't index the files that
+        # sccache optimizes away compilation for
+        'SCCACHE_DISABLE': '1',
+    },
+    'mozconfig_variant': 'debug-searchfox',
+    'artifact_flag_build_variant_in_try': None,
+}
--- a/toolkit/components/alerts/test/mochitest.ini
+++ b/toolkit/components/alerts/test/mochitest.ini
@@ -2,15 +2,15 @@
 support-files =
   image.gif
   image.png
   image_server.sjs
 
 # Synchronous tests like test_alerts.html must come before
 # asynchronous tests like test_alerts_noobserve.html!
 [test_alerts.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || (os == "win" && debug) # Bug 1407296
 [test_alerts_noobserve.html]
 [test_alerts_requireinteraction.html]
 [test_image.html]
 [test_multiple_alerts.html]
 [test_principal.html]
 skip-if = toolkit == 'android' || (os == "win") # Bug 1336638
--- a/toolkit/components/alerts/test/test_alerts.html
+++ b/toolkit/components/alerts/test/test_alerts.html
@@ -76,14 +76,15 @@ function runTest() {
       notifier.closeAlert(alertName);
     }
   } catch (ex) {
     todo(false, "showAlertNotification() failed.", ex);
     SimpleTest.finish();
   }
 }
 
+SimpleTest.requestCompleteLog(); // Bug 1407296
 runTest();
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/backgroundhangmonitor/BackgroundHangMonitor.cpp
+++ b/toolkit/components/backgroundhangmonitor/BackgroundHangMonitor.cpp
@@ -21,22 +21,22 @@
 #include "prthread.h"
 #include "ThreadStackHelper.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 #include "GeckoProfiler.h"
+#include "nsNetCID.h"
+#include "HangDetails.h"
+
 #ifdef MOZ_GECKO_PROFILER
-#include "mozilla/TimeStamp.h"
 #include "ProfilerMarkerPayload.h"
 #endif
-#include "nsNetCID.h"
-#include "HangDetails.h"
 
 #include <algorithm>
 
 // Activate BHR only for one every BHR_BETA_MOD users.
 // We're doing experimentation with collecting a lot more data from BHR, and
 // don't want to enable it for beta users at the moment. We can scale this up in
 // the future.
 #define BHR_BETA_MOD INT32_MAX;
@@ -213,17 +213,17 @@ public:
 
   BackgroundHangThread(const char* aName,
                        uint32_t aTimeoutMs,
                        uint32_t aMaxTimeoutMs,
                        BackgroundHangMonitor::ThreadType aThreadType = BackgroundHangMonitor::THREAD_SHARED);
 
   // Report a hang; aManager->mLock IS locked. The hang will be processed
   // off-main-thread, and will then be submitted back.
-  void ReportHang(PRIntervalTime aHangTime, TimeStamp aHangEndTime);
+  void ReportHang(PRIntervalTime aHangTime);
   // Report a permanent hang; aManager->mLock IS locked
   void ReportPermaHang();
   // Called by BackgroundHangMonitor::NotifyActivity
   void NotifyActivity()
   {
     MonitorAutoLock autoLock(mManager->mLock);
     Update();
   }
@@ -385,17 +385,17 @@ BackgroundHangManager::RunMonitorThread(
           currentThread->mHangStart = interval;
           currentThread->mHanging = true;
           currentThread->mAnnotations =
             currentThread->mAnnotators.GatherAnnotations();
         }
       } else {
         if (MOZ_LIKELY(interval != currentThread->mHangStart)) {
           // A hang ended
-          currentThread->ReportHang(intervalNow - currentThread->mHangStart, TimeStamp::Now());
+          currentThread->ReportHang(intervalNow - currentThread->mHangStart);
           currentThread->mHanging = false;
         }
       }
 
       /* If we are hanging, the next time we check for hang status is when
          the hang turns into a permahang. If we're not hanging, the next
          recheck timeout is when we may be entering a hang. */
       PRIntervalTime nextRecheck;
@@ -463,55 +463,76 @@ BackgroundHangThread::~BackgroundHangThr
 
   // We no longer have a thread
   if (sTlsKeyInitialized && IsShared()) {
     sTlsKey.set(nullptr);
   }
 }
 
 void
-BackgroundHangThread::ReportHang(PRIntervalTime aHangTime, TimeStamp aHangEndTime)
+BackgroundHangThread::ReportHang(PRIntervalTime aHangTime)
 {
   // Recovered from a hang; called on the monitor thread
   // mManager->mLock IS locked
 
-  HangDetails hangDetails(aHangTime,
-                          aHangEndTime,
-                          XRE_GetProcessType(),
-                          mThreadName,
-                          mRunnableName,
-                          Move(mHangStack),
-                          Move(mAnnotations));
+  nsTArray<HangAnnotation> annotations;
+  for (auto& annotation : mAnnotations) {
+    HangAnnotation annot(annotation.mName, annotation.mValue);
+    annotations.AppendElement(mozilla::Move(annot));
+  }
+
+  HangDetails hangDetails(
+    aHangTime,
+    nsDependentCString(XRE_ChildProcessTypeToString(XRE_GetProcessType())),
+    VoidString(),
+    mThreadName,
+    mRunnableName,
+    Move(mHangStack),
+    Move(annotations)
+  );
+
   // If we have the stream transport service avaliable, we can process the
   // native stack on it. Otherwise, we are unable to report a native stack, so
   // we just report without one.
   if (mManager->mSTS) {
     nsCOMPtr<nsIRunnable> processHangStackRunnable =
       new ProcessHangStackRunnable(Move(hangDetails));
     mManager->mSTS->Dispatch(processHangStackRunnable.forget());
   } else {
     NS_WARNING("Unable to report native stack without a StreamTransportService");
     RefPtr<nsHangDetails> hd = new nsHangDetails(Move(hangDetails));
     hd->Submit();
   }
+
+  // If the profiler is enabled, add a marker.
+#ifdef MOZ_GECKO_PROFILER
+  if (profiler_is_active()) {
+    TimeStamp endTime = TimeStamp::Now();
+    TimeStamp startTime = endTime - TimeDuration::FromMilliseconds(aHangTime);
+    profiler_add_marker_for_thread(
+      mStackHelper.GetThreadId(),
+      "BHR-detected hang",
+      MakeUnique<HangMarkerPayload>(startTime, endTime));
+  }
+#endif
 }
 
 void
 BackgroundHangThread::ReportPermaHang()
 {
   // Permanently hanged; called on the monitor thread
   // mManager->mLock IS locked
 
   // NOTE: We used to capture a native stack in this situation if one had not
   // already been captured, but with the new ReportHang design that is less
   // practical.
   //
   // We currently don't look at hang reports outside of nightly, and already
   // collect native stacks eagerly on nightly, so this should be OK.
-  ReportHang(mMaxTimeout, TimeStamp::Now());
+  ReportHang(mMaxTimeout);
 }
 
 MOZ_ALWAYS_INLINE void
 BackgroundHangThread::Update()
 {
   PRIntervalTime intervalNow = mManager->mIntervalNow;
   if (mWaiting) {
     mInterval = intervalNow;
--- a/toolkit/components/backgroundhangmonitor/HangDetails.cpp
+++ b/toolkit/components/backgroundhangmonitor/HangDetails.cpp
@@ -1,74 +1,75 @@
 #include "HangDetails.h"
 #include "nsIHangDetails.h"
 #include "nsPrintfCString.h"
 #include "mozilla/gfx/GPUParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/Unused.h"
 #include "mozilla/GfxMessageUtils.h" // For ParamTraits<GeckoProcessType>
+
 #ifdef MOZ_GECKO_PROFILER
-#include "ProfilerMarkerPayload.h"
+#include "shared-libraries.h"
 #endif
 
 namespace mozilla {
 
 NS_IMETHODIMP
 nsHangDetails::GetDuration(uint32_t* aDuration)
 {
-  *aDuration = mDetails.mDuration;
+  *aDuration = mDetails.duration();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetThread(nsACString& aName)
 {
-  aName.Assign(mDetails.mThreadName);
+  aName.Assign(mDetails.threadName());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetRunnableName(nsACString& aRunnableName)
 {
-  aRunnableName.Assign(mDetails.mRunnableName);
+  aRunnableName.Assign(mDetails.runnableName());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetProcess(nsACString& aName)
 {
-  aName.AssignASCII(XRE_ChildProcessTypeToString(mDetails.mProcess));
+  aName.Assign(mDetails.process());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetRemoteType(nsAString& aName)
 {
-  aName.Assign(mDetails.mRemoteType);
+  aName.Assign(mDetails.remoteType());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetAnnotations(JSContext* aCx, JS::MutableHandleValue aVal)
 {
   // We create an object with { "key" : "value" } string pairs for each item in
   // our annotations object.
   JS::RootedObject jsAnnotation(aCx, JS_NewPlainObject(aCx));
   if (!jsAnnotation) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  for (auto& annot : mDetails.mAnnotations) {
-    JSString* jsString = JS_NewUCStringCopyN(aCx, annot.mValue.get(), annot.mValue.Length());
+  for (auto& annot : mDetails.annotations()) {
+    JSString* jsString = JS_NewUCStringCopyN(aCx, annot.value().get(), annot.value().Length());
     if (!jsString) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     JS::RootedValue jsValue(aCx);
     jsValue.setString(jsString);
-    if (!JS_DefineUCProperty(aCx, jsAnnotation, annot.mName.get(), annot.mName.Length(),
+    if (!JS_DefineUCProperty(aCx, jsAnnotation, annot.name().get(), annot.name().Length(),
                              jsValue, JSPROP_ENUMERATE)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   aVal.setObject(*jsAnnotation);
   return NS_OK;
 }
@@ -93,132 +94,149 @@ StringFrame(JSContext* aCx,
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 } // anonymous namespace
 
 NS_IMETHODIMP
-nsHangDetails::GetStack(JSContext* aCx, JS::MutableHandle<JS::Value> aVal)
+nsHangDetails::GetStack(JSContext* aCx, JS::MutableHandleValue aStack)
 {
-  JS::RootedObject ret(aCx, JS_NewArrayObject(aCx, mDetails.mStack.length()));
+  auto& stack = mDetails.stack();
+  uint32_t length = stack.stack().Length();
+  JS::RootedObject ret(aCx, JS_NewArrayObject(aCx, length));
   if (!ret) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  for (size_t i = 0; i < mDetails.mStack.length(); ++i) {
-    const HangStack::Frame& frame = mDetails.mStack[i];
-    switch (frame.GetKind()) {
-      case HangStack::Frame::Kind::STRING: {
-        nsresult rv = StringFrame(aCx, ret, i, frame.AsString());
+
+  for (uint32_t i = 0; i < length; ++i) {
+    auto& entry = stack.stack()[i];
+    switch (entry.type()) {
+      case HangEntry::TnsCString: {
+        nsresult rv = StringFrame(aCx, ret, i, entry.get_nsCString().get());
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
+      case HangEntry::THangEntryBufOffset: {
+        uint32_t offset = entry.get_HangEntryBufOffset().index();
 
-      case HangStack::Frame::Kind::MODOFFSET: {
+        // NOTE: We can't trust the offset we got, as we might have gotten it
+        // from a compromised content process. Validate that it is in bounds.
+        if (NS_WARN_IF(stack.strbuffer().IsEmpty() ||
+                       offset >= stack.strbuffer().Length())) {
+          MOZ_ASSERT_UNREACHABLE("Corrupted offset data");
+          return NS_ERROR_FAILURE;
+        }
+
+        // NOTE: If our content process is compromised, it could send us back a
+        // strbuffer() which didn't have a null terminator. If the last byte in
+        // the buffer is not '\0', we abort, to make sure we don't read out of
+        // bounds.
+        if (stack.strbuffer().LastElement() != '\0') {
+          MOZ_ASSERT_UNREACHABLE("Corrupted strbuffer data");
+          return NS_ERROR_FAILURE;
+        }
+
+        // We know this offset is safe because of the previous checks.
+        const int8_t* start = stack.strbuffer().Elements() + offset;
+        nsresult rv = StringFrame(aCx, ret, i,
+                                  reinterpret_cast<const char*>(start));
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      }
+      case HangEntry::THangEntryModOffset: {
+        const HangEntryModOffset& mo = entry.get_HangEntryModOffset();
+
         JS::RootedObject jsFrame(aCx, JS_NewArrayObject(aCx, 2));
         if (!jsFrame) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
-        if (!JS_DefineElement(aCx, jsFrame, 0, frame.AsModOffset().mModule, JSPROP_ENUMERATE)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-
-        nsPrintfCString hexString("%" PRIxPTR, (uintptr_t)frame.AsModOffset().mOffset);
-        JS::RootedString hex(aCx, JS_NewStringCopyZ(aCx, hexString.get()));
-        if (!hex || !JS_DefineElement(aCx, jsFrame, 1, hex, JSPROP_ENUMERATE)) {
+        if (!JS_DefineElement(aCx, jsFrame, 0, mo.module(), JSPROP_ENUMERATE)) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
-        if (!JS_DefineElement(aCx, ret, i, jsFrame, JSPROP_ENUMERATE)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-        break;
-      }
-
-      case HangStack::Frame::Kind::PC: {
-        JS::RootedObject jsFrame(aCx, JS_NewArrayObject(aCx, 2));
-        if (!jsFrame) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-
-        if (!JS_DefineElement(aCx, jsFrame, 0, -1, JSPROP_ENUMERATE)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-
-        nsPrintfCString hexString("%" PRIxPTR, frame.AsPC());
+        nsPrintfCString hexString("%" PRIxPTR, (uintptr_t)mo.offset());
         JS::RootedString hex(aCx, JS_NewStringCopyZ(aCx, hexString.get()));
         if (!hex || !JS_DefineElement(aCx, jsFrame, 1, hex, JSPROP_ENUMERATE)) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
         if (!JS_DefineElement(aCx, ret, i, jsFrame, JSPROP_ENUMERATE)) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
         break;
       }
-
-      case HangStack::Frame::Kind::CONTENT: {
+      case HangEntry::THangEntryProgCounter: {
+        // Don't bother recording fixed program counters to JS
+        nsresult rv = StringFrame(aCx, ret, i, "(unresolved)");
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      }
+      case HangEntry::THangEntryContent: {
         nsresult rv = StringFrame(aCx, ret, i, "(content script)");
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
-
-      case HangStack::Frame::Kind::JIT: {
+      case HangEntry::THangEntryJit: {
         nsresult rv = StringFrame(aCx, ret, i, "(jit frame)");
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
-
-      case HangStack::Frame::Kind::WASM: {
+      case HangEntry::THangEntryWasm: {
         nsresult rv = StringFrame(aCx, ret, i, "(wasm)");
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
-
-      case HangStack::Frame::Kind::SUPPRESSED: {
+      case HangEntry::THangEntryChromeScript: {
+        nsresult rv = StringFrame(aCx, ret, i, "(chrome script)");
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      }
+      case HangEntry::THangEntrySuppressed: {
         nsresult rv = StringFrame(aCx, ret, i, "(profiling suppressed)");
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
-
-      default:
-        MOZ_ASSERT_UNREACHABLE("Invalid variant");
-        break;
+      default: MOZ_CRASH("Unsupported HangEntry type?");
     }
   }
 
-  aVal.setObject(*ret);
+  aStack.setObject(*ret);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetModules(JSContext* aCx, JS::MutableHandleValue aVal)
 {
-  auto& modules = mDetails.mStack.GetModules();
+  auto& modules = mDetails.stack().modules();
   size_t length = modules.Length();
   JS::RootedObject retObj(aCx, JS_NewArrayObject(aCx, length));
   if (!retObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (size_t i = 0; i < length; ++i) {
-    const HangStack::Module& module = modules[i];
+    const HangModule& module = modules[i];
     JS::RootedObject jsModule(aCx, JS_NewArrayObject(aCx, 2));
     if (!jsModule) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    JS::RootedString name(aCx, JS_NewUCStringCopyN(aCx, module.mName.BeginReading(), module.mName.Length()));
+    JS::RootedString name(aCx, JS_NewUCStringCopyN(aCx,
+                                                   module.name().BeginReading(),
+                                                   module.name().Length()));
     if (!JS_DefineElement(aCx, jsModule, 0, name, JSPROP_ENUMERATE)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    JS::RootedString breakpadId(aCx, JS_NewStringCopyN(aCx, module.mBreakpadId.BeginReading(), module.mBreakpadId.Length()));
+    JS::RootedString breakpadId(aCx, JS_NewStringCopyN(aCx,
+                                                       module.breakpadId().BeginReading(),
+                                                       module.breakpadId().Length()));
     if (!JS_DefineElement(aCx, jsModule, 1, breakpadId, JSPROP_ENUMERATE)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (!JS_DefineElement(aCx, retObj, i, jsModule, JSPROP_ENUMERATE)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
@@ -242,17 +260,17 @@ nsHangDetails::Submit()
     //
     // In child processes, we report the hang to our parent process, while if
     // we're in the parent process, we report a bhr-thread-hang observer
     // notification.
     switch (XRE_GetProcessType()) {
     case GeckoProcessType_Content: {
       auto cc = dom::ContentChild::GetSingleton();
       if (cc) {
-        hangDetails->mDetails.mRemoteType.Assign(cc->GetRemoteType());
+        hangDetails->mDetails.remoteType().Assign(cc->GetRemoteType());
         Unused << cc->SendBHRThreadHang(hangDetails->mDetails);
       }
       break;
     }
     case GeckoProcessType_GPU: {
       auto gp = gfx::GPUParent::GetSingleton();
       if (gp) {
         Unused << gp->SendBHRThreadHang(hangDetails->mDetails);
@@ -267,91 +285,107 @@ nsHangDetails::Submit()
       break;
     }
     default:
       // XXX: Consider handling GeckoProcessType_GMPlugin and
       // GeckoProcessType_Plugin?
       NS_WARNING("Unsupported BHR process type - discarding hang.");
       break;
     }
-#ifdef MOZ_GECKO_PROFILER
-    if (profiler_is_active()) {
-      TimeStamp endTime = hangDetails->mDetails.mEndTime;
-      TimeStamp startTime = endTime -
-                            TimeDuration::FromMilliseconds(hangDetails->mDetails.mDuration);
-      profiler_add_marker(
-        "BHR-detected hang",
-        MakeUnique<HangMarkerPayload>(startTime, endTime));
-    }
-#endif
   });
 
   nsresult rv = SystemGroup::Dispatch(TaskCategory::Other,
                                       notifyObservers.forget());
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 }
 
 NS_IMPL_ISUPPORTS(nsHangDetails, nsIHangDetails)
 
+namespace {
+
+// Sorting comparator used by ReadModuleInformation. Sorts PC Frames by their
+// PC.
+struct PCFrameComparator {
+  bool LessThan(HangEntry* const& a, HangEntry* const& b) const {
+    return a->get_HangEntryProgCounter().pc() < b->get_HangEntryProgCounter().pc();
+  }
+  bool Equals(HangEntry* const& a, HangEntry* const& b) const {
+    return a->get_HangEntryProgCounter().pc() == b->get_HangEntryProgCounter().pc();
+  }
+};
+
+} // anonymous namespace
+
+void
+ReadModuleInformation(HangStack& stack)
+{
+  // modules() should be empty when we start filling it.
+  stack.modules().Clear();
+
+#ifdef MOZ_GECKO_PROFILER
+  // Create a sorted list of the PCs in the current stack.
+  AutoTArray<HangEntry*, 100> frames;
+  for (auto& frame : stack.stack()) {
+    if (frame.type() == HangEntry::THangEntryProgCounter) {
+      frames.AppendElement(&frame);
+    }
+  }
+  PCFrameComparator comparator;
+  frames.Sort(comparator);
+
+  SharedLibraryInfo rawModules = SharedLibraryInfo::GetInfoForSelf();
+  rawModules.SortByAddress();
+
+  size_t frameIdx = 0;
+  for (size_t i = 0; i < rawModules.GetSize(); ++i) {
+    const SharedLibrary& info = rawModules.GetEntry(i);
+    uintptr_t moduleStart = info.GetStart();
+    uintptr_t moduleEnd = info.GetEnd() - 1;
+    // the interval is [moduleStart, moduleEnd)
+
+    bool moduleReferenced = false;
+    for (; frameIdx < frames.Length(); ++frameIdx) {
+      auto& frame = frames[frameIdx];
+      uint64_t pc = frame->get_HangEntryProgCounter().pc();
+      // We've moved past this frame, let's go to the next one.
+      if (pc >= moduleEnd) {
+        break;
+      }
+      if (pc >= moduleStart) {
+        uint64_t offset = pc - moduleStart;
+        if (NS_WARN_IF(offset > UINT32_MAX)) {
+          continue; // module/offset can only hold 32-bit offsets into shared libraries.
+        }
+
+        // If we found the module, rewrite the Frame entry to instead be a
+        // ModOffset one. mModules.Length() will be the index of the module when
+        // we append it below, and we set moduleReferenced to true to ensure
+        // that we do.
+        moduleReferenced = true;
+        uint32_t module = stack.modules().Length();
+        HangEntryModOffset modOffset(module, static_cast<uint32_t>(offset));
+        *frame = modOffset;
+      }
+    }
+
+    if (moduleReferenced) {
+      nsDependentCString cstr(info.GetBreakpadId().c_str());
+      HangModule module(info.GetDebugName(), cstr);
+      stack.modules().AppendElement(module);
+    }
+  }
+#endif
+}
+
 NS_IMETHODIMP
 ProcessHangStackRunnable::Run()
 {
   // NOTE: Reading module information can take a long time, which is why we do
   // it off-main-thread.
-  mHangDetails.mStack.ReadModuleInformation();
+  ReadModuleInformation(mHangDetails.stack());
 
   RefPtr<nsHangDetails> hangDetails = new nsHangDetails(Move(mHangDetails));
   hangDetails->Submit();
 
   return NS_OK;
 }
 
 } // namespace mozilla
-
-
-/**
- * IPC Serialization / Deserialization logic
- */
-namespace IPC {
-
-void
-ParamTraits<mozilla::HangDetails>::Write(Message* aMsg, const mozilla::HangDetails& aParam)
-{
-  WriteParam(aMsg, aParam.mDuration);
-  WriteParam(aMsg, aParam.mProcess);
-  WriteParam(aMsg, aParam.mRemoteType);
-  WriteParam(aMsg, aParam.mThreadName);
-  WriteParam(aMsg, aParam.mRunnableName);
-  WriteParam(aMsg, aParam.mStack);
-  WriteParam(aMsg, aParam.mAnnotations);
-}
-
-bool
-ParamTraits<mozilla::HangDetails>::Read(const Message* aMsg,
-                                        PickleIterator* aIter,
-                                        mozilla::HangDetails* aResult)
-{
-  if (!ReadParam(aMsg, aIter, &aResult->mDuration)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mProcess)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mRemoteType)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mThreadName)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mRunnableName)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mStack)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mAnnotations)) {
-    return false;
-  }
-
-  return true;
-}
-
-} // namespace IPC
--- a/toolkit/components/backgroundhangmonitor/HangDetails.h
+++ b/toolkit/components/backgroundhangmonitor/HangDetails.h
@@ -6,74 +6,25 @@
 
 #ifndef mozilla_HangDetails_h
 #define mozilla_HangDetails_h
 
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/ProcessedStack.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Move.h"
-#include "mozilla/HangStack.h"
+#include "mozilla/HangTypes.h"
 #include "mozilla/HangAnnotations.h"
 #include "nsTArray.h"
 #include "nsIHangDetails.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 
 /**
- * HangDetails is a POD struct which contains the information collected from the
- * hang. It can be wrapped in a nsHangDetails to provide an XPCOM interface for
- * extracting information from it easily.
- *
- * This type is separate, as it can be sent over IPC while nsHangDetails is an
- * XPCOM interface which is harder to serialize over IPC.
- */
-class HangDetails
-{
-public:
-  HangDetails()
-    : mDuration(0)
-    , mEndTime(TimeStamp::Now())
-    , mProcess(GeckoProcessType_Invalid)
-    , mRemoteType(VoidString())
-  {}
-
-  HangDetails(const HangDetails& aOther) = default;
-  HangDetails(HangDetails&& aOther) = default;
-  HangDetails(uint32_t aDuration,
-              TimeStamp aEndTime,
-              GeckoProcessType aProcess,
-              const nsACString& aThreadName,
-              const nsACString& aRunnableName,
-              HangStack&& aStack,
-              HangMonitor::HangAnnotations&& aAnnotations)
-    : mDuration(aDuration)
-    , mEndTime(aEndTime)
-    , mProcess(aProcess)
-    , mRemoteType(VoidString())
-    , mThreadName(aThreadName)
-    , mRunnableName(aRunnableName)
-    , mStack(Move(aStack))
-    , mAnnotations(Move(aAnnotations))
-  {}
-
-  uint32_t mDuration;
-  TimeStamp mEndTime;
-  GeckoProcessType mProcess;
-  // NOTE: mRemoteType is set in nsHangDetails::Submit before the HangDetails
-  // object is sent to the parent process.
-  nsString mRemoteType;
-  nsCString mThreadName;
-  nsCString mRunnableName;
-  HangStack mStack;
-  HangMonitor::HangAnnotations mAnnotations;
-};
-
-/**
  * HangDetails is the concrete implementaion of nsIHangDetails, and contains the
  * infromation which we want to expose to observers of the bhr-thread-hang
  * observer notification.
  */
 class nsHangDetails : public nsIHangDetails
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
deleted file mode 100644
--- a/toolkit/components/backgroundhangmonitor/HangStack.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-#include "HangStack.h"
-
-#ifdef MOZ_GECKO_PROFILER
-#include "shared-libraries.h"
-#endif
-
-namespace mozilla {
-
-HangStack::HangStack(const HangStack& aOther)
-  : mModules(aOther.mModules)
-{
-  if (NS_WARN_IF(!mBuffer.reserve(aOther.mBuffer.length()) ||
-                 !mImpl.reserve(aOther.mImpl.length()))) {
-    return;
-  }
-  // XXX: I should be able to just memcpy the other stack's mImpl and mBuffer,
-  // and then just re-offset pointers.
-  for (size_t i = 0; i < aOther.length(); ++i) {
-    const Frame& frame = aOther[i];
-
-    // If the source string is a reference to aOther's buffer, we have to append
-    // via buffer, otherwise we can just copy the entry over.
-    if (frame.GetKind() == Frame::Kind::STRING) {
-      const char* s = frame.AsString();
-      if (aOther.IsInBuffer(s)) {
-        InfallibleAppendViaBuffer(s, strlen(s));
-        continue;
-      }
-    }
-
-    infallibleAppend(frame);
-  }
-  MOZ_ASSERT(mImpl.length() == aOther.mImpl.length());
-  MOZ_ASSERT(mBuffer.length() == aOther.mBuffer.length());
-}
-
-void
-HangStack::InfallibleAppendViaBuffer(const char* aText, size_t aLength)
-{
-  MOZ_ASSERT(this->canAppendWithoutRealloc(1));
-  // Include null-terminator in length count.
-  MOZ_ASSERT(mBuffer.canAppendWithoutRealloc(aLength + 1));
-
-  const char* const entry = mBuffer.end();
-  mBuffer.infallibleAppend(aText, aLength);
-  mBuffer.infallibleAppend('\0'); // Explicitly append null-terminator
-
-  this->infallibleAppend(Frame(entry));
-}
-
-bool
-HangStack::AppendViaBuffer(const char* aText, size_t aLength)
-{
-  if (!this->reserve(this->length() + 1)) {
-    return false;
-  }
-
-  // Keep track of the previous buffer in case we need to adjust pointers later.
-  const char* const prevStart = mBuffer.begin();
-  const char* const prevEnd = mBuffer.end();
-
-  // Include null-terminator in length count.
-  if (!mBuffer.reserve(mBuffer.length() + aLength + 1)) {
-    return false;
-  }
-
-  if (prevStart != mBuffer.begin()) {
-    // The buffer has moved; we have to adjust pointers in the stack.
-    for (auto & frame : *this) {
-      if (frame.GetKind() == Frame::Kind::STRING) {
-        const char*& entry = frame.AsString();
-        if (entry >= prevStart && entry < prevEnd) {
-          // Move from old buffer to new buffer.
-          entry += mBuffer.begin() - prevStart;
-        }
-      }
-    }
-  }
-
-  InfallibleAppendViaBuffer(aText, aLength);
-  return true;
-}
-
-namespace {
-
-// Sorting comparator used by ReadModuleInformation. Sorts PC Frames by their
-// PC.
-struct PCFrameComparator {
-  bool LessThan(HangStack::Frame* const& a, HangStack::Frame* const& b) const {
-    return a->AsPC() < b->AsPC();
-  }
-  bool Equals(HangStack::Frame* const& a, HangStack::Frame* const& b) const {
-    return a->AsPC() == b->AsPC();
-  }
-};
-
-} // anonymous namespace
-
-void
-HangStack::ReadModuleInformation()
-{
-  // mModules should be empty when we start filling it.
-  mModules.Clear();
-
-#ifdef MOZ_GECKO_PROFILER
-  // Create a sorted list of the PCs in the current stack.
-  AutoTArray<Frame*, 100> frames;
-  for (auto& frame : *this) {
-    if (frame.GetKind() == Frame::Kind::PC) {
-      frames.AppendElement(&frame);
-    }
-  }
-  PCFrameComparator comparator;
-  frames.Sort(comparator);
-
-  SharedLibraryInfo rawModules = SharedLibraryInfo::GetInfoForSelf();
-  rawModules.SortByAddress();
-
-  size_t frameIdx = 0;
-  for (size_t i = 0; i < rawModules.GetSize(); ++i) {
-    const SharedLibrary& info = rawModules.GetEntry(i);
-    uintptr_t moduleStart = info.GetStart();
-    uintptr_t moduleEnd = info.GetEnd() - 1;
-    // the interval is [moduleStart, moduleEnd)
-
-    bool moduleReferenced = false;
-    for (; frameIdx < frames.Length(); ++frameIdx) {
-      auto& frame = frames[frameIdx];
-      // We've moved past this frame, let's go to the next one.
-      if (frame->AsPC() >= moduleEnd) {
-        break;
-      }
-      if (frame->AsPC() >= moduleStart) {
-        uint64_t offset = frame->AsPC() - moduleStart;
-        if (NS_WARN_IF(offset > UINT32_MAX)) {
-          continue; // module/offset can only hold 32-bit offsets into shared libraries.
-        }
-
-        // If we found the module, rewrite the Frame entry to instead be a
-        // ModOffset one. mModules.Length() will be the index of the module when
-        // we append it below, and we set moduleReferenced to true to ensure
-        // that we do.
-        moduleReferenced = true;
-        uint32_t module = mModules.Length();
-        ModOffset modOffset = {
-          module,
-          static_cast<uint32_t>(offset)
-        };
-        *frame = Frame(modOffset);
-      }
-    }
-
-    if (moduleReferenced) {
-      nsDependentCString cstr(info.GetBreakpadId().c_str());
-      Module module = {
-        info.GetDebugName(),
-        cstr
-      };
-      mModules.AppendElement(module);
-    }
-  }
-#endif
-}
-
-} // namespace mozilla
-
-namespace IPC {
-
-void
-ParamTraits<mozilla::HangStack::ModOffset>::Write(Message* aMsg, const mozilla::HangStack::ModOffset& aParam)
-{
-  WriteParam(aMsg, aParam.mModule);
-  WriteParam(aMsg, aParam.mOffset);
-}
-
-bool
-ParamTraits<mozilla::HangStack::ModOffset>::Read(const Message* aMsg,
-                                                 PickleIterator* aIter,
-                                                 mozilla::HangStack::ModOffset* aResult)
-{
-  if (!ReadParam(aMsg, aIter, &aResult->mModule)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mOffset)) {
-    return false;
-  }
-  return true;
-}
-
-void
-ParamTraits<mozilla::HangStack::Module>::Write(Message* aMsg, const mozilla::HangStack::Module& aParam)
-{
-  WriteParam(aMsg, aParam.mName);
-  WriteParam(aMsg, aParam.mBreakpadId);
-}
-
-bool
-ParamTraits<mozilla::HangStack::Module>::Read(const Message* aMsg, PickleIterator* aIter,
-                                              mozilla::HangStack::Module* aResult)
-{
-  if (!ReadParam(aMsg, aIter, &aResult->mName)) {
-    return false;
-  }
-  if (!ReadParam(aMsg, aIter, &aResult->mBreakpadId)) {
-    return false;
-  }
-  return true;
-}
-
-void
-ParamTraits<mozilla::HangStack>::Write(Message* aMsg, const mozilla::HangStack& aParam)
-{
-  typedef mozilla::HangStack::Frame Frame;
-
-  size_t length = aParam.length();
-  WriteParam(aMsg, length);
-  for (size_t i = 0; i < length; ++i) {
-    const Frame& frame = aParam[i];
-    WriteParam(aMsg, frame.GetKind());
-
-    switch (frame.GetKind()) {
-      case Frame::Kind::STRING: {
-        nsDependentCString str(frame.AsString());
-        WriteParam(aMsg, static_cast<nsACString&>(str));
-        break;
-      }
-      case Frame::Kind::MODOFFSET: {
-        WriteParam(aMsg, frame.AsModOffset());
-        break;
-      }
-      case Frame::Kind::PC: {
-        WriteParam(aMsg, frame.AsPC());
-        break;
-      }
-      case Frame::Kind::CONTENT:
-      case Frame::Kind::WASM:
-      case Frame::Kind::JIT:
-      case Frame::Kind::SUPPRESSED: {
-        // NOTE: no associated data.
-        break;
-      }
-      default: {
-        MOZ_RELEASE_ASSERT(false, "Invalid kind for HangStack Frame");
-        break;
-      }
-    }
-  }
-
-  WriteParam(aMsg, aParam.GetModules());
-}
-
-bool
-ParamTraits<mozilla::HangStack>::Read(const Message* aMsg,
-                                      PickleIterator* aIter,
-                                      mozilla::HangStack* aResult)
-{
-  // Shorten the name of Frame
-  typedef mozilla::HangStack::Frame Frame;
-
-  size_t length;
-  if (!ReadParam(aMsg, aIter, &length)) {
-    return false;
-  }
-
-  if (!aResult->reserve(length)) {
-    return false;
-  }
-
-  for (size_t i = 0; i < length; ++i) {
-    Frame::Kind kind;
-    if (!ReadParam(aMsg, aIter, &kind)) {
-      return false;
-    }
-
-    switch (kind) {
-      case Frame::Kind::STRING: {
-        nsAutoCString str;
-        if (!ReadParam(aMsg, aIter, static_cast<nsACString*>(&str))) {
-          return false;
-        }
-        aResult->AppendViaBuffer(str.get(), str.Length());
-        break;
-      }
-      case Frame::Kind::MODOFFSET: {
-        mozilla::HangStack::ModOffset modOff;
-        if (!ReadParam(aMsg, aIter, &modOff)) {
-          return false;
-        }
-        aResult->infallibleAppend(Frame(modOff));
-        break;
-      }
-      case Frame::Kind::PC: {
-        uintptr_t pc;
-        if (!ReadParam(aMsg, aIter, &pc)) {
-          return false;
-        }
-        aResult->infallibleAppend(Frame(pc));
-        break;
-      }
-      case Frame::Kind::CONTENT:
-        aResult->infallibleAppend(Frame::Content());
-        break;
-      case Frame::Kind::WASM:
-        aResult->infallibleAppend(Frame::Wasm());
-        break;
-      case Frame::Kind::JIT:
-        aResult->infallibleAppend(Frame::Jit());
-        break;
-      case Frame::Kind::SUPPRESSED:
-        aResult->infallibleAppend(Frame::Suppressed());
-        break;
-      default:
-        // We can't deserialize other kinds!
-        return false;
-    }
-  }
-
-  if (!ReadParam(aMsg, aIter, &aResult->GetModules())) {
-    return false;
-  }
-
-  return true;
-}
-
-} // namespace IPC
deleted file mode 100644
--- a/toolkit/components/backgroundhangmonitor/HangStack.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_HangStack_h
-#define mozilla_HangStack_h
-
-#include "ipc/IPCMessageUtils.h"
-#include "mozilla/ProcessedStack.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/Move.h"
-#include "nsTArray.h"
-#include "nsIHangDetails.h"
-
-namespace mozilla {
-
-/* A native stack is a simple list of pointers, so rather than building a
-   wrapper type, we typdef the type here. */
-typedef std::vector<uintptr_t> NativeHangStack;
-
-/* HangStack stores an array of const char pointers,
-   with optional internal storage for strings. */
-class HangStack
-{
-public:
-  static const size_t sMaxInlineStorage = 8;
-
-  // The maximum depth for the native stack frames that we might collect.
-  // XXX: Consider moving this to a different object?
-  static const size_t sMaxNativeFrames = 150;
-
-  struct ModOffset {
-    uint32_t mModule;
-    uint32_t mOffset;
-
-    bool operator==(const ModOffset& aOther) const {
-      return mModule == aOther.mModule && mOffset == aOther.mOffset;
-    }
-  };
-
-  // A HangStack frame is one of the following types:
-  // * Kind::STRING(const char*) : A string representing a pseudostack or chrome JS stack frame.
-  // * Kind::MODOFFSET(ModOffset) : A module index and offset into that module.
-  // * Kind::PC(uintptr_t) : A raw program counter which has not been mapped to a module.
-  // * Kind::CONTENT: A hidden "(content script)" frame.
-  // * Kind::JIT : An unprocessed  "(jit frame)".
-  // * Kind::WASM : An unprocessed "(wasm)" frame.
-  // * Kind::SUPPRESSED : A JS frame while profiling was suppressed.
-  //
-  // NOTE: A manually rolled tagged enum is used instead of mozilla::Variant
-  // here because we cannot use mozilla::Variant's IPC serialization directly.
-  // Unfortunately the const char* variant needs the context of the HangStack
-  // which it is in order to correctly deserialize. For this reason, a Frame by
-  // itself does not have a ParamTraits implementation.
-  class Frame
-  {
-  public:
-    enum class Kind {
-      STRING,
-      MODOFFSET,
-      PC,
-      CONTENT,
-      JIT,
-      WASM,
-      SUPPRESSED,
-      END // Marker
-    };
-
-    Frame()
-      : mKind(Kind::STRING)
-      , mString("")
-    {}
-
-    explicit Frame(const char* aString)
-      : mKind(Kind::STRING)
-      , mString(aString)
-    {}
-
-    explicit Frame(ModOffset aModOffset)
-      : mKind(Kind::MODOFFSET)
-      , mModOffset(aModOffset)
-    {}
-
-    explicit Frame(uintptr_t aPC)
-      : mKind(Kind::PC)
-      , mPC(aPC)
-    {}
-
-    Kind GetKind() const {
-      return mKind;
-    }
-
-    const char*& AsString() {
-      MOZ_ASSERT(mKind == Kind::STRING);
-      return mString;
-    }
-
-    const char* const& AsString() const {
-      MOZ_ASSERT(mKind == Kind::STRING);
-      return mString;
-    }
-
-    const ModOffset& AsModOffset() const {
-      MOZ_ASSERT(mKind == Kind::MODOFFSET);
-      return mModOffset;
-    }
-
-    const uintptr_t& AsPC() const {
-      MOZ_ASSERT(mKind == Kind::PC);
-      return mPC;
-    }
-
-    // Public constant frames copies of each of the data-less frames.
-    static Frame Content() {
-      return Frame(Kind::CONTENT);
-    }
-    static Frame Jit() {
-      return Frame(Kind::JIT);
-    }
-    static Frame Wasm() {
-      return Frame(Kind::WASM);
-    }
-    static Frame Suppressed() {
-      return Frame(Kind::SUPPRESSED);
-    }
-
-  private:
-    explicit Frame(Kind aKind)
-      : mKind(aKind)
-    {
-      MOZ_ASSERT(aKind == Kind::CONTENT ||
-                 aKind == Kind::JIT ||
-                 aKind == Kind::WASM ||
-                 aKind == Kind::SUPPRESSED,
-                 "Kind must only be one of CONTENT, JIT, WASM or SUPPRESSED "
-                 "for the data-free constructor.");
-    }
-
-    Kind mKind;
-    union {
-      const char* mString;
-      ModOffset mModOffset;
-      uintptr_t mPC;
-    };
-  };
-
-  struct Module {
-    // The file name, /foo/bar/libxul.so for example.
-    // It can contain unicode characters.
-    nsString mName;
-    nsCString mBreakpadId;
-
-    bool operator==(const Module& aOther) const {
-      return mName == aOther.mName && mBreakpadId == aOther.mBreakpadId;
-    }
-  };
-
-private:
-  typedef mozilla::Vector<Frame, sMaxInlineStorage> Impl;
-  Impl mImpl;
-
-  // Stack entries can either be a static const char*
-  // or a pointer to within this buffer.
-  mozilla::Vector<char, 0> mBuffer;
-  nsTArray<Module> mModules;
-
-public:
-  HangStack() {}
-
-  HangStack(const HangStack& aOther);
-  HangStack(HangStack&& aOther)
-    : mImpl(mozilla::Move(aOther.mImpl))
-    , mBuffer(mozilla::Move(aOther.mBuffer))
-    , mModules(mozilla::Move(aOther.mModules))
-  {
-  }
-
-  HangStack& operator=(HangStack&& aOther) {
-    mImpl = mozilla::Move(aOther.mImpl);
-    mBuffer = mozilla::Move(aOther.mBuffer);
-    mModules = mozilla::Move(aOther.mModules);
-    return *this;
-  }
-
-  bool operator==(const HangStack& aOther) const {
-    for (size_t i = 0; i < length(); i++) {
-      if (!IsSameAsEntry(operator[](i), aOther[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  bool operator!=(const HangStack& aOther) const {
-    return !operator==(aOther);
-  }
-
-  Frame& operator[](size_t aIndex) {
-    return mImpl[aIndex];
-  }
-
-  Frame const& operator[](size_t aIndex) const {
-    return mImpl[aIndex];
-  }
-
-  size_t capacity() const { return mImpl.capacity(); }
-  size_t length() const { return mImpl.length(); }
-  bool empty() const { return mImpl.empty(); }
-  bool canAppendWithoutRealloc(size_t aNeeded) const {
-    return mImpl.canAppendWithoutRealloc(aNeeded);
-  }
-  void infallibleAppend(Frame aEntry) { mImpl.infallibleAppend(aEntry); }
-  MOZ_MUST_USE bool reserve(size_t aRequest) { return mImpl.reserve(aRequest); }
-  Frame* begin() { return mImpl.begin(); }
-  Frame const* begin() const { return mImpl.begin(); }
-  Frame* end() { return mImpl.end(); }
-  Frame const* end() const { return mImpl.end(); }
-  Frame& back() { return mImpl.back(); }
-  void erase(Frame* aEntry) { mImpl.erase(aEntry); }
-  void erase(Frame* aBegin, Frame* aEnd) {
-    mImpl.erase(aBegin, aEnd);
-  }
-
-  void clear() {
-    mImpl.clear();
-    mBuffer.clear();
-    mModules.Clear();
-  }
-
-  bool IsInBuffer(const char* aEntry) const {
-    return aEntry >= mBuffer.begin() && aEntry < mBuffer.end();
-  }
-
-  bool IsSameAsEntry(const Frame& aFrame, const Frame& aOther) const {
-    if (aFrame.GetKind() != aOther.GetKind()) {
-      return false;
-    }
-
-    switch (aFrame.GetKind()) {
-      case Frame::Kind::STRING:
-        // If the entry came from the buffer, we need to compare its content;
-        // otherwise we only need to compare its pointer.
-        return IsInBuffer(aFrame.AsString()) ?
-          !strcmp(aFrame.AsString(), aOther.AsString()) :
-          (aFrame.AsString() == aOther.AsString());
-      case Frame::Kind::MODOFFSET:
-        return aFrame.AsModOffset() == aOther.AsModOffset();
-      case Frame::Kind::PC:
-        return aFrame.AsPC() == aOther.AsPC();
-      default:
-        MOZ_CRASH();
-    }
-  }
-
-  bool IsSameAsEntry(const char* aEntry, const char* aOther) const {
-    // If the entry came from the buffer, we need to compare its content;
-    // otherwise we only need to compare its pointer.
-    return IsInBuffer(aEntry) ? !strcmp(aEntry, aOther) : (aEntry == aOther);
-  }
-
-  size_t AvailableBufferSize() const {
-    return mBuffer.capacity() - mBuffer.length();
-  }
-
-  MOZ_MUST_USE bool EnsureBufferCapacity(size_t aCapacity) {
-    // aCapacity is the minimal capacity and Vector may make the actual
-    // capacity larger, in which case we want to use up all the space.
-    return mBuffer.reserve(aCapacity) &&
-           mBuffer.reserve(mBuffer.capacity());
-  }
-
-  void InfallibleAppendViaBuffer(const char* aText, size_t aLength);
-  bool AppendViaBuffer(const char* aText, size_t aLength);
-
-  const nsTArray<Module>& GetModules() const {
-    return mModules;
-  }
-  nsTArray<Module>& GetModules() {
-    return mModules;
-  }
-
-  /**
-   * Get the current list of loaded modules, and use it to transform Kind::PC
-   * stack frames from within these modules into Kind::MODOFFSET stack entries.
-   *
-   * This method also populates the mModules list, which should be empty when
-   * this method is called.
-   */
-  void ReadModuleInformation();
-};
-
-} // namespace mozilla
-
-namespace IPC {
-
-template<>
-class ParamTraits<mozilla::HangStack::ModOffset>
-{
-public:
-  typedef mozilla::HangStack::ModOffset paramType;
-  static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg,
-                   PickleIterator* aIter,
-                   paramType* aResult);
-};
-
-template<>
-struct ParamTraits<mozilla::HangStack::Frame::Kind>
-  : public ContiguousEnumSerializer<
-            mozilla::HangStack::Frame::Kind,
-            mozilla::HangStack::Frame::Kind::STRING,
-            mozilla::HangStack::Frame::Kind::END>
-{};
-
-template<>
-struct ParamTraits<mozilla::HangStack::Module>
-{
-public:
-  typedef mozilla::HangStack::Module paramType;
-  static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg,
-                   PickleIterator* aIter,
-                   paramType* aResult);
-};
-
-template<>
-struct ParamTraits<mozilla::HangStack>
-{
-  typedef mozilla::HangStack paramType;
-  static void Write(Message* aMsg, const paramType& aParam);
-  static bool Read(const Message* aMsg,
-                   PickleIterator* aIter,
-                   paramType* aResult);
-};
-
-} // namespace IPC
-
-#endif // mozilla_HangStack_h
new file mode 100644
--- /dev/null
+++ b/toolkit/components/backgroundhangmonitor/HangTypes.ipdlh
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* 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/. */
+
+namespace mozilla {
+
+// The different kinds of hang entries which we're going to need to handle in
+// our HangStacks.
+
+struct HangEntryBufOffset
+{
+    // NOTE: Don't trust this index without checking it is a valid index into
+    // the strbuffer, and that the buffer's last byte is a '\0'.
+    uint32_t index;
+};
+
+struct HangEntryModOffset
+{
+    uint32_t module;
+    uint32_t offset;
+};
+
+struct HangEntryProgCounter
+{
+    uintptr_t pc;
+};
+
+// Singleton structs for the union type.
+struct HangEntryContent {};
+struct HangEntryJit {};
+struct HangEntryWasm {};
+struct HangEntryChromeScript {};
+struct HangEntrySuppressed {};
+
+union HangEntry
+{
+    // String representing a pseudostack or chrome JS stack.
+    nsCString;
+    // The index of the start of a string in the associated buffer.
+    HangEntryBufOffset;
+    // A module index and offset into that module.
+    HangEntryModOffset;
+    // A raw program counter which has not been mapped into a module.
+    HangEntryProgCounter;
+    // A hidden "(content script)" frame.
+    HangEntryContent;
+    // An unprocessed "(jit frame)"
+    HangEntryJit;
+    // An unprocessed "(wasm)" frame.
+    HangEntryWasm;
+    // A chrome script which didn't fit in the buffer.
+    HangEntryChromeScript;
+    // A JS frame while profiling was suppressed.
+    HangEntrySuppressed;
+};
+
+struct HangModule
+{
+    // The file name, /foo/bar/libxul.so for example.
+    // It can contain unicode characters.
+    nsString name;
+    nsCString breakpadId;
+};
+
+struct HangStack
+{
+    HangEntry[] stack;
+    int8_t[] strbuffer;
+    HangModule[] modules;
+};
+
+// Hang annotation information.
+struct HangAnnotation
+{
+    nsString name;
+    nsString value;
+};
+
+// The information about an individual hang which is sent over IPC.
+struct HangDetails
+{
+    uint32_t duration;
+    nsCString process;
+    nsString remoteType;
+    nsCString threadName;
+    nsCString runnableName;
+    HangStack stack;
+    HangAnnotation[] annotations;
+};
+
+} // namespace mozilla
\ No newline at end of file
--- a/toolkit/components/backgroundhangmonitor/ThreadStackHelper.cpp
+++ b/toolkit/components/backgroundhangmonitor/ThreadStackHelper.cpp
@@ -17,17 +17,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Move.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/MemoryChecking.h"
 #include "mozilla/Sprintf.h"
 #include "nsThread.h"
-#include "mozilla/HangStack.h"
+#include "mozilla/HangTypes.h"
 
 #ifdef __GNUC__
 # pragma GCC diagnostic push
 # pragma GCC diagnostic ignored "-Wshadow"
 #endif
 
 #if defined(MOZ_VALGRIND)
 # include <valgrind/valgrind.h>
@@ -63,17 +63,17 @@
 #define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
 #endif
 #endif
 
 namespace mozilla {
 
 ThreadStackHelper::ThreadStackHelper()
   : mStackToFill(nullptr)
-  , mMaxStackSize(HangStack::sMaxInlineStorage)
+  , mMaxStackSize(16)
   , mMaxBufferSize(512)
   , mDesiredStackSize(0)
   , mDesiredBufferSize(0)
 {
   mThreadId = profiler_current_thread_id();
 }
 
 bool
@@ -85,22 +85,26 @@ ThreadStackHelper::PrepareStackBuffer(Ha
     mMaxBufferSize = mDesiredBufferSize;
   }
   if (mDesiredStackSize > mMaxStackSize) {
     mMaxStackSize = mDesiredStackSize;
   }
   mDesiredBufferSize = 0;
   mDesiredStackSize = 0;
 
-  // Return false to skip getting the stack and return an empty stack
-  aStack.clear();
+  // Clear all of the stack entries.
+  aStack.stack().ClearAndRetainStorage();
+  aStack.strbuffer().ClearAndRetainStorage();
+  aStack.modules().Clear();
+
 #ifdef MOZ_THREADSTACKHELPER_PSEUDO
-  if (!aStack.reserve(mMaxStackSize) ||
-      !aStack.reserve(aStack.capacity()) || // reserve up to the capacity
-      !aStack.EnsureBufferCapacity(mMaxBufferSize)) {
+  // Ensure we have enough space in our stack and string buffers for the data we
+  // want to collect.
+  if (!aStack.stack().SetCapacity(mMaxStackSize, fallible) ||
+      !aStack.strbuffer().SetCapacity(mMaxBufferSize, fallible)) {
     return false;
   }
   return true;
 #else
   return false;
 #endif
 }
 
@@ -156,65 +160,67 @@ ThreadStackHelper::SetIsMainThread()
   //
   // Currently we only store the names of runnables which are running on the
   // main thread, so we only want to read sMainThreadRunnableName and copy its
   // value in the case that we are currently suspending the main thread.
   *mRunnableNameBuffer = nsThread::sMainThreadRunnableName;
 }
 
 void
-ThreadStackHelper::TryAppendFrame(HangStack::Frame aFrame)
+ThreadStackHelper::TryAppendFrame(HangEntry aFrame)
 {
   MOZ_RELEASE_ASSERT(mStackToFill);
 
-  // We deduplicate identical frames of kind CONTENT, JIT, WASM, and SUPPRESSED.
-  switch (aFrame.GetKind()) {
-    case HangStack::Frame::Kind::CONTENT:
-    case HangStack::Frame::Kind::JIT:
-    case HangStack::Frame::Kind::WASM:
-    case HangStack::Frame::Kind::SUPPRESSED:
-      if (!mStackToFill->empty() && mStackToFill->back().GetKind() == aFrame.GetKind()) {
+  // We deduplicate identical Content, Jit, Wasm, ChromeScript and Suppressed frames.
+  switch (aFrame.type()) {
+    case HangEntry::THangEntryContent:
+    case HangEntry::THangEntryJit:
+    case HangEntry::THangEntryWasm:
+    case HangEntry::THangEntryChromeScript:
+    case HangEntry::THangEntrySuppressed:
+      if (!mStackToFill->stack().IsEmpty() &&
+          mStackToFill->stack().LastElement().type() == aFrame.type()) {
         return;
       }
       break;
     default:
       break;
   }
 
   // Record that we _want_ to use another frame entry. If this exceeds
   // mMaxStackSize, we'll allocate more room on the next hang.
   mDesiredStackSize += 1;
 
   // Perform the append if we have enough space to do so.
-  if (mStackToFill->canAppendWithoutRealloc(1)) {
-    mStackToFill->infallibleAppend(aFrame);
+  if (mStackToFill->stack().Capacity() > mStackToFill->stack().Length()) {
+    mStackToFill->stack().AppendElement(mozilla::Move(aFrame));
   }
 }
 
 void
 ThreadStackHelper::CollectNativeLeafAddr(void* aAddr)
 {
   MOZ_RELEASE_ASSERT(mStackToFill);
-  TryAppendFrame(HangStack::Frame(reinterpret_cast<uintptr_t>(aAddr)));
+  TryAppendFrame(HangEntryProgCounter(reinterpret_cast<uintptr_t>(aAddr)));
 }
 
 void
 ThreadStackHelper::CollectJitReturnAddr(void* aAddr)
 {
   MOZ_RELEASE_ASSERT(mStackToFill);
-  TryAppendFrame(HangStack::Frame::Jit());
+  TryAppendFrame(HangEntryJit());
 }
 
 void
 ThreadStackHelper::CollectWasmFrame(const char* aLabel)
 {
   MOZ_RELEASE_ASSERT(mStackToFill);
   // We don't want to collect WASM frames, as they are probably for content, so
   // we just add a "(content wasm)" frame.
-  TryAppendFrame(HangStack::Frame::Wasm());
+  TryAppendFrame(HangEntryWasm());
 }
 
 namespace {
 
 bool
 IsChromeJSScript(JSScript* aScript)
 {
   // May be called from another thread or inside a signal handler.
@@ -258,28 +264,49 @@ GetPathAfterComponent(const char* filena
 
 } // namespace
 
 void
 ThreadStackHelper::CollectPseudoEntry(const js::ProfileEntry& aEntry)
 {
   // For non-js frames we just include the raw label.
   if (!aEntry.isJs()) {
-    const char* label = aEntry.label();
-    TryAppendFrame(HangStack::Frame(label));
+    const char* entryLabel = aEntry.label();
+
+    // entryLabel is a statically allocated string, so we want to store a
+    // reference to it without performing any allocations. This is important, as
+    // we aren't allowed to allocate within this function.
+    //
+    // The variant for this kind of label in our HangStack object is a
+    // `nsCString`, which normally contains heap allocated string data. However,
+    // `nsCString` has an optimization for literal strings which causes the
+    // backing data to not be copied when being copied between nsCString
+    // objects.
+    //
+    // We take advantage of that optimization by creating a nsCString object
+    // which has the LITERAL flag set. Without this optimization, this code
+    // would be incorrect.
+    nsCString label;
+    label.AssignLiteral(entryLabel, strlen(entryLabel));
+
+    // Let's make sure we don't deadlock here, by asserting that `label`'s
+    // backing data matches.
+    MOZ_RELEASE_ASSERT(label.BeginReading() == entryLabel,
+        "String copy performed during ThreadStackHelper::CollectPseudoEntry");
+    TryAppendFrame(label);
     return;
   }
 
   if (!aEntry.script()) {
-    TryAppendFrame(HangStack::Frame::Suppressed());
+    TryAppendFrame(HangEntrySuppressed());
     return;
   }
 
   if (!IsChromeJSScript(aEntry.script())) {
-    TryAppendFrame(HangStack::Frame::Content());
+    TryAppendFrame(HangEntryContent());
     return;
   }
 
   // Rather than using the profiler's dynamic string, we compute our own string.
   // This is because we want to do some size-saving strategies, and throw out
   // information which won't help us as much.
   // XXX: We currently don't collect the function name which hung.
   const char* filename = JS_GetScriptFilename(aEntry.script());
@@ -308,26 +335,30 @@ ThreadStackHelper::CollectPseudoEntry(co
     basename = basename ? basename + 1 : filename;
     // Look for Windows path separator as well.
     filename = strrchr(basename, '\\');
     if (filename) {
       basename = filename + 1;
     }
   }
 
-  mDesiredStackSize += 1;
   char buffer[128]; // Enough to fit longest js file name from the tree
   size_t len = SprintfLiteral(buffer, "%s:%u", basename, lineno);
   if (len < sizeof(buffer)) {
     mDesiredBufferSize += len + 1;
-    if (mStackToFill->canAppendWithoutRealloc(1) &&
-        mStackToFill->AvailableBufferSize() >= len + 1) {
-      mStackToFill->InfallibleAppendViaBuffer(buffer, len);
+
+    if (mStackToFill->stack().Capacity() > mStackToFill->stack().Length() &&
+        (mStackToFill->strbuffer().Capacity() -
+         mStackToFill->strbuffer().Length()) > len + 1) {
+      // NOTE: We only increment this if we're going to successfully append.
+      mDesiredStackSize += 1;
+      uint32_t start = mStackToFill->strbuffer().Length();
+      mStackToFill->strbuffer().AppendElements(buffer, len);
+      mStackToFill->strbuffer().AppendElement('\0');
+      mStackToFill->stack().AppendElement(HangEntryBufOffset(start));
       return;
     }
   }
 
-  if (mStackToFill->canAppendWithoutRealloc(1)) {
-    mStackToFill->infallibleAppend(HangStack::Frame("(chrome script)"));
-  }
+  TryAppendFrame(HangEntryChromeScript());
 }
 
 } // namespace mozilla
--- a/toolkit/components/backgroundhangmonitor/ThreadStackHelper.h
+++ b/toolkit/components/backgroundhangmonitor/ThreadStackHelper.h
@@ -48,23 +48,16 @@ namespace mozilla {
  * then another thread can call ThreadStackHelper::GetStack to retrieve
  * the pseudo-stack of the target thread at that instant.
  *
  * Only non-copying labels are included in the stack, which means labels
  * with custom text and markers are not included.
  */
 class ThreadStackHelper : public ProfilerStackCollector
 {
-public:
-  // When a native stack is gathered, this vector holds the raw program counter
-  // values that FramePointerStackWalk will return to us after it walks the
-  // stack. When gathering the Telemetry payload, Telemetry will take care of
-  // mapping these program counters to proper addresses within modules.
-  typedef NativeHangStack NativeStack;
-
 private:
   HangStack* mStackToFill;
   Array<char, nsThread::kRunnableNameBufSize>* mRunnableNameBuffer;
   // const PseudoStack* const mPseudoStack;
   size_t mMaxStackSize;
   size_t mMaxBufferSize;
   size_t mDesiredStackSize;
   size_t mDesiredBufferSize;
@@ -82,28 +75,33 @@ public:
    *
    * @param aStack        HangStack instance to be filled.
    * @param aRunnableName The name of the current runnable on the target thread.
    * @param aStackWalk    If true, native stack frames will be collected
    *                      along with pseudostack frames.
    */
   void GetStack(HangStack& aStack, nsACString& aRunnableName, bool aStackWalk);
 
+  /**
+   * Retrieve the thread's profiler thread ID.
+   */
+  int GetThreadId() const { return mThreadId; }
+
 protected:
   /**
    * ProfilerStackCollector
    */
   virtual void SetIsMainThread() override;
   virtual void CollectNativeLeafAddr(void* aAddr) override;
   virtual void CollectJitReturnAddr(void* aAddr) override;
   virtual void CollectWasmFrame(const char* aLabel) override;
   virtual void CollectPseudoEntry(const js::ProfileEntry& aEntry) override;
 
 private:
-  void TryAppendFrame(mozilla::HangStack::Frame aFrame);
+  void TryAppendFrame(mozilla::HangEntry aFrame);
 
   // The profiler's unique thread identifier for the target thread.
   int mThreadId;
 };
 
 } // namespace mozilla
 
 #endif // MOZ_GECKO_PROFILER
--- a/toolkit/components/backgroundhangmonitor/moz.build
+++ b/toolkit/components/backgroundhangmonitor/moz.build
@@ -27,23 +27,25 @@ XPIDL_SOURCES += [
     'nsIHangDetails.idl',
 ]
 
 XPIDL_MODULE = 'backgroundhangmonitor'
 
 EXPORTS.mozilla += [
     'BackgroundHangMonitor.h',
     'HangDetails.h',
-    'HangStack.h',
 ]
 
 UNIFIED_SOURCES += [
     'BackgroundHangMonitor.cpp',
     'HangDetails.cpp',
-    'HangStack.cpp',
+]
+
+IPDL_SOURCES += [
+    'HangTypes.ipdlh',
 ]
 
 if CONFIG['MOZ_GECKO_PROFILER']:
     UNIFIED_SOURCES += [
         'ThreadStackHelper.cpp',
     ]
 
 LOCAL_INCLUDES += [
--- a/tools/profiler/core/ProfileBufferEntry.cpp
+++ b/tools/profiler/core/ProfileBufferEntry.cpp
@@ -727,17 +727,17 @@ ProfileBuffer::StreamSamplesToJSON(Splic
     // This is useful in three situations.
     //
     // - The circular buffer overwrites old entries, so when we start parsing
     //   we might be in the middle of a sample, and we must skip forward to the
     //   start of the next sample.
     //
     // - We skip samples that don't have an appropriate ThreadId or Time.
     //
-    // - We skip range Pause, Resume, CollectionStart, and CollectionEnd
+    // - We skip range Pause, Resume, CollectionStart, Marker, and CollectionEnd
     //   entries between samples.
     while (e.Has()) {
       if (e.Get().IsThreadId()) {
         break;
       } else {
         e.Next();
       }
     }
@@ -913,26 +913,27 @@ void
 ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
                                    int aThreadId,
                                    const TimeStamp& aProcessStartTime,
                                    double aSinceTime,
                                    UniqueStacks& aUniqueStacks) const
 {
   EntryGetter e(*this);
 
-  int currentThreadID = -1;
-
-  // Stream all markers whose threadId matches aThreadId. All other entries are
-  // skipped, because we process them in StreamSamplesToJSON().
+  // Stream all markers whose threadId matches aThreadId. We skip other entries,
+  // because we process them in StreamSamplesToJSON().
+  //
+  // NOTE: The ThreadId of a marker is determined by its GetThreadId() method,
+  // rather than ThreadId buffer entries, as markers can be added outside of
+  // samples.
   while (e.Has()) {
-    if (e.Get().IsThreadId()) {
-      currentThreadID = e.Get().u.mInt;
-    } else if (currentThreadID == aThreadId && e.Get().IsMarker()) {
+    if (e.Get().IsMarker()) {
       const ProfilerMarker* marker = e.Get().u.mMarker;
-      if (marker->GetTime() >= aSinceTime) {
+      if (marker->GetTime() >= aSinceTime &&
+          marker->GetThreadId() == aThreadId) {
         marker->StreamJSON(aWriter, aProcessStartTime, aUniqueStacks);
       }
     }
     e.Next();
   }
 }
 
 static void
--- a/tools/profiler/core/ProfilerMarker.h
+++ b/tools/profiler/core/ProfilerMarker.h
@@ -17,32 +17,36 @@ class SpliceableJSONWriter;
 class UniqueStacks;
 
 class ProfilerMarker
 {
   friend class ProfilerLinkedList<ProfilerMarker>;
 
 public:
   explicit ProfilerMarker(const char* aMarkerName,
+                          int aThreadId,
                           mozilla::UniquePtr<ProfilerMarkerPayload>
                             aPayload = nullptr,
                           double aTime = 0)
     : mMarkerName(strdup(aMarkerName))
     , mPayload(Move(aPayload))
     , mNext{nullptr}
     , mTime(aTime)
     , mGenID{0}
+    , mThreadId{aThreadId}
     {}
 
   void SetGeneration(uint32_t aGenID) { mGenID = aGenID; }
 
   bool HasExpired(uint32_t aGenID) const { return mGenID + 2 <= aGenID; }
 
   double GetTime() const { return mTime; }
 
+  int GetThreadId() const { return mThreadId; }
+
   void StreamJSON(SpliceableJSONWriter& aWriter,
                   const mozilla::TimeStamp& aProcessStartTime,
                   UniqueStacks& aUniqueStacks) const
   {
     // Schema:
     //   [name, time, data]
 
     aWriter.StartArrayElement();
@@ -64,16 +68,17 @@ public:
   }
 
 private:
   mozilla::UniqueFreePtr<char> mMarkerName;
   mozilla::UniquePtr<ProfilerMarkerPayload> mPayload;
   ProfilerMarker* mNext;
   double mTime;
   uint32_t mGenID;
+  int mThreadId;
 };
 
 template<typename T>
 class ProfilerLinkedList
 {
 public:
   ProfilerLinkedList()
     : mHead(nullptr)
--- a/tools/profiler/core/ThreadInfo.cpp
+++ b/tools/profiler/core/ThreadInfo.cpp
@@ -20,19 +20,18 @@
 #endif
 
 ThreadInfo::ThreadInfo(const char* aName,
                        int aThreadId,
                        bool aIsMainThread,
                        void* aStackTop)
   : mName(strdup(aName))
   , mRegisterTime(TimeStamp::Now())
-  , mThreadId(aThreadId)
   , mIsMainThread(aIsMainThread)
-  , mRacyInfo(mozilla::MakeNotNull<RacyThreadInfo*>())
+  , mRacyInfo(mozilla::MakeNotNull<RacyThreadInfo*>(aThreadId))
   , mPlatformData(AllocPlatformData(aThreadId))
   , mStackTop(aStackTop)
   , mIsBeingProfiled(false)
   , mFirstSavedStreamedSampleTime{0.0}
   , mContext(nullptr)
   , mJSSampling(INACTIVE)
   , mLastSample()
 {
@@ -255,29 +254,29 @@ ThreadInfo::FlushSamplesAndMarkers(const
   // Note that the UniqueStacks instance is persisted so that the frame-index
   // mapping is stable across JS shutdown.
   mUniqueStacks.emplace(mContext);
 
   {
     SpliceableChunkedJSONWriter b;
     b.StartBareList();
     {
-      aBuffer.StreamSamplesToJSON(b, mThreadId, /* aSinceTime = */ 0,
+      aBuffer.StreamSamplesToJSON(b, ThreadId(), /* aSinceTime = */ 0,
                                   &mFirstSavedStreamedSampleTime,
                                   mContext, *mUniqueStacks);
     }
     b.EndBareList();
     mSavedStreamedSamples = b.WriteFunc()->CopyData();
   }
 
   {
     SpliceableChunkedJSONWriter b;
     b.StartBareList();
     {
-      aBuffer.StreamMarkersToJSON(b, mThreadId, aProcessStartTime,
+      aBuffer.StreamMarkersToJSON(b, ThreadId(), aProcessStartTime,
                                   /* aSinceTime = */ 0, *mUniqueStacks);
     }
     b.EndBareList();
     mSavedStreamedMarkers = b.WriteFunc()->CopyData();
   }
 
   // Reset the buffer. Attempting to symbolicate JS samples after mContext has
   // gone away will crash.
--- a/tools/profiler/core/ThreadInfo.h
+++ b/tools/profiler/core/ThreadInfo.h
@@ -18,18 +18,19 @@
 // This class contains the info for a single thread that is accessible without
 // protection from gPSMutex in platform.cpp. Because there is no external
 // protection against data races, it must provide internal protection. Hence
 // the "Racy" prefix.
 //
 class RacyThreadInfo final : public PseudoStack
 {
 public:
-  RacyThreadInfo()
+  explicit RacyThreadInfo(int aThreadId)
     : PseudoStack()
+    , mThreadId(aThreadId)
     , mSleep(AWAKE)
   {
     MOZ_COUNT_CTOR(RacyThreadInfo);
   }
 
   ~RacyThreadInfo()
   {
     MOZ_COUNT_DTOR(RacyThreadInfo);
@@ -52,17 +53,17 @@ public:
     return n;
   }
 
   void AddPendingMarker(const char* aMarkerName,
                         mozilla::UniquePtr<ProfilerMarkerPayload> aPayload,
                         double aTime)
   {
     ProfilerMarker* marker =
-      new ProfilerMarker(aMarkerName, Move(aPayload), aTime);
+      new ProfilerMarker(aMarkerName, mThreadId, Move(aPayload), aTime);
     mPendingMarkers.insert(marker);
   }
 
   // Called within signal. Function must be reentrant.
   ProfilerMarkerLinkedList* GetPendingMarkers()
   {
     // The profiled thread is interrupted, so we can access the list safely.
     // Unless the profiled thread was in the middle of changing the list when
@@ -108,20 +109,26 @@ public:
   void SetAwake()
   {
     MOZ_ASSERT(mSleep != AWAKE);
     mSleep = AWAKE;
   }
 
   bool IsSleeping() { return mSleep != AWAKE; }
 
+  int ThreadId() const { return mThreadId; }
+
 private:
   // A list of pending markers that must be moved to the circular buffer.
   ProfilerSignalSafeLinkedList<ProfilerMarker> mPendingMarkers;
 
+  // mThreadId contains the thread ID of the current thread. It is safe to read
+  // this from multiple threads concurrently, as it will never be mutated.
+  const int mThreadId;
+
   // mSleep tracks whether the thread is sleeping, and if so, whether it has
   // been previously observed. This is used for an optimization: in some cases,
   // when a thread is asleep, we duplicate the previous sample, which is
   // cheaper than taking a new sample.
   //
   // mSleep is atomic because it is accessed from multiple threads.
   //
   // - It is written only by this thread, via setSleeping() and setAwake().
@@ -168,17 +175,20 @@ class ThreadInfo final
 {
 public:
   ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread,
              void* aStackTop);
 
   ~ThreadInfo();
 
   const char* Name() const { return mName.get(); }
-  int ThreadId() const { return mThreadId; }
+
+  // This is a safe read even when the target thread is not blocked, as this
+  // thread id is never mutated.
+  int ThreadId() const { return RacyInfo()->ThreadId(); }
 
   bool IsMainThread() const { return mIsMainThread; }
 
   mozilla::NotNull<RacyThreadInfo*> RacyInfo() const { return mRacyInfo; }
 
   void StartProfiling();
   void StopProfiling();
   bool IsBeingProfiled() { return mIsBeingProfiled; }
@@ -191,17 +201,16 @@ public:
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   ProfileBuffer::LastSample& LastSample() { return mLastSample; }
 
 private:
   mozilla::UniqueFreePtr<char> mName;
   mozilla::TimeStamp mRegisterTime;
   mozilla::TimeStamp mUnregisterTime;
-  int mThreadId;
   const bool mIsMainThread;
 
   // The thread's RacyThreadInfo. This is an owning pointer. It could be an
   // inline member, but we don't do that because RacyThreadInfo is quite large
   // (due to the PseudoStack within it), and we have ThreadInfo vectors and so
   // we'd end up wasting a lot of space in those vectors for excess elements.
   mozilla::NotNull<RacyThreadInfo*> mRacyInfo;
 
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -3278,16 +3278,56 @@ profiler_add_marker(const char* aMarkerN
 }
 
 void
 profiler_add_marker(const char* aMarkerName)
 {
   profiler_add_marker(aMarkerName, nullptr);
 }
 
+// This logic needs to add a marker for a different thread, so we actually need
+// to lock here.
+void
+profiler_add_marker_for_thread(int aThreadId,
+                               const char* aMarkerName,
+                               UniquePtr<ProfilerMarkerPayload> aPayload)
+{
+  MOZ_RELEASE_ASSERT(CorePS::Exists());
+
+  // Create the ProfilerMarker which we're going to store.
+  TimeStamp origin = (aPayload && !aPayload->GetStartTime().IsNull())
+                   ? aPayload->GetStartTime()
+                   : TimeStamp::Now();
+  TimeDuration delta = origin - CorePS::ProcessStartTime();
+  ProfilerMarker* marker =
+    new ProfilerMarker(aMarkerName, aThreadId, Move(aPayload),
+                       delta.ToMilliseconds());
+
+  PSAutoLock lock(gPSMutex);
+
+#ifdef DEBUG
+  // Assert that our thread ID makes sense
+  bool realThread = false;
+  const CorePS::ThreadVector& liveThreads = CorePS::LiveThreads(lock);
+  for (uint32_t i = 0; i < liveThreads.size(); i++) {
+    ThreadInfo* info = liveThreads.at(i);
+    if (info->ThreadId() == aThreadId) {
+      realThread = true;
+      break;
+    }
+  }
+  MOZ_ASSERT(realThread, "Invalid thread id");
+#endif
+
+  // Insert the marker into the buffer
+  ProfileBuffer& buffer = ActivePS::Buffer(lock);
+  buffer.AddStoredMarker(marker);
+  buffer.AddEntry(ProfileBufferEntry::Marker(marker));
+}
+
 void
 profiler_tracing(const char* aCategory, const char* aMarkerName,
                  TracingKind aKind)
 {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   // This function is hot enough that we use RacyFeatures, notActivePS.
   if (!RacyFeatures::IsActiveWithoutPrivacy()) {
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -457,16 +457,21 @@ PseudoStack* profiler_get_pseudo_stack()
 // certain length of time. A no-op if the profiler is inactive or in privacy
 // mode.
 #define PROFILER_ADD_MARKER(markerName) \
   profiler_add_marker(markerName)
 void profiler_add_marker(const char* aMarkerName);
 void profiler_add_marker(const char* aMarkerName,
                          mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
 
+// Insert a marker in the profile timeline for a specified thread.
+void profiler_add_marker_for_thread(int aThreadId,
+                                    const char* aMarkerName,
+                                    mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
+
 enum TracingKind {
   TRACING_EVENT,
   TRACING_INTERVAL_START,
   TRACING_INTERVAL_END,
 };
 
 // Adds a tracing marker to the profile. A no-op if the profiler is inactive or
 // in privacy mode.
--- a/xpcom/ds/ArenaAllocator.h
+++ b/xpcom/ds/ArenaAllocator.h
@@ -163,17 +163,19 @@ private:
 
     /**
      * Allocates a chunk of memory out of the arena and advances the offset.
      */
     void* Allocate(size_t aSize)
     {
       MOZ_ASSERT(aSize <= Available());
       char* p = reinterpret_cast<char*>(header.offset);
+      MOZ_RELEASE_ASSERT(p);
       header.offset += aSize;
+      canary.Check();
       MOZ_MAKE_MEM_UNDEFINED(p, aSize);
       return p;
     }
 
     /**
      * Calculates the amount of space available for allocation in this chunk.
      */
     size_t Available() const {