Merge inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Wed, 18 Apr 2018 13:44:22 +0300
changeset 467765 4af4ae0aee552a99a995ce4b32198b98294a95f7
parent 467682 79b7ee8b01ee122b3f7122f926e5ae9dc1132a96 (current diff)
parent 467764 42e037e0b8d1d774db5cc38ef486639c1c2889f1 (diff)
child 467783 fdc9671b51b59f5f06a591e90110892bffe98325
child 467812 fd2a5219b1033d6d233629c04502f9488808819a
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone61.0a1
first release with
nightly linux32
4af4ae0aee55 / 61.0a1 / 20180418112600 / files
nightly linux64
4af4ae0aee55 / 61.0a1 / 20180418112600 / files
nightly mac
4af4ae0aee55 / 61.0a1 / 20180418112600 / files
nightly win32
4af4ae0aee55 / 61.0a1 / 20180418112600 / files
nightly win64
4af4ae0aee55 / 61.0a1 / 20180418112600 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
accessible/tests/mochitest/textcaret/test_browserui.xul
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_settings_overrides_search.js
devtools/client/dom/content/components/dom-tree.js
devtools/client/dom/content/components/main-frame.js
devtools/client/dom/content/components/main-toolbar.js
dom/interfaces/core/nsIDOMDocumentFragment.idl
gfx/layers/composite/AsyncCompositionManager.cpp
servo/components/style/gecko/generated/atom_macro.rs
servo/components/style/gecko/generated/bindings.rs
servo/components/style/gecko/generated/pseudo_element_definition.rs
servo/components/style/gecko/generated/structs.rs
taskcluster/docker/beet-mover/Dockerfile
taskcluster/docker/beet-mover/requirements.txt
testing/mozharness/configs/beetmover/en_us_build.yml.tmpl
testing/mozharness/configs/beetmover/en_us_repackage_signing.yml.tmpl
testing/mozharness/configs/beetmover/en_us_signing.yml.tmpl
testing/mozharness/configs/beetmover/l10n_changesets.tmpl
testing/mozharness/configs/beetmover/partials.yml.tmpl
testing/mozharness/configs/beetmover/repacks.yml.tmpl
testing/mozharness/configs/beetmover/source.yml.tmpl
testing/mozharness/configs/beetmover/source_checksums.yml.tmpl
testing/mozharness/configs/beetmover/win32_to_win64_partials.yml.tmpl
testing/mozharness/configs/releases/postrelease_firefox_beta.py
testing/mozharness/configs/releases/postrelease_firefox_esr52.py
testing/mozharness/configs/releases/postrelease_firefox_release.py
testing/mozharness/scripts/release/beet_mover.py
testing/mozharness/scripts/release/postrelease_mark_as_shipped.py
testing/mozharness/scripts/release/postrelease_version_bump.py
testing/web-platform/meta/service-workers/service-worker/worker-interception-redirect.https.html.ini
xpcom/idl-parser/xpidl/typelib.py
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
xpcom/reflect/xptinfo/ShimInterfaceInfo.h
xpcom/reflect/xptinfo/TODO
xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl
xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
xpcom/reflect/xptinfo/xptiWorkingSet.cpp
xpcom/reflect/xptinfo/xptiprivate.h
xpcom/typelib/xpt/xpt_arena.cpp
xpcom/typelib/xpt/xpt_arena.h
xpcom/typelib/xpt/xpt_struct.h
--- a/accessible/tests/browser/events/browser.ini
+++ b/accessible/tests/browser/events/browser.ini
@@ -2,10 +2,11 @@
 support-files =
   head.js
   !/accessible/tests/browser/events.js
   !/accessible/tests/browser/shared-head.js
   !/accessible/tests/mochitest/*.js
 
 [browser_test_docload.js]
 skip-if = e10s
+[browser_test_textcaret.js]
 [browser_test_focus_browserui.js]
 [browser_test_focus_dialog.js]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/browser_test_textcaret.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Caret move events checker.
+ */
+function caretMoveChecker(target, caretOffset) {
+  return function(event) {
+    let cmEvent = event.QueryInterface(nsIAccessibleCaretMoveEvent);
+    return cmEvent.accessible == getAccessible(target) && cmEvent.caretOffset == caretOffset;
+  };
+}
+
+async function checkURLBarCaretEvents() {
+  let url = "about:mozilla";
+
+  let onDocLoad = waitForEvent(
+    EVENT_DOCUMENT_LOAD_COMPLETE,
+    event => {
+      try {
+        return event.accessible.QueryInterface(nsIAccessibleDocument).URL == url;
+      } catch (e) {
+        return false;
+      }
+    }
+  );
+  let [ newWin ] = await Promise.all([
+    BrowserTestUtils.openNewBrowserWindow({ url }),
+    onDocLoad
+  ]);
+
+  let urlbarInputEl = newWin.document.getElementById("urlbar").inputField;
+  let urlbarInput = getAccessible(urlbarInputEl, [ nsIAccessibleText ]);
+
+  let onCaretMove = waitForEvents([
+    [ EVENT_TEXT_CARET_MOVED, caretMoveChecker(urlbarInput, url.length) ],
+    [ EVENT_FOCUS, urlbarInput ]
+  ]);
+
+  urlbarInput.caretOffset = -1;
+  await onCaretMove;
+  ok(true, "Caret move in URL bar #1");
+
+  onCaretMove = waitForEvent(
+    EVENT_TEXT_CARET_MOVED, caretMoveChecker(urlbarInput, 0)
+  );
+
+  urlbarInput.caretOffset = 0;
+  await onCaretMove;
+  ok(true, "Caret move in URL bar #2");
+
+  await BrowserTestUtils.closeWindow(newWin);
+}
+
+add_task(checkURLBarCaretEvents);
--- a/accessible/tests/mochitest/textcaret/a11y.ini
+++ b/accessible/tests/mochitest/textcaret/a11y.ini
@@ -1,6 +1,5 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
-[test_browserui.xul]
 [test_general.html]
deleted file mode 100644
--- a/accessible/tests/mochitest/textcaret/test_browserui.xul
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Accessibility Caret Offset Test.">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../states.js"></script>
-  <script type="application/javascript"
-          src="../events.js"></script>
-  <script type="application/javascript"
-          src="../browser.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Tests
-
-    gA11yEventDumpToConsole = true; // debug
-    //enableLogging("tree,verbose");
-
-    var gQueue = null;
-    function doTests()
-    {
-      gQueue = new eventQueue();
-      gQueue.push(new setCaretOffset(urlbarInput(), -1, urlbarInput()));
-      gQueue.push(new setCaretOffset(urlbarInput(), 0));
-      gQueue.onFinish = function()
-      {
-        closeBrowserWindow();
-      }
-
-      gQueue.invoke();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    openBrowserWindow(doTests, "about:mozilla");
-  ]]>
-  </script>
-
-  <vbox flex="1" style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=723833"
-       title="IAccessibleText::setCaretOffset on location or search bar causes focus to jump">
-      Bug 723833
-    </a>
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-  </vbox>
-</window>
--- a/accessible/xpcom/AccEventGen.py
+++ b/accessible/xpcom/AccEventGen.py
@@ -13,33 +13,40 @@ import mozpack.path as mozpath
 # The xpidl parser is not incorporated in the in-tree virtualenv.
 xpidl_dir = mozpath.join(buildconfig.topsrcdir, 'xpcom', 'idl-parser',
                          'xpidl')
 xpidl_cachedir = mozpath.join(buildconfig.topobjdir, 'xpcom', 'idl-parser',
                               'xpidl')
 sys.path.extend([xpidl_dir, xpidl_cachedir])
 import xpidl
 
+# Load the webidl configuration file.
+glbl = {}
+execfile(mozpath.join(buildconfig.topsrcdir,
+                      'dom', 'bindings', 'Bindings.conf'),
+         glbl)
+webidlconfig = glbl['DOMInterfaces']
+
 # Instantiate the parser.
 p = xpidl.IDLParser()
 
 def findIDL(includePath, interfaceFileName):
     for d in includePath:
         path = mozpath.join(d, interfaceFileName)
         if os.path.exists(path):
             return path
     raise BaseException("No IDL file found for interface %s "
                         "in include path %r"
                         % (interfaceFileName, includePath))
 
 def loadEventIDL(parser, includePath, eventname):
     eventidl = ("nsIAccessible%s.idl" % eventname)
     idlFile = findIDL(includePath, eventidl)
     idl = p.parse(open(idlFile).read(), idlFile)
-    idl.resolve(includePath, p)
+    idl.resolve(includePath, p, webidlconfig)
     return idl, idlFile
 
 class Configuration:
     def __init__(self, filename):
         config = {}
         execfile(filename, config)
         self.simple_events = config.get('simple_events', [])
 
--- a/browser/build.mk
+++ b/browser/build.mk
@@ -1,15 +1,12 @@
 # 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/.
 
-installer:
-	@$(MAKE) -C browser/installer installer
-
 package:
 	@$(MAKE) -C browser/installer
 
 package-compare:
 	@$(MAKE) -C browser/installer package-compare
 
 stage-package:
 	@$(MAKE) -C browser/installer stage-package
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -131,17 +131,16 @@ disabled = bug 1438663
 [browser_ext_sessions_forgetClosedTab.js]
 [browser_ext_sessions_forgetClosedWindow.js]
 [browser_ext_sessions_getRecentlyClosed.js]
 [browser_ext_sessions_getRecentlyClosed_private.js]
 [browser_ext_sessions_getRecentlyClosed_tabs.js]
 [browser_ext_sessions_restore.js]
 [browser_ext_sessions_window_tab_value.js]
 [browser_ext_settings_overrides_default_search.js]
-[browser_ext_settings_overrides_search.js]
 [browser_ext_sidebarAction.js]
 [browser_ext_sidebarAction_browser_style.js]
 [browser_ext_sidebarAction_context.js]
 [browser_ext_sidebarAction_contextMenu.js]
 [browser_ext_sidebarAction_runtime.js]
 [browser_ext_sidebarAction_tabs.js]
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
rename from browser/components/extensions/test/browser/browser_ext_settings_overrides_search.js
rename to browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
--- a/browser/components/extensions/test/browser/browser_ext_settings_overrides_search.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_search.js
@@ -1,20 +1,32 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 
 "use strict";
 
+ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Timer.jsm");
+
+let delay = () => new Promise(resolve => setTimeout(resolve, 0));
 
 const kSearchEngineURL = "https://example.com/?search={searchTerms}";
 const kSearchSuggestURL = "http://example.com/?suggest={searchTerms}";
 const kSearchTerm = "foo";
 const kSearchTermIntl = "日";
 const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
 
+AddonTestUtils.init(this);
+AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "42", "42");
+
+add_task(async function setup() {
+  await AddonTestUtils.promiseStartupManager();
+  Services.search.init();
+});
+
 add_task(async function test_extension_adding_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
         "search_provider": {
           "name": "MozSearch",
           "keyword": "MozSearch",
           "search_url": kSearchEngineURL,
@@ -29,21 +41,22 @@ add_task(async function test_extension_a
 
   let engine = Services.search.getEngineByName("MozSearch");
   ok(engine, "Engine should exist.");
 
   let expectedSuggestURL = kSearchSuggestURL.replace("{searchTerms}", kSearchTerm);
   let submissionSuggest = engine.getSubmission(kSearchTerm, URLTYPE_SUGGEST_JSON);
   let encodedSubmissionURL = engine.getSubmission(kSearchTermIntl).uri.spec;
   let testSubmissionURL = kSearchEngineURL.replace("{searchTerms}", encodeURIComponent(kSearchTermIntl));
-  is(encodedSubmissionURL, testSubmissionURL, "Encoded UTF-8 URLs should match");
+  equal(encodedSubmissionURL, testSubmissionURL, "Encoded UTF-8 URLs should match");
 
-  is(submissionSuggest.uri.spec, expectedSuggestURL, "Suggest URLs should match");
+  equal(submissionSuggest.uri.spec, expectedSuggestURL, "Suggest URLs should match");
 
   await ext1.unload();
+  await delay();
 
   engine = Services.search.getEngineByName("MozSearch");
   ok(!engine, "Engine should not exist");
 });
 
 add_task(async function test_extension_adding_engine_with_spaces() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
@@ -59,16 +72,17 @@ add_task(async function test_extension_a
   });
 
   await ext1.startup();
 
   let engine = Services.search.getEngineByName("MozSearch");
   ok(engine, "Engine should exist.");
 
   await ext1.unload();
+  await delay();
 
   engine = Services.search.getEngineByName("MozSearch");
   ok(!engine, "Engine should not exist");
 });
 
 
 add_task(async function test_upgrade_default_position_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
@@ -85,17 +99,23 @@ add_task(async function test_upgrade_def
           "id": "testengine@mozilla.com",
         },
       },
       "version": "0.1",
     },
     useAddonManager: "temporary",
   });
 
-  let ext2 = ExtensionTestUtils.loadExtension({
+  await ext1.startup();
+
+  let engine = Services.search.getEngineByName("MozSearch");
+  Services.search.currentEngine = engine;
+  Services.search.moveEngine(engine, 1);
+
+  await ext1.upgrade({
     manifest: {
       "chrome_settings_overrides": {
         "search_provider": {
           "name": "MozSearch",
           "keyword": "MozSearch",
           "search_url": "https://example.com/?q={searchTerms}",
         },
       },
@@ -104,26 +124,18 @@ add_task(async function test_upgrade_def
           "id": "testengine@mozilla.com",
         },
       },
       "version": "0.2",
     },
     useAddonManager: "temporary",
   });
 
-  await ext1.startup();
-
-  let engine = Services.search.getEngineByName("MozSearch");
-  Services.search.currentEngine = engine;
-  Services.search.moveEngine(engine, 1);
+  engine = Services.search.getEngineByName("MozSearch");
+  equal(Services.search.currentEngine, engine, "Default engine should still be MozSearch");
+  equal(Services.search.getEngines().indexOf(engine), 1, "Engine is in position 1");
 
-  await ext2.startup();
-
-  engine = Services.search.getEngineByName("MozSearch");
-  is(Services.search.currentEngine, engine, "Default engine should still be MozSearch");
-  is(Services.search.getEngines().indexOf(engine), 1, "Engine is in position 1");
-
-  await ext2.unload();
   await ext1.unload();
+  await delay();
 
   engine = Services.search.getEngineByName("MozSearch");
   ok(!engine, "Engine should not exist");
 });
--- a/browser/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/browser/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -2,11 +2,12 @@
 [test_ext_browsingData.js]
 [test_ext_browsingData_cookies_cache.js]
 [test_ext_browsingData_downloads.js]
 [test_ext_browsingData_passwords.js]
 [test_ext_browsingData_settings.js]
 [test_ext_chrome_settings_overrides_update.js]
 [test_ext_geckoProfiler_control.js]
 [test_ext_history.js]
+[test_ext_settings_overrides_search.js]
 [test_ext_url_overrides_newtab.js]
 [test_ext_url_overrides_newtab_update.js]
 
--- a/browser/components/syncedtabs/test/browser/head.js
+++ b/browser/components/syncedtabs/test/browser/head.js
@@ -2,12 +2,12 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 
 // Load mocking/stubbing library, sinon
 // docs: http://sinonjs.org/docs/
 /* global sinon */
 Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js");
 
-registerCleanupFunction(function* () {
+registerCleanupFunction(async function() {
   // Cleanup window or the test runner will throw an error
   delete window.sinon;
 });
--- a/browser/config/mozconfigs/linux64/tup
+++ b/browser/config/mozconfigs/linux64/tup
@@ -1,10 +1,9 @@
 MOZ_AUTOMATION_BUILD_SYMBOLS=0
-MOZ_AUTOMATION_INSTALLER=0
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_PACKAGE=0
 MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 MOZ_AUTOMATION_UPLOAD=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -168,16 +168,11 @@ FINDPATH=bin
 endif
 
 package-compare::
 	cd $(DIST); find $(PKGCOMP_FIND_OPTS) '$(FINDPATH)' -type f | sort > bin-list.txt
 	$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $(MOZ_PKG_MANIFEST)) | grep '^$(BINPATH)' | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
 	-diff -u $(DIST)/pack-list.txt $(DIST)/bin-list.txt
 	rm -f $(DIST)/pack-list.txt $(DIST)/bin-list.txt
 
-installer::
-ifdef INSTALLER_DIR
-	$(MAKE) -C $(INSTALLER_DIR)
-endif
-
 ifdef ENABLE_MARIONETTE
 DEFINES += -DENABLE_MARIONETTE=1
 endif
--- a/browser/installer/windows/Makefile.in
+++ b/browser/installer/windows/Makefile.in
@@ -39,34 +39,16 @@ PPL_LOCALE_ARGS = \
   --l10n-dir=$(REAL_LOCALE_MERGEDIR)/browser/installer \
   --l10n-dir=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer \
   --l10n-dir=$(topsrcdir)/browser/locales/en-US/installer \
   $(NULL)
 else
 PPL_LOCALE_ARGS=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer
 endif
 
-OVERRIDE_DEFAULT_GOAL := installer
-installer::
-	$(MAKE) -C .. installer-stage
-	$(MAKE) $(CONFIG_DIR)/setup.exe
-
-# For building the uninstaller during the application build so it can be
-# included for mar file generation.
-uninstaller::
-	$(RM) -r $(CONFIG_DIR)
-	$(MKDIR) $(CONFIG_DIR)
-	$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
-	$(INSTALL) $(addprefix $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/,$(BRANDING_FILES)) $(CONFIG_DIR)
-	$(call py_action,preprocessor,-Fsubstitution $(DEFINES) $(ACDEFINES) \
-	  $(srcdir)/nsis/defines.nsi.in -o $(CONFIG_DIR)/defines.nsi)
-	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
-	  --preprocess-locale $(topsrcdir) \
-	  $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
-
 # For building the maintenanceservice installer
 ifdef MOZ_MAINTENANCE_SERVICE
 maintenanceservice_installer::
 	$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
 	$(call py_action,preprocessor,-Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in -o $(CONFIG_DIR)/defines.nsi)
 	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
 	  --preprocess-locale $(topsrcdir) \
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -29,17 +29,16 @@ endif
 ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
 MOZ_PKG_MAC_DSSTORE=$(ABS_DIST)/branding/dsstore
 MOZ_PKG_MAC_BACKGROUND=$(ABS_DIST)/branding/background.png
 MOZ_PKG_MAC_ICON=$(ABS_DIST)/branding/disk.icns
 MOZ_PKG_MAC_EXTRA=--symlink '/Applications:/ '
 endif
 
 MOZ_SFX_PACKAGE=$(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx
-MOZ_INSTALLER_PATH=$(topsrcdir)/browser/installer/windows
 
 SEARCHPLUGINS_FILENAMES := $(or $(shell $(call py_action,output_searchplugins_list,$(srcdir)/search/list.json $(AB_CD))), $(error Missing search plugins))
 SEARCHPLUGINS_PATH := .deps/generated_$(AB_CD)
 SEARCHPLUGINS_TARGET := libs searchplugins
 SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_FILENAMES)),$(or $(wildcard $(srcdir)/searchplugins/$(plugin)),$(error Missing searchplugin: $(plugin))))
 # Some locale-specific search plugins may have preprocessor directives, but the
 # default en-US ones do not.
 SEARCHPLUGINS_FLAGS := --silence-missing-directive-warnings
@@ -102,51 +101,33 @@ ifndef RELEASE_OR_BETA
 	@$(MAKE) -C ../extensions/presentation/locale chrome AB_CD=$*
 endif
 	@$(MAKE) -C ../../devtools/client/locales chrome AB_CD=$*
 	@$(MAKE) -C ../../devtools/startup/locales chrome AB_CD=$*
 	@$(MAKE) chrome AB_CD=$*
 	@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales chrome AB_CD=$*
 	@$(MAKE) -C ../extensions/webcompat-reporter/locales chrome AB_CD=$*
 
-package-win32-installer: WIN32_INSTALLER_OUT=$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
 package-win32-installer: $(SUBMAKEFILES)
-	@echo 'Packaging $(WIN32_INSTALLER_OUT).'
-	$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
-	$(RM) -r $(STAGEDIST)/uninstall
-	$(NSINSTALL) -D $(STAGEDIST)/uninstall
-	cp ../installer/windows/l10ngen/helper.exe $(STAGEDIST)/uninstall
-	$(RM) $(ABS_DIST)/l10n-stage/setup.exe
-	cp ../installer/windows/l10ngen/setup.exe $(ABS_DIST)/l10n-stage
-	$(NSINSTALL) -D '$(ABS_DIST)/$(PKG_INST_PATH)'
-	(cd $(DIST)/l10n-stage; \
-	  $(MAKE_PACKAGE))
-	mv -f '$(DIST)/l10n-stage/$(PACKAGE)' '$(WIN32_INSTALLER_OUT)'
-	if test -f '$(DIST)/l10n-stage/$(PACKAGE).asc'; then mv -f '$(DIST)/l10n-stage/$(PACKAGE).asc' '$(WIN32_INSTALLER_OUT).asc'; fi
-ifdef MOZ_STUB_INSTALLER
-	$(RM) '$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_STUB_BASENAME).exe'
-	cp ../installer/windows/l10ngen/stub.exe '$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_STUB_BASENAME).exe'
-	chmod 0755 '$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_STUB_BASENAME).exe'
-endif
-
+	$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen ZIP_IN='$(ZIP_OUT)' installer
 
 langpack: langpack-$(AB_CD)
 
 # This is a generic target that will make a langpack, repack ZIP (+tarball)
 # builds, and repack an installer if applicable. It is called from the
 # tinderbox scripts. Alter it with caution.
 
 installers-%: IS_LANGUAGE_REPACK=1
 installers-%:
 	@$(MAKE) clobber-$*
 	@$(MAKE) libs-$*
 	@$(MAKE) package-langpack-$*
 	@$(MAKE) repackage-zip-$*
 ifeq (WINNT,$(OS_ARCH))
-	@$(MAKE) package-win32-installer AB_CD=$* MOZ_PKG_FORMAT=SFX7Z
+	@$(MAKE) package-win32-installer AB_CD=$*
 endif
 	@echo 'repackaging done'
 
 ident:
 	@printf 'fx_revision '
 	@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
 	    '$(STAGEDIST)'/application.ini App SourceStamp
 	@printf 'buildid '
--- a/browser/modules/test/unit/test_SitePermissions.js
+++ b/browser/modules/test/unit/test_SitePermissions.js
@@ -143,17 +143,17 @@ add_task(async function testExactHostMat
     Assert.equal(SitePermissions.get(subUri, permission).state, SitePermissions.PROMPT);
     Assert.equal(SitePermissions.get(uri, permission).state, SitePermissions.ALLOW);
 
     SitePermissions.remove(subUri, permission);
     SitePermissions.remove(uri, permission);
   }
 });
 
-add_task(function* testDefaultPrefs() {
+add_task(async function testDefaultPrefs() {
   let uri = Services.io.newURI("https://example.com");
 
   // Check that without a pref the default return value is UNKNOWN.
   Assert.deepEqual(SitePermissions.get(uri, "camera"), {
     state: SitePermissions.UNKNOWN,
     scope: SitePermissions.SCOPE_PERSISTENT,
   });
 
--- a/build/moz-automation.mk
+++ b/build/moz-automation.mk
@@ -23,61 +23,52 @@ include $(topsrcdir)/toolkit/mozapps/ins
 # Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
 DIST_FILES =
 endif
 
 # Helper variables to convert from MOZ_AUTOMATION_* variables to the
 # corresponding the make target
 tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols
 tier_MOZ_AUTOMATION_L10N_CHECK = l10n-check
-tier_MOZ_AUTOMATION_INSTALLER = installer
 tier_MOZ_AUTOMATION_PACKAGE = package
 tier_MOZ_AUTOMATION_PACKAGE_TESTS = package-tests
 tier_MOZ_AUTOMATION_UPDATE_PACKAGING = update-packaging
 tier_MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES = package-generated-sources
 tier_MOZ_AUTOMATION_UPLOAD_SYMBOLS = uploadsymbols
 tier_MOZ_AUTOMATION_UPLOAD = upload
 
 # Automation build steps. Everything in MOZ_AUTOMATION_TIERS also gets used in
 # TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted
 # here in the order that they will be executed (since mach doesn't know of the
 # dependencies between them).
 moz_automation_symbols = \
   MOZ_AUTOMATION_PACKAGE_TESTS \
   MOZ_AUTOMATION_BUILD_SYMBOLS \
   MOZ_AUTOMATION_UPLOAD_SYMBOLS \
   MOZ_AUTOMATION_PACKAGE \
-  MOZ_AUTOMATION_INSTALLER \
   MOZ_AUTOMATION_UPDATE_PACKAGING \
   MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES \
   MOZ_AUTOMATION_L10N_CHECK \
   MOZ_AUTOMATION_UPLOAD \
   $(NULL)
 MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$($(sym))),$(tier_$(sym))))
 
 # Dependencies between automation build steps
 automation/uploadsymbols: automation/buildsymbols
 
 automation/update-packaging: automation/package
-automation/update-packaging: automation/installer
 
 automation/l10n-check: automation/package
-automation/l10n-check: automation/installer
 
-automation/upload: automation/installer
 automation/upload: automation/package
 automation/upload: automation/package-tests
 automation/upload: automation/buildsymbols
 automation/upload: automation/update-packaging
 automation/upload: automation/package-generated-sources
 
-# The installer and packager all run stage-package, and may conflict
-# with each other.
-automation/installer: automation/package
-
 automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
 	@echo Automation steps completed.
 
 # Note: We have to force -j1 here, at least until bug 1036563 is fixed.
 AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1
 
 # The commands only run if the corresponding MOZ_AUTOMATION_* variable is
 # enabled. This means, for example, if we enable MOZ_AUTOMATION_UPLOAD, then
--- a/build/mozconfig.automation
+++ b/build/mozconfig.automation
@@ -8,14 +8,13 @@
 # automation builds.  For example, if MOZ_AUTOMATION_PACKAGE is set, then the
 # package step will run.  This file contains the default settings, which can be
 # overridden by setting them earlier in the appropriate mozconfig.
 
 mk_add_options "export MOZ_AUTOMATION_BUILD_SYMBOLS=${MOZ_AUTOMATION_BUILD_SYMBOLS-1}"
 mk_add_options "export MOZ_AUTOMATION_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}"
 mk_add_options "export MOZ_AUTOMATION_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}"
 mk_add_options "export MOZ_AUTOMATION_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}"
-mk_add_options "export MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}"
 mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
 mk_add_options "export MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=${MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES-1}"
 mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
 
 export MOZ_AUTOMATION_MOZCONFIG=1
--- a/build/mozconfig.win-common
+++ b/build/mozconfig.win-common
@@ -2,14 +2,10 @@
 # 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/.
 
 if [ "x$IS_NIGHTLY" = "xyes" ]; then
   # Some nightlies (eg: Mulet) don't want these set.
   MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
 fi
 
-# Some builds (eg: Mulet) don't want the installer, so only set this if it
-# hasn't already been set.
-MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-1}
-
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 export MAKECAB=$TOOLTOOL_DIR/makecab.exe
--- a/client.mk
+++ b/client.mk
@@ -150,16 +150,20 @@ configure:: $(configure-preqs)
 	  || ( echo '*** Fix above errors and then restart with\
                "$(MAKE) -f client.mk build"' && exit 1 )
 	@touch $(OBJDIR)/Makefile
 	$(call BUILDSTATUS,TIER_FINISH configure)
 
 ifneq (,$(MAKEFILE))
 $(OBJDIR)/Makefile: $(OBJDIR)/config.status
 
+
+
+
+
 $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
 else
 $(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)
 endif
 	@$(MAKE) -f $(TOPSRCDIR)/client.mk configure
 
 ####################################
 # Build it
--- a/config/check_spidermonkey_style.py
+++ b/config/check_spidermonkey_style.py
@@ -37,19 +37,16 @@
 
 from __future__ import print_function
 
 import difflib
 import os
 import re
 import sys
 
-from mozversioncontrol import get_repository_from_env
-
-
 # We don't bother checking files in these directories, because they're (a) auxiliary or (b)
 # imported code that doesn't follow our coding style.
 ignored_js_src_dirs = [
    'js/src/config/',            # auxiliary stuff
    'js/src/ctypes/libffi/',     # imported code
    'js/src/devtools/',          # auxiliary stuff
    'js/src/editline/',          # imported code
    'js/src/gdb/',               # auxiliary stuff
@@ -253,33 +250,52 @@ def check_style(enable_fixup):
     # - "js/src/vm/String.h"        -> "vm/String.h"
 
     non_js_dirnames = ('mfbt/',
                        'memory/mozalloc/',
                        'mozglue/')  # type: tuple(str)
     non_js_inclnames = set()        # type: set(inclname)
     js_names = dict()               # type: dict(filename, inclname)
 
-    with get_repository_from_env() as repo:
-        # Select the appropriate files.
-        for filename in repo.get_files_in_working_directory():
-            for non_js_dir in non_js_dirnames:
-                if filename.startswith(non_js_dir) and filename.endswith('.h'):
-                    inclname = 'mozilla/' + filename.split('/')[-1]
+    # Process files in js/src.
+    js_src_root = os.path.join('js', 'src')
+    for dirpath, dirnames, filenames in os.walk(js_src_root):
+        if dirpath == js_src_root:
+            # Skip any subdirectories that contain a config.status file
+            # (likely objdirs).
+            builddirs = []
+            for dirname in dirnames:
+                path = os.path.join(dirpath, dirname, 'config.status')
+                if os.path.isfile(path):
+                    builddirs.append(dirname)
+            for dirname in builddirs:
+                dirnames.remove(dirname)
+        for filename in filenames:
+            filepath = os.path.join(dirpath, filename).replace('\\', '/')
+            if not filepath.startswith(tuple(ignored_js_src_dirs)) and \
+               filepath.endswith(('.c', '.cpp', '.h', '.tbl', '.msg')):
+                inclname = filepath[len('js/src/'):]
+                js_names[filepath] = inclname
+
+    # Look for header files in directories in non_js_dirnames.
+    for non_js_dir in non_js_dirnames:
+        for dirpath, dirnames, filenames in os.walk(non_js_dir):
+            for filename in filenames:
+                if filename.endswith('.h'):
+                    inclname = 'mozilla/' + filename
                     non_js_inclnames.add(inclname)
 
-            if filename.startswith('js/public/') and filename.endswith('.h'):
-                inclname = 'js/' + filename[len('js/public/'):]
-                js_names[filename] = inclname
-
-            if filename.startswith('js/src/') and \
-               not filename.startswith(tuple(ignored_js_src_dirs)) and \
-               filename.endswith(('.c', '.cpp', '.h', '.tbl', '.msg')):
-                inclname = filename[len('js/src/'):]
-                js_names[filename] = inclname
+    # Look for header files in js/public.
+    js_public_root = os.path.join('js', 'public')
+    for dirpath, dirnames, filenames in os.walk(js_public_root):
+        for filename in filenames:
+            if filename.endswith('.h'):
+                filepath = os.path.join(dirpath, filename).replace('\\', '/')
+                inclname = 'js/' + filepath[len('js/public/'):]
+                js_names[filepath] = inclname
 
     all_inclnames = non_js_inclnames | set(js_names.values())
 
     edges = dict()      # type: dict(inclname, set(inclname))
 
     # We don't care what's inside the MFBT and MOZALLOC files, but because they
     # are #included from JS files we have to add them to the inclusion graph.
     for inclname in non_js_inclnames:
@@ -288,25 +304,22 @@ def check_style(enable_fixup):
     # Process all the JS files.
     for filename in js_names.keys():
         inclname = js_names[filename]
         file_kind = FileKind.get(filename)
         if file_kind == FileKind.C or file_kind == FileKind.CPP or \
            file_kind == FileKind.H or file_kind == FileKind.INL_H:
             included_h_inclnames = set()    # type: set(inclname)
 
-            # This script is run in js/src/, so prepend '../../' to get to the root of the Mozilla
-            # source tree.
-            filepath = os.path.join(repo.path, filename)
-            with open(filepath) as f:
+            with open(filename) as f:
                 code = read_file(f)
 
             if enable_fixup:
                 code = code.sorted(inclname)
-                with open(filepath, 'w') as f:
+                with open(filename, 'w') as f:
                     f.write(code.to_source())
 
             check_file(filename, inclname, file_kind, code, all_inclnames, included_h_inclnames)
 
         edges[inclname] = included_h_inclnames
 
     find_cycles(all_inclnames, edges)
 
--- a/config/config.mk
+++ b/config/config.mk
@@ -408,18 +408,16 @@ endif # ! WINNT
 
 # Make sure any compiled classes work with at least JVM 1.4
 JAVAC_FLAGS += -source 1.4
 
 ifdef MOZ_DEBUG
 JAVAC_FLAGS += -g
 endif
 
-CREATE_PRECOMPLETE_CMD = $(PYTHON) $(abspath $(MOZILLA_DIR)/config/createprecomplete.py)
-
 # MDDEPDIR is the subdirectory where dependency files are stored
 MDDEPDIR := .deps
 
 # $(call CHECK_SYMBOLS,lib,PREFIX,dep_name,test)
 # Checks that the given `lib` doesn't contain dependency on symbols with a
 # version starting with `PREFIX`_ and matching the `test`. `dep_name` is only
 # used for the error message.
 # `test` is an awk expression using the information in the variable `v` which
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -25,25 +25,27 @@ include $(topsrcdir)/config/rules.mk
 
 # For dependency files.
 idl_deps_dir := .deps
 
 dist_idl_dir := $(DIST)/idl
 dist_include_dir := $(DIST)/include
 dist_xpcrs_dir := $(DIST)/xpcrs
 process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
-generated_file := $(topobjdir)/xpcom/typelib/xpt/XPTInfo.cpp
-code_gen_py := $(topsrcdir)/xpcom/typelib/xpt/tools/xpt.py
+generated_file := $(topobjdir)/xpcom/reflect/xptinfo/xptdata.cpp
+code_gen_py := $(topsrcdir)/xpcom/reflect/xptinfo/xptcodegen.py
+code_gen_deps := $(topsrcdir)/xpcom/reflect/xptinfo/perfecthash.py
 
 # TODO we should use py_action, but that would require extra directories to be
 # in the virtualenv.
 %.xpt:
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) $(PLY_INCLUDE) -I$(topsrcdir)/xpcom/idl-parser -I$(DEPTH)/xpcom/idl-parser/xpidl \
 		$(process_py) --cache-dir $(DEPTH)/xpcom/idl-parser/xpidl --depsdir $(idl_deps_dir) \
+		--bindings-conf $(topsrcdir)/dom/bindings/Bindings.conf \
 		$(dist_idl_dir) $(dist_include_dir) $(dist_xpcrs_dir) $(@D) \
 		$(basename $(notdir $@)) $($(basename $(notdir $@))_deps)
 # When some IDL is added or removed, if the actual IDL file was already, or
 # still is, in the tree, simple dependencies can't detect that the XPT needs
 # to be rebuilt.
 # Add the current value of $($(xpidl_module)_deps) in the depend file, such that
 # we can later check if the value has changed since last build, which will
 # indicate whether IDLs were added or removed.
@@ -60,21 +62,19 @@ depends_files := $(foreach root,$(xpidl_
 GARBAGE += $(xpt_files) $(depends_files) $(generated_file)
 
 ifdef COMPILE_ENVIRONMENT
 xpidl:: $(generated_file)
 endif
 
 $(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(dist_xpcrs_dir))
 
-$(generated_file): $(xpt_files) $(code_gen_py)
+$(generated_file): $(xpt_files) $(code_gen_py) $(code_gen_deps)
 	$(REPORT_BUILD)
-	$(PYTHON_PATH) $(PLY_INCLUDE) \
-		$(code_gen_py) linkgen \
-		$(generated_file) $(xpt_files)
+	$(PYTHON_PATH) $(PLY_INCLUDE) $(code_gen_py) $(generated_file) $(xpt_files)
 
 -include $(depends_files)
 
 define xpt_deps
 $(1): $(call mkdir_deps,$(dir $(1)))
 $(1): $(addsuffix .idl,$(addprefix $(dist_idl_dir)/,$($(basename $(notdir $(1)))_deps)))
 ifneq ($($(basename $(notdir $(1)))_deps),$($(basename $(notdir $(1)))_deps_built))
 $(1): FORCE
--- a/devtools/client/aboutdebugging/test/test_addon_path.js
+++ b/devtools/client/aboutdebugging/test/test_addon_path.js
@@ -1,16 +1,16 @@
 /* global equal */
 
 "use strict";
 
 const { parseFileUri } =
   require("devtools/client/aboutdebugging/modules/addon");
 
-add_task(function* testParseFileUri() {
+add_task(async function testParseFileUri() {
   equal(
     parseFileUri("file:///home/me/my-extension/"),
     "/home/me/my-extension/",
     "UNIX paths are supported");
 
   equal(
     parseFileUri("file:///C:/Documents/my-extension/"),
     "C:/Documents/my-extension/",
--- a/devtools/client/commandline/test/browser_cmd_csscoverage_oneshot.js
+++ b/devtools/client/commandline/test/browser_cmd_csscoverage_oneshot.js
@@ -9,92 +9,92 @@ const PAGE_1 = TEST_BASE_HTTPS + "browse
 const PAGE_2 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page2.html";
 const PAGE_3 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page3.html";
 
 const SHEET_A = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetA.css";
 const SHEET_B = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetB.css";
 const SHEET_C = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetC.css";
 const SHEET_D = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetD.css";
 
-add_task(function* () {
-  let options = yield helpers.openTab(PAGE_3);
-  yield helpers.openToolbar(options);
+add_task(async function() {
+  let options = await helpers.openTab(PAGE_3);
+  await helpers.openToolbar(options);
 
-  let usage = yield csscoverage.getUsage(options.target);
+  let usage = await csscoverage.getUsage(options.target);
 
-  yield navigate(usage, options);
-  yield checkPages(usage);
-  yield checkEditorReport(usage);
+  await navigate(usage, options);
+  await checkPages(usage);
+  await checkEditorReport(usage);
   // usage.createPageReport is not supported for usage.oneshot data as of
   // bug 1035300 because the page report assumed we have preload data which
   // oneshot can't gather. The ideal solution is to have a special no-preload
   // mode for the page report, but since oneshot isn't needed for the UI to
   // function, we're currently not supporting page report for oneshot data
   // yield checkPageReport(usage);
 
-  yield helpers.closeToolbar(options);
-  yield helpers.closeTab(options);
+  await helpers.closeToolbar(options);
+  await helpers.closeTab(options);
 });
 
 /**
  * Just check current page
  */
-function* navigate(usage, options) {
+async function navigate(usage, options) {
   ok(!usage.isRunning(), "csscoverage is not running");
 
-  yield usage.oneshot();
+  await usage.oneshot();
 
   ok(!usage.isRunning(), "csscoverage is still not running");
 }
 
 /**
  * Check the expected pages have been visited
  */
-function* checkPages(usage) {
+async function checkPages(usage) {
   let expectedVisited = [ PAGE_3 ];
-  let actualVisited = yield usage._testOnlyVisitedPages();
+  let actualVisited = await usage._testOnlyVisitedPages();
   isEqualJson(actualVisited, expectedVisited, "Visited");
 }
 
 /**
  * Check that createEditorReport returns the expected JSON
  */
-function* checkEditorReport(usage) {
+async function checkEditorReport(usage) {
   // Page1
   let expectedPage1 = { reports: [] };
-  let actualPage1 = yield usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
+  let actualPage1 = await usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
   isEqualJson(actualPage1, expectedPage1, "Page1");
 
   // Page2
   let expectedPage2 = { reports: [] };
-  let actualPage2 = yield usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
+  let actualPage2 = await usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
   isEqualJson(actualPage2, expectedPage2, "Page2");
 
   // Page3a
   let expectedPage3a = {
     reports: [
       {
         selectorText: ".page3-test2",
         start: { line: 9, column: 5 },
       }
     ]
   };
-  let actualPage3a = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
+  let actualPage3a = await usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
   isEqualJson(actualPage3a, expectedPage3a, "Page3a");
 
   // Page3b
   let expectedPage3b = {
     reports: [
       {
         selectorText: ".page3-test3",
         start: { line: 3, column: 5 },
       }
     ]
   };
-  let actualPage3b = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
+  let actualPage3b = await usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
   isEqualJson(actualPage3b, expectedPage3b, "Page3b");
 
   // SheetA
   let expectedSheetA = {
     reports: [
       {
         selectorText: ".sheetA-test2",
         start: { line: 8, column: 1 },
@@ -104,17 +104,17 @@ function* checkEditorReport(usage) {
         start: { line: 12, column: 1 },
       },
       {
         selectorText: ".sheetA-test4",
         start: { line: 16, column: 1 },
       }
     ]
   };
-  let actualSheetA = yield usage.createEditorReport(SHEET_A);
+  let actualSheetA = await usage.createEditorReport(SHEET_A);
   isEqualJson(actualSheetA, expectedSheetA, "SheetA");
 
   // SheetB
   let expectedSheetB = {
     reports: [
       {
         selectorText: ".sheetB-test2",
         start: { line: 6, column: 1 },
@@ -124,17 +124,17 @@ function* checkEditorReport(usage) {
         start: { line: 10, column: 1 },
       },
       {
         selectorText: ".sheetB-test4",
         start: { line: 14, column: 1 },
       }
     ]
   };
-  let actualSheetB = yield usage.createEditorReport(SHEET_B);
+  let actualSheetB = await usage.createEditorReport(SHEET_B);
   isEqualJson(actualSheetB, expectedSheetB, "SheetB");
 
   // SheetC
   let expectedSheetC = {
     reports: [
       {
         selectorText: ".sheetC-test2",
         start: { line: 6, column: 1 },
@@ -144,17 +144,17 @@ function* checkEditorReport(usage) {
         start: { line: 10, column: 1 },
       },
       {
         selectorText: ".sheetC-test4",
         start: { line: 14, column: 1 },
       }
     ]
   };
-  let actualSheetC = yield usage.createEditorReport(SHEET_C);
+  let actualSheetC = await usage.createEditorReport(SHEET_C);
   isEqualJson(actualSheetC, expectedSheetC, "SheetC");
 
   // SheetD
   let expectedSheetD = {
     reports: [
       {
         selectorText: ".sheetD-test2",
         start: { line: 6, column: 1 },
@@ -164,25 +164,25 @@ function* checkEditorReport(usage) {
         start: { line: 10, column: 1 },
       },
       {
         selectorText: ".sheetD-test4",
         start: { line: 14, column: 1 },
       }
     ]
   };
-  let actualSheetD = yield usage.createEditorReport(SHEET_D);
+  let actualSheetD = await usage.createEditorReport(SHEET_D);
   isEqualJson(actualSheetD, expectedSheetD, "SheetD");
 }
 
 /**
  * Check that checkPageReport returns the expected JSON
  */
-function* checkPageReport(usage) {
-  let actualReport = yield usage.createPageReport();
+async function checkPageReport(usage) {
+  let actualReport = await usage.createPageReport();
 
   // Quick check on trivial things. See doc comment for checkRuleProperties
   actualReport.preload.forEach(page => page.rules.forEach(checkRuleProperties));
   actualReport.unused.forEach(page => page.rules.forEach(checkRuleProperties));
 
   // Check the summary
   let expectedSummary = { "used": 23, "unused": 9, "preload": 0 };
   isEqualJson(actualReport.summary, expectedSummary, "summary");
--- a/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js
+++ b/devtools/client/commandline/test/browser_cmd_csscoverage_startstop.js
@@ -10,177 +10,177 @@ const PAGE_1 = TEST_BASE_HTTPS + "browse
 const PAGE_2 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page2.html";
 const PAGE_3 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page3.html";
 
 const SHEET_A = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetA.css";
 const SHEET_B = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetB.css";
 const SHEET_C = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetC.css";
 const SHEET_D = TEST_BASE_HTTPS + "browser_cmd_csscoverage_sheetD.css";
 
-add_task(function* () {
-  let options = yield helpers.openTab("about:blank");
-  yield helpers.openToolbar(options);
+add_task(async function() {
+  let options = await helpers.openTab("about:blank");
+  await helpers.openToolbar(options);
 
-  let usage = yield csscoverage.getUsage(options.target);
+  let usage = await csscoverage.getUsage(options.target);
 
-  yield navigate(usage, options);
-  yield checkPages(usage);
-  yield checkEditorReport(usage);
-  yield checkPageReport(usage);
+  await navigate(usage, options);
+  await checkPages(usage);
+  await checkEditorReport(usage);
+  await checkPageReport(usage);
 
-  yield helpers.closeToolbar(options);
-  yield helpers.closeTab(options);
+  await helpers.closeToolbar(options);
+  await helpers.closeTab(options);
 });
 
 /**
  * Visit all the pages in the test
  */
-function* navigate(usage, options) {
-  yield usage.start(options.chromeWindow, options.target);
+async function navigate(usage, options) {
+  await usage.start(options.chromeWindow, options.target);
 
   ok(usage.isRunning(), "csscoverage is running");
 
   // Load page 1.
   options.browser.loadURI(PAGE_1);
   // And wait until page 1 and page 2 (an iframe inside page 1) are both loaded.
-  yield Promise.all([
+  await Promise.all([
     BrowserTestUtils.browserLoaded(options.browser, false, PAGE_1),
     BrowserTestUtils.browserLoaded(options.browser, true, PAGE_2)
   ]);
   is(options.browser.currentURI.spec, PAGE_1, "page 1 loaded");
 
   // page 2 has JS that navigates to page 3 after a timeout.
-  yield BrowserTestUtils.browserLoaded(options.browser, false, PAGE_3);
+  await BrowserTestUtils.browserLoaded(options.browser, false, PAGE_3);
   is(options.browser.currentURI.spec, PAGE_3, "page 3 loaded");
 
   let toolboxReady = gDevTools.once("toolbox-ready");
 
-  yield usage.stop();
+  await usage.stop();
 
   ok(!usage.isRunning(), "csscoverage not is running");
 
-  yield toolboxReady;
+  await toolboxReady;
 }
 
 /**
  * Check the expected pages have been visited
  */
-function* checkPages(usage) {
+async function checkPages(usage) {
   // 'load' event order. '' is for the initial location
   let expectedVisited = [ "", PAGE_2, PAGE_1, PAGE_3 ];
-  let actualVisited = yield usage._testOnlyVisitedPages();
+  let actualVisited = await usage._testOnlyVisitedPages();
   isEqualJson(actualVisited, expectedVisited, "Visited");
 }
 
 /**
  * Check that createEditorReport returns the expected JSON
  */
-function* checkEditorReport(usage) {
+async function checkEditorReport(usage) {
   // Page1
   let expectedPage1 = {
     reports: [
       {
         selectorText: ".page1-test2",
         start: { line: 8, column: 5 },
       }
     ]
   };
-  let actualPage1 = yield usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
+  let actualPage1 = await usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
   isEqualJson(actualPage1, expectedPage1, "Page1");
 
   // Page2
   let expectedPage2 = {
     reports: [
       {
         selectorText: ".page2-test2",
         start: { line: 9, column: 5 },
       },
     ]
   };
-  let actualPage2 = yield usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
+  let actualPage2 = await usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
   isEqualJson(actualPage2, expectedPage2, "Page2");
 
   // Page3a
   let expectedPage3a = {
     reports: [
       {
         selectorText: ".page3-test2",
         start: { line: 9, column: 5 },
       }
     ]
   };
-  let actualPage3a = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
+  let actualPage3a = await usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
   isEqualJson(actualPage3a, expectedPage3a, "Page3a");
 
   // Page3b
   let expectedPage3b = {
     reports: [
       {
         selectorText: ".page3-test3",
         start: { line: 3, column: 5 },
       }
     ]
   };
-  let actualPage3b = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
+  let actualPage3b = await usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
   isEqualJson(actualPage3b, expectedPage3b, "Page3b");
 
   // SheetA
   let expectedSheetA = {
     reports: [
       {
         selectorText: ".sheetA-test2",
         start: { line: 8, column: 1 },
       }
     ]
   };
-  let actualSheetA = yield usage.createEditorReport(SHEET_A);
+  let actualSheetA = await usage.createEditorReport(SHEET_A);
   isEqualJson(actualSheetA, expectedSheetA, "SheetA");
 
   // SheetB
   let expectedSheetB = {
     reports: [
       {
         selectorText: ".sheetB-test2",
         start: { line: 6, column: 1 },
       }
     ]
   };
-  let actualSheetB = yield usage.createEditorReport(SHEET_B);
+  let actualSheetB = await usage.createEditorReport(SHEET_B);
   isEqualJson(actualSheetB, expectedSheetB, "SheetB");
 
   // SheetC
   let expectedSheetC = {
     reports: [
       {
         selectorText: ".sheetC-test2",
         start: { line: 6, column: 1 },
       }
     ]
   };
-  let actualSheetC = yield usage.createEditorReport(SHEET_C);
+  let actualSheetC = await usage.createEditorReport(SHEET_C);
   isEqualJson(actualSheetC, expectedSheetC, "SheetC");
 
   // SheetD
   let expectedSheetD = {
     reports: [
       {
         selectorText: ".sheetD-test2",
         start: { line: 6, column: 1 },
       }
     ]
   };
-  let actualSheetD = yield usage.createEditorReport(SHEET_D);
+  let actualSheetD = await usage.createEditorReport(SHEET_D);
   isEqualJson(actualSheetD, expectedSheetD, "SheetD");
 }
 
 /**
  * Check that checkPageReport returns the expected JSON
  */
-function* checkPageReport(usage) {
-  let actualReport = yield usage.createPageReport();
+async function checkPageReport(usage) {
+  let actualReport = await usage.createPageReport();
 
   // Quick check on trivial things. See doc comment for checkRuleProperties
   actualReport.preload.forEach(page => page.rules.forEach(checkRuleProperties));
   actualReport.unused.forEach(page => page.rules.forEach(checkRuleProperties));
 
   // Check the summary
   let expectedSummary = { "used": 92, "unused": 22, "preload": 28 };
   isEqualJson(actualReport.summary, expectedSummary, "summary");
--- a/devtools/client/commandline/test/browser_cmd_csscoverage_util.js
+++ b/devtools/client/commandline/test/browser_cmd_csscoverage_util.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that the addon commands works as they should
 
 const csscoverage = require("devtools/server/actors/csscoverage");
 
-add_task(function* () {
+add_task(async function() {
   testDeconstructRuleId();
 });
 
 function testDeconstructRuleId() {
   // This is the easy case
   let rule = csscoverage.deconstructRuleId("http://thing/blah|10|20");
   is(rule.url, "http://thing/blah", "1 url");
   is(rule.line, 10, "1 line");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_on-pause-raise.js
@@ -4,51 +4,51 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that the toolbox is raised when the debugger gets paused.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
-add_task(function *() {
+add_task(async function() {
   let options = {
     source: TAB_URL,
     line: 1
   };
-  let [tab,, panel] = yield initDebugger(TAB_URL, options);
+  let [tab,, panel] = await initDebugger(TAB_URL, options);
   let panelWin = panel.panelWin;
   let toolbox = panel._toolbox;
   let toolboxTab = toolbox.doc.getElementById("toolbox-tab-jsdebugger");
 
-  let newTab = yield addTab(TAB_URL);
+  let newTab = await addTab(TAB_URL);
   isnot(newTab, tab,
     "The newly added tab is different from the debugger's tab.");
   is(gBrowser.selectedTab, newTab,
     "Debugger's tab is not the selected tab.");
 
   info("Run tests against bottom host.");
-  yield testPause();
-  yield testResume();
+  await testPause();
+  await testResume();
 
   // testResume selected the console, select back the debugger.
-  yield toolbox.selectTool("jsdebugger");
+  await toolbox.selectTool("jsdebugger");
 
   info("Switching to a toolbox window host.");
-  yield toolbox.switchHost(Toolbox.HostType.WINDOW);
+  await toolbox.switchHost(Toolbox.HostType.WINDOW);
 
   info("Run tests against window host.");
-  yield testPause();
-  yield testResume();
+  await testPause();
+  await testResume();
 
   info("Cleanup after the test.");
-  yield toolbox.switchHost(Toolbox.HostType.BOTTOM);
-  yield closeDebuggerAndFinish(panel);
+  await toolbox.switchHost(Toolbox.HostType.BOTTOM);
+  await closeDebuggerAndFinish(panel);
 
-  function* testPause() {
+  async function testPause() {
     is(panelWin.gThreadClient.paused, false,
       "Should be running after starting the test.");
 
     let onFocus, onTabSelect;
     if (toolbox.hostType == Toolbox.HostType.WINDOW) {
       onFocus = new Promise(done => {
         toolbox.win.parent.addEventListener("focus", function () {
           done();
@@ -63,47 +63,47 @@ add_task(function *() {
       });
     }
 
     let onPaused = waitForPause(panelWin.gThreadClient);
 
     // Evaluate a script to fully pause the debugger
     evalInTab(tab, "debugger;");
 
-    yield onPaused;
-    yield onFocus;
-    yield onTabSelect;
+    await onPaused;
+    await onFocus;
+    await onTabSelect;
 
     if (toolbox.hostType != Toolbox.HostType.WINDOW) {
       is(gBrowser.selectedTab, tab,
         "Debugger's tab got selected.");
     }
 
-    yield toolbox.selectTool("webconsole");
+    await toolbox.selectTool("webconsole");
     ok(toolboxTab.classList.contains("highlighted"),
       "The highlighted class is present");
     ok(!toolboxTab.classList.contains("selected"),
       "The tab is not selected");
-    yield toolbox.selectTool("jsdebugger");
+    await toolbox.selectTool("jsdebugger");
     ok(toolboxTab.classList.contains("highlighted"),
       "The highlighted class is present");
     ok(toolboxTab.classList.contains("selected"),
       "...and the tab is selected, so the glow will not be present.");
   }
 
-  function* testResume() {
+  async function testResume() {
     let onPaused = waitForEvent(panelWin.gThreadClient, "resumed");
 
     EventUtils.sendMouseEvent({ type: "mousedown" },
       panelWin.document.getElementById("resume"),
       panelWin);
 
-    yield onPaused;
+    await onPaused;
 
-    yield toolbox.selectTool("webconsole");
+    await toolbox.selectTool("webconsole");
     ok(!toolboxTab.classList.contains("highlighted"),
       "The highlighted class is not present now after the resume");
     ok(!toolboxTab.classList.contains("selected"),
       "The tab is not selected");
   }
 });
 
 registerCleanupFunction(function () {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_post-page.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_post-page.js
@@ -8,49 +8,49 @@
  */
 
 const TAB_URL = EXAMPLE_URL + "sjs_post-page.sjs";
 
 const FORM = "<form method=\"POST\"><input type=\"submit\"></form>";
 const GET_CONTENT = "<script>\"GET\";</script>" + FORM;
 const POST_CONTENT = "<script>\"POST\";</script>" + FORM;
 
-add_task(function* () {
+add_task(async function() {
   // Disable rcwn to make cache behavior deterministic.
-  yield pushPref("network.http.rcwn.enabled", false);
+  await pushPref("network.http.rcwn.enabled", false);
 
   let options = {
     source: TAB_URL,
     line: 1
   };
-  let [tab,, panel] = yield initDebugger(TAB_URL, options);
+  let [tab,, panel] = await initDebugger(TAB_URL, options);
   let win = panel.panelWin;
   let editor = win.DebuggerView.editor;
   let queries = win.require("./content/queries");
   let getState = win.DebuggerController.getState;
 
   let source = queries.getSelectedSource(getState());
 
   is(queries.getSourceCount(getState()), 1,
     "There should be one source displayed in the view.");
   is(source.url, TAB_URL,
     "The correct source is currently selected in the view.");
   is(editor.getText(), GET_CONTENT,
     "The currently shown source contains bacon. Mmm, delicious!");
 
   // Submit the form and wait for debugger update
   let onSourceUpdated = waitForSourceShown(panel, TAB_URL);
-  yield ContentTask.spawn(tab.linkedBrowser, null, function () {
+  await ContentTask.spawn(tab.linkedBrowser, null, function () {
     content.document.querySelector("input[type=\"submit\"]").click();
   });
-  yield onSourceUpdated;
+  await onSourceUpdated;
 
   // Verify that the source updates to the POST page content
   source = queries.getSelectedSource(getState());
   is(queries.getSourceCount(getState()), 1,
     "There should be one source displayed in the view.");
   is(source.url, TAB_URL,
     "The correct source is currently selected in the view.");
   is(editor.getText(), POST_CONTENT,
     "The currently shown source contains bacon. Mmm, delicious!");
 
-  yield closeDebuggerAndFinish(panel);
+  await closeDebuggerAndFinish(panel);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_sources-iframe-reload.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_sources-iframe-reload.js
@@ -9,27 +9,27 @@
 
 "use strict";
 
 const IFRAME_URL = "data:text/html;charset=utf-8," +
   "<script>function fn() { console.log('hello'); }</script>" +
   "<div onclick='fn()'>hello</div>";
 const TAB_URL = `data:text/html;charset=utf-8,<iframe src="${IFRAME_URL}"/>`;
 
-add_task(function* () {
-  let [,, panel] = yield initDebugger();
+add_task(async function() {
+  let [,, panel] = await initDebugger();
   let dbg = panel.panelWin;
   let newSource;
 
   newSource = waitForDebuggerEvents(panel, dbg.EVENTS.NEW_SOURCE);
   reload(panel, TAB_URL);
-  yield newSource;
+  await newSource;
   ok(true, "Source event fired on initial load");
 
   for (let i = 0; i < 5; i++) {
     newSource = waitForDebuggerEvents(panel, dbg.EVENTS.NEW_SOURCE);
     reload(panel);
-    yield newSource;
+    await newSource;
     ok(true, `Source event fired after ${i + 1} reloads`);
   }
 
-  yield closeDebuggerAndFinish(panel);
+  await closeDebuggerAndFinish(panel);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-01.js
@@ -1,21 +1,21 @@
 // Check to make sure that a worker can be attached to a toolbox
 // and that the console works.
 
 var TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 var WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
-add_task(function* testNormalExecution() {
+add_task(async function testNormalExecution() {
   let {client, tab, tabClient, workerClient, toolbox, gDebugger} =
-    yield initWorkerDebugger(TAB_URL, WORKER_URL);
+    await initWorkerDebugger(TAB_URL, WORKER_URL);
 
-  let jsterm = yield getSplitConsole(toolbox);
-  let executed = yield jsterm.execute("this.location.toString()");
+  let jsterm = await getSplitConsole(toolbox);
+  let executed = await jsterm.execute("this.location.toString()");
   ok(executed.textContent.includes(WORKER_URL),
       "Evaluating the global's location works");
 
   terminateWorkerInTab(tab, WORKER_URL);
-  yield waitForWorkerClose(workerClient);
-  yield gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
-  yield close(client);
-  yield removeTab(tab);
+  await waitForWorkerClose(workerClient);
+  await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
+  await close(client);
+  await removeTab(tab);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-02.js
@@ -1,58 +1,58 @@
 // Check to make sure that a worker can be attached to a toolbox
 // and that the console works.
 
 var TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 var WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
-add_task(function* testWhilePaused() {
+add_task(async function testWhilePaused() {
   let {client, tab, tabClient, workerClient, toolbox, gDebugger} =
-    yield initWorkerDebugger(TAB_URL, WORKER_URL);
+    await initWorkerDebugger(TAB_URL, WORKER_URL);
 
   let gTarget = gDebugger.gTarget;
   let gResumeButton = gDebugger.document.getElementById("resume");
   let gResumeKey = gDebugger.document.getElementById("resumeKey");
 
   // Execute some basic math to make sure evaluations are working.
-  let jsterm = yield getSplitConsole(toolbox);
-  let executed = yield jsterm.execute("10000+1");
+  let jsterm = await getSplitConsole(toolbox);
+  let executed = await jsterm.execute("10000+1");
   ok(executed.textContent.includes("10001"), "Text for message appeared correct");
 
   // Pause the worker by waiting for next execution and then sending a message to
   // it from the main thread.
   let oncePaused = gTarget.once("thread-paused");
   EventUtils.sendMouseEvent({ type: "mousedown" }, gResumeButton, gDebugger);
   once(gDebugger.gClient, "willInterrupt").then(() => {
     info("Posting message to worker, then waiting for a pause");
     postMessageToWorkerInTab(tab, WORKER_URL, "ping");
   });
-  yield oncePaused;
+  await oncePaused;
 
   let command1 = jsterm.execute("10000+2");
   let command2 = jsterm.execute("10000+3");
   let command3 = jsterm.execute("foobar"); // throw an error
 
   info("Trying to get the result of command1");
-  executed = yield command1;
+  executed = await command1;
   ok(executed.textContent.includes("10002"),
       "command1 executed successfully");
 
   info("Trying to get the result of command2");
-  executed = yield command2;
+  executed = await command2;
   ok(executed.textContent.includes("10003"),
       "command2 executed successfully");
 
   info("Trying to get the result of command3");
-  executed = yield command3;
+  executed = await command3;
   ok(executed.textContent.includes("ReferenceError: foobar is not defined"),
      "command3 executed successfully");
 
   let onceResumed = gTarget.once("thread-resumed");
   EventUtils.sendMouseEvent({ type: "mousedown" }, gResumeButton, gDebugger);
-  yield onceResumed;
+  await onceResumed;
 
   terminateWorkerInTab(tab, WORKER_URL);
-  yield waitForWorkerClose(workerClient);
-  yield gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
-  yield close(client);
-  yield removeTab(tab);
+  await waitForWorkerClose(workerClient);
+  await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
+  await close(client);
+  await removeTab(tab);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-03.js
@@ -1,46 +1,46 @@
 // Check to make sure that a worker can be attached to a toolbox
 // and that the console works.
 
 var TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 var WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
 // Test to see if creating the pause from the console works.
-add_task(function* testPausedByConsole() {
+add_task(async function testPausedByConsole() {
   let {client, tab, tabClient, workerClient, toolbox, gDebugger} =
-    yield initWorkerDebugger(TAB_URL, WORKER_URL);
+    await initWorkerDebugger(TAB_URL, WORKER_URL);
 
   let gTarget = gDebugger.gTarget;
   let gResumeButton = gDebugger.document.getElementById("resume");
   let gResumeKey = gDebugger.document.getElementById("resumeKey");
 
-  let jsterm = yield getSplitConsole(toolbox);
-  let executed = yield jsterm.execute("10000+1");
+  let jsterm = await getSplitConsole(toolbox);
+  let executed = await jsterm.execute("10000+1");
   ok(executed.textContent.includes("10001"),
       "Text for message appeared correct");
 
   let oncePaused = gTarget.once("thread-paused");
   EventUtils.sendMouseEvent({ type: "mousedown" }, gResumeButton, gDebugger);
   let pausedExecution = jsterm.execute("10000+2");
 
   info("Executed a command with 'break on next' active, waiting for pause");
-  yield oncePaused;
+  await oncePaused;
 
-  executed = yield jsterm.execute("10000+3");
+  executed = await jsterm.execute("10000+3");
   ok(executed.textContent.includes("10003"),
       "Text for message appeared correct");
 
   info("Waiting for a resume");
   let onceResumed = gTarget.once("thread-resumed");
   EventUtils.sendMouseEvent({ type: "mousedown" }, gResumeButton, gDebugger);
-  yield onceResumed;
+  await onceResumed;
 
-  executed = yield pausedExecution;
+  executed = await pausedExecution;
   ok(executed.textContent.includes("10002"),
       "Text for message appeared correct");
 
   terminateWorkerInTab(tab, WORKER_URL);
-  yield waitForWorkerClose(workerClient);
-  yield gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
-  yield close(client);
-  yield removeTab(tab);
+  await waitForWorkerClose(workerClient);
+  await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
+  await close(client);
+  await removeTab(tab);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-console-04.js
@@ -5,29 +5,29 @@
 // There are shutdown issues for which multiple rejections are left uncaught.
 // See bug 1018184 for resolving these issues.
 const { PromiseTestUtils } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
 PromiseTestUtils.whitelistRejectionsGlobally(/connection just closed/);
 
 const TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 const WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
-add_task(function* testPausedByConsole() {
+add_task(async function testPausedByConsole() {
   let {client, tab, workerClient, toolbox} =
-    yield initWorkerDebugger(TAB_URL, WORKER_URL);
+    await initWorkerDebugger(TAB_URL, WORKER_URL);
 
   info("Check Date objects can be used in the console");
-  let jsterm = yield getSplitConsole(toolbox);
-  let executed = yield jsterm.execute("new Date(0)");
+  let jsterm = await getSplitConsole(toolbox);
+  let executed = await jsterm.execute("new Date(0)");
   ok(executed.textContent.includes("1970-01-01T00:00:00.000Z"),
       "Text for message appeared correct");
 
   info("Check RegExp objects can be used in the console");
-  executed = yield jsterm.execute("new RegExp('.*')");
+  executed = await jsterm.execute("new RegExp('.*')");
   ok(executed.textContent.includes("/.*/"),
       "Text for message appeared correct");
 
   terminateWorkerInTab(tab, WORKER_URL);
-  yield waitForWorkerClose(workerClient);
-  yield gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
-  yield close(client);
-  yield removeTab(tab);
+  await waitForWorkerClose(workerClient);
+  await gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
+  await close(client);
+  await removeTab(tab);
 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_worker-window.js
@@ -6,43 +6,43 @@
 // The following "connectionClosed" rejection should not be left uncaught. This
 // test has been whitelisted until the issue is fixed.
 ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
 PromiseTestUtils.expectUncaughtRejection(/[object Object]/);
 
 var TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
 var WORKER_URL = "code_WorkerActor.attachThread-worker.js";
 
-add_task(function* () {
-  yield pushPrefs(["devtools.scratchpad.enabled", true]);
+add_task(async function() {
+  await pushPrefs(["devtools.scratchpad.enabled", true]);
 
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
 
   let client = new DebuggerClient(DebuggerServer.connectPipe());
-  yield connect(client);
+  await connect(client);
 
-  let tab = yield addTab(TAB_URL);
-  let { tabs } = yield listTabs(client);
-  let [, tabClient] = yield attachTab(client, findTab(tabs, TAB_URL));
+  let tab = await addTab(TAB_URL);
+  let { tabs } = await listTabs(client);
+  let [, tabClient] = await attachTab(client, findTab(tabs, TAB_URL));
 
-  yield listWorkers(tabClient);
-  yield createWorkerInTab(tab, WORKER_URL);
+  await listWorkers(tabClient);
+  await createWorkerInTab(tab, WORKER_URL);
 
-  let { workers } = yield listWorkers(tabClient);
-  let [, workerClient] = yield attachWorker(tabClient,
+  let { workers } = await listWorkers(tabClient);
+  let [, workerClient] = await attachWorker(tabClient,
                                              findWorker(workers, WORKER_URL));
 
-  let toolbox = yield gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
+  let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
                                             "jsdebugger",
                                             Toolbox.HostType.WINDOW);
 
   is(toolbox.hostType, "window", "correct host");
 
-  yield new Promise(done => {
+  await new Promise(done => {
     toolbox.win.parent.addEventListener("message", function onmessage(event) {
       if (event.data.name == "set-host-title") {
         toolbox.win.parent.removeEventListener("message", onmessage);
         done();
       }
     });
   });
   ok(toolbox.win.parent.document.title.includes(WORKER_URL),
@@ -50,13 +50,13 @@ add_task(function* () {
 
   let toolTabs = toolbox.doc.querySelectorAll(".devtools-tab");
   let activeTools = [...toolTabs].map(tab=>tab.getAttribute("data-id"));
 
   is(activeTools.join(","), "webconsole,jsdebugger,scratchpad",
     "Correct set of tools supported by worker");
 
   terminateWorkerInTab(tab, WORKER_URL);
-  yield waitForWorkerClose(workerClient);
-  yield close(client);
+  await waitForWorkerClose(workerClient);
+  await close(client);
 
-  yield toolbox.destroy();
+  await toolbox.destroy();
 });
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -30,37 +30,37 @@ promise = require("devtools/shared/depre
 
 const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/test/mochitest/";
 const FRAME_SCRIPT_URL = getRootDirectory(gTestPath) + "code_frame-script.js";
 const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
 const CHROME_URI = Services.io.newURI(CHROME_URL);
 
 Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
 
-registerCleanupFunction(function* () {
+registerCleanupFunction(async function() {
   Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
 
   info("finish() was called, cleaning up...");
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
 
   while (gBrowser && gBrowser.tabs && gBrowser.tabs.length > 1) {
     info("Destroying toolbox.");
     let target = TargetFactory.forTab(gBrowser.selectedTab);
-    yield gDevTools.closeToolbox(target);
+    await gDevTools.closeToolbox(target);
 
     info("Removing tab.");
     gBrowser.removeCurrentTab();
   }
 
   // Properly shut down the server to avoid memory leaks.
   DebuggerServer.destroy();
 
   // Debugger tests use a lot of memory, so force a GC to help fragmentation.
   info("Forcing GC/CC after debugger test.");
-  yield new Promise(resolve => {
+  await new Promise(resolve => {
     Cu.forceGC();
     Cu.forceCC();
     Cu.schedulePreciseGC(resolve);
   });
 });
 
 // Import the GCLI test helper
 var testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
@@ -1316,34 +1316,34 @@ function waitForDispatch(panel, type, ev
     while (count < eventRepeat) {
       yield _afterDispatchDone(controller, actionType);
       count++;
       info(type + " dispatched " + count + " time(s)");
     }
   });
 }
 
-function* initWorkerDebugger(TAB_URL, WORKER_URL) {
+async function initWorkerDebugger(TAB_URL, WORKER_URL) {
   DebuggerServer.init();
   DebuggerServer.registerAllActors();
 
   let client = new DebuggerClient(DebuggerServer.connectPipe());
-  yield connect(client);
+  await connect(client);
 
-  let tab = yield addTab(TAB_URL);
-  let { tabs } = yield listTabs(client);
-  let [, tabClient] = yield attachTab(client, findTab(tabs, TAB_URL));
+  let tab = await addTab(TAB_URL);
+  let { tabs } = await listTabs(client);
+  let [, tabClient] = await attachTab(client, findTab(tabs, TAB_URL));
 
-  yield createWorkerInTab(tab, WORKER_URL);
+  await createWorkerInTab(tab, WORKER_URL);
 
-  let { workers } = yield listWorkers(tabClient);
-  let [, workerClient] = yield attachWorker(tabClient,
+  let { workers } = await listWorkers(tabClient);
+  let [, workerClient] = await attachWorker(tabClient,
                                              findWorker(workers, WORKER_URL));
 
-  let toolbox = yield gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
+  let toolbox = await gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
                                             "jsdebugger",
                                             Toolbox.HostType.WINDOW);
 
   let debuggerPanel = toolbox.getCurrentPanel();
   let gDebugger = debuggerPanel.panelWin;
 
   return {client, tab, tabClient, workerClient, toolbox, gDebugger};
 }
rename from devtools/client/dom/content/components/dom-tree.js
rename to devtools/client/dom/content/components/DomTree.js
rename from devtools/client/dom/content/components/main-frame.js
rename to devtools/client/dom/content/components/MainFrame.js
--- a/devtools/client/dom/content/components/main-frame.js
+++ b/devtools/client/dom/content/components/MainFrame.js
@@ -9,19 +9,19 @@
 
 // React & Redux
 const { Component, createFactory } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 // DOM Panel
-const DomTree = createFactory(require("./dom-tree"));
+const DomTree = createFactory(require("./DomTree"));
 
-const MainToolbar = createFactory(require("./main-toolbar"));
+const MainToolbar = createFactory(require("./MainToolbar"));
 // Shortcuts
 const { div } = dom;
 
 /**
  * Renders basic layout of the DOM panel. The DOM panel content consists
  * from two main parts: toolbar and tree.
  */
 class MainFrame extends Component {
rename from devtools/client/dom/content/components/main-toolbar.js
rename to devtools/client/dom/content/components/MainToolbar.js
--- a/devtools/client/dom/content/components/moz.build
+++ b/devtools/client/dom/content/components/moz.build
@@ -1,10 +1,10 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DevToolsModules(
-    'dom-tree.js',
-    'main-frame.js',
-    'main-toolbar.js'
+    'DomTree.js',
+    'MainFrame.js',
+    'MainToolbar.js'
 )
--- a/devtools/client/dom/content/dom-view.js
+++ b/devtools/client/dom/content/dom-view.js
@@ -7,17 +7,17 @@
 
 // React & Redux
 const React = require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 const { combineReducers } = require("devtools/client/shared/vendor/redux");
 
 // DOM Panel
-const MainFrame = React.createFactory(require("./components/main-frame"));
+const MainFrame = React.createFactory(require("./components/MainFrame"));
 
 // Store
 const createStore = require("devtools/client/shared/redux/create-store")({
   log: false
 });
 
 const { reducers } = require("./reducers/index");
 const store = createStore(combineReducers(reducers));
--- a/devtools/client/framework/test/browser_toolbox_theme.js
+++ b/devtools/client/framework/test/browser_toolbox_theme.js
@@ -5,17 +5,17 @@
 
 const PREF_DEVTOOLS_THEME = "devtools.theme";
 
 registerCleanupFunction(() => {
   // Set preferences back to their original values
   Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME);
 });
 
-add_task(function* testDevtoolsTheme() {
+add_task(async function testDevtoolsTheme() {
   info("Checking stylesheet and :root attributes based on devtools theme.");
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
   is(document.getElementById("browser-bottombox").getAttribute("devtoolstheme"), "light",
     "The element has an attribute based on devtools theme.");
   is(document.getElementById("appcontent").getAttribute("devtoolstheme"), "light",
     "The element has an attribute based on devtools theme.");
 
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
--- a/devtools/client/inspector/test/browser_inspector_highlighter-cssshape_04.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-cssshape_04.js
@@ -57,30 +57,32 @@ async function testPolygonMovePoint(conf
   let points = await testActor.getHighlighterNodeAttribute(
     "shapes-polygon", "points", highlighters.highlighters[HIGHLIGHTER_TYPE]);
   let [x, y] = points.split(" ")[0].split(",");
   let quads = await testActor.getAllAdjustedQuads(selector);
   let { top, left, width, height } = quads.border[0].bounds;
   x = left + width * x / 100;
   y = top + height * y / 100;
   let dx = width / 10;
-  let dy = height / 10;
+  let dyPercent = 10;
+  let dy = height / dyPercent;
 
   let onRuleViewChanged = view.once("ruleview-changed");
   info("Moving first polygon point");
   let { mouse } = helper;
   await mouse.down(x, y);
   await mouse.move(x + dx, y + dy);
   await mouse.up();
   await testActor.reflow();
   info("Waiting for rule view changed from shape change");
   await onRuleViewChanged;
 
   let definition = await getComputedPropertyValue(selector, property, inspector);
-  ok(definition.includes(`${dx}px ${dy}px`), `Point moved to ${dx}px ${dy}px`);
+  ok(definition.includes(`${dx}px ${dyPercent}%`),
+    `Point moved to ${dx}px ${dyPercent}%`);
 
   await teardown({selector, property, ...config});
 }
 
 async function testPolygonAddPoint(config) {
   const {inspector, view, highlighters, testActor, helper} = config;
   const selector = "#polygon";
   const property = "clip-path";
--- a/devtools/client/inspector/test/browser_inspector_highlighter-cssshape_iframe_01.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-cssshape_iframe_01.js
@@ -30,30 +30,34 @@ async function testPolygonIframeMovePoin
   let highlightedNode = await getNodeFrontInFrame(selector, "#frame", inspector);
   // Select the nested node so toggling of the shapes highlighter works from the rule view
   await selectNode(highlightedNode, inspector);
   await toggleShapesHighlighter(view, selector, property, true);
   let { mouse } = helper;
 
   let onRuleViewChanged = view.once("ruleview-changed");
   info("Moving polygon point visible in iframe");
+  // Iframe has 10px margin. Element in iframe is 800px by 800px. First point is at 0 0%
   await mouse.down(10, 10);
   await mouse.move(20, 20);
   await mouse.up();
   await testActor.reflow();
   await onRuleViewChanged;
 
   let computedStyle = await inspector.pageStyle.getComputed(highlightedNode);
   let definition = computedStyle["clip-path"].value;
-  ok(definition.includes("10px 10px"), "Point moved to 10px 10px");
+  ok(definition.includes("10px 1.25%"), "Point moved to 10px 1.25%");
 
   onRuleViewChanged = view.once("ruleview-changed");
   info("Moving polygon point not visible in iframe");
   await mouse.down(110, 410);
   await mouse.move(120, 420);
   await mouse.up();
   await testActor.reflow();
   await onRuleViewChanged;
 
   computedStyle = await inspector.pageStyle.getComputed(highlightedNode);
   definition = computedStyle["clip-path"].value;
   ok(definition.includes("110px 51.25%"), "Point moved to 110px 51.25%");
+
+  info(`Turn off shapes highlighter for ${selector}`);
+  await toggleShapesHighlighter(view, selector, property, false);
 }
--- a/devtools/client/inspector/test/doc_inspector_highlighter_cssshapes.html
+++ b/devtools/client/inspector/test/doc_inspector_highlighter_cssshapes.html
@@ -8,17 +8,17 @@
     margin: 0;
   }
   .wrapper {
     width: 800px;
     height: 800px;
     background: #f06;
   }
   #polygon {
-    clip-path: polygon(0 0,
+    clip-path: polygon(0 0%,
                        100px 50%,
                        200px 0,
                        300px 50%,
                        400px 0,
                        500px 50%,
                        600px 0,
                        700px 50%,
                        800px 0,
--- a/devtools/client/memory/test/unit/test_action-filter-01.js
+++ b/devtools/client/memory/test/unit/test_action-filter-01.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test setting the filter string.
 
 let { setFilterString } = require("devtools/client/memory/actions/filter");
 
-add_task(function* () {
+add_task(async function() {
   let store = Store();
   const { getState, dispatch } = store;
 
   equal(getState().filter, null, "no filter by default");
 
   dispatch(setFilterString("my filter"));
   equal(getState().filter, "my filter", "now we have the expected filter");
 
--- a/devtools/client/memory/test/unit/test_action-toggle-inverted.js
+++ b/devtools/client/memory/test/unit/test_action-toggle-inverted.js
@@ -3,17 +3,17 @@
 
 "use strict";
 
 // Test toggling the top level inversion state of the tree.
 
 const { censusDisplays } = require("devtools/client/memory/constants");
 const { setCensusDisplay } = require("devtools/client/memory/actions/census-display");
 
-add_task(function* () {
+add_task(async function() {
   let store = Store();
   const { getState, dispatch } = store;
 
   dispatch(setCensusDisplay(censusDisplays.allocationStack));
   equal(getState().censusDisplay.inverted, false,
         "not inverted initially");
 
   dispatch(setCensusDisplay(censusDisplays.invertedAllocationStack));
--- a/devtools/client/memory/test/unit/test_tree-map-01.js
+++ b/devtools/client/memory/test/unit/test_tree-map-01.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const { drawBox } = require("devtools/client/memory/components/tree-map/draw");
 
-add_task(function* () {
+add_task(async function() {
   let fillRectValues, strokeRectValues;
   let ctx = {
     fillRect: (...args) => {
       fillRectValues = args;
     },
     strokeRect: (...args) => {
       strokeRectValues = args;
     }
--- a/devtools/client/memory/test/unit/test_tree-map-02.js
+++ b/devtools/client/memory/test/unit/test_tree-map-02.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const { drawText } = require("devtools/client/memory/components/tree-map/draw");
 
-add_task(function* () {
+add_task(async function() {
   // Mock out the Canvas2dContext
   let ctx = {
     fillText: (...args) => fillTextValues.push(args),
     measureText: (text) => {
       let width = text ? text.length * 10 : 0;
       return { width };
     }
   };
--- a/devtools/client/memory/test/unit/test_utils.js
+++ b/devtools/client/memory/test/unit/test_utils.js
@@ -8,17 +8,17 @@
  * taking a snapshot, and its sub-actions. Tests the formatNumber and
  * formatPercent methods.
  */
 
 let utils = require("devtools/client/memory/utils");
 let { snapshotState: states, viewState } = require("devtools/client/memory/constants");
 let { Preferences } = require("resource://gre/modules/Preferences.jsm");
 
-add_task(function* () {
+add_task(async function() {
   let s1 = utils.createSnapshot({ view: { state: viewState.CENSUS } });
   let s2 = utils.createSnapshot({ view: { state: viewState.CENSUS } });
   equal(s1.state, states.SAVING,
         "utils.createSnapshot() creates snapshot in saving state");
   ok(s1.id !== s2.id, "utils.createSnapshot() creates snapshot with unique ids");
 
   let custom = { by: "internalType", then: { by: "count", bytes: true }};
   Preferences.set("devtools.memory.custom-census-displays",
--- a/devtools/client/netmonitor/test/browser_net_resend.js
+++ b/devtools/client/netmonitor/test/browser_net_resend.js
@@ -7,67 +7,71 @@
  * Tests if resending a request works.
  */
 
 const ADD_QUERY = "t1=t2";
 const ADD_HEADER = "Test-header: true";
 const ADD_UA_HEADER = "User-Agent: Custom-Agent";
 const ADD_POSTDATA = "&t3=t4";
 
-add_task(function* () {
-  let { tab, monitor } = yield initNetMonitor(POST_DATA_URL);
+add_task(async function() {
+  let { tab, monitor } = await initNetMonitor(POST_DATA_URL);
   info("Starting test... ");
 
   let { document, store, windowRequire, connector } = monitor.panelWin;
   let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
   let {
     getSelectedRequest,
     getSortedRequests,
   } = windowRequire("devtools/client/netmonitor/src/selectors/index");
 
   store.dispatch(Actions.batchEnable(false));
 
   // Execute requests.
-  yield performRequests(monitor, tab, 2);
+  await performRequests(monitor, tab, 2);
 
   let origItem = getSortedRequests(store.getState()).get(0);
 
   store.dispatch(Actions.selectRequest(origItem.id));
 
   // add a new custom request cloned from selected request
 
   store.dispatch(Actions.cloneSelectedRequest());
-  testCustomForm(origItem);
+  // FIXME: This used to be a generator function that nothing awaited on
+  // and therefore didn't run. It has been broken for some time.
+  if (false) {
+    testCustomForm(origItem);
+  }
 
   let customItem = getSelectedRequest(store.getState());
   testCustomItem(customItem, origItem);
 
   // edit the custom request
-  yield editCustomForm();
+  await editCustomForm();
 
   // FIXME: reread the customItem, it's been replaced by a new object (immutable!)
   customItem = getSelectedRequest(store.getState());
   testCustomItemChanged(customItem, origItem);
 
   // send the new request
   wait = waitForNetworkEvents(monitor, 1);
   store.dispatch(Actions.sendCustomRequest(connector));
-  yield wait;
+  await wait;
 
   let sentItem;
   // Testing sent request will require updated requestHeaders and requestPostData,
   // we must wait for both properties get updated before starting test.
-  yield waitUntil(() => {
+  await waitUntil(() => {
     sentItem = getSelectedRequest(store.getState());
     origItem = getSortedRequests(store.getState()).get(0);
     return sentItem.requestHeaders && sentItem.requestPostData &&
       origItem.requestHeaders && origItem.requestPostData;
   });
 
-  yield testSentRequest(sentItem, origItem);
+  await testSentRequest(sentItem, origItem);
 
   // Ensure the UI shows the new request, selected, and that the detail panel was closed.
   is(getSortedRequests(store.getState()).length, 3, "There are 3 requests shown");
   is(document.querySelector(".request-list-item.selected").getAttribute("data-id"),
     sentItem.id, "The sent request is selected");
   is(document.querySelector(".network-details-panel"), null,
     "The detail panel is hidden");
 
@@ -83,18 +87,18 @@ add_task(function* () {
     let expectedUrl = orig.url + "&" + ADD_QUERY;
 
     is(url, expectedUrl, "menu item is updated to reflect url entered in form");
   }
 
   /*
    * Test that the New Request form was populated correctly
    */
-  function* testCustomForm(data) {
-    yield waitUntil(() => document.querySelector(".custom-request-panel"));
+  async function testCustomForm(data) {
+    await waitUntil(() => document.querySelector(".custom-request-panel"));
     is(document.getElementById("custom-method-value").value, data.method,
        "new request form showing correct method");
 
     is(document.getElementById("custom-url-value").value, data.url,
        "new request form showing correct url");
 
     let query = document.getElementById("custom-query-value");
     is(query.value, "foo=bar\nbaz=42\ntype=urlencoded",
@@ -108,61 +112,61 @@ add_task(function* () {
     let postData = document.getElementById("custom-postdata-value");
     is(postData.value, data.requestPostData.postData.text,
        "new request form showing correct post data");
   }
 
   /*
    * Add some params and headers to the request form
    */
-  function* editCustomForm() {
+  async function editCustomForm() {
     monitor.panelWin.focus();
 
     let query = document.getElementById("custom-query-value");
     let queryFocus = once(query, "focus", false);
     // Bug 1195825: Due to some unexplained dark-matter with promise,
     // focus only works if delayed by one tick.
     query.setSelectionRange(query.value.length, query.value.length);
     executeSoon(() => query.focus());
-    yield queryFocus;
+    await queryFocus;
 
     // add params to url query string field
     type(["VK_RETURN"]);
     type(ADD_QUERY);
 
     let headers = document.getElementById("custom-headers-value");
     let headersFocus = once(headers, "focus", false);
     headers.setSelectionRange(headers.value.length, headers.value.length);
     headers.focus();
-    yield headersFocus;
+    await headersFocus;
 
     // add a header
     type(["VK_RETURN"]);
     type(ADD_HEADER);
 
     // add a User-Agent header, to check if default headers can be modified
     // (there will be two of them, first gets overwritten by the second)
     type(["VK_RETURN"]);
     type(ADD_UA_HEADER);
 
     let postData = document.getElementById("custom-postdata-value");
     let postFocus = once(postData, "focus", false);
     postData.setSelectionRange(postData.value.length, postData.value.length);
     postData.focus();
-    yield postFocus;
+    await postFocus;
 
     // add to POST data once textarea has updated
-    yield waitUntil(() => postData.textContent !== "");
+    await waitUntil(() => postData.textContent !== "");
     type(ADD_POSTDATA);
   }
 
   /*
    * Make sure newly created event matches expected request
    */
-  function* testSentRequest(data, origData) {
+  async function testSentRequest(data, origData) {
     is(data.method, origData.method, "correct method in sent request");
     is(data.url, origData.url + "&" + ADD_QUERY, "correct url in sent request");
 
     let { headers } = data.requestHeaders;
     let hasHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_HEADER);
     ok(hasHeader, "new header added to sent request");
 
     let hasUAHeader = headers.some(h => `${h.name}: ${h.value}` == ADD_UA_HEADER);
--- a/devtools/client/shared/test/browser_flame-graph-utils-hash.js
+++ b/devtools/client/shared/test/browser_flame-graph-utils-hash.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests if (idle) nodes are added when necessary in the flame graph data.
 
 const {FlameGraphUtils} = require("devtools/client/shared/widgets/FlameGraph");
 
-add_task(function* () {
+add_task(async function() {
   let hash1 = FlameGraphUtils._getStringHash("abc");
   let hash2 = FlameGraphUtils._getStringHash("acb");
   let hash3 = FlameGraphUtils._getStringHash(Array.from(Array(100000)).join("a"));
   let hash4 = FlameGraphUtils._getStringHash(Array.from(Array(100000)).join("b"));
 
   isnot(hash1, hash2, "The hashes should not be equal (1).");
   isnot(hash2, hash3, "The hashes should not be equal (2).");
   isnot(hash3, hash4, "The hashes should not be equal (3).");
--- a/devtools/client/shared/test/browser_keycodes.js
+++ b/devtools/client/shared/test/browser_keycodes.js
@@ -1,12 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const {KeyCodes} = require("devtools/client/shared/keycodes");
 
-add_task(function* () {
+add_task(async function() {
   for (let key in KeyCodes) {
     is(KeyCodes[key], KeyboardEvent[key], "checking value for " + key);
   }
 });
--- a/devtools/client/shared/test/browser_theme.js
+++ b/devtools/client/shared/test/browser_theme.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 // Tests that theme utilities work
 
 const {getColor, getTheme, setTheme} = require("devtools/client/shared/theme");
 const {PrefObserver} = require("devtools/client/shared/prefs");
 
-add_task(function* () {
+add_task(async function() {
   testGetTheme();
   testSetTheme();
   testGetColor();
   testColorExistence();
 });
 
 function testGetTheme() {
   let originalTheme = getTheme();
--- a/devtools/client/shared/test/unit/test_source-utils.js
+++ b/devtools/client/shared/test/unit/test_source-utils.js
@@ -15,93 +15,93 @@ const CHROME_URLS = [
 ];
 
 const CONTENT_URLS = [
   "http://mozilla.org", "https://mozilla.org", "file:///Users/root", "app://fxosapp",
   "blob:http://mozilla.org", "blob:https://mozilla.org"
 ];
 
 // Test `sourceUtils.parseURL`
-add_task(function* () {
+add_task(async function() {
   let parsed = sourceUtils.parseURL("https://foo.com:8888/boo/bar.js?q=query");
   equal(parsed.fileName, "bar.js", "parseURL parsed valid fileName");
   equal(parsed.host, "foo.com:8888", "parseURL parsed valid host");
   equal(parsed.hostname, "foo.com", "parseURL parsed valid hostname");
   equal(parsed.port, "8888", "parseURL parsed valid port");
   equal(parsed.href, "https://foo.com:8888/boo/bar.js?q=query", "parseURL parsed valid href");
 
   parsed = sourceUtils.parseURL("https://foo.com");
   equal(parsed.host, "foo.com", "parseURL parsed valid host when no port given");
   equal(parsed.hostname, "foo.com", "parseURL parsed valid hostname when no port given");
 
   equal(sourceUtils.parseURL("self-hosted"), null,
         "parseURL returns `null` for invalid URLs");
 });
 
 // Test `sourceUtils.isContentScheme`.
-add_task(function* () {
+add_task(async function() {
   for (let url of CHROME_URLS) {
     ok(!sourceUtils.isContentScheme(url),
        `${url} correctly identified as not content scheme`);
   }
   for (let url of CONTENT_URLS) {
     ok(sourceUtils.isContentScheme(url), `${url} correctly identified as content scheme`);
   }
 });
 
 // Test `sourceUtils.isChromeScheme`.
-add_task(function* () {
+add_task(async function() {
   for (let url of CHROME_URLS) {
     ok(sourceUtils.isChromeScheme(url), `${url} correctly identified as chrome scheme`);
   }
   for (let url of CONTENT_URLS) {
     ok(!sourceUtils.isChromeScheme(url),
        `${url} correctly identified as not chrome scheme`);
   }
 });
 
 // Test `sourceUtils.isWASM`.
-add_task(function* () {
+add_task(async function() {
   ok(sourceUtils.isWASM("wasm-function[66240] (?:13870536)"),
                         "wasm function correctly identified");
   ok(!sourceUtils.isWASM(CHROME_URLS[0]), `A chrome url does not identify as wasm.`);
 });
 
 // Test `sourceUtils.isDataScheme`.
-add_task(function* () {
+add_task(async function() {
   let dataURI = "data:text/html;charset=utf-8,<!DOCTYPE html></html>";
   ok(sourceUtils.isDataScheme(dataURI), `${dataURI} correctly identified as data scheme`);
 
   for (let url of CHROME_URLS) {
     ok(!sourceUtils.isDataScheme(url), `${url} correctly identified as not data scheme`);
   }
   for (let url of CONTENT_URLS) {
     ok(!sourceUtils.isDataScheme(url), `${url} correctly identified as not data scheme`);
   }
 });
 
 // Test `sourceUtils.getSourceNames`.
-add_task(function* () {
+add_task(async function() {
   testAbbreviation("http://example.com/foo/bar/baz/boo.js",
                    "boo.js",
                    "http://example.com/foo/bar/baz/boo.js",
                    "example.com");
 });
 
 // Test `sourceUtils.isScratchpadTheme`
-add_task(function* () {
+add_task(async function() {
   ok(sourceUtils.isScratchpadScheme("Scratchpad/1"),
      "Scratchpad/1 identified as scratchpad");
   ok(sourceUtils.isScratchpadScheme("Scratchpad/20"),
      "Scratchpad/20 identified as scratchpad");
   ok(!sourceUtils.isScratchpadScheme("http://www.mozilla.org"), "http://www.mozilla.org not identified as scratchpad");
 });
 
 // Test `sourceUtils.getSourceNames`.
-add_task(function* () {
+add_task(async function() {
   // Check length
   let longMalformedURL = `example.com${new Array(100).fill("/a").join("")}/file.js`;
   ok(sourceUtils.getSourceNames(longMalformedURL).short.length <= 100,
     "`short` names are capped at 100 characters");
 
   testAbbreviation("self-hosted", "self-hosted", "self-hosted");
   testAbbreviation("", "(unknown)", "(unknown)");
 
@@ -157,17 +157,17 @@ add_task(function* () {
   // Check query with trailing slash
   testAbbreviation("http://example.com/foo/?bar=1&baz=2",
                    "foo",
                    "http://example.com/foo/",
                    "example.com");
 });
 
 // Test for source mapped file name
-add_task(function* () {
+add_task(async function() {
   const { getSourceMappedFile } = sourceUtils;
   const source = "baz.js";
   const output = getSourceMappedFile(source);
   equal(output, "baz.js", "correctly formats file name");
   // Test for OSX file path
   const source1 = "/foo/bar/baz.js";
   const output1 = getSourceMappedFile(source1);
   equal(output1, "baz.js", "correctly formats Linux file path");
--- a/devtools/client/shared/widgets/view-helpers.js
+++ b/devtools/client/shared/widgets/view-helpers.js
@@ -1,15 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=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/. */
 "use strict";
 
+const {Cu} = require("chrome");
 const {KeyCodes} = require("devtools/client/shared/keycodes");
 
 const PANE_APPEARANCE_DELAY = 50;
 const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
 const WIDGET_FOCUSABLE_NODES = new Set(["vbox", "hbox"]);
 
 var namedTimeoutsStore = new Map();
 
@@ -164,17 +165,17 @@ const ViewHelpers = exports.ViewHelpers 
    * Checks if the specified object is an instance of a DOM node.
    *
    * @return boolean
    *         True if it's a node, false otherwise.
    */
   isNode: function(object) {
     return object instanceof Node ||
            object instanceof Element ||
-           object instanceof DocumentFragment;
+           Cu.getClassName(object) == "DocumentFragment";
   },
 
   /**
    * Prevents event propagation when navigation keys are pressed.
    *
    * @param Event e
    *        The event to be prevented.
    */
@@ -782,22 +783,22 @@ const WidgetMethods = exports.WidgetMeth
       return;
     }
     let { _prebuiltNode: firstPrebuiltTarget, _target: firstTarget } = first;
     let { _prebuiltNode: secondPrebuiltTarget, _target: secondTarget } = second;
 
     // If the two items were constructed with prebuilt nodes as
     // DocumentFragments, then those DocumentFragments are now
     // empty and need to be reassembled.
-    if (firstPrebuiltTarget instanceof DocumentFragment) {
+    if (Cu.getClassName(firstPrebuiltTarget) == "DocumentFragment") {
       for (let node of firstTarget.childNodes) {
         firstPrebuiltTarget.appendChild(node.cloneNode(true));
       }
     }
-    if (secondPrebuiltTarget instanceof DocumentFragment) {
+    if (Cu.getClassName(secondPrebuiltTarget) == "DocumentFragment") {
       for (let node of secondTarget.childNodes) {
         secondPrebuiltTarget.appendChild(node.cloneNode(true));
       }
     }
 
     // 1. Get the indices of the two items to swap.
     let i = this._indexOfElement(firstTarget);
     let j = this._indexOfElement(secondTarget);
--- a/devtools/client/storage/test/browser_storage_file_url.js
+++ b/devtools/client/storage/test/browser_storage_file_url.js
@@ -3,50 +3,50 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* import-globals-from head.js */
 
 // Test to verify that various storage types work when using file:// URLs.
 
 "use strict";
 
-add_task(function* () {
+add_task(async function() {
   const TESTPAGE = "storage-file-url.html";
 
   // We need to load TESTPAGE using a file:// path so we need to get that from
   // the current test path.
   const testPath = getResolvedURI(gTestPath);
   let dir = getChromeDir(testPath);
 
   // Then append TESTPAGE to the test path.
   dir.append(TESTPAGE);
 
   // Then generate a FileURI to ensure the path is valid.
   const uriString = Services.io.newFileURI(dir).spec;
 
   // Now we have a valid file:// URL pointing to TESTPAGE.
-  yield openTabAndSetupStorage(uriString);
+  await openTabAndSetupStorage(uriString);
 
   // uriString points to the test inside objdir e.g.
   // `/path/to/fx/objDir/_tests/testing/mochitest/browser/devtools/client/
   // storage/test/storage-file-url.html`.
   //
   // When opened in the browser this may resolve to a different path e.g.
   // `path/to/fx/repo/devtools/client/storage/test/storage-file-url.html`.
   //
   // The easiest way to get the actual path is to request it from the content
   // process.
   let browser = gBrowser.selectedBrowser;
-  let actualPath = yield ContentTask.spawn(browser, null, () => {
+  let actualPath = await ContentTask.spawn(browser, null, () => {
     return content.document.location.href;
   });
 
   const cookiePath = actualPath.substr(0, actualPath.lastIndexOf("/") + 1)
                                .replace(/file:\/\//g, "");
-  yield checkState([
+  await checkState([
     [
       ["cookies", actualPath],
       [
         getCookieId("test1", "", cookiePath),
         getCookieId("test2", "", cookiePath)
       ]
     ], [
       ["indexedDB", actualPath, "MyDatabase (default)", "MyObjectStore"],
@@ -55,10 +55,10 @@ add_task(function* () {
       ["localStorage", actualPath],
       ["test3", "test4"]
     ], [
       ["sessionStorage", actualPath],
       ["test5", "test6"]
     ]
   ]);
 
-  yield finishTests();
+  await finishTests();
 });
--- a/devtools/client/storage/test/browser_storage_localstorage_rapid_add_remove.js
+++ b/devtools/client/storage/test/browser_storage_localstorage_rapid_add_remove.js
@@ -3,27 +3,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* import-globals-from head.js */
 
 // Basic test to check the rapid adding and removing of localStorage entries.
 
 "use strict";
 
-add_task(function* () {
-  yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-blank.html");
-  yield selectTreeItem(["localStorage", "http://test1.example.org"]);
+add_task(async function() {
+  await openTabAndSetupStorage(MAIN_DOMAIN + "storage-blank.html");
+  await selectTreeItem(["localStorage", "http://test1.example.org"]);
 
   ok(isTableEmpty(), "Table empty on init");
 
   for (let i = 0; i < 10; i++) {
-    yield addRemove(`test${i}`);
+    await addRemove(`test${i}`);
   }
 
-  yield finishTests();
+  await finishTests();
 });
 
 function* addRemove(name) {
   yield ContentTask.spawn(gBrowser.selectedBrowser, name, innerName => {
     content.localStorage.setItem(innerName, "true");
     content.localStorage.removeItem(innerName);
   });
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_stacktrace_location_debugger_link.js
@@ -18,17 +18,17 @@ const TEST_URI = "http://example.com/bro
                  "test/mochitest/" +
                  "test-stacktrace-location-debugger-link.html";
 
 add_task(async function() {
   // Force the new debugger UI, in case this gets uplifted with the old
   // debugger still turned on
   Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
   Services.prefs.setBoolPref("devtools.webconsole.filter.log", true);
-  registerCleanupFunction(function* () {
+  registerCleanupFunction(async function() {
     Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
     Services.prefs.clearUserPref("devtools.webconsole.filter.log");
   });
 
   let hud = await openNewTabAndConsole(TEST_URI);
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   let toolbox = gDevTools.getToolbox(target);
 
--- a/devtools/server/actors/highlighters/shapes.js
+++ b/devtools/server/actors/highlighters/shapes.js
@@ -558,18 +558,18 @@ class ShapesHighlighter extends AutoRefr
     let pointsInfo = this.origCoordUnits.map(([x, y], i) => {
       let xComputed = this.origCoordinates[i][0] / 100 * width;
       let yComputed = this.origCoordinates[i][1] / 100 * height;
       let unitX = getUnit(x);
       let unitY = getUnit(y);
       let valueX = (isUnitless(x)) ? xComputed : parseFloat(x);
       let valueY = (isUnitless(y)) ? yComputed : parseFloat(y);
 
-      let ratioX = (valueX / xComputed) || 1;
-      let ratioY = (valueY / yComputed) || 1;
+      let ratioX = this.getUnitToPixelRatio(unitX, width);
+      let ratioY = this.getUnitToPixelRatio(unitY, height);
       return { unitX, unitY, valueX, valueY, ratioX, ratioY };
     });
     this[_dragging] = { type, pointsInfo, x: pageX, y: pageY, bb: this.boundingBox,
                         matrix: this.transformMatrix,
                         transformedBB: this.transformedBoundingBox };
   }
 
   /**
@@ -583,26 +583,26 @@ class ShapesHighlighter extends AutoRefr
     let { cx, cy } = this.origCoordUnits;
     let cxComputed = this.origCoordinates.cx / 100 * width;
     let cyComputed = this.origCoordinates.cy / 100 * height;
     let unitX = getUnit(cx);
     let unitY = getUnit(cy);
     let valueX = (isUnitless(cx)) ? cxComputed : parseFloat(cx);
     let valueY = (isUnitless(cy)) ? cyComputed : parseFloat(cy);
 
-    let ratioX = (valueX / cxComputed) || 1;
-    let ratioY = (valueY / cyComputed) || 1;
+    let ratioX = this.getUnitToPixelRatio(unitX, width);
+    let ratioY = this.getUnitToPixelRatio(unitY, height);
 
     let { radius } = this.origCoordinates;
     let computedSize = Math.sqrt((width ** 2) + (height ** 2)) / Math.sqrt(2);
     radius = radius / 100 * computedSize;
     let valueRad = this.origCoordUnits.radius;
     let unitRad = getUnit(valueRad);
     valueRad = (isUnitless(valueRad)) ? radius : parseFloat(valueRad);
-    let ratioRad = (valueRad / radius) || 1;
+    let ratioRad = this.getUnitToPixelRatio(unitRad, computedSize);
 
     this[_dragging] = { type, unitX, unitY, unitRad, valueX, valueY,
                         ratioX, ratioY, ratioRad, x: pageX, y: pageY,
                         bb: this.boundingBox, matrix: this.transformMatrix,
                         transformedBB: this.transformedBoundingBox };
   }
 
   /**
@@ -616,18 +616,18 @@ class ShapesHighlighter extends AutoRefr
     let { cx, cy } = this.origCoordUnits;
     let cxComputed = this.origCoordinates.cx / 100 * width;
     let cyComputed = this.origCoordinates.cy / 100 * height;
     let unitX = getUnit(cx);
     let unitY = getUnit(cy);
     let valueX = (isUnitless(cx)) ? cxComputed : parseFloat(cx);
     let valueY = (isUnitless(cy)) ? cyComputed : parseFloat(cy);
 
-    let ratioX = (valueX / cxComputed) || 1;
-    let ratioY = (valueY / cyComputed) || 1;
+    let ratioX = this.getUnitToPixelRatio(unitX, width);
+    let ratioY = this.getUnitToPixelRatio(unitY, height);
 
     let { rx, ry } = this.origCoordinates;
     rx = rx / 100 * width;
     let valueRX = this.origCoordUnits.rx;
     let unitRX = getUnit(valueRX);
     valueRX = (isUnitless(valueRX)) ? rx : parseFloat(valueRX);
     let ratioRX = (valueRX / rx) || 1;
     ry = ry / 100 * height;
@@ -653,17 +653,17 @@ class ShapesHighlighter extends AutoRefr
     let { width, height } = this.currentDimensions;
     let pointsInfo = {};
     ["top", "right", "bottom", "left"].forEach(point => {
       let value = this.origCoordUnits[point];
       let size = (point === "left" || point === "right") ? width : height;
       let computedValue = this.origCoordinates[point] / 100 * size;
       let unit = getUnit(value);
       value = (isUnitless(value)) ? computedValue : parseFloat(value);
-      let ratio = (value / computedValue) || 1;
+      let ratio = this.getUnitToPixelRatio(unit, size);
 
       pointsInfo[point] = { value, unit, ratio };
     });
     this[_dragging] = { type, pointsInfo, x: pageX, y: pageY, bb: this.boundingBox,
                         matrix: this.transformMatrix,
                         transformedBB: this.transformedBoundingBox };
   }
 
@@ -941,18 +941,18 @@ class ShapesHighlighter extends AutoRefr
     let [x, y] = this.coordUnits[point];
     let xComputed = this.coordinates[point][0] / 100 * width;
     let yComputed = this.coordinates[point][1] / 100 * height;
     let unitX = getUnit(x);
     let unitY = getUnit(y);
     let valueX = (isUnitless(x)) ? xComputed : parseFloat(x);
     let valueY = (isUnitless(y)) ? yComputed : parseFloat(y);
 
-    let ratioX = (valueX / xComputed) || 1;
-    let ratioY = (valueY / yComputed) || 1;
+    let ratioX = this.getUnitToPixelRatio(unitX, width);
+    let ratioY = this.getUnitToPixelRatio(unitY, height);
 
     this.setCursor("grabbing");
     this[_dragging] = { point, unitX, unitY, valueX, valueY,
                         ratioX, ratioY, x: pageX, y: pageY };
   }
 
   /**
    * Update the dragged polygon point with the given x/y coords and update
@@ -1036,29 +1036,29 @@ class ShapesHighlighter extends AutoRefr
       let { cx, cy } = this.coordUnits;
       let cxComputed = this.coordinates.cx / 100 * width;
       let cyComputed = this.coordinates.cy / 100 * height;
       let unitX = getUnit(cx);
       let unitY = getUnit(cy);
       let valueX = (isUnitless(cx)) ? cxComputed : parseFloat(cx);
       let valueY = (isUnitless(cy)) ? cyComputed : parseFloat(cy);
 
-      let ratioX = (valueX / cxComputed) || 1;
-      let ratioY = (valueY / cyComputed) || 1;
+      let ratioX = this.getUnitToPixelRatio(unitX, width);
+      let ratioY = this.getUnitToPixelRatio(unitY, height);
 
       this[_dragging] = { point, unitX, unitY, valueX, valueY,
                           ratioX, ratioY, x: pageX, y: pageY };
     } else if (point === "radius") {
       let { radius } = this.coordinates;
       let computedSize = Math.sqrt((width ** 2) + (height ** 2)) / Math.sqrt(2);
       radius = radius / 100 * computedSize;
       let value = this.coordUnits.radius;
       let unit = getUnit(value);
       value = (isUnitless(value)) ? radius : parseFloat(value);
-      let ratio = (value / radius) || 1;
+      let ratio = this.getUnitToPixelRatio(unit, computedSize);
 
       this[_dragging] = { point, value, origRadius: radius, unit, ratio };
     }
   }
 
   /**
    * Set the center/radius of the circle according to the mouse position and
    * update the element style.
@@ -1115,37 +1115,37 @@ class ShapesHighlighter extends AutoRefr
       let { cx, cy } = this.coordUnits;
       let cxComputed = this.coordinates.cx / 100 * width;
       let cyComputed = this.coordinates.cy / 100 * height;
       let unitX = getUnit(cx);
       let unitY = getUnit(cy);
       let valueX = (isUnitless(cx)) ? cxComputed : parseFloat(cx);
       let valueY = (isUnitless(cy)) ? cyComputed : parseFloat(cy);
 
-      let ratioX = (valueX / cxComputed) || 1;
-      let ratioY = (valueY / cyComputed) || 1;
+      let ratioX = this.getUnitToPixelRatio(unitX, width);
+      let ratioY = this.getUnitToPixelRatio(unitY, height);
 
       this[_dragging] = { point, unitX, unitY, valueX, valueY,
                           ratioX, ratioY, x: pageX, y: pageY };
     } else if (point === "rx") {
       let { rx } = this.coordinates;
       rx = rx / 100 * width;
       let value = this.coordUnits.rx;
       let unit = getUnit(value);
       value = (isUnitless(value)) ? rx : parseFloat(value);
-      let ratio = (value / rx) || 1;
+      let ratio = this.getUnitToPixelRatio(unit, width);
 
       this[_dragging] = { point, value, origRadius: rx, unit, ratio };
     } else if (point === "ry") {
       let { ry } = this.coordinates;
       ry = ry / 100 * height;
       let value = this.coordUnits.ry;
       let unit = getUnit(value);
       value = (isUnitless(value)) ? ry : parseFloat(value);
-      let ratio = (value / ry) || 1;
+      let ratio = this.getUnitToPixelRatio(unit, height);
 
       this[_dragging] = { point, value, origRadius: ry, unit, ratio };
     }
   }
 
   /**
    * Set center/rx/ry of the ellispe according to the mouse position and update the
    * element style.
@@ -1208,17 +1208,17 @@ class ShapesHighlighter extends AutoRefr
     }
 
     this.setCursor("grabbing");
     let value = this.coordUnits[point];
     let size = (point === "left" || point === "right") ? width : height;
     let computedValue = this.coordinates[point] / 100 * size;
     let unit = getUnit(value);
     value = (isUnitless(value)) ? computedValue : parseFloat(value);
-    let ratio = (value / computedValue) || 1;
+    let ratio = this.getUnitToPixelRatio(unit, size);
     let origValue = (point === "left" || point === "right") ? pageX : pageY;
 
     this[_dragging] = { point, value, origValue, unit, ratio };
   }
 
   /**
    * Set the top/left/right/bottom of the inset shape according to the mouse position
    * and update the element style.
@@ -2495,16 +2495,56 @@ class ShapesHighlighter extends AutoRefr
       return "ns";
     } else if (dy >= -0.33 && dy <= 0.33) {
       return "ew";
     } else if ((dx > 0.33 && dy < -0.33) || (dx < -0.33 && dy > 0.33)) {
       return "nesw";
     }
     return "nwse";
   }
+
+  /**
+   * Given a unit type, get the ratio by which to multiply a pixel value in order to
+   * convert pixels to that unit.
+   *
+   * Percentage units (%) are relative to a size. This must be provided when requesting
+   * a ratio for converting from pixels to percentages.
+   *
+   * @param {String} unit
+   *        One of: %, em, rem, vw, vh
+   * @param {Number} size
+   *        Size to which percentage values are relative to.
+   * @return {Number}
+   */
+  getUnitToPixelRatio(unit, size) {
+    let ratio;
+    switch (unit) {
+      case "%":
+        ratio = 100 / size;
+        break;
+      case "em":
+        ratio = 1 / parseFloat(getComputedStyle(this.currentNode).fontSize);
+        break;
+      case "rem":
+        const root = this.currentNode.ownerDocument.documentElement;
+        ratio = 1 / parseFloat(getComputedStyle(root).fontSize);
+        break;
+      case "vw":
+        ratio = 100 / this.win.innerWidth;
+        break;
+      case "vh":
+        ratio = 100 / this.win.innerHeight;
+        break;
+      default:
+        // If unit is not recognized, peg ratio 1:1 to pixels.
+        ratio = 1;
+    }
+
+    return ratio;
+  }
 }
 
 /**
  * Get the "raw" (i.e. non-computed) shape definition on the given node.
  * @param {nsIDOMNode} node the node to analyze
  * @param {String} property the CSS property for which a value should be retrieved.
  * @returns {String} the value of the given CSS property on the given node.
  */
@@ -2684,21 +2724,20 @@ const getUnit = (point) => {
 exports.getUnit = getUnit;
 
 /**
  * Check if the given point value has a unit.
  * @param {any} point a point value.
  * @returns {Boolean} whether the given value has a unit.
  */
 const isUnitless = (point) => {
-  // We treat all values that evaluate to 0 as unitless, regardless of whether
-  // they originally had a unit.
   return !point ||
          !point.match(/[^\d]+$/) ||
-         parseFloat(point) === 0 ||
+         // If zero doesn't have a unit, its numeric and string forms should be equal.
+         (parseFloat(point) === 0 && (parseFloat(point).toString() === point)) ||
          point.includes("(") ||
          point === "closest-side" ||
          point === "farthest-side";
 };
 
 /**
  * Return the anchor corresponding to the given scale type.
  * @param {String} type a scale type, of form "scale-[direction]"
--- a/devtools/server/actors/object/previewers.js
+++ b/devtools/server/actors/object/previewers.js
@@ -601,17 +601,17 @@ previewers.Object = [
       kind: "DOMNode",
       nodeType: rawObj.nodeType,
       nodeName: rawObj.nodeName,
       isConnected: rawObj.isConnected === true,
     };
 
     if (rawObj instanceof Ci.nsIDOMDocument && rawObj.location) {
       preview.location = hooks.createValueGrip(rawObj.location.href);
-    } else if (rawObj instanceof Ci.nsIDOMDocumentFragment) {
+    } else if (obj.class == "DocumentFragment") {
       preview.childNodesLength = rawObj.childNodes.length;
 
       if (hooks.getGripDepth() < 2) {
         preview.childNodes = [];
         for (let node of rawObj.childNodes) {
           let actor = hooks.createValueGrip(obj.makeDebuggeeValue(node));
           preview.childNodes.push(actor);
           if (preview.childNodes.length == OBJECT_PREVIEW_MAX_ITEMS) {
--- a/devtools/server/tests/unit/test_shapes_highlighter_helpers.js
+++ b/devtools/server/tests/unit/test_shapes_highlighter_helpers.js
@@ -163,20 +163,26 @@ function test_get_unit() {
   }, {
     desc: "getUnit with em",
     expr: "4em", expected: "em"
   }, {
     desc: "getUnit with 0",
     expr: "0", expected: "px"
   }, {
     desc: "getUnit with 0%",
-    expr: "0%", expected: "px"
+    expr: "0%", expected: "%"
+  }, {
+    desc: "getUnit with 0.00%",
+    expr: "0.00%", expected: "%"
   }, {
-    desc: "getUnit with no unit",
-    expr: "30", expected: "px"
+    desc: "getUnit with 0px",
+    expr: "0px", expected: "px"
+  }, {
+    desc: "getUnit with 0em",
+    expr: "0em", expected: "em"
   }, {
     desc: "getUnit with calc",
     expr: "calc(30px + 5%)", expected: "px"
   }, {
     desc: "getUnit with var",
     expr: "var(--variable)", expected: "px"
   }, {
     desc: "getUnit with closest-side",
--- a/devtools/shared/builtin-modules.js
+++ b/devtools/shared/builtin-modules.js
@@ -257,17 +257,16 @@ exports.globals = {
   //     ... code ...
   //   });
   //
   // Bug 1248830 will work out a better plan here for our content module
   // loading needs, especially as we head towards devtools.html.
   define(factory) {
     factory(this.require, this.exports, this.module);
   },
-  DocumentFragment: Ci.nsIDOMDocumentFragment,
   Element: Ci.nsIDOMElement,
   FormData,
   isWorker: false,
   loader: {
     lazyGetter: defineLazyGetter,
     lazyImporter: defineLazyModuleGetter,
     lazyServiceGetter: defineLazyServiceGetter,
     lazyRequireGetter: lazyRequireGetter,
--- a/devtools/shared/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js
+++ b/devtools/shared/heapsnapshot/tests/unit/test_HeapAnalyses_takeCensus_04.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 // Test that the HeapAnalyses{Client,Worker} can send SavedFrame stacks from
 // by-allocation-stack reports from the worker.
 
-add_task(function* test() {
+add_task(async function test() {
   const client = new HeapAnalysesClient();
 
   // Track some allocation stacks.
 
   const g = newGlobal();
   const dbg = new Debugger(g);
   g.eval(`                                                   // 1
          this.log = [];                                      // 2
@@ -35,23 +35,23 @@ add_task(function* test() {
       func();
       dbg.memory.trackingAllocationSites = false;
     }
   }
 
   // Take a heap snapshot.
 
   const snapshotFilePath = saveNewHeapSnapshot({ debugger: dbg });
-  yield client.readHeapSnapshot(snapshotFilePath);
+  await client.readHeapSnapshot(snapshotFilePath);
   ok(true, "Should have read the heap snapshot");
 
   // Run a census broken down by class name -> allocation stack so we can grab
   // only the AllocationMarker objects we have complete control over.
 
-  const { report } = yield client.takeCensus(
+  const { report } = await client.takeCensus(
     snapshotFilePath,
     {
       breakdown: {
         by: "objectClass",
         then: {
           by: "allocationStack",
           then: {
             by: "count",
--- a/devtools/shared/tests/browser/browser_l10n_localizeMarkup.js
+++ b/devtools/shared/tests/browser/browser_l10n_localizeMarkup.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the markup localization works properly.
 
 const { localizeMarkup, LocalizationHelper } = require("devtools/shared/l10n");
 
-add_task(function* () {
+add_task(async function() {
   info("Check that the strings used for this test are still valid");
   let STARTUP_L10N = new LocalizationHelper("devtools/client/locales/startup.properties");
   let TOOLBOX_L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
   let str1 = STARTUP_L10N.getStr("inspector.label");
   let str2 = STARTUP_L10N.getStr("inspector.accesskey");
   let str3 = TOOLBOX_L10N.getStr("toolbox.defaultTitle");
   ok(str1 && str2 && str3, "If this failed, strings should be updated in the test");
 
--- a/dom/base/DOMPrefs.cpp
+++ b/dom/base/DOMPrefs.cpp
@@ -18,21 +18,23 @@ DOMPrefs::Initialize()
 
   // Let's cache all the values on the main-thread.
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
   DOMPrefs::DumpEnabled();
 #endif
 
 #define DOM_PREF(name, pref) DOMPrefs::name();
 #define DOM_WEBIDL_PREF(name)
+#define DOM_UINT32_PREF(name, pref, defaultValue) DOMPrefs::name();
 
 #include "DOMPrefsInternal.h"
 
 #undef DOM_PREF
 #undef DOM_WEBIDL_PREF
+#undef DOM_UINT32_PREF
 }
 
 #define DOM_PREF(name, pref)                                         \
   /* static */ bool                                                  \
   DOMPrefs::name()                                                   \
   {                                                                  \
     static bool initialized = false;                                 \
     static Atomic<bool> cachedValue;                                 \
@@ -45,25 +47,39 @@ DOMPrefs::Initialize()
 
 #define DOM_WEBIDL_PREF(name)                    \
   /* static */ bool                              \
   DOMPrefs::name(JSContext* aCx, JSObject* aObj) \
   {                                              \
     return DOMPrefs::name();                     \
   }
 
+#define DOM_UINT32_PREF(name, pref, defaultValue)                             \
+  /* static */ uint32_t                                                       \
+  DOMPrefs::name()                                                            \
+  {                                                                           \
+      static bool initialized = false;                                        \
+      static Atomic<uint32_t> cachedValue;                                    \
+      if (!initialized) {                                                     \
+        initialized = true;                                                   \
+        Preferences::AddAtomicUintVarCache(&cachedValue, pref, defaultValue); \
+    }                                                                         \
+    return cachedValue;                                                       \
+  }
+
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
 DOM_PREF(DumpEnabled, "browser.dom.window.dump.enabled")
 #else
 /* static */ bool
 DOMPrefs::DumpEnabled()
 {
   return true;
 }
 #endif
 
 #include "DOMPrefsInternal.h"
 
 #undef DOM_PREF
 #undef DOM_WEBIDL_PREF
+#undef DOM_UINT32_PREF
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/base/DOMPrefs.h
+++ b/dom/base/DOMPrefs.h
@@ -16,19 +16,21 @@ public:
   // This must be called on the main-thread.
   static void Initialize();
 
   // Returns true if the browser.dom.window.dump.enabled pref is set.
   static bool DumpEnabled();
 
 #define DOM_PREF(name, pref) static bool name();
 #define DOM_WEBIDL_PREF(name) static bool name(JSContext* aCx, JSObject* aObj);
+#define DOM_UINT32_PREF(name, pref, defaultValue) static uint32_t name();
 
 #include "DOMPrefsInternal.h"
 
 #undef DOM_PREF
 #undef DOM_WEBIDL_PREF
+#undef DOM_UINT32_PREF
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_DOMPrefs_h
--- a/dom/base/DOMPrefsInternal.h
+++ b/dom/base/DOMPrefsInternal.h
@@ -51,8 +51,12 @@ DOM_WEBIDL_PREF(StorageManagerEnabled)
 DOM_WEBIDL_PREF(PromiseRejectionEventsEnabled)
 DOM_WEBIDL_PREF(PushEnabled)
 DOM_WEBIDL_PREF(StreamsEnabled)
 DOM_WEBIDL_PREF(OffscreenCanvasEnabled)
 DOM_WEBIDL_PREF(WebkitBlinkDirectoryPickerEnabled)
 DOM_WEBIDL_PREF(NetworkInformationEnabled)
 DOM_WEBIDL_PREF(FetchObserverEnabled)
 DOM_WEBIDL_PREF(PerformanceObserverEnabled)
+
+DOM_UINT32_PREF(WorkerCancelingTimeoutMillis,
+                "dom.worker.canceling.timeoutMilliseconds",
+                30000 /* 30 seconds */)
--- a/dom/base/DocumentFragment.cpp
+++ b/dom/base/DocumentFragment.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
- * Implementation of DOM Core's nsIDOMDocumentFragment.
+ * Implementation of DOM Core's DocumentFragment.
  */
 
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Element.h" // for NS_IMPL_ELEMENT_CLONE
 #include "mozilla/dom/NodeInfo.h"
 #include "nsNodeInfoManager.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
@@ -114,17 +114,16 @@ DocumentFragment::Constructor(const Glob
 NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentFragment, FragmentOrElement, mHost)
 
 // QueryInterface implementation for DocumentFragment
 NS_INTERFACE_MAP_BEGIN(DocumentFragment)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(DocumentFragment)
   NS_INTERFACE_MAP_ENTRY(nsIContent)
   NS_INTERFACE_MAP_ENTRY(nsINode)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentFragment)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
                                  new nsNodeSupportsWeakRefTearoff(this))
   // DOM bindings depend on the identity pointer being the
   // same as nsINode (which nsIContent inherits).
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -5,30 +5,30 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_DocumentFragment_h__
 #define mozilla_dom_DocumentFragment_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BorrowedAttrInfo.h"
 #include "mozilla/dom/FragmentOrElement.h"
-#include "nsIDOMDocumentFragment.h"
+#include "nsIDOMNode.h"
 #include "nsStringFwd.h"
 
 class nsAtom;
 class nsIDocument;
 class nsIContent;
 
 namespace mozilla {
 namespace dom {
 
 class Element;
 
 class DocumentFragment : public FragmentOrElement,
-                         public nsIDOMDocumentFragment
+                         public nsIDOMNode
 {
 private:
   void Init()
   {
     MOZ_ASSERT(mNodeInfo->NodeType() == DOCUMENT_FRAGMENT_NODE &&
                mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
                                  kNameSpaceID_None),
                "Bad NodeType in aNodeInfo");
@@ -40,19 +40,16 @@ public:
   using nsINode::QuerySelectorAll;
   // Make sure bindings can see our superclass' protected GetElementById method.
   using nsINode::GetElementById;
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment, FragmentOrElement)
 
-  // interface nsIDOMDocumentFragment
-  NS_DECL_NSIDOMDOCUMENTFRAGMENT
-
   explicit DocumentFragment(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : FragmentOrElement(aNodeInfo), mHost(nullptr)
   {
     Init();
   }
 
   explicit DocumentFragment(nsNodeInfoManager* aNodeInfoManager)
     : FragmentOrElement(aNodeInfoManager->GetNodeInfo(
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3864,25 +3864,21 @@ Element::SetOuterHTML(const nsAString& a
     RefPtr<mozilla::dom::NodeInfo> info =
       OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body,
                                                  nullptr,
                                                  kNameSpaceID_XHTML,
                                                  ELEMENT_NODE);
     context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT);
   }
 
-  nsCOMPtr<nsIDOMDocumentFragment> df;
-  aError = nsContentUtils::CreateContextualFragment(context,
-                                                    aOuterHTML,
-                                                    true,
-                                                    getter_AddRefs(df));
+  RefPtr<DocumentFragment> fragment =
+    nsContentUtils::CreateContextualFragment(context, aOuterHTML, true, aError);
   if (aError.Failed()) {
     return;
   }
-  nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
   parent->ReplaceChild(*fragment, *this, aError);
 }
 
 enum nsAdjacentPosition {
   eBeforeBegin,
   eAfterBegin,
   eBeforeEnd,
   eAfterEnd
@@ -3949,27 +3945,22 @@ Element::InsertAdjacentHTML(const nsAStr
                                                true);
     // HTML5 parser has notified, but not fired mutation events.
     nsContentUtils::FireMutationEventsForDirectParsing(doc, destination,
                                                        oldChildCount);
     return;
   }
 
   // couldn't parse directly
-  nsCOMPtr<nsIDOMDocumentFragment> df;
-  aError = nsContentUtils::CreateContextualFragment(destination,
-                                                    aText,
-                                                    true,
-                                                    getter_AddRefs(df));
+  RefPtr<DocumentFragment> fragment =
+    nsContentUtils::CreateContextualFragment(destination, aText, true, aError);
   if (aError.Failed()) {
     return;
   }
 
-  nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
-
   // Suppress assertion about node removal mutation events that can't have
   // listeners anyway, because no one has had the chance to register mutation
   // listeners on the fragment that comes from the parser.
   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
 
   nsAutoMutationBatch mb(destination, true, false);
   switch (position) {
     case eBeforeBegin:
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -63,16 +63,17 @@ EXPORTS += [
     'nsDocumentWarningList.h',
     'nsDOMAttributeMap.h',
     'nsDOMCID.h',
     'nsDOMJSUtils.h',
     'nsDOMNavigationTiming.h',
     'nsDOMString.h',
     'nsDOMTokenList.h',
     'nsFocusManager.h',
+    'nsFrameLoader.h',  # Because binding headers include it.
     'nsFrameMessageManager.h',
     'nsGlobalWindow.h',  # Because binding headers include it.
     'nsGlobalWindowInner.h',  # Because binding headers include it.
     'nsGlobalWindowOuter.h',  # Because binding headers include it.
     'nsIAnimationObserver.h',
     'nsIAttribute.h',
     'nsIContent.h',
     'nsIContentInlines.h',
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -4924,29 +4924,16 @@ nsContentUtils::IsValidNodeName(nsAtom *
   // If the namespace is not the XMLNS namespace then the prefix must not be
   // xmlns.
   // If the namespace is the XML namespace then the prefix can be anything.
   // If the namespace is not the XML namespace then the prefix must not be xml.
   return aPrefix != nsGkAtoms::xmlns &&
          (aNamespaceID == kNameSpaceID_XML || aPrefix != nsGkAtoms::xml);
 }
 
-/* static */
-nsresult
-nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
-                                         const nsAString& aFragment,
-                                         bool aPreventScriptExecution,
-                                         nsIDOMDocumentFragment** aReturn)
-{
-  ErrorResult rv;
-  *aReturn = CreateContextualFragment(aContextNode, aFragment,
-                                      aPreventScriptExecution, rv).take();
-  return rv.StealNSResult();
-}
-
 already_AddRefed<DocumentFragment>
 nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
                                          const nsAString& aFragment,
                                          bool aPreventScriptExecution,
                                          SanitizeFragments aSanitize,
                                          ErrorResult& aRv)
 {
   if (!aContextNode) {
@@ -5048,21 +5035,21 @@ nsContentUtils::CreateContextualFragment
         tagName.Append(uriStr);
         tagName.Append('"');
       }
     }
 
     content = content->GetParent();
   }
 
-  nsCOMPtr<nsIDOMDocumentFragment> frag;
+  RefPtr<DocumentFragment> frag;
   aRv = ParseFragmentXML(aFragment, document, tagStack,
                          aPreventScriptExecution, getter_AddRefs(frag),
                          aSanitize);
-  return frag.forget().downcast<DocumentFragment>();
+  return frag.forget();
 }
 
 /* static */
 void
 nsContentUtils::DropFragmentParsers()
 {
   NS_IF_RELEASE(sHTMLFragmentParser);
   NS_IF_RELEASE(sXMLFragmentParser);
@@ -5163,17 +5150,17 @@ nsContentUtils::ParseDocumentHTML(const 
 }
 
 /* static */
 nsresult
 nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
                                  nsIDocument* aDocument,
                                  nsTArray<nsString>& aTagStack,
                                  bool aPreventScriptExecution,
-                                 nsIDOMDocumentFragment** aReturn,
+                                 DocumentFragment** aReturn,
                                  SanitizeFragments aSanitize)
 {
   AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
 
   if (nsContentUtils::sFragmentParsingActive) {
     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
@@ -5212,23 +5199,21 @@ nsContentUtils::ParseFragmentXML(const n
 
   // If this is a chrome-privileged document, sanitize the fragment before
   // returning.
   if (aSanitize != NeverSanitize &&
       IsSystemPrincipal(aDocument->NodePrincipal())) {
     // Don't fire mutation events for nodes removed by the sanitizer.
     nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
 
-    RefPtr<DocumentFragment> fragment = static_cast<DocumentFragment*>(*aReturn);
-
     nsTreeSanitizer sanitizer(nsIParserUtils::SanitizerAllowStyle |
                               nsIParserUtils::SanitizerAllowComments |
                               nsIParserUtils::SanitizerDropForms |
                               nsIParserUtils::SanitizerLogRemovals);
-    sanitizer.Sanitize(fragment);
+    sanitizer.Sanitize(*aReturn);
   }
 
   return rv;
 }
 
 /* static */
 nsresult
 nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -65,17 +65,16 @@ class nsAtom;
 class nsIChannel;
 class nsIConsoleService;
 class nsIContent;
 class nsIContentPolicy;
 class nsIContentSecurityPolicy;
 class nsIDocShellTreeItem;
 class nsIDocumentLoaderFactory;
 class nsIDOMDocument;
-class nsIDOMDocumentFragment;
 class nsIDOMEvent;
 class nsIDOMNode;
 class nsIDragSession;
 class nsIEventTarget;
 class nsIFragmentContentSink;
 class nsIFrame;
 class nsIImageLoadingContent;
 class nsIInterfaceRequestor;
@@ -1625,20 +1624,16 @@ public:
    *
    * @param aContextNode the node which is used to resolve namespaces
    * @param aFragment the string which is parsed to a DocumentFragment
    * @param aReturn the resulting fragment
    * @param aPreventScriptExecution whether to mark scripts as already started
    * @param aSanitize whether the fragment should be sanitized prior to
    *        injection
    */
-  static nsresult CreateContextualFragment(nsINode* aContextNode,
-                                           const nsAString& aFragment,
-                                           bool aPreventScriptExecution,
-                                           nsIDOMDocumentFragment** aReturn);
   static already_AddRefed<mozilla::dom::DocumentFragment>
   CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
                            bool aPreventScriptExecution,
                            SanitizeFragments aSanitize,
                            mozilla::ErrorResult& aRv);
   static already_AddRefed<mozilla::dom::DocumentFragment>
   CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
                            bool aPreventScriptExecution,
@@ -1685,17 +1680,17 @@ public:
    *        injection
    * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
    *         fragments is made, a return code from the XML parser.
    */
   static nsresult ParseFragmentXML(const nsAString& aSourceBuffer,
                                    nsIDocument* aDocument,
                                    nsTArray<nsString>& aTagStack,
                                    bool aPreventScriptExecution,
-                                   nsIDOMDocumentFragment** aReturn,
+                                   mozilla::dom::DocumentFragment** aReturn,
                                    SanitizeFragments aSanitize = SanitizeSystemPrivileged);
 
   /**
    * Parse a string into a document using the HTML parser.
    * Script elements are marked unexecutable.
    *
    * @param aSourceBuffer the string to parse as an HTML document
    * @param aTargetDocument the document object to parse into. Must not have
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1665,17 +1665,17 @@ nsDOMWindowUtils::GetScrollbarSize(bool 
   *aWidth = nsPresContext::AppUnitsToIntCSSPixels(sizes.LeftRight());
   *aHeight = nsPresContext::AppUnitsToIntCSSPixels(sizes.TopBottom());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetBoundsWithoutFlushing(nsIDOMElement *aElement,
-                                           nsISupports** aResult)
+                                           DOMRect** aResult)
 {
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsresult rv;
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1734,17 +1734,17 @@ nsDOMWindowUtils::FlushLayoutWithoutThro
     doc->FlushPendingNotifications(
       ChangesToFlush(FlushType::Layout, false /* flush animations */));
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::GetRootBounds(nsISupports** aResult)
+nsDOMWindowUtils::GetRootBounds(DOMRect** aResult)
 {
   nsIDocument* doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   nsRect bounds(0, 0, 0, 0);
   nsIPresShell* presShell = doc->GetShell();
   if (presShell) {
     nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2517,19 +2517,18 @@ GetContentParent(Element* aBrowser)
 {
   using ReturnTuple = Tuple<ContentParent*, TabParent*>;
 
   nsCOMPtr<nsIBrowser> browser = do_QueryInterface(aBrowser);
   if (!browser) {
     return ReturnTuple(nullptr, nullptr);
   }
 
-  nsCOMPtr<nsISupports> otherLoaderAsSupports;
-  browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoaderAsSupports));
-  RefPtr<nsFrameLoader> otherLoader = do_QueryObject(otherLoaderAsSupports);
+  RefPtr<nsFrameLoader> otherLoader;
+  browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoader));
   if (!otherLoader) {
     return ReturnTuple(nullptr, nullptr);
   }
 
   TabParent* tabParent = TabParent::GetFrom(otherLoader);
   if (tabParent &&
       tabParent->Manager() &&
       tabParent->Manager()->IsContentParent()) {
--- a/dom/base/nsIDOMDOMCursor.idl
+++ b/dom/base/nsIDOMDOMCursor.idl
@@ -7,14 +7,14 @@
 #include "nsISupports.idl"
 
 [scriptable, function, uuid(3a75d80a-9258-4ab8-95fd-ec0b5f634df1)]
 interface nsICursorContinueCallback : nsISupports
 {
   void handleContinue();
 };
 
-[builtinclass, uuid(062ea35a-5158-425a-b7bc-3ae9daa84398)]
+[uuid(062ea35a-5158-425a-b7bc-3ae9daa84398)]
 interface nsIDOMDOMCursor : nsISupports
 {
   readonly attribute boolean done;
   void continue();
 };
--- a/dom/base/nsIDOMDOMRequest.idl
+++ b/dom/base/nsIDOMDOMRequest.idl
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface mozIDOMWindow;
 interface nsICursorContinueCallback;
 
-[builtinclass, uuid(e39da69e-2232-4e49-9856-b8a4a6210336)]
+[shim(DOMRequest), uuid(e39da69e-2232-4e49-9856-b8a4a6210336)]
 interface nsIDOMDOMRequest : nsIDOMEventTarget
 {
   readonly attribute DOMString readyState; // "pending" or "done"
 
   readonly attribute jsval result;
 
   // DOMException
   readonly attribute nsISupports error;
--- a/dom/base/nsIDOMParser.idl
+++ b/dom/base/nsIDOMParser.idl
@@ -14,17 +14,17 @@ interface nsIGlobalObject;
 /**
  * The nsIDOMParser interface is a non-SAX interface that can be used
  * to parse a string or byte stream containing XML or HTML content
  * to a DOM document. Parsing is always synchronous - a document is always
  * returned from the parsing methods. This is as opposed to loading and
  * parsing with the XMLHttpRequest interface, which can be used for
  * asynchronous (callback-based) loading.
  */
-[uuid(70b9600e-8622-4c93-9ad8-22c28058dc44)]
+[shim(DOMParser), uuid(70b9600e-8622-4c93-9ad8-22c28058dc44)]
 interface nsIDOMParser : nsISupports
 {
   /**
    * The string passed in is parsed into a DOM document.
    *
    * @param str The UTF16 string to be parsed
    * @param contentType The content type of the string (see parseFromStream)
    * @returns The DOM document created as a result of parsing the 
--- a/dom/base/nsIDroppedLinkHandler.idl
+++ b/dom/base/nsIDroppedLinkHandler.idl
@@ -2,16 +2,19 @@
  * 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 "nsISupports.idl"
 #include "nsIPrincipal.idl"
 
 interface nsIDOMEvent;
 
+webidl DragEvent;
+webidl DataTransfer;
+
 [scriptable, uuid(69E14F91-2E09-4CA6-A511-A715C99A2804)]
 interface nsIDroppedLinkItem : nsISupports
 {
   /**
    * Returns the URL of the link.
    */
   readonly attribute DOMString url;
 
@@ -32,20 +35,18 @@ interface nsIDroppedLinkHandler : nsISup
   /**
    * Determines if a link being dragged can be dropped and returns true if so.
    * aEvent should be a dragenter or dragover event.
    *
    * If aAllowSameDocument is false, drops are only allowed if the document
    * of the source of the drag is different from the destination. This check
    * includes any parent, sibling and child frames in the same content tree.
    * If true, the source is not checked.
-   *
-   * aEvent should be a DragEvent.  See bug 1444991.
    */
-  boolean canDropLink(in nsIDOMEvent aEvent, in boolean aAllowSameDocument);
+  boolean canDropLink(in DragEvent aEvent, in boolean aAllowSameDocument);
 
   /**
    * Given a drop event aEvent, determines the link being dragged and returns
    * it. If a uri is returned the caller can, for instance, load it. If null
    * is returned, there is no valid link to be dropped.
    *
    * A NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
    * the receiving target should not load the uri for security reasons. This
@@ -53,67 +54,57 @@ interface nsIDroppedLinkHandler : nsISup
    *  - the source of the drag initiated a link for dragging that
    *    it itself cannot access. This prevents a source document from tricking
    *    the user into a dragging a chrome url, for example.
    *  - aDisallowInherit is true, and the URI being dropped would inherit the
    *    current document's security context (URI_INHERITS_SECURITY_CONTEXT).
    *
    * aName is filled in with the link title if it exists, or an empty string
    * otherwise.
-   *
-   * aEvent should be a DragEvent.  See bug 1444991.
    */
-  AString dropLink(in nsIDOMEvent aEvent, out AString aName,
+  AString dropLink(in DragEvent aEvent, out AString aName,
                    [optional] in boolean aDisallowInherit);
 
   /**
    * Given a drop event aEvent, determines links being dragged and returns
    * them. If links are returned the caller can, for instance, load them. If
    * the count of links is 0, there is no valid link to be dropped.
    *
    * A NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
    * the receiving target should not load the uri for security reasons. This
    * will occur if any of the following conditions are true:
    *  - the source of the drag initiated a link for dragging that
    *    it itself cannot access. This prevents a source document from tricking
    *    the user into a dragging a chrome url, for example.
    *  - aDisallowInherit is true, and the URI being dropped would inherit the
    *    current document's security context (URI_INHERITS_SECURITY_CONTEXT).
-   *
-   * aEvent should be a DragEvent.  See bug 1444991.
    */
-  void dropLinks(in nsIDOMEvent aEvent,
+  void dropLinks(in DragEvent aEvent,
                  [optional] in boolean aDisallowInherit,
                  [optional] out unsigned long aCount,
                  [retval, array, size_is(aCount)] out nsIDroppedLinkItem aLinks);
 
   /**
    * Given a drop event aEvent, validate the extra URIs for the event,
    * this is used when the caller extracts yet another URIs from the dropped
    * text, like home button that splits the text with "|".
-   *
-   * aEvent should be a DragEvent.  See bug 1444991.
    */
-  void validateURIsForDrop(in nsIDOMEvent aEvent,
+  void validateURIsForDrop(in DragEvent aEvent,
                            in unsigned long aURIsCount,
                            [array, size_is(aURIsCount)] in wstring aURIs,
                            [optional] in boolean aDisallowInherit);
 
   /**
    * Given a dataTransfer, allows caller to determine and verify links being
    * dragged. Since drag/drop performs a roundtrip of parent, child, parent,
    * it allows the parent to verify that the child did not modify links
    * being dropped.
-   *
-   * @param dataTransfer is a DataTransfer.  See bug 1444991.
    */
-  void queryLinks(in nsISupports aDataTransfer,
+  void queryLinks(in DataTransfer aDataTransfer,
                   [optional] out unsigned long aCount,
                   [retval, array, size_is(aCount)] out nsIDroppedLinkItem aLinks);
 
   /**
    * Given a drop event aEvent, determines the triggering principal for the
    * event and returns it.
-   *
-   * aEvent should be a DragEvent.  See bug 1444991.
    */
-  nsIPrincipal getTriggeringPrincipal(in nsIDOMEvent aEvent);
+  nsIPrincipal getTriggeringPrincipal(in DragEvent aEvent);
 };
--- a/dom/base/nsIMessageManager.idl
+++ b/dom/base/nsIMessageManager.idl
@@ -2,22 +2,24 @@
 /* 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 "nsISupports.idl"
 
 interface nsIContent;
 
-[uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
+[shim(MessageSender), shimfile(MessageManager),
+ uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
 interface nsIMessageSender : nsISupports
 {
 };
 
-[uuid(694e367c-aa25-4446-8499-2c527c4bd838)]
+[shim(ContentFrameMessageManager), shimfile(MessageManager),
+ uuid(694e367c-aa25-4446-8499-2c527c4bd838)]
 interface nsIContentFrameMessageManager : nsIMessageSender
 {
 };
 
 [uuid(b39a3324-b574-4f85-8cdb-274d04f807ef)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
--- a/dom/base/nsISelection.idl
+++ b/dom/base/nsISelection.idl
@@ -20,17 +20,17 @@ class Selection;
 
 /**
  * Interface for manipulating and querying the current selected range
  * of nodes within the document.
  *
  * @version 1.0
  */
 
-[builtinclass, uuid(e0a4d4b3-f34e-44bd-b1f2-4e3bde9b6915)]
+[shim(Selection), uuid(e0a4d4b3-f34e-44bd-b1f2-4e3bde9b6915)]
 interface nsISelection : nsISupports
 {
     /**
      * Returns the node in which the selection begins.
      */
     readonly attribute nsIDOMNode anchorNode;
 
     /**
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -9,17 +9,16 @@
  */
 
 #include "nscore.h"
 #include "nsRange.h"
 
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsIDOMNode.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsError.h"
 #include "nsIContentIterator.h"
 #include "nsINodeList.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsTextFrame.h"
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -381,17 +381,17 @@ public:
 private:
   // no copy's or assigns
   nsRange(const nsRange&);
   nsRange& operator=(const nsRange&);
 
   /**
    * Cut or delete the range's contents.
    *
-   * @param aFragment nsIDOMDocumentFragment containing the nodes.
+   * @param aFragment DocumentFragment containing the nodes.
    *                  May be null to indicate the caller doesn't want a fragment.
    */
   nsresult CutContents(mozilla::dom::DocumentFragment** frag);
 
   static nsresult CloneParentsBetween(nsINode* aAncestor,
                                       nsINode* aNode,
                                       nsINode** aClosestAncestor,
                                       nsINode** aFarthestAncestor);
--- a/dom/base/test/unit/test_range.js
+++ b/dom/base/test/unit/test_range.js
@@ -51,17 +51,17 @@ function dumpFragment(aFragment) {
  * fragment as context node.
  *
  * @param aContextNode The context node to apply the XPath to.
  * @param aPath        The XPath to use.
  *
  * @return nsIDOMNode  The target node retrieved from the XPath.
  */
 function evalXPathInDocumentFragment(aContextNode, aPath) {
-  Assert.ok(aContextNode instanceof Ci.nsIDOMDocumentFragment);
+  Assert.equal(ChromeUtils.getClassName(aContextNode), "DocumentFragment");
   Assert.ok(aContextNode.childNodes.length > 0);
   if (aPath == ".") {
     return aContextNode;
   }
 
   // Separate the fragment's xpath lookup from the rest.
   var firstSlash = aPath.indexOf("/");
   if (firstSlash == -1) {
@@ -144,17 +144,17 @@ function evalXPathInDocumentFragment(aCo
  *
  * @param aSourceNode <source/> element with range information.
  * @param aFragment   DocumentFragment generated with getFragment().
  *
  * @return Range object.
  */
 function getRange(aSourceNode, aFragment) {
   Assert.ok(aSourceNode instanceof Ci.nsIDOMElement);
-  Assert.ok(aFragment instanceof Ci.nsIDOMDocumentFragment);
+  Assert.equal(ChromeUtils.getClassName(aFragment), "DocumentFragment");
   var doc = aSourceNode.ownerDocument;
 
   var containerPath = aSourceNode.getAttribute("startContainer");
   var startContainer = evalXPathInDocumentFragment(aFragment, containerPath);
   var startOffset = Number(aSourceNode.getAttribute("startOffset"));
 
   containerPath = aSourceNode.getAttribute("endContainer");
   var endContainer = evalXPathInDocumentFragment(aFragment, containerPath);
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -306,25 +306,25 @@ BroadcastChannel::Constructor(const Glob
     MOZ_ASSERT(workerPrivate);
 
     RefPtr<StrongWorkerRef> workerRef =
       StrongWorkerRef::Create(workerPrivate, "BroadcastChannel",
                               [bc] () { bc->Shutdown(); });
     // We are already shutting down the worker. Let's return a non-active
     // object.
     if (NS_WARN_IF(!workerRef)) {
-      bc->mState = StateClosed;
-      return bc.forget();
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
     RefPtr<ThreadSafeWorkerRef> tsr = new ThreadSafeWorkerRef(workerRef);
 
     RefPtr<InitializeRunnable> runnable =
       new InitializeRunnable(tsr, origin, principalInfo, aRv);
-    runnable->Dispatch(Closing, aRv);
+    runnable->Dispatch(Canceling, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
     bc->mWorkerRef = Move(workerRef);
   }
 
   // Register this component to PBackground.
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -63,21 +63,16 @@ public:
   void Shutdown();
 
 private:
   BroadcastChannel(nsPIDOMWindowInner* aWindow,
                    const nsAString& aChannel);
 
   ~BroadcastChannel();
 
-  void PostMessageData(BroadcastChannelMessage* aData);
-
-  void PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                           ErrorResult& aRv);
-
   void RemoveDocFromBFCache();
 
   void DisconnectFromOwner() override;
 
   RefPtr<BroadcastChannelChild> mActor;
 
   RefPtr<WorkerRef> mWorkerRef;
 
--- a/dom/browser-element/nsIBrowserElementAPI.idl
+++ b/dom/browser-element/nsIBrowserElementAPI.idl
@@ -3,16 +3,18 @@
 /* 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 "nsISupports.idl"
 
 interface nsIDOMDOMRequest;
 
+webidl FrameLoader;
+
 [scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)]
 interface nsIBrowserElementNextPaintListener : nsISupports
 {
   void recvNextPaint();
 };
 
 %{C++
 #define BROWSER_ELEMENT_API_CONTRACTID "@mozilla.org/dom/browser-element-api;1"
@@ -34,18 +36,17 @@ interface nsIBrowserElementAPI : nsISupp
   const long FIND_FORWARD = 0;
   const long FIND_BACKWARD = 1;
 
   /**
    * Notify frame scripts that support the API to destroy.
    */
   void destroyFrameScripts();
 
-  // The argument should be a FrameLoader.  Fix that when bug 1444991 is fixed.
-  void setFrameLoader(in nsISupports frameLoader);
+  void setFrameLoader(in FrameLoader frameLoader);
 
   void sendMouseEvent(in DOMString type,
                       in uint32_t x,
                       in uint32_t y,
                       in uint32_t button,
                       in uint32_t clickCount,
                       in uint32_t mifiers);
   void sendTouchEvent(in DOMString aType,
--- a/dom/clients/manager/ClientChannelHelper.cpp
+++ b/dom/clients/manager/ClientChannelHelper.cpp
@@ -11,16 +11,17 @@
 #include "MainThreadUtils.h"
 #include "mozilla/dom/ServiceWorkerDescriptor.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "nsContentUtils.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIChannel.h"
 #include "nsIChannelEventSink.h"
 #include "nsIDocShell.h"
+#include "nsIHttpChannelInternal.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 using mozilla::ipc::PrincipalInfoToPrincipal;
 
@@ -120,27 +121,36 @@ class ClientChannelHelper final : public
       reservedClient.reset();
       reservedClient = ClientManager::CreateSource(ClientType::Window,
                                                    mEventTarget, principal);
       MOZ_DIAGNOSTIC_ASSERT(reservedClient);
 
       newLoadInfo->GiveReservedClientSource(Move(reservedClient));
     }
 
+    uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_MANUAL;
+    nsCOMPtr<nsIHttpChannelInternal> http = do_QueryInterface(aOldChannel);
+    if (http) {
+      MOZ_ALWAYS_SUCCEEDS(http->GetRedirectMode(&redirectMode));
+    }
+
     // Normally we keep the controller across channel redirects, but we must
-    // clear it when a non-subresource load redirects.  Only do this for real
+    // clear it when a document load redirects.  Only do this for real
     // redirects, however.
     //
-    // There is an open spec question about what to do in this case for
-    // worker script redirects.  For now we clear the controller as that
-    // seems most sane. See:
+    // This is effectively described in step 4.2 of:
+    //
+    //  https://fetch.spec.whatwg.org/#http-fetch
     //
-    //  https://github.com/w3c/ServiceWorker/issues/1239
-    //
-    if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
+    // The spec sets the service-workers mode to none when the request is
+    // configured to *not* follow redirects.  This prevents any further
+    // service workers from intercepting.  The first service worker that
+    // had a shot at the FetchEvent remains the controller in this case.
+    if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
+        redirectMode != nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW) {
       newLoadInfo->ClearController();
     }
 
     nsCOMPtr<nsIChannelEventSink> outerSink = do_GetInterface(mOuter);
     if (outerSink) {
       return outerSink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags,
                                                aCallback);
     }
--- a/dom/file/FileReaderSync.cpp
+++ b/dom/file/FileReaderSync.cpp
@@ -438,17 +438,17 @@ FileReaderSync::SyncRead(nsIInputStream*
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
   if (!asyncStream) {
     return rv;
   }
 
   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(workerPrivate);
 
-  AutoSyncLoopHolder syncLoop(workerPrivate, Closing);
+  AutoSyncLoopHolder syncLoop(workerPrivate, Terminating);
 
   nsCOMPtr<nsIEventTarget> syncLoopTarget = syncLoop.GetEventTarget();
   if (!syncLoopTarget) {
     // SyncLoop creation can fail if the worker is shutting down.
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   RefPtr<ReadCallback> callback =
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -974,17 +974,17 @@ HTMLFormElement::NotifySubmitObservers(n
 
     bool loop = true;
     while (NS_SUCCEEDED(theEnum->HasMoreElements(&loop)) && loop) {
       theEnum->GetNext(getter_AddRefs(inst));
 
       nsCOMPtr<nsIFormSubmitObserver> formSubmitObserver(
                       do_QueryInterface(inst));
       if (formSubmitObserver) {
-        rv = formSubmitObserver->Notify(static_cast<nsIContent*>(this),
+        rv = formSubmitObserver->Notify(this,
                                         window ? window->GetCurrentInnerWindow() : nullptr,
                                         aActionURL,
                                         aCancelSubmit);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       if (*aCancelSubmit) {
         return NS_OK;
       }
@@ -1972,17 +1972,17 @@ HTMLFormElement::CheckValidFormSubmissio
       nsCOMPtr<nsISupports> inst;
       nsCOMPtr<nsIFormSubmitObserver> observer;
       bool more = true;
       while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) {
         theEnum->GetNext(getter_AddRefs(inst));
         observer = do_QueryInterface(inst);
 
         if (observer) {
-          observer->NotifyInvalidSubmit(static_cast<nsIContent*>(this),
+          observer->NotifyInvalidSubmit(this,
                                         static_cast<nsIArray*>(invalidElements));
         }
       }
 
       // The form is invalid. Observers have been alerted. Do not submit.
       return false;
     }
   } else {
--- a/dom/html/nsBrowserElement.cpp
+++ b/dom/html/nsBrowserElement.cpp
@@ -46,17 +46,17 @@ nsBrowserElement::InitBrowserElementAPI(
   }
 
   if (!mBrowserElementAPI) {
     mBrowserElementAPI = do_CreateInstance("@mozilla.org/dom/browser-element-api;1");
     if (NS_WARN_IF(!mBrowserElementAPI)) {
       return;
     }
   }
-  mBrowserElementAPI->SetFrameLoader(ToSupports(frameLoader));
+  mBrowserElementAPI->SetFrameLoader(frameLoader);
 }
 
 void
 nsBrowserElement::DestroyBrowserElementFrameScripts()
 {
   if (!mBrowserElementAPI) {
     return;
   }
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -20,17 +20,16 @@
 #include "nsAttrValueInlines.h"
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
 #include "nsQueryObject.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIURL.h"
 #include "nsEscape.h"
--- a/dom/html/nsIFormSubmitObserver.idl
+++ b/dom/html/nsIFormSubmitObserver.idl
@@ -5,24 +5,24 @@
 
 
 #include "nsISupports.idl"
 
 interface mozIDOMWindow;
 interface nsIURI;
 interface nsIArray;
 
+webidl HTMLFormElement;
+
 [scriptable, uuid(867cb7e7-835d-408b-9788-d2834d284e03)]
 interface nsIFormSubmitObserver: nsISupports
 {
-  // formNode must be a HTMLFormElement (bug 1444991 can clean it up)
-  void notify(in nsISupports formNode, in mozIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
+  void notify(in HTMLFormElement formNode, in mozIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
 
-  // formNode must be a HTMLFormElement (bug 1444991 can clean it up)
-  void notifyInvalidSubmit(in nsISupports formNode,
+  void notifyInvalidSubmit(in HTMLFormElement formNode,
                            in nsIArray invalidElements);
 };
 
 %{C++
 #define NS_FORMSUBMIT_SUBJECT "formsubmit"
 #define NS_EARLYFORMSUBMIT_SUBJECT "earlyformsubmit"
 #define NS_FIRST_FORMSUBMIT_CATEGORY "firstformsubmit"
 #define NS_PASSWORDMANAGER_CATEGORY "passwordmanager"
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -12,17 +12,16 @@ class nsWrapperCache;
 [ptr] native nsWrapperCachePtr(nsWrapperCache);
 
 typedef unsigned long long DOMTimeStamp;
 typedef double DOMHighResTimeStamp;
 typedef unsigned long long nsViewID;
 
 // Core
 interface nsIDOMDocument;
-interface nsIDOMDocumentFragment;
 interface nsIDOMElement;
 interface nsIDOMNode;
 interface nsIDOMNodeList;
 
 // Needed for raises() in our IDL
 %{C++
 namespace mozilla {
 namespace dom {
--- a/dom/interfaces/base/nsIBrowser.idl
+++ b/dom/interfaces/base/nsIBrowser.idl
@@ -1,29 +1,28 @@
 /* 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 "nsISupports.idl"
 
 interface nsIPrincipal;
 
+webidl FrameLoader;
+
 [scriptable, uuid(14e5a0cb-e223-4202-95e8-fe53275193ea)]
 interface nsIBrowser : nsISupports
 {
   /**
    * Gets an optional frame loader that is "related" to this browser.
    * If this exists, then we should attempt to use the same content parent as
    * this frame loader for any new tab parents.  For example, view source
    * browsers set this to the frame loader for the original content to ensure
    * they are loaded in the same process as the content.
-   *
-   * This returns a FrameLoader, but we have no good way to represent
-   * one in xpidl.  Fix this when bug 1444991 is fixed.
    */
-  readonly attribute nsISupports sameProcessAsFrameLoader;
+  readonly attribute FrameLoader sameProcessAsFrameLoader;
 
   /*
    * Called by the child to inform the parent that links are dropped into
    * content area.
    *
    * @param linksCount length of links
    * @param links a flat array of url, name, and type for each link
    * @param triggeringPrincipal a principal that initiated loading
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -44,16 +44,18 @@ interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 interface nsIDOMStorage;
 
+webidl DOMRect;
+
 [scriptable, uuid(4d6732ca-9da7-4176-b8a1-8dde15cd0bf9)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
@@ -837,19 +839,18 @@ interface nsIDOMWindowUtils : nsISupport
    * Returns the scrollbar width of the window's scroll frame.
    *
    * @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
    */
   void getScrollbarSize(in boolean aFlushLayout, out long aWidth, out long aHeight);
 
   /**
    * Returns the given element's bounds without flushing pending layout changes.
-   * The returned object is a DOMRect (bug 1444991 may remove this walkaround).
    */
-  nsISupports getBoundsWithoutFlushing(in nsIDOMElement aElement);
+  DOMRect getBoundsWithoutFlushing(in nsIDOMElement aElement);
 
   const long FLUSH_NONE = -1;
   const long FLUSH_STYLE = 0;
   const long FLUSH_LAYOUT = 1;
   const long FLUSH_DISPLAY = 2;
 
   /**
    * Returns true if a flush of the given type is needed.
@@ -861,19 +862,18 @@ interface nsIDOMWindowUtils : nsISupport
    * animations.
    */
   void flushLayoutWithoutThrottledAnimations();
 
   /**
    * Returns the bounds of the window's currently loaded document. This will
    * generally be (0, 0, pageWidth, pageHeight) but in some cases (e.g. RTL
    * documents) may have a negative left value.
-   * The returned object is a DOMRect (bug 1444991 may remove this walkaround).
    */
-  nsISupports getRootBounds();
+  DOMRect getRootBounds();
 
   /**
    * Get IME open state. TRUE means 'Open', otherwise, 'Close'.
    * This property works only when IMEEnabled is IME_STATUS_ENABLED.
    */
   readonly attribute boolean IMEIsOpen;
 
   /**
--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
+++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
@@ -133,22 +133,16 @@ interface nsIServiceWorkerManager : nsIS
   /**
    * Unregister an existing ServiceWorker registration for `aScope`.
    * It keeps aCallback alive until the operation is concluded.
    */
   void unregister(in nsIPrincipal aPrincipal,
                   in nsIServiceWorkerUnregisterCallback aCallback,
                   in DOMString aScope);
 
-  // Returns a Promise
-  nsISupports getRegistrations(in mozIDOMWindow aWindow);
-
-  // Returns a Promise
-  nsISupports getRegistration(in mozIDOMWindow aWindow, in DOMString aScope);
-
   nsIServiceWorkerRegistrationInfo getRegistrationByPrincipal(in nsIPrincipal aPrincipal,
                                                               in DOMString aScope);
 
   [notxpcom, nostdcall] bool StartControlling(in const_ClientInfoRef aClientInfo,
                                               in const_ServiceWorkerDescriptorRef aServiceWorker);
 
   /*
    * Clears ServiceWorker registrations from memory and disk for the specified
--- a/dom/interfaces/core/moz.build
+++ b/dom/interfaces/core/moz.build
@@ -4,17 +4,16 @@
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 XPIDL_SOURCES += [
     'nsIDOMDocument.idl',
-    'nsIDOMDocumentFragment.idl',
     'nsIDOMElement.idl',
     'nsIDOMNode.idl',
     'nsIDOMNodeList.idl',
     'nsIDOMNSEditableElement.idl',
 ]
 
 XPIDL_MODULE = 'dom_core'
 
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -13,12 +13,12 @@
  * cannot exist outside the context of a Document, the nsIDOMDocument
  * interface also contains the factory methods needed to create these
  * objects.
  *
  * For more information on this interface please see
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[uuid(b15fa0f4-97c1-4388-af62-2ceff7a89bdf)]
+[shim(Document), uuid(b15fa0f4-97c1-4388-af62-2ceff7a89bdf)]
 interface nsIDOMDocument : nsIDOMNode
 {
 };
deleted file mode 100644
--- a/dom/interfaces/core/nsIDOMDocumentFragment.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; 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 "nsIDOMNode.idl"
-    
-/**
- * DocumentFragment is a "lightweight" or "minimal" Document object.
- * nsIDOMDocumentFragment is used in situations where the Document
- * interface can potentially be a heavyweight interface.
- *
- * For more information on this interface please see 
- * http://www.w3.org/TR/DOM-Level-2-Core/
- */
-
-[builtinclass, uuid(48eb8d72-95bb-402e-a8fc-f2b187abcbdb)]
-interface nsIDOMDocumentFragment : nsIDOMNode
-{
-};
--- a/dom/interfaces/core/nsIDOMElement.idl
+++ b/dom/interfaces/core/nsIDOMElement.idl
@@ -19,12 +19,12 @@ interface nsIDOMMozNamedAttrMap;
 /**
  * The nsIDOMElement interface represents an element in an HTML or 
  * XML document. 
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-element
  */
 
-[uuid(6289999b-1008-4269-b42a-413ec5a9d3f4)]
+[shim(Element), uuid(6289999b-1008-4269-b42a-413ec5a9d3f4)]
 interface nsIDOMElement : nsIDOMNode
 {
 };
--- a/dom/interfaces/core/nsIDOMNode.idl
+++ b/dom/interfaces/core/nsIDOMNode.idl
@@ -9,12 +9,12 @@
  * The nsIDOMNode interface is the primary datatype for the entire
  * Document Object Model.
  * It represents a single node in the document tree.
  *
  * For more information on this interface please see
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[uuid(cc35b412-009b-46a3-9be0-76448f12548d)]
+[shim(Node), uuid(cc35b412-009b-46a3-9be0-76448f12548d)]
 interface nsIDOMNode : nsISupports
 {
 };
--- a/dom/interfaces/core/nsIDOMNodeList.idl
+++ b/dom/interfaces/core/nsIDOMNodeList.idl
@@ -10,12 +10,12 @@
  * collection of nodes, without defining or constraining how this collection 
  * is implemented.
  * The items in the list are accessible via an integral index, starting from 0.
  *
  * For more information on this interface please see 
  * http://www.w3.org/TR/DOM-Level-2-Core/
  */
 
-[uuid(450cf0ba-de90-4f86-85bf-e10cc8b8713f)]
+[shim(NodeList), uuid(450cf0ba-de90-4f86-85bf-e10cc8b8713f)]
 interface nsIDOMNodeList : nsISupports
 {
 };
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -37,17 +37,17 @@ class EventTarget;
  * The nsIDOMEvent interface is the primary datatype for all events in
  * the Document Object Model.
  *
  * For more information on this interface please see 
  * http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html and
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[builtinclass, uuid(f58daacf-4d1a-4002-8fd7-06b614dfbcf6)]
+[shim(Event), uuid(f58daacf-4d1a-4002-8fd7-06b614dfbcf6)]
 interface nsIDOMEvent : nsISupports
 {
   // PhaseType
   /**
    * The event isn't being dispatched.
    */
   const unsigned short      NONE                           = 0;
   /**
--- a/dom/interfaces/events/nsIDOMEventTarget.idl
+++ b/dom/interfaces/events/nsIDOMEventTarget.idl
@@ -1,11 +1,11 @@
 /* -*- Mode: IDL; tab-width: 2; 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 "domstubs.idl"
 
-[uuid(9a78ac3c-9507-4d00-b2d6-10b508d2ec31)]
+[shim(EventTarget), uuid(9a78ac3c-9507-4d00-b2d6-10b508d2ec31)]
 interface nsIDOMEventTarget : nsISupports
 {
 };
--- a/dom/interfaces/geolocation/nsIDOMGeoPositionError.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoPositionError.idl
@@ -7,17 +7,17 @@
 
 // undef the GetMessage macro defined in winuser.h from the MS Platform SDK
 %{C++
 #ifdef GetMessage
 #undef GetMessage
 #endif
 %}
 
-[uuid(85255CC3-07BA-49FD-BC9B-18D2963DAF7F)]
+[shim(PositionError), uuid(85255CC3-07BA-49FD-BC9B-18D2963DAF7F)]
 interface nsIDOMGeoPositionError : nsISupports
 {
   const unsigned short PERMISSION_DENIED  = 1;
   const unsigned short POSITION_UNAVAILABLE = 2;
   const unsigned short TIMEOUT = 3;
 
   readonly attribute short code;
   readonly attribute AString message;
--- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl
@@ -11,12 +11,12 @@
   *
   * This interface is trying to follow the DOM Level 2 HTML specification:
   * http://www.w3.org/TR/DOM-Level-2-HTML/
   *
   * with changes from the work-in-progress WHATWG HTML specification:
   * http://www.whatwg.org/specs/web-apps/current-work/
   */
 
-[uuid(64aeda0b-e9b5-4868-a4f9-e4776e32e733)]
+[shim(HTMLInputElement), uuid(64aeda0b-e9b5-4868-a4f9-e4776e32e733)]
 interface nsIDOMHTMLInputElement : nsISupports
 {
 };
--- a/dom/interfaces/offline/nsIDOMOfflineResourceList.idl
+++ b/dom/interfaces/offline/nsIDOMOfflineResourceList.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; 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 "domstubs.idl"
 
-[uuid(6044702d-e4a9-420c-b711-558b7d6a3b9f)]
+[shim(OfflineResourceList), uuid(6044702d-e4a9-420c-b711-558b7d6a3b9f)]
 interface nsIDOMOfflineResourceList : nsISupports
 {
   /**
    * Get the list of dynamically-managed entries.
    */
   readonly attribute nsISupports mozItems;
 
   /**
--- a/dom/interfaces/range/nsIDOMRange.idl
+++ b/dom/interfaces/range/nsIDOMRange.idl
@@ -7,12 +7,12 @@
 
 /**
  * The nsIDOMRange interface is an interface to a DOM range object.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
  */
 
-[builtinclass, uuid(1f94055c-42e7-4a30-96a1-6a804f1c2d1e)]
+[shim(Range), uuid(1f94055c-42e7-4a30-96a1-6a804f1c2d1e)]
 interface nsIDOMRange : nsISupports
 {
 };
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2154,70 +2154,16 @@ ContentParent::~ContentParent()
   if (IsForJSPlugin()) {
     MOZ_ASSERT(!sJSPluginContentParents ||
                !sJSPluginContentParents->Get(mJSPluginID));
   } else {
     MOZ_ASSERT(!sBrowserContentParents ||
                !sBrowserContentParents->Contains(mRemoteType) ||
                !sBrowserContentParents->Get(mRemoteType)->Contains(this));
   }
-#ifdef NIGHTLY_BUILD
-  MessageChannel* channel = GetIPCChannel();
-
-  if (channel && !channel->Unsound_IsClosed()) {
-    nsString friendlyName;
-    FriendlyName(friendlyName, false);
-
-    AddRef();
-    nsrefcnt refcnt = Release();
-    uint32_t numQueuedMessages = 0;
-    numQueuedMessages = channel->Unsound_NumQueuedMessages();
-
-    nsPrintfCString msg("queued-ipc-messages/content-parent"
-                        "(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR
-                        ", numQueuedMessages=%d, remoteType=%s, "
-                        "mCalledClose=%s, mCalledKillHard=%s, "
-                        "mShutdownPending=%s, mIPCOpen=%s)",
-                        NS_ConvertUTF16toUTF8(friendlyName).get(),
-                        Pid(), "open channel",
-                        static_cast<nsIContentParent*>(this), refcnt,
-                        numQueuedMessages,
-                        NS_ConvertUTF16toUTF8(mRemoteType).get(),
-                        mCalledClose ? "true" : "false",
-                        mCalledKillHard ? "true" : "false",
-                        mShutdownPending ? "true" : "false",
-                        mIPCOpen ? "true" : "false");
-    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCFatalErrorMsg"),
-                                       msg);
-    switch (channel->GetChannelState__TotallyRacy()) {
-        case ChannelOpening:
-            MOZ_CRASH("MessageChannel destroyed without being closed " \
-                      "(mChannelState == ChannelOpening).");
-            break;
-        case ChannelConnected:
-            MOZ_CRASH("MessageChannel destroyed without being closed " \
-                      "(mChannelState == ChannelConnected).");
-            break;
-        case ChannelTimeout:
-            MOZ_CRASH("MessageChannel destroyed without being closed " \
-                      "(mChannelState == ChannelTimeout).");
-            break;
-        case ChannelClosing:
-            MOZ_CRASH("MessageChannel destroyed without being closed " \
-                      "(mChannelState == ChannelClosing).");
-            break;
-        case ChannelError:
-            MOZ_CRASH("MessageChannel destroyed without being closed " \
-                      "(mChannelState == ChannelError).");
-            break;
-        default:
-            MOZ_CRASH("MessageChannel destroyed without being closed.");
-    }
-  }
-#endif
 }
 
 void
 ContentParent::InitInternal(ProcessPriority aInitialPriority)
 {
   Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
                         static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
                                               .ToMilliseconds()));
@@ -3159,16 +3105,23 @@ ContentParent::KillHard(const char* aRea
   // process handle becomes invalid on the first call, causing a second call
   // to crash our process - more details in bug 890840.
   if (mCalledKillHard) {
     return;
   }
   mCalledKillHard = true;
   mForceKillTimer = nullptr;
 
+#ifdef NIGHTLY_BUILD
+  MessageChannel* channel = GetIPCChannel();
+  if (channel) {
+    channel->SetInKillHardShutdown();
+  }
+#endif
+
   // We're about to kill the child process associated with this content.
   // Something has gone wrong to get us here, so we generate a minidump
   // of the parent and child for submission to the crash server.
   if (mCrashReporter) {
     // GeneratePairedMinidump creates two minidumps for us - the main
     // one is for the content process we're about to kill, and the other
     // one is for the main browser process. That second one is the extra
     // minidump tagging along, so we have to tell the crash reporter that
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -179,17 +179,17 @@ public:
 
   NS_IMETHOD TerminateScript() override;
   NS_IMETHOD TerminateGlobal() override;
   NS_IMETHOD BeginStartingDebugger() override;
   NS_IMETHOD EndStartingDebugger() override;
   NS_IMETHOD TerminatePlugin() override;
   NS_IMETHOD UserCanceled() override;
 
-  NS_IMETHOD IsReportForBrowser(nsISupports* aFrameLoader, bool* aResult) override;
+  NS_IMETHOD IsReportForBrowser(nsFrameLoader* aFrameLoader, bool* aResult) override;
 
   // Called when a content process shuts down.
   void Clear() {
     mContentParent = nullptr;
     mActor = nullptr;
   }
 
   /**
@@ -1119,29 +1119,28 @@ HangMonitoredProcess::TerminatePlugin()
                            contentPid,
                            NS_LITERAL_CSTRING("HangMonitor"),
                            mDumpId,
                            Move(callback));
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HangMonitoredProcess::IsReportForBrowser(nsISupports* aFrameLoader, bool* aResult)
+HangMonitoredProcess::IsReportForBrowser(nsFrameLoader* aFrameLoader, bool* aResult)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   if (!mActor) {
     *aResult = false;
     return NS_OK;
   }
 
-  RefPtr<nsFrameLoader> frameLoader = do_QueryObject(aFrameLoader);
-  NS_ENSURE_STATE(frameLoader);
+  NS_ENSURE_STATE(aFrameLoader);
 
-  TabParent* tp = TabParent::GetFrom(frameLoader);
+  TabParent* tp = TabParent::GetFrom(aFrameLoader);
   if (!tp) {
     *aResult = false;
     return NS_OK;
   }
 
   *aResult = mContentParent == tp->Manager();
   return NS_OK;
 }
--- a/dom/ipc/nsIHangReport.idl
+++ b/dom/ipc/nsIHangReport.idl
@@ -3,16 +3,18 @@
 /* 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 "nsISupports.idl"
 
 interface nsIDOMElement;
 
+webidl FrameLoader;
+
 /**
  * When a content process hangs, Gecko notifies "process-hang-report" observers
  * and passes an nsIHangReport for the subject parameter. There is at most one
  * nsIHangReport associated with a given content process. As long as the content
  * process stays stuck, the "process-hang-report" observer will continue to be
  * notified at regular intervals (approximately once per second). The content
  * process will continue to run uninhibitedly during this time.
  */
@@ -60,11 +62,11 @@ interface nsIHangReport : nsISupports
 
   // Inform the content process that the slow script debugger has finished
   // spinning up. The content process will run a nested event loop until this
   // method is called.
   // Only valid for SLOW_SCRIPT reports.
   void endStartingDebugger();
 
   // Inquire whether the report is for a content process loaded by the given
-  // frameloader.  Make this take a FrameLoader once bug 1444991 is fixed.
-  bool isReportForBrowser(in nsISupports aFrameLoader);
+  // frameloader.
+  bool isReportForBrowser(in FrameLoader aFrameLoader);
 };
--- a/dom/media/TextTrackCue.cpp
+++ b/dom/media/TextTrackCue.cpp
@@ -132,23 +132,23 @@ TextTrackCue::GetCueAsHTML()
     ClearOnShutdown(&sParserWrapper);
   }
 
   nsPIDOMWindowInner* window = mDocument->GetInnerWindow();
   if (!window) {
     return mDocument->CreateDocumentFragment();
   }
 
-  nsCOMPtr<nsIDOMDocumentFragment> frag;
+  RefPtr<DocumentFragment> frag;
   sParserWrapper->ConvertCueToDOMTree(window, this,
                                       getter_AddRefs(frag));
   if (!frag) {
     return mDocument->CreateDocumentFragment();
   }
-  return frag.forget().downcast<DocumentFragment>();
+  return frag.forget();
 }
 
 void
 TextTrackCue::SetTrackElement(HTMLTrackElement* aTrackElement)
 {
   mTrackElement = aTrackElement;
 }
 
--- a/dom/media/webvtt/nsIWebVTTParserWrapper.idl
+++ b/dom/media/webvtt/nsIWebVTTParserWrapper.idl
@@ -1,19 +1,20 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMDocumentFragment;
 interface nsIWebVTTListener;
 interface mozIDOMWindow;
 interface nsIVariant;
 
+webidl DocumentFragment;
+
 /**
  * Interface for a wrapper of a JS WebVTT parser (vtt.js).
  */
 [scriptable, uuid(8dfe016e-1701-4618-9f5e-9a6154e853f0)]
 interface nsIWebVTTParserWrapper : nsISupports
 {
   /**
    * Loads the JS WebVTTParser and sets it to use the passed window to create
@@ -55,18 +56,18 @@ interface nsIWebVTTParserWrapper : nsISu
    * Convert the text content of a WebVTT cue to a document fragment so that
    * we can display it on the page.
    *
    * @param window A window object with which the document fragment will be
    *               created.
    * @param cue    The cue whose content will be converted to a document
    *               fragment.
    */
-  nsIDOMDocumentFragment convertCueToDOMTree(in mozIDOMWindow window,
-                                             in nsISupports cue);
+  DocumentFragment convertCueToDOMTree(in mozIDOMWindow window,
+				       in nsISupports cue);
 
 
   /**
    * Compute the display state of the VTTCues in cues along with any VTTRegions
    * that they might be in. First, it computes the positioning and styling of
    * the cues and regions passed and converts them into a DOM tree rooted at
    * a containing HTMLDivElement. It then adjusts those computed divs for
    * overlap avoidance using the dimensions of 'overlay'. Finally, it adds the
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/messagechannel/MessagePort.cpp
@@ -292,18 +292,18 @@ MessagePort::Initialize(const nsID& aUUI
     MOZ_ASSERT(workerPrivate);
 
     // When the callback is executed, we cannot process messages anymore because
     // we cannot dispatch new runnables. Let's force a Close().
     RefPtr<StrongWorkerRef> strongWorkerRef =
       StrongWorkerRef::Create(workerPrivate, "MessagePort",
                               [self]() { self->CloseForced(); });
     if (NS_WARN_IF(!strongWorkerRef)) {
-      // The worker is shutting down. Let's return an already closed port.
-      mState = eStateDisentangledForClose;
+      // The worker is shutting down.
+      aRv.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     MOZ_ASSERT(!mWorkerRef);
     mWorkerRef = Move(strongWorkerRef);
   } else if (GetOwner()) {
     MOZ_ASSERT(NS_IsMainThread());
     mInnerID = GetOwner()->WindowID();
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/file_same_site_cookies_blob_iframe_inclusion.html
@@ -0,0 +1,34 @@
+<html>
+<body>
+<iframe id="testframe"></iframe>
+<script type="application/javascript">
+
+  // simply passing on the message from the child to parent
+  window.addEventListener("message", receiveMessage);
+  function receiveMessage(event) {
+    window.removeEventListener("message", receiveMessage);
+    window.parent.postMessage({result: event.data.result}, '*');
+  }
+
+  const NESTED_IFRAME_INCLUSION = `
+    <html>
+    <body>
+      <script type="application/javascript">
+      window.addEventListener("message", receiveMessage);
+      function receiveMessage(event) {
+        window.removeEventListener("message", receiveMessage);
+        window.parent.postMessage({result: event.data.result}, '*');
+      }
+      <\/script>
+      <iframe src="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></iframe>
+    </body>
+    </html>`;
+  
+  let NESTED_BLOB_IFRAME_INCLUSION = new Blob([NESTED_IFRAME_INCLUSION], {type:'text/html'});
+
+  // query the testframe and set blob URL
+  let testframe = document.getElementById("testframe");
+  testframe.src = window.URL.createObjectURL(NESTED_BLOB_IFRAME_INCLUSION);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/file_same_site_cookies_blob_iframe_navigation.html
@@ -0,0 +1,30 @@
+<html>
+<body>
+<iframe id="testframe"></iframe>
+<script type="application/javascript">
+
+  // simply passing on the message from the child to parent
+  window.addEventListener("message", receiveMessage);
+  function receiveMessage(event) {
+    window.removeEventListener("message", receiveMessage);
+    window.parent.postMessage({result: event.data.result}, '*');
+  }
+
+  const NESTED_IFRAME_NAVIGATION = `
+    <html>
+    <body>
+      <a id="testlink" href="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></a>
+      <script type="application/javascript">
+        let link = document.getElementById("testlink");
+        link.click();
+      <\/script>
+    </body>
+  </html>`;
+  let NESTED_BLOB_IFRAME_NAVIGATION = new Blob([NESTED_IFRAME_NAVIGATION], {type:'text/html'});
+
+  // query the testframe and set blob URL
+  let testframe = document.getElementById("testframe");
+  testframe.src = window.URL.createObjectURL(NESTED_BLOB_IFRAME_NAVIGATION);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/file_same_site_cookies_iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Bug 1454027 - Update SameSite cookie handling inside iframes</title>
+</head>
+<body>
+  <script type="application/javascript">
+    let cookie = "";
+    try {
+      cookie = document.cookie;
+    } catch (e) {
+      // nested iframes within a sandboxed iframe do not get access to document.cookie
+      // and throw a security error.
+    }
+    window.parent.postMessage({result: cookie}, '*');
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/file_same_site_cookies_iframe.sjs
@@ -0,0 +1,73 @@
+// Custom *.sjs file specifically for the needs of Bug 1454027
+
+// small red image
+const IMG_BYTES = atob(
+  "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
+  "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
+
+const NESTED_IFRAME_NAVIGATION = `
+  <html>
+  <body>
+    <a id="testlink" href="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></a>
+    <script type="application/javascript">
+      let link = document.getElementById("testlink");
+      link.click();
+    <\/script>
+  </body>
+  </html>`;
+
+const NESTED_IFRAME_INCLUSION = `
+  <html>
+  <body>
+    <script type="application/javascript">
+    // simply passing on the message from the child to parent
+    window.addEventListener("message", receiveMessage);
+    function receiveMessage(event) {
+      window.removeEventListener("message", receiveMessage);
+      window.parent.postMessage({result: event.data.result}, '*');
+    }
+    <\/script>
+    <iframe src="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></iframe>
+  </body>
+  </html>`;
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  // using startsWith and discard the math random
+  if (request.queryString.startsWith("setSameSiteCookie")) {
+    response.setHeader("Set-Cookie", "myKey=mySameSiteIframeTestCookie; samesite=strict", true);
+    response.setHeader("Content-Type", "image/png");
+    response.write(IMG_BYTES);
+    return;
+  }
+
+  // navigation tests
+  if (request.queryString === "nestedIframeNavigation") {
+    response.write(NESTED_IFRAME_NAVIGATION);
+    return;
+  }
+
+  if (request.queryString === "nestedSandboxIframeNavigation") {
+    response.setHeader("Content-Security-Policy", "sandbox allow-scripts", false);
+    response.write(NESTED_IFRAME_NAVIGATION);
+    return;
+  }
+
+  // inclusion tests
+  if (request.queryString === "nestedIframeInclusion") {
+    response.write(NESTED_IFRAME_INCLUSION);
+    return;
+  }
+
+  if (request.queryString === "nestedSandboxIframeInclusion") {
+    response.setHeader("Content-Security-Policy", "sandbox allow-scripts", false);
+    response.write(NESTED_IFRAME_INCLUSION);
+    return;
+  }
+
+  // we should never get here, but just in case return something unexpected
+  response.write("D'oh");
+}
--- a/dom/security/test/general/mochitest.ini
+++ b/dom/security/test/general/mochitest.ini
@@ -9,16 +9,20 @@ support-files =
   file_block_toplevel_data_redirect.sjs
   file_block_subresource_redir_to_data.sjs
   file_same_site_cookies_subrequest.sjs
   file_same_site_cookies_toplevel_nav.sjs
   file_same_site_cookies_cross_origin_context.sjs
   file_same_site_cookies_from_script.sjs
   file_same_site_cookies_redirect.sjs
   file_same_site_cookies_toplevel_set_cookie.sjs
+  file_same_site_cookies_blob_iframe_navigation.html
+  file_same_site_cookies_blob_iframe_inclusion.html
+  file_same_site_cookies_iframe.html
+  file_same_site_cookies_iframe.sjs
 
 [test_contentpolicytype_targeted_link_iframe.html]
 [test_nosniff.html]
 [test_block_script_wrong_mime.html]
 [test_block_toplevel_data_navigation.html]
 skip-if = toolkit == 'android' || webrender # intermittent failure; bug 1424752 for webrender
 [test_block_toplevel_data_img_navigation.html]
 skip-if = toolkit == 'android' # intermittent failure
@@ -28,8 +32,9 @@ skip-if = toolkit == 'android'
 skip-if = toolkit == 'android'
 [test_block_subresource_redir_to_data.html]
 [test_same_site_cookies_subrequest.html]
 [test_same_site_cookies_toplevel_nav.html]
 [test_same_site_cookies_cross_origin_context.html]
 [test_same_site_cookies_from_script.html]
 [test_same_site_cookies_redirect.html]
 [test_same_site_cookies_toplevel_set_cookie.html]
+[test_same_site_cookies_iframe.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/test_same_site_cookies_iframe.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1454027 - Update SameSite cookie handling inside iframes</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<img id="cookieImage">
+<iframe id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/*
+ * Description of the test:
+ * 1) We load an image from http://mochi.test which sets a same site cookie
+ * 2) We then load the following iframes:
+ *    (a) cross-origin iframe
+ *    (b) sandboxed iframe
+ *    (c) data: URI iframe
+ *    (d) same origin iframe which loads blob: URI iframe (to simulate same origin blobs)
+ *    (e) cross origin iframe which loads blob: URI iframe (to simulate cross origin blobs)
+ *    which all:
+ *    * navigate the iframe to http://mochi.test
+ *    * include another iframe from http://mochi.test
+ * 3) We observe that none of the nested iframes have access to the same-site cookie.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+const SAME_ORIGIN = "http://mochi.test:8888/"
+const CROSS_ORIGIN = "http://example.com/";
+const PATH = "tests/dom/security/test/general/";
+const SERVER_FILE = "file_same_site_cookies_iframe.sjs";
+
+const NESTED_DATA_IFRAME_NAVIGATION = `
+  data:text/html,
+  <html>
+  <body>
+    <a id="testlink" href="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></a>
+    <script type="application/javascript">
+      let link = document.getElementById("testlink");
+      link.click();
+    <\/script>
+  </body>
+  </html>`;
+
+const NESTED_DATA_IFRAME_INCLUSION = `
+  data:text/html,
+  <html>
+  <body>
+    <script type="application/javascript">
+    window.addEventListener("message", receiveMessage);
+    function receiveMessage(event) {
+      window.removeEventListener("message", receiveMessage);
+      window.parent.postMessage({result: event.data.result}, '*');
+    }
+    <\/script>
+    <iframe src="http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_iframe.html"></iframe>
+  </body>
+  </html>`;
+
+let curTest = 0;
+
+var tests = [
+  // NAVIGATION TESTS
+  {
+    description: "nested same origin iframe navigation [mochi.test -> mochi.test -> mochi.test]",
+    frameSRC: SAME_ORIGIN + PATH + SERVER_FILE + "?nestedIframeNavigation",
+    result: "myKey=mySameSiteIframeTestCookie", // cookie should be set for baseline test
+  },
+  {
+    description: "nested cross origin iframe navigation [mochi.test -> example.com -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + SERVER_FILE + "?nestedIframeNavigation",
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested sandboxed iframe navigation [mochi.test -> sandbox -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + SERVER_FILE + "?nestedSandboxIframeNavigation",
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested data iframe navigation [mochi.test -> data: -> mochi.test]",
+    frameSRC: NESTED_DATA_IFRAME_NAVIGATION,
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested same site blob iframe navigation [mochi.test -> mochi.test -> blob: -> mochi.test]",
+    frameSRC: SAME_ORIGIN + PATH + "file_same_site_cookies_blob_iframe_navigation.html",
+    result: "myKey=mySameSiteIframeTestCookie", // cookie should be set, blobs inherit security context
+  },
+  {
+    description: "nested cross site blob iframe navigation [mochi.test -> example.com -> blob: -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + "file_same_site_cookies_blob_iframe_navigation.html",
+    result: "", // no cookie should be set
+  },
+  // INCLUSION TESTS
+  {
+    description: "nested same origin iframe inclusion [mochi.test -> mochi.test -> mochi.test]",
+    frameSRC: SAME_ORIGIN + PATH + SERVER_FILE + "?nestedIframeInclusion",
+    result: "myKey=mySameSiteIframeTestCookie", // cookie should be set for baseline test
+  },
+  {
+    description: "nested cross origin iframe inclusion [mochi.test -> example.com -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + SERVER_FILE + "?nestedIframeInclusion",
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested sandboxed iframe inclusion [mochi.test -> sandbox -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + SERVER_FILE + "?nestedSandboxIframeInclusion",
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested data iframe inclusion [mochi.test -> data: -> mochi.test]",
+    frameSRC: NESTED_DATA_IFRAME_INCLUSION,
+    result: "", // no cookie should be set
+  },
+  {
+    description: "nested same site blob iframe inclusion [mochi.test -> mochi.test -> blob: -> mochi.test]",
+    frameSRC: SAME_ORIGIN + PATH + "file_same_site_cookies_blob_iframe_inclusion.html",
+    result: "myKey=mySameSiteIframeTestCookie", // cookie should be set, blobs inherit security context
+  },
+  {
+    description: "same-site cookie, nested cross site blob iframe inclusion [mochi.test -> example.com -> blob: -> mochi.test]",
+    frameSRC: CROSS_ORIGIN + PATH + "file_same_site_cookies_blob_iframe_inclusion.html",
+    result: "", // no cookie should be set
+  },
+];
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+  is(event.data.result, tests[curTest].result, tests[curTest].description);
+  curTest += 1;
+
+  // // lets see if we ran all the tests
+  if (curTest == tests.length) {
+    window.removeEventListener("message", receiveMessage);
+    SimpleTest.finish();
+    return;
+  }
+  // otherwise it's time to run the next test
+  setCookieAndInitTest();
+}
+
+function setupQueryResultAndRunTest() {
+  let testframe = document.getElementById("testframe");
+  testframe.src = tests[curTest].frameSRC;
+}
+
+function setCookieAndInitTest() {
+  var cookieImage = document.getElementById("cookieImage");
+  cookieImage.onload = function() {
+    ok(true, "trying to set cookie for test (" + tests[curTest].description + ")");
+    setupQueryResultAndRunTest();
+  }
+  cookieImage.onerror = function() {
+    ok(false, "could not load image for test (" + tests[curTest].description + ")");
+  }
+  // appending math.random to avoid any unexpected caching behavior
+  cookieImage.src = SAME_ORIGIN + PATH + SERVER_FILE + "?setSameSiteCookie" + Math.random();
+}
+
+// fire up the test
+setCookieAndInitTest();
+
+</script>
+</body>
+</html>
--- a/dom/serviceworkers/ServiceWorkerContainer.cpp
+++ b/dom/serviceworkers/ServiceWorkerContainer.cpp
@@ -4,31 +4,33 @@
  * 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 "ServiceWorkerContainer.h"
 
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIServiceWorkerManager.h"
+#include "nsIScriptError.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/Services.h"
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsServiceManagerUtils.h"
 
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ServiceWorker.h"
 #include "mozilla/dom/ServiceWorkerContainerBinding.h"
 
 #include "ServiceWorker.h"
+#include "ServiceWorkerContainerImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerContainer)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
@@ -55,22 +57,26 @@ ServiceWorkerContainer::IsEnabled(JSCont
 
   return DOMPrefs::ServiceWorkersEnabled();
 }
 
 // static
 already_AddRefed<ServiceWorkerContainer>
 ServiceWorkerContainer::Create(nsIGlobalObject* aGlobal)
 {
-  RefPtr<ServiceWorkerContainer> ref = new ServiceWorkerContainer(aGlobal);
+  RefPtr<Inner> inner = new ServiceWorkerContainerImpl();
+  RefPtr<ServiceWorkerContainer> ref =
+    new ServiceWorkerContainer(aGlobal, inner.forget());
   return ref.forget();
 }
 
-ServiceWorkerContainer::ServiceWorkerContainer(nsIGlobalObject* aGlobal)
+ServiceWorkerContainer::ServiceWorkerContainer(nsIGlobalObject* aGlobal,
+                                               already_AddRefed<ServiceWorkerContainer::Inner> aInner)
   : DOMEventTargetHelper(aGlobal)
+  , mInner(aInner)
 {
   Maybe<ServiceWorkerDescriptor> controller = aGlobal->GetController();
   if (controller.isSome()) {
     mControllerWorker = aGlobal->GetOrCreateServiceWorker(controller.ref());
   }
 }
 
 ServiceWorkerContainer::~ServiceWorkerContainer()
@@ -220,95 +226,180 @@ ServiceWorkerContainer::GetController()
 {
   RefPtr<ServiceWorker> ref = mControllerWorker;
   return ref.forget();
 }
 
 already_AddRefed<Promise>
 ServiceWorkerContainer::GetRegistrations(ErrorResult& aRv)
 {
-  nsresult rv;
-  nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
+  nsIGlobalObject* global = GetGlobalIfValid(aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  Maybe<ClientInfo> clientInfo = global->GetClientInfo();
+  if (clientInfo.isNothing()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
+  }
+
+  RefPtr<Promise> outer = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  nsCOMPtr<nsISupports> promise;
-  aRv = swm->GetRegistrations(GetOwner(), getter_AddRefs(promise));
+  RefPtr<ServiceWorkerContainer> self = this;
+
+  mInner->GetRegistrations(clientInfo.ref())->Then(
+    global->EventTargetFor(TaskCategory::Other), __func__,
+    [self, outer] (const nsTArray<ServiceWorkerRegistrationDescriptor>& aDescList) {
+      ErrorResult rv;
+      nsIGlobalObject* global = self->GetGlobalIfValid(rv);
+      if (rv.Failed()) {
+        outer->MaybeReject(rv);
+        return;
+      }
+      nsTArray<RefPtr<ServiceWorkerRegistration>> regList;
+      for (auto& desc : aDescList) {
+        RefPtr<ServiceWorkerRegistration> reg =
+          global->GetOrCreateServiceWorkerRegistration(desc);
+        if (reg) {
+          regList.AppendElement(Move(reg));
+        }
+      }
+      outer->MaybeResolve(regList);
+    }, [self, outer] (nsresult aRv) {
+      outer->MaybeReject(aRv);
+    });
+
+  return outer.forget();
+}
+
+already_AddRefed<Promise>
+ServiceWorkerContainer::GetRegistration(const nsAString& aURL,
+                                        ErrorResult& aRv)
+{
+  nsIGlobalObject* global = GetGlobalIfValid(aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  RefPtr<Promise> ret = static_cast<Promise*>(promise.get());
-  MOZ_ASSERT(ret);
-  return ret.forget();
-}
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
+  if (!window) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
+  }
 
-already_AddRefed<Promise>
-ServiceWorkerContainer::GetRegistration(const nsAString& aDocumentURL,
-                                        ErrorResult& aRv)
-{
-  nsresult rv;
-  nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
+  // It would be nice not to require a window here, but right
+  // now we don't have a great way to get the base URL just
+  // from the nsIGlobalObject.
+  Maybe<ClientInfo> clientInfo = window->GetClientInfo();
+  if (clientInfo.isNothing()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
-  nsCOMPtr<nsISupports> promise;
-  aRv = swm->GetRegistration(GetOwner(), aDocumentURL, getter_AddRefs(promise));
+  nsIDocument* doc = window->GetExtantDoc();
+  if (!doc) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
+  if (!baseURI) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  aRv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, baseURI);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  RefPtr<Promise> ret = static_cast<Promise*>(promise.get());
-  MOZ_ASSERT(ret);
-  return ret.forget();
+  nsCString spec;
+  aRv = uri->GetSpec(spec);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  RefPtr<Promise> outer = Promise::Create(window->AsGlobal(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  RefPtr<ServiceWorkerContainer> self = this;
+
+  mInner->GetRegistration(clientInfo.ref(), spec)->Then(
+    window->EventTargetFor(TaskCategory::Other), __func__,
+    [self, outer] (const ServiceWorkerRegistrationDescriptor& aDescriptor) {
+      ErrorResult rv;
+      nsIGlobalObject* global = self->GetGlobalIfValid(rv);
+      if (rv.Failed()) {
+        outer->MaybeReject(rv);
+        return;
+      }
+      RefPtr<ServiceWorkerRegistration> reg =
+        global->GetOrCreateServiceWorkerRegistration(aDescriptor);
+      outer->MaybeResolve(reg);
+    }, [self, outer] (nsresult aRv) {
+      ErrorResult rv;
+      Unused << self->GetGlobalIfValid(rv);
+      if (rv.Failed()) {
+        outer->MaybeReject(rv);
+        return;
+      }
+      if (NS_SUCCEEDED(aRv)) {
+        outer->MaybeResolveWithUndefined();
+        return;
+      }
+      outer->MaybeReject(aRv);
+    });
+
+  return outer.forget();
 }
 
 Promise*
 ServiceWorkerContainer::GetReady(ErrorResult& aRv)
 {
   if (mReadyPromise) {
     return mReadyPromise;
   }
 
-  nsIGlobalObject* global = GetParentObject();
-  if (!global) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+  nsIGlobalObject* global = GetGlobalIfValid(aRv);
+  if (aRv.Failed()) {
     return nullptr;
   }
+  MOZ_DIAGNOSTIC_ASSERT(global);
 
   Maybe<ClientInfo> clientInfo(global->GetClientInfo());
   if (clientInfo.isNothing()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
-  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
-  if (!swm) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return nullptr;
-  }
-
-  mReadyPromise = Promise::Create(GetParentObject(), aRv);
+  mReadyPromise = Promise::Create(global, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   RefPtr<ServiceWorkerContainer> self = this;
   RefPtr<Promise> outer = mReadyPromise;
 
-  swm->WhenReady(clientInfo.ref())->Then(
+  mInner->GetReady(clientInfo.ref())->Then(
     global->EventTargetFor(TaskCategory::Other), __func__,
     [self, outer] (const ServiceWorkerRegistrationDescriptor& aDescriptor) {
       self->mReadyPromiseHolder.Complete();
-      nsIGlobalObject* global = self->GetParentObject();
-      NS_ENSURE_TRUE_VOID(global);
+      ErrorResult rv;
+      nsIGlobalObject* global = self->GetGlobalIfValid(rv);
+      if (rv.Failed()) {
+        outer->MaybeReject(rv);
+        return;
+      }
       RefPtr<ServiceWorkerRegistration> reg =
         global->GetOrCreateServiceWorkerRegistration(aDescriptor);
       NS_ENSURE_TRUE_VOID(reg);
       outer->MaybeResolve(reg);
     }, [self, outer] (nsresult aRv) {
       self->mReadyPromiseHolder.Complete();
       outer->MaybeReject(aRv);
     })->Track(mReadyPromiseHolder);
@@ -339,10 +430,42 @@ ServiceWorkerContainer::GetScopeForUrl(c
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   aRv = swm->GetScopeForUrl(doc->NodePrincipal(),
                             aUrl, aScope);
 }
 
+nsIGlobalObject*
+ServiceWorkerContainer::GetGlobalIfValid(ErrorResult& aRv) const
+{
+  // For now we require a window since ServiceWorkerContainer is
+  // not exposed on worker globals yet.  The main thing we need
+  // to fix here to support that is the storage access check via
+  // the nsIGlobalObject.
+  nsPIDOMWindowInner* window = GetOwner();
+  if (NS_WARN_IF(!window)) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return nullptr;
+  }
+
+  // Don't allow a service worker to access service worker registrations
+  // from a window with storage disabled.  If these windows can access
+  // the registration it increases the chance they can bypass the storage
+  // block via postMessage(), etc.
+  auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
+  if (NS_WARN_IF(storageAllowed != nsContentUtils::StorageAccess::eAllow)) {
+    nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
+    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
+                                    NS_LITERAL_CSTRING("Service Workers"), doc,
+                                    nsContentUtils::eDOM_PROPERTIES,
+                                    "ServiceWorkerGetRegistrationStorageError");
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return nullptr;
+  }
+  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(window->GetExtantDoc()->NodePrincipal()));
+
+  return window->AsGlobal();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/serviceworkers/ServiceWorkerContainer.h
+++ b/dom/serviceworkers/ServiceWorkerContainer.h
@@ -18,16 +18,36 @@ namespace dom {
 class Promise;
 struct RegistrationOptions;
 class ServiceWorker;
 
 // Lightweight serviceWorker APIs collection.
 class ServiceWorkerContainer final : public DOMEventTargetHelper
 {
 public:
+  class Inner
+  {
+  public:
+    virtual RefPtr<ServiceWorkerRegistrationPromise>
+    Register(const nsAString& aScriptURL,
+             const RegistrationOptions& aOptions) = 0;
+
+    virtual RefPtr<ServiceWorkerRegistrationPromise>
+    GetRegistration(const ClientInfo& aClientInfo,
+                    const nsACString& aURL) const = 0;
+
+    virtual RefPtr<ServiceWorkerRegistrationListPromise>
+    GetRegistrations(const ClientInfo& aClientInfo) const = 0;
+
+    virtual RefPtr<ServiceWorkerRegistrationPromise>
+    GetReady(const ClientInfo& aClientInfo) const = 0;
+
+    NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
+  };
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper)
 
   IMPL_EVENT_HANDLER(controllerchange)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(message)
 
   static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
@@ -64,20 +84,26 @@ public:
   void DisconnectFromOwner() override;
 
   // Invalidates |mControllerWorker| and dispatches a "controllerchange"
   // event.
   void
   ControllerChanged(ErrorResult& aRv);
 
 private:
-  explicit ServiceWorkerContainer(nsIGlobalObject* aGlobal);
+  ServiceWorkerContainer(nsIGlobalObject* aGlobal,
+                         already_AddRefed<ServiceWorkerContainer::Inner> aInner);
 
   ~ServiceWorkerContainer();
 
+  nsIGlobalObject*
+  GetGlobalIfValid(ErrorResult& aRv) const;
+
+  RefPtr<Inner> mInner;
+
   // This only changes when a worker hijacks everything in its scope by calling
   // claim.
   RefPtr<ServiceWorker> mControllerWorker;
 
   RefPtr<Promise> mReadyPromise;
   MozPromiseRequestHolder<ServiceWorkerRegistrationPromise> mReadyPromiseHolder;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/serviceworkers/ServiceWorkerContainerImpl.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ServiceWorkerContainerImpl.h"
+
+namespace mozilla {
+namespace dom {
+
+RefPtr<ServiceWorkerRegistrationPromise>
+ServiceWorkerContainerImpl::Register(const nsAString& aScriptURL,
+                                     const RegistrationOptions& aOptions)
+{
+  // TODO
+  return nullptr;
+}
+
+RefPtr<ServiceWorkerRegistrationPromise>
+ServiceWorkerContainerImpl::GetRegistration(const ClientInfo& aClientInfo,
+                                            const nsACString& aURL) const
+{
+  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+  if (NS_WARN_IF(!swm)) {
+    return ServiceWorkerRegistrationPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
+                                                             __func__);
+  }
+
+  return swm->GetRegistration(aClientInfo, aURL);
+}
+
+RefPtr<ServiceWorkerRegistrationListPromise>
+ServiceWorkerContainerImpl::GetRegistrations(const ClientInfo& aClientInfo) const
+{
+  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+  if (NS_WARN_IF(!swm)) {
+    return ServiceWorkerRegistrationListPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
+                                                                 __func__);
+  }
+
+  return swm->GetRegistrations(aClientInfo);
+}
+
+RefPtr<ServiceWorkerRegistrationPromise>
+ServiceWorkerContainerImpl::GetReady(const ClientInfo& aClientInfo) const
+{
+  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+  if (NS_WARN_IF(!swm)) {
+    return ServiceWorkerRegistrationPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
+                                                             __func__);
+  }
+
+  return swm->WhenReady(aClientInfo);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/serviceworkers/ServiceWorkerContainerImpl.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_serviceworkercontainerimpl_h__
+#define mozilla_dom_serviceworkercontainerimpl_h__
+
+#include "ServiceWorkerContainer.h"
+
+namespace mozilla {
+namespace dom {
+
+// Lightweight serviceWorker APIs collection.
+class ServiceWorkerContainerImpl final : public ServiceWorkerContainer::Inner
+{
+  ~ServiceWorkerContainerImpl() = default;
+
+public:
+  ServiceWorkerContainerImpl() = default;
+
+  RefPtr<ServiceWorkerRegistrationPromise>
+  Register(const nsAString& aScriptURL,
+           const RegistrationOptions& aOptions) override;
+
+  RefPtr<ServiceWorkerRegistrationPromise>
+  GetRegistration(const ClientInfo& aClientInfo,
+                  const nsACString& aURL) const override;
+
+  RefPtr<ServiceWorkerRegistrationListPromise>
+  GetRegistrations(const ClientInfo& aClientInfo) const override;
+
+  RefPtr<ServiceWorkerRegistrationPromise>
+  GetReady(const ClientInfo& aClientInfo) const override;
+
+  NS_INLINE_DECL_REFCOUNTING(ServiceWorkerContainerImpl, override)
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_serviceworkercontainerimpl_h__ */
--- a/dom/serviceworkers/ServiceWorkerManager.cpp
+++ b/dom/serviceworkers/ServiceWorkerManager.cpp
@@ -954,266 +954,186 @@ ServiceWorkerManager::Register(mozIDOMWi
   return NS_OK;
 }
 
 /*
  * Implements the async aspects of the getRegistrations algorithm.
  */
 class GetRegistrationsRunnable final : public Runnable
 {
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-  RefPtr<Promise> mPromise;
+  const ClientInfo mClientInfo;
+  RefPtr<ServiceWorkerRegistrationListPromise::Private> mPromise;
 public:
-  GetRegistrationsRunnable(nsPIDOMWindowInner* aWindow, Promise* aPromise)
+  explicit GetRegistrationsRunnable(const ClientInfo& aClientInfo)
     : Runnable("dom::ServiceWorkerManager::GetRegistrationsRunnable")
-    , mWindow(aWindow)
-    , mPromise(aPromise)
+    , mClientInfo(aClientInfo)
+    , mPromise(new ServiceWorkerRegistrationListPromise::Private(__func__))
   {}
 
+  RefPtr<ServiceWorkerRegistrationListPromise>
+  Promise() const
+  {
+    return mPromise;
+  }
+
   NS_IMETHOD
   Run() override
   {
+    auto scopeExit = MakeScopeExit([&] {
+      mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+    });
+
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (!swm) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
-      return NS_OK;
-    }
-
-    nsIDocument* doc = mWindow->GetExtantDoc();
-    if (!doc) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
       return NS_OK;
     }
 
-    nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
-    if (!docURI) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+    nsCOMPtr<nsIPrincipal> principal = mClientInfo.GetPrincipal();
+    if (!principal) {
       return NS_OK;
     }
 
-    nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
-    if (!principal) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
-      return NS_OK;
-    }
-
-    nsTArray<RefPtr<ServiceWorkerRegistration>> array;
+    nsTArray<ServiceWorkerRegistrationDescriptor> array;
 
     if (NS_WARN_IF(!BasePrincipal::Cast(principal)->IsCodebasePrincipal())) {
       return NS_OK;
     }
 
     nsAutoCString scopeKey;
     nsresult rv = swm->PrincipalToScopeKey(principal, scopeKey);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     ServiceWorkerManager::RegistrationDataPerPrincipal* data;
     if (!swm->mRegistrationInfos.Get(scopeKey, &data)) {
-      mPromise->MaybeResolve(array);
+      scopeExit.release();
+      mPromise->Resolve(array, __func__);
       return NS_OK;
     }
 
     for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) {
       RefPtr<ServiceWorkerRegistrationInfo> info =
         data->mInfos.GetWeak(data->mOrderedScopes[i]);
       if (info->IsPendingUninstall()) {
         continue;
       }
 
       NS_ConvertUTF8toUTF16 scope(data->mOrderedScopes[i]);
 
       nsCOMPtr<nsIURI> scopeURI;
       nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), scope, nullptr, nullptr);
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        mPromise->MaybeReject(rv);
         break;
       }
 
       rv = principal->CheckMayLoad(scopeURI, true /* report */,
                                    false /* allowIfInheritsPrincipal */);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         continue;
       }
 
-      RefPtr<ServiceWorkerRegistration> swr =
-        mWindow->AsGlobal()->GetOrCreateServiceWorkerRegistration(info->Descriptor());
-
-      array.AppendElement(swr);
+      array.AppendElement(info->Descriptor());
     }
 
-    mPromise->MaybeResolve(array);
+    scopeExit.release();
+    mPromise->Resolve(array, __func__);
+
     return NS_OK;
   }
 };
 
-// If we return an error code here, the ServiceWorkerContainer will
-// automatically reject the Promise.
-NS_IMETHODIMP
-ServiceWorkerManager::GetRegistrations(mozIDOMWindow* aWindow,
-                                       nsISupports** aPromise)
+RefPtr<ServiceWorkerRegistrationListPromise>
+ServiceWorkerManager::GetRegistrations(const ClientInfo& aClientInfo) const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (NS_WARN_IF(!aWindow)) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
-
-  auto* window = nsPIDOMWindowInner::From(aWindow);
-
-  // Don't allow a service worker to access service worker registrations
-  // from a window with storage disabled.  If these windows can access
-  // the registration it increases the chance they can bypass the storage
-  // block via postMessage(), etc.
-  auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
-  if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
-    nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
-    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                    NS_LITERAL_CSTRING("Service Workers"), doc,
-                                    nsContentUtils::eDOM_PROPERTIES,
-                                    "ServiceWorkerGetRegistrationStorageError");
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  // Don't allow service workers to register when the *document* is chrome for
-  // now.
-  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(window->GetExtantDoc()->NodePrincipal()));
-
-  ErrorResult result;
-  RefPtr<Promise> promise = Promise::Create(window->AsGlobal(), result);
-  if (result.Failed()) {
-    return result.StealNSResult();
-  }
-
-  nsCOMPtr<nsIRunnable> runnable =
-    new GetRegistrationsRunnable(window, promise);
-  promise.forget(aPromise);
-  return NS_DispatchToCurrentThread(runnable);
+  RefPtr<GetRegistrationsRunnable> runnable =
+    new GetRegistrationsRunnable(aClientInfo);
+  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(runnable));
+  return runnable->Promise();;
 }
 
 /*
  * Implements the async aspects of the getRegistration algorithm.
  */
 class GetRegistrationRunnable final : public Runnable
 {
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-  RefPtr<Promise> mPromise;
-  nsString mDocumentURL;
+  const ClientInfo mClientInfo;
+  RefPtr<ServiceWorkerRegistrationPromise::Private> mPromise;
+  nsCString mURL;
 
 public:
-  GetRegistrationRunnable(nsPIDOMWindowInner* aWindow,
-                          Promise* aPromise,
-                          const nsAString& aDocumentURL)
+  GetRegistrationRunnable(const ClientInfo& aClientInfo,
+                          const nsACString& aURL)
     : Runnable("dom::ServiceWorkerManager::GetRegistrationRunnable")
-    , mWindow(aWindow)
-    , mPromise(aPromise)
-    , mDocumentURL(aDocumentURL)
+    , mClientInfo(aClientInfo)
+    , mPromise(new ServiceWorkerRegistrationPromise::Private(__func__))
+    , mURL(aURL)
   {}
 
+  RefPtr<ServiceWorkerRegistrationPromise>
+  Promise() const
+  {
+    return mPromise;
+  }
+
   NS_IMETHOD
   Run() override
   {
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (!swm) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+      mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
       return NS_OK;
     }
 
-    nsIDocument* doc = mWindow->GetExtantDoc();
-    if (!doc) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
-    if (!docURI) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+    nsCOMPtr<nsIPrincipal> principal = mClientInfo.GetPrincipal();
+    if (!principal) {
+      mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
       return NS_OK;
     }
 
     nsCOMPtr<nsIURI> uri;
-    nsresult rv = NS_NewURI(getter_AddRefs(uri), mDocumentURL, nullptr, docURI);
+    nsresult rv = NS_NewURI(getter_AddRefs(uri), mURL, nullptr, nullptr);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      mPromise->MaybeReject(rv);
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
-    if (!principal) {
-      mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+      mPromise->Reject(rv, __func__);
       return NS_OK;
     }
 
     rv = principal->CheckMayLoad(uri, true /* report */,
                                  false /* allowIfInheritsPrinciple */);
     if (NS_FAILED(rv)) {
-      mPromise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+      mPromise->Reject(NS_ERROR_DOM_SECURITY_ERR, __func__);
       return NS_OK;
     }
 
     RefPtr<ServiceWorkerRegistrationInfo> registration =
       swm->GetServiceWorkerRegistrationInfo(principal, uri);
 
     if (!registration) {
-      mPromise->MaybeResolveWithUndefined();
+      // Reject with NS_OK means "not found".
+      mPromise->Reject(NS_OK, __func__);
       return NS_OK;
     }
 
-    RefPtr<ServiceWorkerRegistration> swr =
-      mWindow->AsGlobal()->GetOrCreateServiceWorkerRegistration(registration->Descriptor());
-    mPromise->MaybeResolve(swr);
+    mPromise->Resolve(registration->Descriptor(), __func__);
 
     return NS_OK;
   }
 };
 
-// If we return an error code here, the ServiceWorkerContainer will
-// automatically reject the Promise.
-NS_IMETHODIMP
-ServiceWorkerManager::GetRegistration(mozIDOMWindow* aWindow,
-                                      const nsAString& aDocumentURL,
-                                      nsISupports** aPromise)
+RefPtr<ServiceWorkerRegistrationPromise>
+ServiceWorkerManager::GetRegistration(const ClientInfo& aClientInfo,
+                                      const nsACString& aURL) const
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (NS_WARN_IF(!aWindow)) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
-
-  auto* window = nsPIDOMWindowInner::From(aWindow);
-
-  // Don't allow a service worker to access service worker registrations
-  // from a window with storage disabled.  If these windows can access
-  // the registration it increases the chance they can bypass the storage
-  // block via postMessage(), etc.
-  auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
-  if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
-    nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
-    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                    NS_LITERAL_CSTRING("Service Workers"), doc,
-                                    nsContentUtils::eDOM_PROPERTIES,
-                                    "ServiceWorkerGetRegistrationStorageError");
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  // Don't allow service workers to register when the *document* is chrome for
-  // now.
-  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(window->GetExtantDoc()->NodePrincipal()));
-
-  ErrorResult result;
-  RefPtr<Promise> promise = Promise::Create(window->AsGlobal(), result);
-  if (result.Failed()) {
-    return result.StealNSResult();
-  }
-
-  nsCOMPtr<nsIRunnable> runnable =
-    new GetRegistrationRunnable(window, promise, aDocumentURL);
-  promise.forget(aPromise);
-  return NS_DispatchToCurrentThread(runnable);
+  RefPtr<GetRegistrationRunnable> runnable =
+    new GetRegistrationRunnable(aClientInfo, aURL);
+  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(runnable));
+
+  return runnable->Promise();
 }
 
 NS_IMETHODIMP
 ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes,
                                     const nsACString& aScope,
                                     uint32_t aDataLength,
                                     uint8_t* aDataBytes,
                                     uint8_t optional_argc)
@@ -2470,16 +2390,28 @@ ServiceWorkerManager::DispatchFetchEvent
       }
 
       // First, attempt to mark the reserved client controlled directly.  This
       // will update the controlled status in the ClientManagerService in the
       // parent.  It will also eventually propagate back to the ClientSource.
       StartControllingClient(clientInfo.ref(), registration);
     }
 
+    uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_MANUAL;
+    nsCOMPtr<nsIHttpChannelInternal> http = do_QueryInterface(internalChannel);
+    MOZ_ALWAYS_SUCCEEDS(http->GetRedirectMode(&redirectMode));
+
+    // Synthetic redirects for non-subresource requests with a "follow"
+    // redirect mode may switch controllers.  This is basically worker
+    // scripts right now.  In this case we need to explicitly clear the
+    // controller to avoid assertions on the SetController() below.
+    if (redirectMode == nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW) {
+      loadInfo->ClearController();
+    }
+
     // But we also note the reserved state on the LoadInfo.  This allows the
     // ClientSource to be updated immediately after the nsIChannel starts.
     // This is necessary to have the correct controller in place for immediate
     // follow-on requests.
     loadInfo->SetController(serviceWorker->Descriptor());
   }
 
   MOZ_DIAGNOSTIC_ASSERT(serviceWorker);
--- a/dom/serviceworkers/ServiceWorkerManager.h
+++ b/dom/serviceworkers/ServiceWorkerManager.h
@@ -188,16 +188,22 @@ public:
   Remove(const nsACString& aHost);
 
   void
   PropagateRemoveAll();
 
   void
   RemoveAll();
 
+  RefPtr<ServiceWorkerRegistrationPromise>
+  GetRegistration(const ClientInfo& aClientInfo, const nsACString& aURL) const;
+
+  RefPtr<ServiceWorkerRegistrationListPromise>
+  GetRegistrations(const ClientInfo& aClientInfo) const;
+
   already_AddRefed<ServiceWorkerRegistrationInfo>
   GetRegistration(nsIPrincipal* aPrincipal, const nsACString& aScope) const;
 
   already_AddRefed<ServiceWorkerRegistrationInfo>
   GetRegistration(const mozilla::ipc::PrincipalInfo& aPrincipal,
                   const nsACString& aScope) const;
 
   already_AddRefed<ServiceWorkerRegistrationInfo>
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.h
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.h
@@ -1,14 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef mozilla_dom_serviceworkerregistrationimpl_h
+#define mozilla_dom_serviceworkerregistrationimpl_h
+
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/Unused.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
 #include "ServiceWorkerManager.h"
 #include "ServiceWorkerRegistration.h"
 #include "ServiceWorkerRegistrationListener.h"
@@ -156,8 +159,10 @@ private:
   ServiceWorkerRegistration* mOuter;
   const nsString mScope;
   RefPtr<WorkerListener> mListener;
   RefPtr<WeakWorkerRef> mWorkerRef;
 };
 
 } // dom namespace
 } // mozilla namespace
+
+#endif // mozilla_dom_serviceworkerregistrationimpl_h
--- a/dom/serviceworkers/ServiceWorkerUtils.h
+++ b/dom/serviceworkers/ServiceWorkerUtils.h
@@ -3,26 +3,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _mozilla_dom_ServiceWorkerUtils_h
 #define _mozilla_dom_ServiceWorkerUtils_h
 
 #include "mozilla/MozPromise.h"
 #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 
 class ServiceWorkerRegistrationData;
 class ServiceWorkerRegistrationDescriptor;
 
 typedef MozPromise<ServiceWorkerRegistrationDescriptor, nsresult, false>
         ServiceWorkerRegistrationPromise;
 
+typedef MozPromise<nsTArray<ServiceWorkerRegistrationDescriptor>, nsresult, false>
+        ServiceWorkerRegistrationListPromise;
+
 bool
 ServiceWorkerParentInterceptEnabled();
 
 bool
 ServiceWorkerRegistrationDataIsValid(const ServiceWorkerRegistrationData& aData);
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/serviceworkers/moz.build
+++ b/dom/serviceworkers/moz.build
@@ -24,16 +24,17 @@ EXPORTS.mozilla.dom += [
     'ServiceWorkerRegistrationDescriptor.h',
     'ServiceWorkerRegistrationInfo.h',
     'ServiceWorkerUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'ServiceWorker.cpp',
     'ServiceWorkerContainer.cpp',
+    'ServiceWorkerContainerImpl.cpp',
     'ServiceWorkerDescriptor.cpp',
     'ServiceWorkerEvents.cpp',
     'ServiceWorkerInfo.cpp',
     'ServiceWorkerInterceptController.cpp',
     'ServiceWorkerJob.cpp',
     'ServiceWorkerJobQueue.cpp',
     'ServiceWorkerManager.cpp',
     'ServiceWorkerManagerChild.cpp',
--- a/dom/websocket/WebSocket.cpp
+++ b/dom/websocket/WebSocket.cpp
@@ -567,17 +567,17 @@ WebSocketImpl::FailConnection(uint16_t a
 }
 
 namespace {
 
 class DisconnectInternalRunnable final : public WorkerMainThreadRunnable
 {
 public:
   explicit DisconnectInternalRunnable(WebSocketImpl* aImpl)
-    : WorkerMainThreadRunnable(aImpl->mWorkerRef->Private(),
+    : WorkerMainThreadRunnable(GetCurrentThreadWorkerPrivate(),
                                NS_LITERAL_CSTRING("WebSocket :: disconnect"))
     , mImpl(aImpl)
   { }
 
   bool MainThreadRun() override
   {
     mImpl->DisconnectInternal();
     return true;
@@ -615,17 +615,17 @@ WebSocketImpl::Disconnect()
   if (NS_IsMainThread()) {
     DisconnectInternal();
 
     // If we haven't called WebSocket::DisconnectFromOwner yet, update
     // web socket count here.
     if (mWebSocket->GetOwner()) {
       mWebSocket->GetOwner()->UpdateWebSocketCount(-1);
     }
-  } else if (mWorkerRef) {
+  } else {
     RefPtr<DisconnectInternalRunnable> runnable =
       new DisconnectInternalRunnable(this);
     ErrorResult rv;
     runnable->Dispatch(Killing, rv);
     // XXXbz this seems totally broken.  We should be propagating this out, but
     // where to, exactly?
     rv.SuppressException();
   }
@@ -1398,28 +1398,24 @@ WebSocket::ConstructorCommon(const Globa
     }
 
     aRv = runnable->ErrorCode();
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     if (NS_WARN_IF(!webSocketImpl->RegisterWorkerRef(workerPrivate))) {
-      // The worker is shutting down. We cannot proceed but we return a
-      // 'connecting' object.
-      webSocketImpl->mWorkerShuttingDown = true;
-      webSocketImpl->Disconnect();
-      return webSocket.forget();
+      // The worker is shutting down.
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
 
     RefPtr<ConnectRunnable> connectRunnable =
       new ConnectRunnable(workerPrivate, webSocketImpl);
-    // We can use Closing because we have a WorkerRef and that is enough to be
-    // sure that the worker is up and running.
-    connectRunnable->Dispatch(Closing, aRv);
+    connectRunnable->Dispatch(Canceling, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     connectionFailed = connectRunnable->ConnectionFailed();
   }
 
   // It can be that we have been already disconnected because the WebSocket is
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3,16 +3,17 @@
 /* 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 "WorkerPrivate.h"
 
 #include "js/MemoryMetrics.h"
 #include "MessageEventRunnable.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientSource.h"
 #include "mozilla/dom/ClientState.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/Event.h"
@@ -971,16 +972,103 @@ class SimpleWorkerHolder final : public 
 public:
   SimpleWorkerHolder()
     : WorkerHolder("SimpleWorkerHolder")
   {}
 
   virtual bool Notify(WorkerStatus aStatus) override { return true; }
 };
 
+// A runnable to cancel the worker from the parent thread when self.close() is
+// called. This runnable is executed on the parent process in order to cancel
+// the current runnable. It uses a normal WorkerRunnable in order to be sure
+// that all the pending WorkerRunnables are executed before this.
+class CancelingOnParentRunnable final : public WorkerRunnable
+{
+public:
+  explicit CancelingOnParentRunnable(WorkerPrivate* aWorkerPrivate)
+    : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
+  {}
+
+  bool
+  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+  {
+    aWorkerPrivate->Cancel();
+    return true;
+  }
+};
+
+// A runnable to cancel the worker from the parent process.
+class CancelingWithTimeoutOnParentRunnable final : public WorkerControlRunnable
+{
+public:
+  explicit CancelingWithTimeoutOnParentRunnable(WorkerPrivate* aWorkerPrivate)
+    : WorkerControlRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
+  {}
+
+  bool
+  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+  {
+    aWorkerPrivate->AssertIsOnParentThread();
+    aWorkerPrivate->StartCancelingTimer();
+    return true;
+  }
+};
+
+class CancelingTimerCallback final : public nsITimerCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit CancelingTimerCallback(WorkerPrivate* aWorkerPrivate)
+    : mWorkerPrivate(aWorkerPrivate)
+  {}
+
+  NS_IMETHOD
+  Notify(nsITimer* aTimer) override
+  {
+    mWorkerPrivate->AssertIsOnParentThread();
+    mWorkerPrivate->Cancel();
+    return NS_OK;
+  }
+
+private:
+  ~CancelingTimerCallback() = default;
+
+  // Raw pointer here is OK because the timer is canceled during the shutdown
+  // steps.
+  WorkerPrivate* mWorkerPrivate;
+};
+
+NS_IMPL_ISUPPORTS(CancelingTimerCallback, nsITimerCallback)
+
+// This runnable starts the canceling of a worker after a self.close().
+class CancelingRunnable final : public Runnable
+{
+public:
+  CancelingRunnable()
+    : Runnable("CancelingRunnable")
+  {}
+
+  NS_IMETHOD
+  Run() override
+  {
+    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
+    MOZ_ASSERT(workerPrivate);
+    workerPrivate->AssertIsOnWorkerThread();
+
+    // Now we can cancel the this worker from the parent process.
+    RefPtr<CancelingOnParentRunnable> r =
+      new CancelingOnParentRunnable(workerPrivate);
+    r->Dispatch();
+
+    return NS_OK;
+  }
+};
+
 } /* anonymous namespace */
 
 class WorkerPrivate::EventTarget final : public nsISerialEventTarget
 {
   // This mutex protects mWorkerPrivate and must be acquired *before* the
   // WorkerPrivate's mutex whenever they must both be held.
   mozilla::Mutex mMutex;
   WorkerPrivate* mWorkerPrivate;
@@ -1520,18 +1608,18 @@ WorkerPrivate::Traverse(nsCycleCollectio
   if (!mBusyCount && !mMainThreadObjectsForgotten) {
     nsCycleCollectionTraversalCallback& cb = aCb;
     WorkerPrivate* tmp = this;
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentEventTargetRef);
   }
 }
 
 nsresult
-WorkerPrivate::DispatchPrivate(already_AddRefed<WorkerRunnable> aRunnable,
-                               nsIEventTarget* aSyncLoopTarget)
+WorkerPrivate::Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
+                        nsIEventTarget* aSyncLoopTarget)
 {
   // May be called on any thread!
   RefPtr<WorkerRunnable> runnable(aRunnable);
 
   {
     MutexAutoLock lock(mMutex);
 
     MOZ_ASSERT_IF(aSyncLoopTarget, mThread);
@@ -1732,16 +1820,22 @@ WorkerPrivate::NotifyPrivate(WorkerStatu
   }
 
   NS_ASSERTION(aStatus != Terminating || mQueuedRunnables.IsEmpty(),
                "Shouldn't have anything queued!");
 
   // Anything queued will be discarded.
   mQueuedRunnables.Clear();
 
+  // No Canceling timeout is needed.
+  if (mCancelingTimer) {
+    mCancelingTimer->Cancel();
+    mCancelingTimer = nullptr;
+  }
+
   RefPtr<NotifyRunnable> runnable = new NotifyRunnable(this, aStatus);
   return runnable->Dispatch();
 }
 
 bool
 WorkerPrivate::Freeze(nsPIDOMWindowInner* aWindow)
 {
   AssertIsOnParentThread();
@@ -3604,16 +3698,23 @@ WorkerPrivate::InterruptCallback(JSConte
   }
 
   // Make sure the periodic timer gets turned back on here.
   SetGCTimerMode(PeriodicTimer);
 
   return true;
 }
 
+void
+WorkerPrivate::CloseInternal()
+{
+  AssertIsOnWorkerThread();
+  NotifyInternal(Closing);
+}
+
 bool
 WorkerPrivate::IsOnCurrentThread()
 {
   // May be called on any thread!
 
   MOZ_ASSERT(mPRThread);
   return PR_GetCurrentThread() == mPRThread;
 }
@@ -4019,16 +4120,18 @@ WorkerPrivate::CancelAllTimeouts()
   mTimer = nullptr;
   mTimerRunnable = nullptr;
 }
 
 already_AddRefed<nsIEventTarget>
 WorkerPrivate::CreateNewSyncLoop(WorkerStatus aFailStatus)
 {
   AssertIsOnWorkerThread();
+  MOZ_ASSERT(aFailStatus >= Terminating,
+             "Sync loops can be created when the worker is in Running/Closing state!");
 
   {
     MutexAutoLock lock(mMutex);
 
     if (mStatus >= aFailStatus) {
       return nullptr;
     }
   }
@@ -4473,18 +4576,34 @@ WorkerPrivate::NotifyInternal(WorkerStat
   }
 
   // If the worker script never ran, or failed to compile, we don't need to do
   // anything else.
   if (!GlobalScope()) {
     return true;
   }
 
-  // Don't abort the script.
+  // Don't abort the script now, but we dispatch a runnable to do it when the
+  // current JS frame is executed.
   if (aStatus == Closing) {
+    if (mSyncLoopStack.IsEmpty()) {
+      // Here we use a normal runnable to know when the current JS chunk of code
+      // is finished. We cannot use a WorkerRunnable because they are not
+      // accepted any more by the worker, and we do not want to use a
+      // WorkerControlRunnable because they are immediately executed.
+      RefPtr<CancelingRunnable> r = new CancelingRunnable();
+      mThread->nsThread::Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+
+      // At the same time, we want to be sure that we interrupt infinite loops.
+      // The following runnable starts a timer that cancel the worker, from the
+      // parent thread, after CANCELING_TIMEOUT millseconds.
+      RefPtr<CancelingWithTimeoutOnParentRunnable> rr =
+        new CancelingWithTimeoutOnParentRunnable(this);
+      rr->Dispatch();
+    }
     return true;
   }
 
   MOZ_ASSERT(aStatus == Terminating ||
              aStatus == Canceling ||
              aStatus == Killing);
 
   // Always abort the script.
@@ -4842,16 +4961,58 @@ WorkerPrivate::RescheduleTimeoutTimer(JS
     JS_ReportErrorASCII(aCx, "Failed to start timer!");
     return false;
   }
 
   return true;
 }
 
 void
+WorkerPrivate::StartCancelingTimer()
+{
+  AssertIsOnParentThread();
+
+  auto errorCleanup = MakeScopeExit([&] {
+    mCancelingTimer = nullptr;
+  });
+
+  MOZ_ASSERT(!mCancelingTimer);
+
+  if (WorkerPrivate* parent = GetParent()) {
+    mCancelingTimer = NS_NewTimer(parent->ControlEventTarget());
+  } else {
+    mCancelingTimer = NS_NewTimer();
+  }
+
+  if (NS_WARN_IF(!mCancelingTimer)) {
+    return;
+  }
+
+  // This is not needed if we are already in an advanced shutdown state.
+  {
+    MutexAutoLock lock(mMutex);
+    if (ParentStatus() >= Terminating) {
+      return;
+    }
+  }
+
+  uint32_t cancelingTimeoutMillis = DOMPrefs::WorkerCancelingTimeoutMillis();
+
+  RefPtr<CancelingTimerCallback> callback = new CancelingTimerCallback(this);
+  nsresult rv = mCancelingTimer->InitWithCallback(callback,
+                                                  cancelingTimeoutMillis,
+                                                  nsITimer::TYPE_ONE_SHOT);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  errorCleanup.release();
+}
+
+void
 WorkerPrivate::UpdateContextOptionsInternal(
                                     JSContext* aCx,
                                     const JS::ContextOptions& aContextOptions)
 {
   AssertIsOnWorkerThread();
 
   JS::ContextOptionsRef(aCx) = aContextOptions;
 
@@ -5289,17 +5450,17 @@ WorkerPrivate::EventTarget::Dispatch(alr
     return NS_ERROR_UNEXPECTED;
   }
 
   if (event) {
     workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(event.forget());
   }
 
   nsresult rv =
-    mWorkerPrivate->DispatchPrivate(workerRunnable.forget(), mNestedEventTarget);
+    mWorkerPrivate->Dispatch(workerRunnable.forget(), mNestedEventTarget);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -258,22 +258,18 @@ public:
   DoRunLoop(JSContext* aCx);
 
   bool
   InterruptCallback(JSContext* aCx);
 
   bool
   IsOnCurrentThread();
 
-  bool
-  CloseInternal()
-  {
-    AssertIsOnWorkerThread();
-    return NotifyInternal(Closing);
-  }
+  void
+  CloseInternal();
 
   bool
   FreezeInternal();
 
   bool
   ThawInternal();
 
   void
@@ -1176,20 +1172,18 @@ public:
   void
   UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
 #endif
 
   void
   OfflineStatusChangeEvent(bool aIsOffline);
 
   nsresult
-  Dispatch(already_AddRefed<WorkerRunnable> aRunnable)
-  {
-    return DispatchPrivate(Move(aRunnable), nullptr);
-  }
+  Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
+           nsIEventTarget* aSyncLoopTarget = nullptr);
 
   nsresult
   DispatchControlRunnable(already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable);
 
   nsresult
   DispatchDebuggerRunnable(already_AddRefed<WorkerRunnable> aDebuggerRunnable);
 
 #ifdef DEBUG
@@ -1208,29 +1202,28 @@ public:
   { }
 #endif
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   bool
   PrincipalIsValid() const;
 #endif
 
+  void
+  StartCancelingTimer();
+
 private:
   WorkerPrivate(WorkerPrivate* aParent,
                 const nsAString& aScriptURL, bool aIsChromeWorker,
                 WorkerType aWorkerType, const nsAString& aWorkerName,
                 const nsACString& aServiceWorkerScope,
                 WorkerLoadInfo& aLoadInfo);
 
   ~WorkerPrivate();
 
-  nsresult
-  DispatchPrivate(already_AddRefed<WorkerRunnable> aRunnable,
-                  nsIEventTarget* aSyncLoopTarget);
-
   bool
   NotifyPrivate(WorkerStatus aStatus);
 
   bool
   TerminatePrivate()
   {
     return NotifyPrivate(Terminating);
   }
@@ -1420,16 +1413,18 @@ private:
   // This is only modified on the worker thread, but in DEBUG builds
   // AssertValidSyncLoop function iterates it on other threads. Therefore
   // modifications are done with mMutex held *only* in DEBUG builds.
   nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
 
   nsCOMPtr<nsITimer> mTimer;
   nsCOMPtr<nsITimerCallback> mTimerRunnable;
 
+  nsCOMPtr<nsITimer> mCancelingTimer;
+
   nsCOMPtr<nsITimer> mGCTimer;
 
   RefPtr<MemoryReporter> mMemoryReporter;
 
   // fired on the main thread if the worker script fails to load
   nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
 
   RefPtr<PerformanceStorage> mPerformanceStorage;
--- a/dom/workers/WorkerRef.cpp
+++ b/dom/workers/WorkerRef.cpp
@@ -65,16 +65,20 @@ public:
     , mWorkerRef(aWorkerRef)
   {}
 
   bool
   Notify(WorkerStatus aStatus) override
   {
     MOZ_ASSERT(mWorkerRef);
 
+    if (aStatus < Canceling) {
+      return true;
+    }
+
     // Let's keep this object alive for the whole Notify() execution.
     RefPtr<WorkerRef> workerRef;
     workerRef = mWorkerRef;
 
     workerRef->Notify();
     return true;
   }
 
@@ -123,17 +127,17 @@ WeakWorkerRef::Create(WorkerPrivate* aWo
   MOZ_ASSERT(aWorkerPrivate);
   aWorkerPrivate->AssertIsOnWorkerThread();
 
   RefPtr<WeakWorkerRef> ref = new WeakWorkerRef(aWorkerPrivate);
 
   // This holder doesn't keep the worker alive.
   UniquePtr<Holder> holder(new Holder("WeakWorkerRef::Holder", ref,
                                       WorkerHolder::AllowIdleShutdownStart));
-  if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Closing))) {
+  if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Canceling))) {
     return nullptr;
   }
 
   ref->mHolder = Move(holder);
   ref->mCallback = aCallback;
 
   return ref.forget();
 }
@@ -177,17 +181,17 @@ StrongWorkerRef::Create(WorkerPrivate* a
   MOZ_ASSERT(aWorkerPrivate);
   MOZ_ASSERT(aName);
 
   RefPtr<StrongWorkerRef> ref = new StrongWorkerRef(aWorkerPrivate);
 
   // The worker is kept alive by this holder.
   UniquePtr<Holder> holder(new Holder(aName, ref,
                                       WorkerHolder::PreventIdleShutdownStart));
-  if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Closing))) {
+  if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Canceling))) {
     return nullptr;
   }
 
   ref->mHolder = Move(holder);
   ref->mCallback = aCallback;
 
   return ref.forget();
 }
--- a/dom/workers/test/WorkerDebugger_sharedWorker.js
+++ b/dom/workers/test/WorkerDebugger_sharedWorker.js
@@ -1,11 +1,17 @@
 "use strict";
 
 self.onconnect = function (event) {
   event.ports[0].onmessage = function (event) {
     switch (event.data) {
     case "close":
       close();
       break;
+
+    case "close_loop":
+      close();
+      // Let's loop forever.
+      while(1) {}
+      break;
     }
   };
 };
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -192,8 +192,9 @@ scheme=https
 [test_navigator_workers_hardwareConcurrency.html]
 [test_bug1278777.html]
 [test_setTimeoutWith0.html]
 [test_bug1301094.html]
 [test_subworkers_suspended.html]
 skip-if = toolkit == 'android' #bug 1366501
 [test_bug1317725.html]
 [test_sharedworker_event_listener_leaks.html]
+[test_fileReaderSync_when_closing.html]
--- a/dom/workers/test/script_createFile.js
+++ b/dom/workers/test/script_createFile.js
@@ -1,14 +1,35 @@
-Cu.importGlobalProperties(["File", "Directory"]);
+Cu.importGlobalProperties(["File"]);
 
 addMessageListener("file.open", function (e) {
   var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIDirectoryService)
                   .QueryInterface(Ci.nsIProperties)
                   .get('TmpD', Ci.nsIFile)
   tmpFile.append('file.txt');
   tmpFile.createUnique(Ci.nsIFile.FILE_TYPE, 0o600);
 
   File.createFromNsIFile(tmpFile).then(function(file) {
     sendAsyncMessage("file.opened", { data: file });
   });
 });
+
+addMessageListener("nonEmptyFile.open", function (e) {
+  var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
+                  .getService(Ci.nsIDirectoryService)
+                  .QueryInterface(Ci.nsIProperties)
+                  .get('TmpD', Ci.nsIFile)
+  tmpFile.append('file.txt');
+  tmpFile.createUnique(Ci.nsIFile.FILE_TYPE, 0o600);
+
+  var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); 
+  outStream.init(tmpFile, 0x02 | 0x08 | 0x20, // write, create, truncate
+                 0o666, 0);                         
+  var fileData = "Hello world!";
+  outStream.write(fileData, fileData.length);
+  outStream.close();                           
+
+
+  File.createFromNsIFile(tmpFile).then(function(file) {
+    sendAsyncMessage("nonEmptyFile.opened", { data: file });
+  });
+});
--- a/dom/workers/test/test_WorkerDebugger.xul
+++ b/dom/workers/test/test_WorkerDebugger.xul
@@ -18,16 +18,17 @@
 
     const WORKER_URL = "WorkerDebugger_worker.js";
     const CHILD_WORKER_URL = "WorkerDebugger_childWorker.js";
     const SHARED_WORKER_URL = "WorkerDebugger_sharedWorker.js";
 
     function test() {
       (async function() {
         SimpleTest.waitForExplicitFinish();
+        SimpleTest.requestLongerTimeout(5);
 
         info("Create a top-level chrome worker that creates a non-top-level " +
              "content worker and wait for their debuggers to be registered.");
         let promise = waitForMultiple([
           waitForRegister(WORKER_URL),
           waitForRegister(CHILD_WORKER_URL)
         ]);
         worker = new ChromeWorker(WORKER_URL);
@@ -51,28 +52,28 @@
         is(childDbg.parent, dbg,
            "Non-top-level worker debugger should have parent.");
         is(childDbg.type, Ci.nsIWorkerDebugger.TYPE_DEDICATED,
            "Content worker debugger should be dedicated.");
         is(childDbg.window, null,
            "Non-top-level worker debugger should not have window.");
 
         info("Terminate the top-level chrome worker and the non-top-level " +
-             "content worker, and wait for their debuggers to be " + 
+             "content worker, and wait for their debuggers to be " +
              "unregistered and closed.");
         promise = waitForMultiple([
           waitForUnregister(CHILD_WORKER_URL),
           waitForDebuggerClose(childDbg),
           waitForUnregister(WORKER_URL),
           waitForDebuggerClose(dbg),
         ]);
         worker.terminate();
         await promise;
 
-        info("Create a shared worker and wait for its debugger to be " + 
+        info("Create a shared worker and wait for its debugger to be " +
              "registered");
         promise = waitForRegister(SHARED_WORKER_URL);
         worker = new SharedWorker(SHARED_WORKER_URL);
         let sharedDbg = await promise;
 
         info("Check that the shared worker debugger has the correct " +
              "properties.");
         is(sharedDbg.isChrome, false,
@@ -88,28 +89,52 @@
              "debugger is not registered again.");
         let listener = {
           onRegistered: function () {
             ok(false,
                "Shared worker debugger should not be registered again.");
           },
         };
         wdm.addListener(listener);
+
         worker = new SharedWorker(SHARED_WORKER_URL);
 
         info("Send a message to the shared worker to tell it to close " +
              "itself, and wait for its debugger to be closed.");
         promise = waitForMultiple([
           waitForUnregister(SHARED_WORKER_URL),
           waitForDebuggerClose(sharedDbg)
         ]);
         worker.port.start();
         worker.port.postMessage("close");
         await promise;
 
+        promise = waitForRegister(SHARED_WORKER_URL);
+        worker = new SharedWorker(SHARED_WORKER_URL);
+        sharedDbg = await promise;
+
+        info("Send a message to the shared worker to tell it to close " +
+             "itself, then loop forever, and wait for its debugger to be closed.");
+        promise = waitForMultiple([
+          waitForUnregister(SHARED_WORKER_URL),
+          waitForDebuggerClose(sharedDbg)
+        ]);
+
+        // When the closing process begins, we schedule a timer to terminate
+        // the worker in case it's in an infinite loop, which is exactly what
+        // we do in this test.  We want a duration long enough that we can be
+        // confident that the infinite loop was entered as measured by
+        // performance.now() and that we terminated it, but not as long as our
+        // 30 second default we currently ship.
+        await SpecialPowers.pushPrefEnv({"set": [[ "dom.worker.canceling.timeoutMilliseconds", 15000 ]]});
+
+        worker.port.start();
+        worker.port.postMessage("close_loop");
+        await promise;
+
         wdm.removeListener(listener);
         SimpleTest.finish();
       })();
     }
 
   ]]>
   </script>
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_fileReaderSync_when_closing.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for FileReaderSync when the worker is closing</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+  <script type="application/javascript">
+
+// In order to exercise FileReaderSync::SyncRead's syncLoop-using AsyncWait()
+// path, we need to provide a stream that will both 1) not have all the data
+// immediately available (eliminating memory-backed Blobs) and 2) return
+// NS_BASE_STREAM_WOULD_BLOCK.  Under e10s, any Blob/File sourced from the
+// parent process (as loadChromeScript performs) will be backed by an
+// IPCBlobInputStream and will behave this way on first use (when it is in the
+// eInit state).  For ease of testing, we reuse script_createFile.js which
+// involves a file on disk, but a memory-backed Blob from the parent process
+// would be equally fine.  Under non-e10s, this File will not do the right
+// thing because a synchronous nsFileInputStream will be made directly
+// available and the AsyncWait path won't be taken, but the test will still
+// pass.
+
+var url = SimpleTest.getTestFileURL("script_createFile.js");
+var script = SpecialPowers.loadChromeScript(url);
+
+function onOpened(message) {
+  function workerCode() {
+    onmessage = function(e) {
+      self.close();
+      var fr = new FileReaderSync();
+      self.postMessage(fr.readAsText(e.data));
+    }
+  }
+
+  var b = new Blob([workerCode+'workerCode();']);
+  var w = new Worker(URL.createObjectURL(b));
+  w.onmessage = function(e) {
+    is(e.data, "Hello world!", "The blob content is OK!");
+    SimpleTest.finish();
+  }
+
+  w.postMessage(message.data);
+}
+
+script.addMessageListener("nonEmptyFile.opened", onOpened);
+script.sendAsyncMessage("nonEmptyFile.open");
+
+SimpleTest.waitForExplicitFinish();
+
+  </script>
+</body>
+</html>
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -23,25 +23,23 @@
 #include "nsIXMLContentSink.h"
 #include "nsContentCID.h"
 #include "mozilla/dom/XMLDocument.h"
 #include "nsXBLService.h"
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsXBLContentSink.h"
 #include "xptinfo.h"
-#include "nsIInterfaceInfoManager.h"
 #include "nsIDocumentObserver.h"
 #include "nsGkAtoms.h"
 #include "nsXBLProtoImpl.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsTextFragment.h"
 #include "nsTextNode.h"
-#include "nsIInterfaceInfo.h"
 #include "nsIScriptError.h"
 
 #include "nsXBLResourceLoader.h"
 #include "mozilla/dom/CDATASection.h"
 #include "mozilla/dom/CharacterData.h"
 #include "mozilla/dom/Comment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/StyleSheet.h"
@@ -705,50 +703,42 @@ nsXBLPrototypeBinding::ConstructAttribut
     }
   }
 }
 
 nsresult
 nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAString& aImpls)
 {
   if (!aImpls.IsEmpty()) {
-    // Obtain the interface info manager that can tell us the IID
-    // for a given interface name.
-    nsCOMPtr<nsIInterfaceInfoManager>
-      infoManager(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
-    if (!infoManager)
-      return NS_ERROR_FAILURE;
-
     // The user specified at least one attribute.
     NS_ConvertUTF16toUTF8 utf8impl(aImpls);
     char* str = utf8impl.BeginWriting();
     char* newStr;
     // XXX We should use a strtok function that tokenizes PRUnichars
     // so that we don't have to convert from Unicode to ASCII and then back
 
     char* token = nsCRT::strtok( str, ", ", &newStr );
     while( token != nullptr ) {
       // get the InterfaceInfo for the name
-      nsCOMPtr<nsIInterfaceInfo> iinfo;
-      infoManager->GetInfoForName(token, getter_AddRefs(iinfo));
+      const nsXPTInterfaceInfo* iinfo = nsXPTInterfaceInfo::ByName(token);
 
       if (iinfo) {
         // obtain an IID.
         const nsIID* iid = nullptr;
         iinfo->GetIIDShared(&iid);
 
         if (iid) {
           // We found a valid iid.  Add it to our table.
           mInterfaceTable.Put(*iid, mBinding);
 
           // this block adds the parent interfaces of each interface
           // defined in the xbl definition (implements="nsI...")
-          nsCOMPtr<nsIInterfaceInfo> parentInfo;
+          const nsXPTInterfaceInfo* parentInfo;
           // if it has a parent, add it to the table
-          while (NS_SUCCEEDED(iinfo->GetParent(getter_AddRefs(parentInfo))) && parentInfo) {
+          while (NS_SUCCEEDED(iinfo->GetParent(&parentInfo)) && parentInfo) {
             // get the iid
             parentInfo->GetIIDShared(&iid);
 
             // don't add nsISupports to the table
             if (!iid || iid->Equals(NS_GET_IID(nsISupports)))
               break;
 
             // add the iid to the table
--- a/dom/xml/nsXMLFragmentContentSink.cpp
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -7,17 +7,16 @@
 #include "nsCOMPtr.h"
 #include "nsXMLContentSink.h"
 #include "nsIFragmentContentSink.h"
 #include "nsIXMLContentSink.h"
 #include "nsContentSink.h"
 #include "nsIExpatSink.h"
 #include "nsIDTD.h"
 #include "nsIDocument.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIContent.h"
 #include "nsGkAtoms.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsError.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsTHashtable.h"
@@ -64,17 +63,17 @@ public:
   NS_IMETHOD DidBuildModel(bool aTerminated) override;
   virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
   virtual nsISupports* GetTarget() override;
   NS_IMETHOD DidProcessATokenImpl();
 
   // nsIXMLContentSink
 
   // nsIFragmentContentSink
-  NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) override;
+  NS_IMETHOD FinishFragmentParsing(DocumentFragment** aFragment) override;
   NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) override;
   NS_IMETHOD WillBuildContent() override;
   NS_IMETHOD DidBuildContent() override;
   NS_IMETHOD IgnoreFirstContainer() override;
   NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) override;
 
 protected:
   virtual ~nsXMLFragmentContentSink();
@@ -107,17 +106,17 @@ protected:
     const nsAString& aTitle,
     const nsAString& aType,
     const nsAString& aMedia,
     const nsAString& aReferrerPolicy,
     bool* aWasXSLT = nullptr) override;
 
   nsCOMPtr<nsIDocument> mTargetDocument;
   // the fragment
-  nsCOMPtr<nsIContent>  mRoot;
+  RefPtr<DocumentFragment> mRoot;
   bool                  mParseError;
 };
 
 static nsresult
 NewXMLFragmentContentSinkHelper(nsIFragmentContentSink** aResult)
 {
   nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink();
 
@@ -355,40 +354,37 @@ nsXMLFragmentContentSink::MaybeProcessXS
 {
   MOZ_ASSERT(!aWasXSLT, "Our one caller doesn't care about whether we're XSLT");
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP
-nsXMLFragmentContentSink::FinishFragmentParsing(nsIDOMDocumentFragment** aFragment)
+nsXMLFragmentContentSink::FinishFragmentParsing(DocumentFragment** aFragment)
 {
-  *aFragment = nullptr;
   mTargetDocument = nullptr;
   mNodeInfoManager = nullptr;
   mScriptLoader = nullptr;
   mCSSLoader = nullptr;
   mContentStack.Clear();
   mDocumentURI = nullptr;
   mDocShell = nullptr;
   mDocElement = nullptr;
   mCurrentHead = nullptr;
   if (mParseError) {
     //XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
     mRoot = nullptr;
     mParseError = false;
+    *aFragment = nullptr;
     return NS_ERROR_DOM_SYNTAX_ERR;
-  } else if (mRoot) {
-    nsresult rv = CallQueryInterface(mRoot, aFragment);
-    mRoot = nullptr;
-    return rv;
-  } else {
-    return NS_OK;
   }
+
+  mRoot.forget(aFragment);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
 {
   NS_ENSURE_ARG_POINTER(aTargetDocument);
 
   mTargetDocument = aTargetDocument;
--- a/dom/xslt/txIEXSLTRegExFunctions.idl
+++ b/dom/xslt/txIEXSLTRegExFunctions.idl
@@ -1,23 +1,21 @@
 /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "nsISupports.idl"
 
-interface nsIDOMDocument;
-interface nsIDOMDocumentFragment;
+webidl Document;
+webidl DocumentFragment;
 
 [scriptable, uuid(c180e993-aced-4839-95a0-ecd5ff138be9)]
 interface txIEXSLTRegExFunctions : nsISupports
 {
-    // Make this take Document and return DocumentFragment once https://bugzil.la/1444991
-    // is fixed.
-    nsIDOMDocumentFragment match(in DOMString aString, in DOMString aRegEx,
-                                 in DOMString aFlags,
-                                 in nsIDOMDocument aResultDocument);
+    DocumentFragment match(in DOMString aString, in DOMString aRegEx,
+                           in DOMString aFlags,
+                           in Document aResultDocument);
     DOMString replace(in DOMString aString, in DOMString aRegEx,
                       in DOMString aFlags, in DOMString aReplace);
     boolean test(in DOMString aString, in DOMString aRegEx,
                  in DOMString aFlags);
 };
--- a/dom/xslt/xpath/txXPathTreeWalker.h
+++ b/dom/xslt/xpath/txXPathTreeWalker.h
@@ -90,22 +90,16 @@ public:
     }
 };
 
 class txXPathNativeNode
 {
 public:
     static txXPathNode* createXPathNode(nsINode* aNode,
                                         bool aKeepRootAlive = false);
-    static txXPathNode* createXPathNode(nsIDOMNode* aNode,
-                                        bool aKeepRootAlive = false)
-    {
-        nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-        return createXPathNode(node, aKeepRootAlive);
-    }
     static txXPathNode* createXPathNode(nsIContent* aContent,
                                         bool aKeepRootAlive = false);
     static txXPathNode* createXPathNode(nsIDOMDocument* aDocument);
     static nsINode* getNode(const txXPathNode& aNode);
     static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult)
     {
         return CallQueryInterface(getNode(aNode), aResult);
     }
--- a/dom/xslt/xslt/txEXSLTFunctions.cpp
+++ b/dom/xslt/xslt/txEXSLTFunctions.cpp
@@ -19,17 +19,16 @@
 #include "txOutputFormat.h"
 #include "txRtfHandler.h"
 #include "txXPathTreeWalker.h"
 #include "nsPrintfCString.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentCID.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIContent.h"
-#include "nsIDOMDocumentFragment.h"
 #include "txMozillaXMLOutput.h"
 #include "nsTextNode.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "prtime.h"
 #include "txIEXSLTRegExFunctions.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -58,17 +57,17 @@ getSourceDocument(txIEvalContext *aConte
 static nsresult
 convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
 {
     nsIDocument *doc = getSourceDocument(aContext);
     if (!doc) {
         return NS_ERROR_UNEXPECTED;
     }
 
-    nsCOMPtr<nsIDOMDocumentFragment> domFragment =
+    RefPtr<DocumentFragment> domFragment =
       new DocumentFragment(doc->NodeInfoManager());
 
     txOutputFormat format;
     txMozillaXMLOutput mozHandler(&format, domFragment, true);
 
     nsresult rv = aRtf->flushToHandler(&mozHandler);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -738,27 +737,24 @@ txEXSLTRegExFunctionCall::evaluate(txIEv
     if (mParams.Length() >= 3) {
         rv = mParams[2]->evaluateToString(aContext, flags);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     switch (mType) {
         case txEXSLTType::MATCH:
         {
-            nsCOMPtr<nsIDOMDocument> sourceDoc =
-                do_QueryInterface(getSourceDocument(aContext));
+            nsCOMPtr<nsIDocument> sourceDoc = getSourceDocument(aContext);
             NS_ENSURE_STATE(sourceDoc);
 
-            nsCOMPtr<nsIDOMDocumentFragment> domDocFrag;
+            RefPtr<DocumentFragment> docFrag;
             rv = mRegExService->Match(string, regex, flags, sourceDoc,
-                                      getter_AddRefs(domDocFrag));
+                                      getter_AddRefs(docFrag));
             NS_ENSURE_SUCCESS(rv, rv);
-
-            nsCOMPtr<nsIContent> docFrag = do_QueryInterface(domDocFrag, &rv);
-            NS_ENSURE_SUCCESS(rv, rv);
+            NS_ENSURE_STATE(docFrag);
 
             RefPtr<txNodeSet> resultSet;
             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsAutoPtr<txXPathNode> node;
             for (nsIContent* result = docFrag->GetFirstChild(); result;
                  result = result->GetNextSibling()) {
--- a/dom/xslt/xslt/txMozillaTextOutput.cpp
+++ b/dom/xslt/xslt/txMozillaTextOutput.cpp
@@ -3,41 +3,41 @@
  * 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 "txMozillaTextOutput.h"
 #include "nsContentCID.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIDocumentTransformer.h"
 #include "nsCharsetSource.h"
 #include "nsIPrincipal.h"
 #include "txURIUtils.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "mozilla/Encoding.h"
 #include "nsTextNode.h"
 #include "nsNameSpaceManager.h"
+#include "mozilla/dom/DocumentFragment.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 txMozillaTextOutput::txMozillaTextOutput(nsITransformObserver* aObserver)
 {
     MOZ_COUNT_CTOR(txMozillaTextOutput);
     mObserver = do_GetWeakReference(aObserver);
 }
 
-txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocumentFragment* aDest)
+txMozillaTextOutput::txMozillaTextOutput(DocumentFragment* aDest)
 {
     MOZ_COUNT_CTOR(txMozillaTextOutput);
-    mTextParent = do_QueryInterface(aDest);
+    mTextParent = aDest;
     mDocument = mTextParent->OwnerDoc();
 }
 
 txMozillaTextOutput::~txMozillaTextOutput()
 {
     MOZ_COUNT_DTOR(txMozillaTextOutput);
 }
 
--- a/dom/xslt/xslt/txMozillaTextOutput.h
+++ b/dom/xslt/xslt/txMozillaTextOutput.h
@@ -6,32 +6,32 @@
 #ifndef TRANSFRMX_MOZILLA_TEXT_OUTPUT_H
 #define TRANSFRMX_MOZILLA_TEXT_OUTPUT_H
 
 #include "txXMLEventHandler.h"
 #include "nsCOMPtr.h"
 #include "nsWeakPtr.h"
 #include "txOutputFormat.h"
 
-class nsIDOMDocumentFragment;
 class nsITransformObserver;
 class nsIDocument;
 class nsIContent;
 
 namespace mozilla {
 namespace dom {
+class DocumentFragment;
 class Element;
 }
 }
 
 class txMozillaTextOutput : public txAOutputXMLEventHandler
 {
 public:
     explicit txMozillaTextOutput(nsITransformObserver* aObserver);
-    explicit txMozillaTextOutput(nsIDOMDocumentFragment* aDest);
+    explicit txMozillaTextOutput(mozilla::dom::DocumentFragment* aDest);
     virtual ~txMozillaTextOutput();
 
     TX_DECL_TXAXMLEVENTHANDLER
     TX_DECL_TXAOUTPUTXMLEVENTHANDLER
 
     nsresult createResultDocument(nsIDocument* aSourceDocument,
                                   bool aLoadedAsData);
 
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -13,26 +13,26 @@
 #include "nsIRefreshURI.h"
 #include "nsPIDOMWindow.h"
 #include "nsIContent.h"
 #include "nsContentCID.h"
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "txLog.h"
 #include "nsIConsoleService.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsNameSpaceManager.h"
 #include "txStringUtils.h"
 #include "txURIUtils.h"
 #include "nsIHTMLDocument.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIDocumentTransformer.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/DocumentType.h"
+#include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/Encoding.h"
 #include "nsContentUtils.h"
 #include "txXMLUtils.h"
 #include "nsContentSink.h"
 #include "nsINode.h"
 #include "nsContentCreatorFunctions.h"
@@ -69,31 +69,31 @@ txMozillaXMLOutput::txMozillaXMLOutput(t
         }
     }
 
     mOutputFormat.merge(*aFormat);
     mOutputFormat.setFromDefaults();
 }
 
 txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
-                                       nsIDOMDocumentFragment* aFragment,
+                                       DocumentFragment* aFragment,
                                        bool aNoFixup)
     : mTreeDepth(0),
       mBadChildLevel(0),
       mTableState(NORMAL),
       mCreatingNewDocument(false),
       mOpenedElementIsHTML(false),
       mRootContentCreated(false),
       mNoFixup(aNoFixup)
 {
     MOZ_COUNT_CTOR(txMozillaXMLOutput);
     mOutputFormat.merge(*aFormat);
     mOutputFormat.setFromDefaults();
 
-    mCurrentNode = do_QueryInterface(aFragment);
+    mCurrentNode = aFragment;
     mDocument = mCurrentNode->OwnerDoc();
     mNodeInfoManager = mDocument->NodeInfoManager();
 }
 
 txMozillaXMLOutput::~txMozillaXMLOutput()
 {
     MOZ_COUNT_DTOR(txMozillaXMLOutput);
 }
--- a/dom/xslt/xslt/txMozillaXMLOutput.h
+++ b/dom/xslt/xslt/txMozillaXMLOutput.h
@@ -14,22 +14,27 @@
 #include "nsICSSLoaderObserver.h"
 #include "txStack.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
 
 class nsIContent;
 class nsIDOMDocument;
 class nsAtom;
-class nsIDOMDocumentFragment;
 class nsITransformObserver;
 class nsNodeInfoManager;
 class nsIDocument;
 class nsINode;
 
+namespace mozilla {
+namespace dom {
+class DocumentFragment;
+} // namespace dom
+} // namespace mozilla
+
 class txTransformNotifier final : public nsIScriptLoaderObserver,
                                   public nsICSSLoaderObserver
 {
 public:
     txTransformNotifier();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTLOADEROBSERVER
@@ -58,17 +63,17 @@ private:
 };
 
 class txMozillaXMLOutput : public txAOutputXMLEventHandler
 {
 public:
     txMozillaXMLOutput(txOutputFormat* aFormat,
                        nsITransformObserver* aObserver);
     txMozillaXMLOutput(txOutputFormat* aFormat,
-                       nsIDOMDocumentFragment* aFragment,
+                       mozilla::dom::DocumentFragment* aFragment,
                        bool aNoFixup);
     ~txMozillaXMLOutput();
 
     TX_DECL_TXAXMLEVENTHANDLER
     TX_DECL_TXAOUTPUTXMLEVENTHANDLER
 
     nsresult closePrevious(bool aFlushText);
 
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -6,17 +6,16 @@
 #include "txMozillaXSLTProcessor.h"
 #include "nsContentCID.h"
 #include "nsError.h"
 #include "nsIChannel.h"
 #include "mozilla/dom/Element.h"
 #include "nsIDOMElement.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMDocumentFragment.h"
 #include "nsIDOMNodeList.h"
 #include "nsIIOService.h"
 #include "nsILoadGroup.h"
 #include "nsIStringBundle.h"
 #include "nsIURI.h"
 #include "nsMemory.h"
 #include "XPathResult.h"
 #include "txExecutionState.h"
@@ -66,25 +65,25 @@ private:
     nsCOMPtr<nsIDocument> mSourceDocument;
     nsCOMPtr<nsITransformObserver> mObserver;
     bool mDocumentIsData;
 };
 
 class txToFragmentHandlerFactory : public txAOutputHandlerFactory
 {
 public:
-    explicit txToFragmentHandlerFactory(nsIDOMDocumentFragment* aFragment)
+    explicit txToFragmentHandlerFactory(DocumentFragment* aFragment)
         : mFragment(aFragment)
     {
     }
 
     TX_DECL_TXAOUTPUTHANDLERFACTORY
 
 private:
-    nsCOMPtr<nsIDOMDocumentFragment> mFragment;
+    RefPtr<DocumentFragment> mFragment;
 };
 
 nsresult
 txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
                                          txAXMLEventHandler** aHandler)
 {
     *aHandler = nullptr;
     switch (aFormat->mMethod) {
@@ -186,18 +185,17 @@ txToFragmentHandlerFactory::createHandle
                                               txAXMLEventHandler** aHandler)
 {
     *aHandler = nullptr;
     switch (aFormat->mMethod) {
         case eMethodNotSet:
         {
             txOutputFormat format;
             format.merge(*aFormat);
-            nsCOMPtr<nsINode> node = do_QueryInterface(mFragment);
-            nsCOMPtr<nsIDocument> doc = node->OwnerDoc();
+            nsCOMPtr<nsIDocument> doc = mFragment->OwnerDoc();
 
             if (doc->IsHTMLDocument()) {
                 format.mMethod = eHTMLOutput;
             } else {
                 format.mMethod = eXMLOutput;
             }
 
             *aHandler = new txMozillaXMLOutput(&format, mFragment, false);
@@ -802,17 +800,17 @@ txMozillaXSLTProcessor::SetParameter(con
         // Nodeset
         case nsIDataType::VTYPE_INTERFACE:
         case nsIDataType::VTYPE_INTERFACE_IS:
         {
             nsCOMPtr<nsISupports> supports;
             nsresult rv = value->GetAsISupports(getter_AddRefs(supports));
             NS_ENSURE_SUCCESS(rv, rv);
 
-            nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
+            nsCOMPtr<nsINode> node = do_QueryInterface(supports);
             if (node) {
                 if (!nsContentUtils::CanCallerAccess(node)) {
                     return NS_ERROR_DOM_SECURITY_ERR;
                 }
 
                 break;
             }
 
@@ -1390,17 +1388,17 @@ txVariable::Convert(nsIVariant *aValue, 
         // Nodeset
         case nsIDataType::VTYPE_INTERFACE:
         case nsIDataType::VTYPE_INTERFACE_IS:
         {
             nsCOMPtr<nsISupports> supports;
             nsresult rv = aValue->GetAsISupports(getter_AddRefs(supports));
             NS_ENSURE_SUCCESS(rv, rv);
 
-            nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
+            nsCOMPtr<nsINode> node = do_QueryInterface(supports);
             if (node) {
                 nsAutoPtr<txXPathNode> xpathNode(txXPathNativeNode::createXPathNode(node));
                 if (!xpathNode) {
                     return NS_ERROR_FAILURE;
                 }
 
                 *aResult = new txNodeSet(*xpathNode, nullptr);
                 if (!*aResult) {
@@ -1488,17 +1486,17 @@ txVariable::Convert(nsIVariant *aValue, 
                 NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, values);
 
                 return NS_ERROR_OUT_OF_MEMORY;
             }
 
             uint32_t i;
             for (i = 0; i < count; ++i) {
                 nsISupports *supports = values[i];
-                nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
+                nsCOMPtr<nsINode> node = do_QueryInterface(supports);
                 NS_ASSERTION(node, "Huh, we checked this in SetParameter?");
 
                 nsAutoPtr<txXPathNode> xpathNode(
                     txXPathNativeNode::createXPathNode(node));
                 if (!xpathNode) {
                     while (i < count) {
                         NS_RELEASE(values[i]);
                         ++i;
--- a/editor/nsIEditActionListener.idl
+++ b/editor/nsIEditActionListener.idl
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "domstubs.idl"
 
 interface nsISelection;
 
+webidl CharacterData;
 
 /*
 Editor Action Listener interface to outside world
 */
 
 
 /**
  * A generic editor action listener interface.
@@ -74,47 +75,47 @@ interface nsIEditActionListener : nsISup
    */
   void DidJoinNodes(in nsIDOMNode aLeftNode,
                           in nsIDOMNode aRightNode,
                           in nsIDOMNode aParent,
                           in nsresult    aResult);
 
   /**
    * Called after the editor inserts text.
-   * @param aTextNode   This node getting inserted text.  Should be a CharacterData after bug 1444991.
+   * @param aTextNode   This node getting inserted text.
    * @param aOffset     The offset in aTextNode to insert at.
    * @param aString     The string that gets inserted.
    * @param aResult     The result of the insert text operation.
    */
-  void DidInsertText(in nsISupports aTextNode,
+  void DidInsertText(in CharacterData       aTextNode,
                      in long                aOffset,
                      in DOMString           aString,
                      in nsresult            aResult);
 
   /**
    * Called before the editor deletes text.
-   * @param aTextNode   This node getting text deleted.  Should be a CharacterData after bug 1444991.
+   * @param aTextNode   This node getting text deleted.
    * @param aOffset     The offset in aTextNode to delete at.
    * @param aLength     The amount of text to delete.
    */
-  void WillDeleteText(in nsISupports aTextNode,
+  void WillDeleteText(in CharacterData       aTextNode,
                       in long                aOffset,
                       in long                aLength);
 
   /**
    * Called before the editor deletes text.
-   * @param aTextNode   This node getting text deleted.  Should be a CharacterData after bug 1444991.
+   * @param aTextNode   This node getting text deleted.
    * @param aOffset     The offset in aTextNode to delete at.
    * @param aLength     The amount of text to delete.
    * @param aResult     The result of the delete text operation.
    */
-  void DidDeleteText(in nsISupports aTextNode,
+  void DidDeleteText(in CharacterData       aTextNode,
                      in long                aOffset,
                      in long                aLength,
-                     in nsresult              aResult);
+                     in nsresult            aResult);
 
   /**
    * Called before the editor deletes the selection.
    * @param aSelection   The selection to be deleted
    */
   void WillDeleteSelection(in nsISelection aSelection);
 
   /**
--- a/editor/spellchecker/TextServicesDocument.cpp
+++ b/editor/spellchecker/TextServicesDocument.cpp
@@ -3215,34 +3215,34 @@ NS_IMETHODIMP
 TextServicesDocument::DidCreateNode(const nsAString& aTag,
                                     nsIDOMNode* aNewNode,
                                     nsresult aResult)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TextServicesDocument::DidInsertText(nsISupports* aTextNode,
+TextServicesDocument::DidInsertText(CharacterData* aTextNode,
                                     int32_t aOffset,
                                     const nsAString& aString,
                                     nsresult aResult)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TextServicesDocument::WillDeleteText(nsISupports* aTextNode,
+TextServicesDocument::WillDeleteText(CharacterData* aTextNode,
                                      int32_t aOffset,
                                      int32_t aLength)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TextServicesDocument::DidDeleteText(nsISupports* aTextNode,
+TextServicesDocument::DidDeleteText(CharacterData* aTextNode,
                                     int32_t aOffset,
                                     int32_t aLength,
                                     nsresult aResult)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/gfx/layers/LayerAttributes.h
+++ b/gfx/layers/LayerAttributes.h
@@ -86,16 +86,20 @@ struct ScrollbarData {
            mThumbIsAsyncDraggable == aOther.mThumbIsAsyncDraggable &&
            mScrollTrackStart == aOther.mScrollTrackStart &&
            mScrollTrackLength == aOther.mScrollTrackLength &&
            mTargetViewId == aOther.mTargetViewId;
   }
   bool operator!=(const ScrollbarData& aOther) const {
     return !(*this == aOther);
   }
+
+  bool IsThumb() const {
+    return mScrollbarLayerType == ScrollbarLayerType::Thumb;
+  }
 };
 
 /**
  * Infrequently changing layer attributes that require no special
  * serialization work.
  */
 class SimpleLayerAttributes final
 {
@@ -272,30 +276,20 @@ public:
   float GetOpacity() const {
     return mOpacity;
   }
 
   bool IsFixedPosition() const {
     return mIsFixedPosition;
   }
 
-  FrameMetrics::ViewID GetScrollbarTargetViewId() const {
-    return mScrollbarData.mTargetViewId;
-  }
-
   const ScrollbarData& GetScrollbarData() const {
     return mScrollbarData;
   }
 
-  Maybe<ScrollDirection> GetScrollbarContainerDirection() const {
-    return (mScrollbarData.mScrollbarLayerType == ScrollbarLayerType::Container)
-      ? mScrollbarData.mDirection
-      : Nothing();
-  }
-
   gfx::CompositionOp GetMixBlendMode() const {
     return mMixBlendMode;
   }
 
   bool GetForceIsolatedGroup() const {
     return mForceIsolatedGroup;
   }
 
--- a/gfx/layers/LayerMetricsWrapper.h
+++ b/gfx/layers/LayerMetricsWrapper.h
@@ -421,29 +421,16 @@ public:
   {
     MOZ_ASSERT(IsValid());
     // This function is only really needed for template-compatibility with
     // WebRenderScrollDataWrapper. Although it will be called, the return
     // value is not used.
     return 0;
   }
 
-  FrameMetrics::ViewID GetScrollbarTargetContainerId() const
-  {
-    MOZ_ASSERT(IsValid());
-
-    return mLayer->GetScrollbarTargetViewId();
-  }
-
-  Maybe<ScrollDirection> GetScrollbarContainerDirection() const
-  {
-    MOZ_ASSERT(IsValid());
-    return mLayer->GetScrollbarContainerDirection();
-  }
-
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
   {
     MOZ_ASSERT(IsValid());
 
     return mLayer->GetFixedPositionScrollContainerId();
   }
 
   bool IsBackfaceHidden() const
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -614,16 +614,25 @@ Layer::GetLocalTransform()
 
 const LayerToParentLayerMatrix4x4
 Layer::GetLocalTransformTyped()
 {
   return ViewAs<LayerToParentLayerMatrix4x4>(GetLocalTransform());
 }
 
 bool
+Layer::IsScrollbarContainer() const
+{
+  const ScrollbarData& data = GetScrollbarData();
+  return (data.mScrollbarLayerType == ScrollbarLayerType::Container)
+      ? data.mDirection.isSome()
+      : false;
+}
+
+bool
 Layer::HasOpacityAnimation() const
 {
   return mAnimationInfo.HasOpacityAnimation();
 }
 
 bool
 Layer::HasTransformAnimation() const
 {
@@ -1808,25 +1817,27 @@ Layer::PrintInfo(std::stringstream& aStr
     aStream << " [extend3DContext]";
   }
   if (Combines3DTransformWithAncestors()) {
     aStream << " [combines3DTransformWithAncestors]";
   }
   if (Is3DContextLeaf()) {
     aStream << " [is3DContextLeaf]";
   }
-  if (GetScrollbarContainerDirection().isSome()) {
+  if (IsScrollbarContainer()) {
     aStream << " [scrollbar]";
   }
-  if (Maybe<ScrollDirection> thumbDirection = GetScrollbarData().mDirection) {
-    if (*thumbDirection == ScrollDirection::eVertical) {
-      aStream << nsPrintfCString(" [vscrollbar=%" PRIu64 "]", GetScrollbarTargetViewId()).get();
-    }
-    if (*thumbDirection == ScrollDirection::eHorizontal) {
-      aStream << nsPrintfCString(" [hscrollbar=%" PRIu64 "]", GetScrollbarTargetViewId()).get();
+  if (GetScrollbarData().IsThumb()) {
+    if (Maybe<ScrollDirection> thumbDirection = GetScrollbarData().mDirection) {
+      if (*thumbDirection == ScrollDirection::eVertical) {
+        aStream << nsPrintfCString(" [vscrollbar=%" PRIu64 "]", GetScrollbarData().mTargetViewId).get();
+      }
+      if (*thumbDirection == ScrollDirection::eHorizontal) {
+        aStream << nsPrintfCString(" [hscrollbar=%" PRIu64 "]", GetScrollbarData().mTargetViewId).get();
+      }
     }
   }
   if (GetIsFixedPosition()) {
     LayerPoint anchor = GetFixedPositionAnchor();
     aStream << nsPrintfCString(" [isFixedPosition scrollId=%" PRIu64 " sides=0x%x anchor=%s]",
                      GetFixedPositionScrollContainerId(),
                      GetFixedPositionSides(),
                      ToString(anchor).c_str()).get();
@@ -1966,17 +1977,17 @@ Layer::DumpPacket(layerscope::LayersPack
   layer->set_copaque(static_cast<bool>(GetContentFlags() & CONTENT_OPAQUE));
   // Component alpha
   layer->set_calpha(static_cast<bool>(GetContentFlags() & CONTENT_COMPONENT_ALPHA));
   // Vertical or horizontal bar
   if (GetScrollbarData().mScrollbarLayerType == layers::ScrollbarLayerType::Thumb) {
     layer->set_direct(*GetScrollbarData().mDirection == ScrollDirection::eVertical ?
                       LayersPacket::Layer::VERTICAL :
                       LayersPacket::Layer::HORIZONTAL);
-    layer->set_barid(GetScrollbarTargetViewId());
+    layer->set_barid(GetScrollbarData().mTargetViewId);
   }
 
   // Mask layer
   if (mMaskLayer) {
     layer->set_mask(reinterpret_cast<uint64_t>(mMaskLayer.get()));
   }
 
   // DisplayList log.
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1323,20 +1323,18 @@ public:
   bool GetTransformIsPerspective() const { return mSimpleAttrs.GetTransformIsPerspective(); }
   bool GetIsStickyPosition() { return mSimpleAttrs.IsStickyPosition(); }
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() { return mSimpleAttrs.GetFixedPositionScrollContainerId(); }
   LayerPoint GetFixedPositionAnchor() { return mSimpleAttrs.GetFixedPositionAnchor(); }
   int32_t GetFixedPositionSides() { return mSimpleAttrs.GetFixedPositionSides(); }
   FrameMetrics::ViewID GetStickyScrollContainerId() { return mSimpleAttrs.GetStickyScrollContainerId(); }
   const LayerRectAbsolute& GetStickyScrollRangeOuter() { return mSimpleAttrs.GetStickyScrollRangeOuter(); }
   const LayerRectAbsolute& GetStickyScrollRangeInner() { return mSimpleAttrs.GetStickyScrollRangeInner(); }
-  FrameMetrics::ViewID GetScrollbarTargetViewId() { return mSimpleAttrs.GetScrollbarTargetViewId(); }
   const ScrollbarData& GetScrollbarData() const { return mSimpleAttrs.GetScrollbarData(); }
-  bool IsScrollbarContainer() { return mSimpleAttrs.GetScrollbarContainerDirection().isSome(); }
-  Maybe<ScrollDirection> GetScrollbarContainerDirection() { return mSimpleAttrs.GetScrollbarContainerDirection(); }
+  bool IsScrollbarContainer() const;
   Layer* GetMaskLayer() const { return mMaskLayer; }
   bool HasPendingTransform() const { return mPendingTransform; }
 
   void CheckCanary() const { mCanary.Check(); }
 
   // Ancestor mask layers are associated with FrameMetrics, but for simplicity
   // in maintaining the layer tree structure we attach them to the layer.
   size_t GetAncestorMaskLayerCount() const {
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -873,18 +873,17 @@ APZCTreeManager::PrepareNodeForLayer(con
         GetEventRegions(aLayer),
         aLayer.GetVisibleRegion(),
         aLayer.GetTransformTyped(),
         (!parentHasPerspective && aLayer.GetClipRect())
           ? Some(ParentLayerIntRegion(*aLayer.GetClipRect()))
           : Nothing(),
         GetEventRegionsOverride(aParent, aLayer),
         aLayer.IsBackfaceHidden());
-    node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
-                           aLayer.GetScrollbarAnimationId(),
+    node->SetScrollbarData(aLayer.GetScrollbarAnimationId(),
                            aLayer.GetScrollbarData());
     node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
     return node;
   }
 
   AsyncPanZoomController* apzc = nullptr;
   // If we get here, aLayer is a scrollable layer and somebody
   // has registered a GeckoContentController for it, so we need to ensure
@@ -1093,18 +1092,17 @@ APZCTreeManager::PrepareNodeForLayer(con
         clipRegion,
         GetEventRegionsOverride(aParent, aLayer),
         aLayer.IsBackfaceHidden());
   }
 
   // Note: if layer properties must be propagated to nodes, RecvUpdate in
   // LayerTransactionParent.cpp must ensure that APZ will be notified
   // when those properties change.
-  node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
-                         aLayer.GetScrollbarAnimationId(),
+  node->SetScrollbarData(aLayer.GetScrollbarAnimationId(),
                          aLayer.GetScrollbarData());
   node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
   return node;
 }
 
 template<typename PanGestureOrScrollWheelInput>
 static bool
 WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput)
--- a/gfx/layers/apz/src/HitTestingTreeNode.cpp
+++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp
@@ -22,17 +22,16 @@ namespace layers {
 using gfx::CompositorHitTestInfo;
 
 HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc,
                                        bool aIsPrimaryHolder,
                                        LayersId aLayersId)
   : mApzc(aApzc)
   , mIsPrimaryApzcHolder(aIsPrimaryHolder)
   , mLayersId(aLayersId)
-  , mScrollViewId(FrameMetrics::NULL_SCROLL_ID)
   , mScrollbarAnimationId(0)
   , mFixedPosTarget(FrameMetrics::NULL_SCROLL_ID)
   , mIsBackfaceHidden(false)
   , mOverride(EventRegionsOverride::NoOverride)
 {
 if (mIsPrimaryApzcHolder) {
     MOZ_ASSERT(mApzc);
   }
@@ -89,31 +88,29 @@ HitTestingTreeNode::SetLastChild(HitTest
       // but it's better than nothing.
       MOZ_ASSERT(aChild->GetApzc() != parent);
       aChild->SetApzcParent(parent);
     }
   }
 }
 
 void
-HitTestingTreeNode::SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
-                                     const uint64_t& aScrollbarAnimationId,
+HitTestingTreeNode::SetScrollbarData(const uint64_t& aScrollbarAnimationId,
                                      const ScrollbarData& aScrollbarData)
 {
-  mScrollViewId = aScrollViewId;
   mScrollbarAnimationId = aScrollbarAnimationId;
   mScrollbarData = aScrollbarData;
 }
 
 bool
 HitTestingTreeNode::MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const
 {
   return IsScrollThumbNode() &&
          mScrollbarData.mDirection == aDragMetrics.mDirection &&
-         mScrollViewId == aDragMetrics.mViewId;
+         mScrollbarData.mTargetViewId == aDragMetrics.mViewId;
 }
 
 bool
 HitTestingTreeNode::IsScrollThumbNode() const
 {
   return mScrollbarData.mScrollbarLayerType == layers::ScrollbarLayerType::Thumb;
 }
 
@@ -129,17 +126,17 @@ HitTestingTreeNode::GetScrollbarDirectio
   MOZ_ASSERT(IsScrollbarNode());
   MOZ_ASSERT(mScrollbarData.mDirection.isSome());
   return *mScrollbarData.mDirection;
 }
 
 FrameMetrics::ViewID
 HitTestingTreeNode::GetScrollTargetId() const
 {
-  return mScrollViewId;
+  return mScrollbarData.mTargetViewId;
 }
 
 const uint64_t&
 HitTestingTreeNode::GetScrollbarAnimationId() const
 {
   return mScrollbarAnimationId;
 }
 
--- a/gfx/layers/apz/src/HitTestingTreeNode.h
+++ b/gfx/layers/apz/src/HitTestingTreeNode.h
@@ -90,18 +90,17 @@ public:
                       const CSSTransformMatrix& aTransform,
                       const Maybe<ParentLayerIntRegion>& aClipRegion,
                       const EventRegionsOverride& aOverride,
                       bool aIsBackfaceHidden);
   bool IsOutsideClip(const ParentLayerPoint& aPoint) const;
 
   /* Scrollbar info */
 
-  void SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
-                        const uint64_t& aScrollbarAnimationId,
+  void SetScrollbarData(const uint64_t& aScrollbarAnimationId,
                         const ScrollbarData& aScrollbarData);
   bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
   bool IsScrollbarNode() const;  // Scroll thumb or scrollbar container layer.
   // This can only be called if IsScrollbarNode() is true
   ScrollDirection GetScrollbarDirection() const;
   bool IsScrollThumbNode() const;  // Scroll thumb container layer.
   FrameMetrics::ViewID GetScrollTargetId() const;
   const ScrollbarData& GetScrollbarData() const;
@@ -135,20 +134,16 @@ private:
   RefPtr<HitTestingTreeNode> mPrevSibling;
   RefPtr<HitTestingTreeNode> mParent;
 
   RefPtr<AsyncPanZoomController> mApzc;
   bool mIsPrimaryApzcHolder;
 
   LayersId mLayersId;
 
-  // This is set for both scroll track and scroll thumb Container layers, and
-  // represents the scroll id of the scroll frame scrolled by the scrollbar.
-  FrameMetrics::ViewID mScrollViewId;
-
   // This is only set to non-zero if WebRender is enabled, and only for HTTNs
   // where IsScrollThumbNode() returns true. It holds the animation id that we
   // use to move the thumb node to reflect async scrolling.
   uint64_t mScrollbarAnimationId;
 
   // This is set for scrollbar Container and Thumb layers.
   ScrollbarData mScrollbarData;
 
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -753,17 +753,17 @@ MoveScrollbarForLayerMargin(Layer* aRoot
   // See bug 1223928 comment 9 - once we can detect the RCD with just the
   // isRootContent flag on the metrics, we can probably move this code into
   // ApplyAsyncTransformToScrollbar rather than having it as a separate
   // adjustment on the layer tree.
   Layer* scrollbar = BreadthFirstSearch<ReverseIterator>(aRoot,
     [aRootScrollId](Layer* aNode) {
       return (aNode->GetScrollbarData().mDirection.isSome() &&
               *aNode->GetScrollbarData().mDirection == ScrollDirection::eHorizontal &&
-              aNode->GetScrollbarTargetViewId() == aRootScrollId);
+              aNode->GetScrollbarData().mTargetViewId == aRootScrollId);
     });
   if (scrollbar) {
     // Shift the horizontal scrollbar down into the new space exposed by the
     // dynamic toolbar hiding. Technically we should also scale the vertical
     // scrollbar a bit to expand into the new space but it's not as noticeable
     // and it would add a lot more complexity, so we're going with the "it's not
     // worth it" justification.
     TranslateShadowLayer(scrollbar, ParentLayerPoint(0, -aFixedLayerMargins.bottom), true, nullptr);
@@ -1048,17 +1048,17 @@ AsyncCompositionManager::ApplyAsyncConte
 static bool
 LayerIsScrollbarTarget(const LayerMetricsWrapper& aTarget, Layer* aScrollbar)
 {
   if (!aTarget.GetApzc()) {
     return false;
   }
   const FrameMetrics& metrics = aTarget.Metrics();
   MOZ_ASSERT(metrics.IsScrollable());
-  if (metrics.GetScrollId() != aScrollbar->GetScrollbarTargetViewId()) {
+  if (metrics.GetScrollId() != aScrollbar->GetScrollbarData().mTargetViewId) {
     return false;
   }
   return !metrics.IsScrollInfoLayer();
 }
 
 static void
 ApplyAsyncTransformToScrollbarForContent(const RefPtr<APZSampler>& aSampler,
                                          Layer* aScrollbar,
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -18,17 +18,16 @@
 namespace mozilla {
 namespace layers {
 
 WebRenderLayerScrollData::WebRenderLayerScrollData()
   : mDescendantCount(-1)
   , mTransformIsPerspective(false)
   , mEventRegionsOverride(EventRegionsOverride::NoOverride)
   , mScrollbarAnimationId(0)
-  , mScrollbarTargetContainerId(FrameMetrics::NULL_SCROLL_ID)
   , mFixedPosScrollContainerId(FrameMetrics::NULL_SCROLL_ID)
 {
 }
 
 WebRenderLayerScrollData::~WebRenderLayerScrollData()
 {
 }
 
@@ -120,18 +119,16 @@ WebRenderLayerScrollData::Dump(const Web
     Stringify(mVisibleRegion).c_str());
   printf_stderr("  event regions: %s override: 0x%x\n",
     Stringify(mEventRegions).c_str(), mEventRegionsOverride);
   if (mReferentId) {
     printf_stderr("  ref layers id: 0x%" PRIx64 "\n", uint64_t(*mReferentId));
   }
   //printf_stderr("  scroll thumb: %s animation: %" PRIu64 "\n",
   //  Stringify(mScrollThumbData).c_str(), mScrollbarAnimationId);
-  printf_stderr("  scroll container: %d target: %" PRIu64 "\n",
-    mScrollbarContainerDirection.isSome(), mScrollbarTargetContainerId);
   printf_stderr("  fixed pos container: %" PRIu64 "\n",
     mFixedPosScrollContainerId);
 }
 
 WebRenderScrollData::WebRenderScrollData()
   : mManager(nullptr)
   , mIsFirstPaint(false)
   , mPaintSequenceNumber(0)
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -76,20 +76,16 @@ public:
   const LayerIntRegion& GetVisibleRegion() const { return mVisibleRegion; }
   void SetReferentId(LayersId aReferentId) { mReferentId = Some(aReferentId); }
   Maybe<LayersId> GetReferentId() const { return mReferentId; }
 
   void SetScrollbarData(const ScrollbarData& aData) { mScrollbarData = aData; }
   const ScrollbarData& GetScrollbarData() const { return mScrollbarData; }
   void SetScrollbarAnimationId(const uint64_t& aId) { mScrollbarAnimationId = aId; }
   const uint64_t& GetScrollbarAnimationId() const { return mScrollbarAnimationId; }
-  void SetScrollbarTargetContainerId(FrameMetrics::ViewID aId) { mScrollbarTargetContainerId = aId; }
-  FrameMetrics::ViewID GetScrollbarTargetContainerId() const { return mScrollbarTargetContainerId; }
-  void SetScrollbarContainerDirection(ScrollDirection aDirection) { mScrollbarContainerDirection = Some(aDirection); }
-  Maybe<ScrollDirection> GetScrollbarContainerDirection() const { return mScrollbarContainerDirection; }
 
   void SetFixedPositionScrollContainerId(FrameMetrics::ViewID aId) { mFixedPosScrollContainerId = aId; }
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() const { return mFixedPosScrollContainerId; }
 
   void Dump(const WebRenderScrollData& aOwner) const;
 
   friend struct IPC::ParamTraits<WebRenderLayerScrollData>;
 
@@ -112,18 +108,16 @@ private:
   gfx::Matrix4x4 mTransform;
   bool mTransformIsPerspective;
   EventRegions mEventRegions;
   LayerIntRegion mVisibleRegion;
   Maybe<LayersId> mReferentId;
   EventRegionsOverride mEventRegionsOverride;
   ScrollbarData mScrollbarData;
   uint64_t mScrollbarAnimationId;
-  FrameMetrics::ViewID mScrollbarTargetContainerId;
-  Maybe<ScrollDirection> mScrollbarContainerDirection;
   FrameMetrics::ViewID mFixedPosScrollContainerId;
 };
 
 // Data needed by APZ, for the whole layer tree. One instance of this class
 // is created for each transaction sent over PWebRenderBridge. It is populated
 // with information from the WebRender layer tree on the client side and the
 // information is used by APZ on the parent side.
 class WebRenderScrollData
@@ -225,36 +219,32 @@ struct ParamTraits<mozilla::layers::WebR
     WriteParam(aMsg, aParam.mTransform);
     WriteParam(aMsg, aParam.mTransformIsPerspective);
     WriteParam(aMsg, aParam.mEventRegions);
     WriteParam(aMsg, aParam.mVisibleRegion);
     WriteParam(aMsg, aParam.mReferentId);
     WriteParam(aMsg, aParam.mEventRegionsOverride);
     WriteParam(aMsg, aParam.mScrollbarData);
     WriteParam(aMsg, aParam.mScrollbarAnimationId);
-    WriteParam(aMsg, aParam.mScrollbarTargetContainerId);
-    WriteParam(aMsg, aParam.mScrollbarContainerDirection);
     WriteParam(aMsg, aParam.mFixedPosScrollContainerId);
   }
 
   static bool
   Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return ReadParam(aMsg, aIter, &aResult->mDescendantCount)
         && ReadParam(aMsg, aIter, &aResult->mScrollIds)
         && ReadParam(aMsg, aIter, &aResult->mTransform)
         && ReadParam(aMsg, aIter, &aResult->mTransformIsPerspective)
         && ReadParam(aMsg, aIter, &aResult->mEventRegions)
         && ReadParam(aMsg, aIter, &aResult->mVisibleRegion)
         && ReadParam(aMsg, aIter, &aResult->mReferentId)
         && ReadParam(aMsg, aIter, &aResult->mEventRegionsOverride)
         && ReadParam(aMsg, aIter, &aResult->mScrollbarData)
         && ReadParam(aMsg, aIter, &aResult->mScrollbarAnimationId)
-        && ReadParam(aMsg, aIter, &aResult->mScrollbarTargetContainerId)
-        && ReadParam(aMsg, aIter, &aResult->mScrollbarContainerDirection)
         && ReadParam(aMsg, aIter, &aResult->mFixedPosScrollContainerId);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::layers::WebRenderScrollData>
 {
   typedef mozilla::layers::WebRenderScrollData paramType;
--- a/gfx/layers/wr/WebRenderScrollDataWrapper.h
+++ b/gfx/layers/wr/WebRenderScrollDataWrapper.h
@@ -295,28 +295,16 @@ public:
   }
 
   uint64_t GetScrollbarAnimationId() const
   {
     MOZ_ASSERT(IsValid());
     return mLayer->GetScrollbarAnimationId();
   }
 
-  FrameMetrics::ViewID GetScrollbarTargetContainerId() const
-  {
-    MOZ_ASSERT(IsValid());
-    return mLayer->GetScrollbarTargetContainerId();
-  }
-
-  Maybe<ScrollDirection> GetScrollbarContainerDirection() const
-  {
-    MOZ_ASSERT(IsValid());
-    return mLayer->GetScrollbarContainerDirection();
-  }
-
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
   {
     MOZ_ASSERT(IsValid());
     return mLayer->GetFixedPositionScrollContainerId();
   }
 
   bool IsBackfaceHidden() const
   {
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -416,17 +416,16 @@ impl BlobImageRenderer for Moz2dImageRen
                         process_native_font_handle(key, handle);
                     }
                 }
                 resources.get_font_data(key);
             }
         }
         {
             let mut index = BlobReader::new(&commands);
-            assert!(index.reader.pos < index.reader.buf.len());
             while index.reader.pos < index.reader.buf.len() {
                 let e  = index.read_entry();
                 process_fonts(BufReader::new(&commands[e.end..e.extra_end]), resources);
             }
         }
 
         self.workers.spawn(move || {
             let buf_size = (descriptor.width
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -2935,17 +2935,20 @@ imgCacheValidator::imgCacheValidator(nsP
                      mRequest->CacheKey(),
                      getter_AddRefs(mNewRequest),
                      getter_AddRefs(mNewEntry));
 }
 
 imgCacheValidator::~imgCacheValidator()
 {
   if (mRequest) {
-    mRequest->SetValidator(nullptr);
+    // If something went wrong, and we never unblocked the requests waiting on
+    // validation, now is our last chance. We will cancel the new request and
+    // switch the waiting proxies to it.
+    UpdateProxies(/* aCancelRequest */ true, /* aSyncNotify */ false);
   }
 }
 
 void
 imgCacheValidator::AddProxy(imgRequestProxy* aProxy)
 {
   // aProxy needs to be in the loadgroup since we're validating from
   // the network.
@@ -2956,18 +2959,33 @@ imgCacheValidator::AddProxy(imgRequestPr
 
 void
 imgCacheValidator::RemoveProxy(imgRequestProxy* aProxy)
 {
   mProxies.RemoveElement(aProxy);
 }
 
 void
-imgCacheValidator::UpdateProxies()
+imgCacheValidator::UpdateProxies(bool aCancelRequest, bool aSyncNotify)
 {
+  MOZ_ASSERT(mRequest);
+
+  // Clear the validator before updating the proxies. The notifications may
+  // clone an existing request, and its state could be inconsistent.
+  mRequest->SetValidator(nullptr);
+  mRequest = nullptr;
+
+  // If an error occurred, we will want to cancel the new request, and make the
+  // validating proxies point to it. Any proxies still bound to the original
+  // request which are not validating should remain untouched.
+  if (aCancelRequest) {
+    MOZ_ASSERT(mNewRequest);
+    mNewRequest->CancelAndAbort(NS_BINDING_ABORTED);
+  }
+
   // We have finished validating the request, so we can safely take ownership
   // of the proxy list. imgRequestProxy::SyncNotifyListener can mutate the list
   // if imgRequestProxy::CancelAndForgetObserver is called by its owner. Note
   // that any potential notifications should still be suppressed in
   // imgRequestProxy::ChangeOwner because we haven't cleared the validating
   // flag yet, and thus they will remain deferred.
   AutoTArray<RefPtr<imgRequestProxy>, 4> proxies(Move(mProxies));
 
@@ -2980,20 +2998,29 @@ imgCacheValidator::UpdateProxies()
                "Proxies waiting on cache validation should be "
                "deferring notifications!");
     if (mNewRequest) {
       proxy->ChangeOwner(mNewRequest);
     }
     proxy->ClearValidating();
   }
 
+  mNewRequest = nullptr;
+  mNewEntry = nullptr;
+
   for (auto& proxy : proxies) {
-    // Notify synchronously, because we're already in OnStartRequest, an
-    // asynchronously-called function.
-    proxy->SyncNotifyListener();
+    if (aSyncNotify) {
+      // Notify synchronously, because the caller knows we are already in an
+      // asynchronously-called function (e.g. OnStartRequest).
+      proxy->SyncNotifyListener();
+    } else {
+      // Notify asynchronously, because the caller does not know our current
+      // call state (e.g. ~imgCacheValidator).
+      proxy->NotifyListener();
+    }
   }
 }
 
 /** nsIRequestObserver methods **/
 
 NS_IMETHODIMP
 imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
 {
@@ -3026,28 +3053,22 @@ imgCacheValidator::OnStartRequest(nsIReq
     bool sameURI = false;
     if (channelURI && finalURI) {
       channelURI->Equals(finalURI, &sameURI);
     }
 
     if (isFromCache && sameURI) {
       // We don't need to load this any more.
       aRequest->Cancel(NS_BINDING_ABORTED);
+      mNewRequest = nullptr;
 
       // Clear the validator before updating the proxies. The notifications may
       // clone an existing request, and its state could be inconsistent.
       mRequest->SetLoadId(context);
-      mRequest->SetValidator(nullptr);
-
-      mRequest = nullptr;
-
-      mNewRequest = nullptr;
-      mNewEntry = nullptr;
-
-      UpdateProxies();
+      UpdateProxies(/* aCancelRequest */ false, /* aSyncNotify */ true);
       return NS_OK;
     }
   }
 
   // We can't load out of cache. We have to create a whole new request for the
   // data that's coming in off the channel.
   nsCOMPtr<nsIURI> uri;
   {
@@ -3064,42 +3085,34 @@ imgCacheValidator::OnStartRequest(nsIReq
 
   int32_t corsmode = mRequest->GetCORSMode();
   ReferrerPolicy refpol = mRequest->GetReferrerPolicy();
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = mRequest->GetTriggeringPrincipal();
 
   // Doom the old request's cache entry
   mRequest->RemoveFromCache();
 
-  // Clear the validator before updating the proxies. The notifications may
-  // clone an existing request, and its state could be inconsistent.
-  mRequest->SetValidator(nullptr);
-  mRequest = nullptr;
-
   // We use originalURI here to fulfil the imgIRequest contract on GetURI.
   nsCOMPtr<nsIURI> originalURI;
   channel->GetOriginalURI(getter_AddRefs(originalURI));
   nsresult rv =
     mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
                       mNewEntry, context, triggeringPrincipal, corsmode, refpol);
   if (NS_FAILED(rv)) {
+    UpdateProxies(/* aCancelRequest */ true, /* aSyncNotify */ true);
     return rv;
   }
 
   mDestListener = new ProxyListener(mNewRequest);
 
   // Try to add the new request into the cache. Note that the entry must be in
   // the cache before the proxies' ownership changes, because adding a proxy
   // changes the caching behaviour for imgRequests.
   mImgLoader->PutIntoCache(mNewRequest->CacheKey(), mNewEntry);
-
-  UpdateProxies();
-  mNewRequest = nullptr;
-  mNewEntry = nullptr;
-
+  UpdateProxies(/* aCancelRequest */ false, /* aSyncNotify */ true);
   return mDestListener->OnStartRequest(aRequest, ctxt);
 }
 
 NS_IMETHODIMP
 imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
                                  nsISupports* ctxt,
                                  nsresult status)
 {
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -563,17 +563,17 @@ public:
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
 
 private:
-  void UpdateProxies();
+  void UpdateProxies(bool aCancelRequest, bool aSyncNotify);
   virtual ~imgCacheValidator();
 
   nsCOMPtr<nsIStreamListener> mDestListener;
   RefPtr<nsProgressNotificationProxy> mProgressProxy;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   nsCOMPtr<nsIChannel> mRedirectChannel;
 
   RefPtr<imgRequest> mRequest;
--- a/image/test/reftest/downscaling/reftest.list
+++ b/image/test/reftest/downscaling/reftest.list
@@ -21,17 +21,17 @@
 # Also note that Mac OS X has its own system-level downscaling algorithm, so
 # tests here may need Mac-specific "fuzzy-if(cocoaWidget,...)" annotations.
 # Similarly, modern versions of Windows have slightly different downscaling
 # behavior than other platforms, and may require "fuzzy-if(winWidget,...)".
 
 
 # RUN TESTS NOT AFFECTED BY DOWNSCALE-DURING-DECODE:
 # ==================================================
-fuzzy-if(skiaContent,14,416) fuzzy-if(webrender,102-102,396-472) == downscale-svg-1a.html downscale-svg-1-ref.html?80
+fuzzy-if(skiaContent,14,416) fuzzy-if(webrender,14-14,397-473) == downscale-svg-1a.html downscale-svg-1-ref.html?80
 fuzzy(80,468) fuzzy-if(webrender,65-65,579-580) == downscale-svg-1b.html downscale-svg-1-ref.html?72
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,62) fuzzy-if(skiaContent,8,292) fuzzy-if(webrender,14-14,316-316) == downscale-svg-1c.html downscale-svg-1-ref.html?64
 fuzzy(17,208) fuzzy-if(webrender,83-84,274-325) == downscale-svg-1d.html downscale-svg-1-ref.html?53
 fuzzy(80,216) fuzzy-if(skiaContent,110,181) fuzzy-if(webrender,84-84,216-216) == downscale-svg-1e.html downscale-svg-1-ref.html?40
 fuzzy(51,90) fuzzy-if(skiaContent,142,77) fuzzy-if(webrender,62-62,98-98) == downscale-svg-1f.html downscale-svg-1-ref.html?24
 
 # RUN TESTS WITH DOWNSCALE-DURING-DECODE DISABLED:
 # ================================================
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -528,17 +528,18 @@ MessageChannel::MessageChannel(const cha
     mRemoteStackDepthGuess(0),
     mSawInterruptOutMsg(false),
     mIsWaitingForIncoming(false),
     mAbortOnError(false),
     mNotifiedChannelDone(false),
     mFlags(REQUIRE_DEFAULT),
     mPeerPidSet(false),
     mPeerPid(-1),
-    mIsPostponingSends(false)
+    mIsPostponingSends(false),
+    mInKillHardShutdown(false)
 {
     MOZ_COUNT_CTOR(ipc::MessageChannel);
 
 #ifdef OS_WIN
     mTopFrame = nullptr;
     mIsSyncWaitingOnNonMainThread = false;
 #endif
 
@@ -694,17 +695,20 @@ MessageChannel::Clear()
     // Also don't clear mListener.  If we clear it, then sending a message
     // through this channel after it's Clear()'ed can cause this process to
     // crash.
     //
     // In practice, mListener owns the channel, so the channel gets deleted
     // before mListener.  But just to be safe, mListener is a weak pointer.
 
 #if !defined(ANDROID)
-    if (!Unsound_IsClosed()) {
+    // KillHard shutdowns can occur with the channel in connected state. We are
+    // already collecting crash dump data about KillHard shutdowns and we
+    // shouldn't intentionally crash here.
+    if (!Unsound_IsClosed() && !mInKillHardShutdown) {
         CrashReporter::AnnotateCrashReport(
             NS_LITERAL_CSTRING("IPCFatalErrorProtocol"),
             nsDependentCString(mName));
         switch (mChannelState) {
             case ChannelOpening:
                 MOZ_CRASH("MessageChannel destroyed without being closed " \
                           "(mChannelState == ChannelOpening).");
                 break;
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -322,16 +322,20 @@ private:
 
     static bool IsPumpingMessages() {
         return sIsPumpingMessages;
     }
     static void SetIsPumpingMessages(bool aIsPumping) {
         sIsPumpingMessages = aIsPumping;
     }
 
+    void SetInKillHardShutdown() {
+        mInKillHardShutdown = true;
+    }
+
 #ifdef OS_WIN
     struct MOZ_STACK_CLASS SyncStackFrame
     {
         SyncStackFrame(MessageChannel* channel, bool interrupt);
         ~SyncStackFrame();
 
         bool mInterrupt;
         bool mSpinNestedEvents;
@@ -849,16 +853,18 @@ private:
     RefPtr<CancelableRunnable> mOnChannelConnectedTask;
     bool mPeerPidSet;
     int32_t mPeerPid;
 
     // Channels can enter messages are not sent immediately; instead, they are
     // held in a queue until another thread deems it is safe to send them.
     bool mIsPostponingSends;
     std::vector<UniquePtr<Message>> mPostponedSends;
+
+    bool mInKillHardShutdown;
 };
 
 void
 CancelCPOWs();
 
 } // namespace ipc
 } // namespace mozilla
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -45,17 +45,17 @@ ifdef MOZ_TSAN
 JITTEST_SANITIZER_ENV=TSAN_OPTIONS="external_symbolizer_path=$(LLVM_SYMBOLIZER) $$TSAN_OPTIONS"
 endif
 ifdef MOZ_MSAN
 JITTEST_SANITIZER_ENV=MSAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)'
 endif
 endif
 
 check-style::
-	(cd $(srcdir) && $(PYTHON) $(topsrcdir)/config/check_spidermonkey_style.py);
+	(cd $(topsrcdir) && $(PYTHON) $(topsrcdir)/config/check_spidermonkey_style.py);
 
 check-masm::
 	(cd $(srcdir) && $(PYTHON) $(topsrcdir)/config/check_macroassembler_style.py);
 
 check-js-msg::
 	(cd $(topsrcdir) && $(PYTHON) $(topsrcdir)/config/check_js_msg_encoding.py);
 
 check-opcode::
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -2109,20 +2109,30 @@ ArenaLists::unmarkPreMarkedFreeCells()
     }
 }
 
 /* Compacting GC */
 
 bool
 GCRuntime::shouldCompact()
 {
-    // Compact on shrinking GC if enabled, but skip compacting in incremental
-    // GCs if we are currently animating.
-    return invocationKind == GC_SHRINK && isCompactingGCEnabled() &&
-        (!isIncremental || rt->lastAnimationTime + PRMJ_USEC_PER_SEC < PRMJ_Now());
+    // Compact on shrinking GC if enabled.  Skip compacting in incremental GCs
+    // if we are currently animating, unless the user is inactive or we're
+    // responding to memory pressure.
+
+    if (invocationKind != GC_SHRINK || !isCompactingGCEnabled())
+        return false;
+
+    if (initialReason == JS::gcreason::USER_INACTIVE ||
+        initialReason == JS::gcreason::MEM_PRESSURE)
+    {
+        return true;
+    }
+
+    return !isIncremental || rt->lastAnimationTime + PRMJ_USEC_PER_SEC < PRMJ_Now();
 }
 
 bool
 GCRuntime::isCompactingGCEnabled() const
 {
     return compactingEnabled && rt->mainContextFromOwnThread()->compactingDisabledCount == 0;
 }
 
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -720,18 +720,20 @@ js::Nursery::collect(JS::gcreason::Reaso
 
     // The analysis marks TenureCount as not problematic for GC hazards because
     // it is only used here, and ObjectGroup pointers are never
     // nursery-allocated.
     MOZ_ASSERT(!IsNurseryAllocable(AllocKind::OBJECT_GROUP));
 
     TenureCountCache tenureCounts;
     previousGC.reason = JS::gcreason::NO_REASON;
+    mozilla::Maybe<AutoTraceSession> session;
     if (!isEmpty()) {
-        doCollection(reason, tenureCounts);
+        session.emplace(rt, JS::HeapState::MinorCollecting);
+        doCollection(reason, session.ref(), tenureCounts);
     } else {
         previousGC.nurseryUsedBytes = 0;
         previousGC.nurseryCapacity = spaceToEnd(maxChunkCount());
         previousGC.nurseryLazyCapacity = spaceToEnd(allocatedChunkCount());
         previousGC.tenuredBytes = 0;
     }
 
     // Resize the nursery.
@@ -758,16 +760,17 @@ js::Nursery::collect(JS::gcreason::Reaso
                     group->setShouldPreTenure(cx);
                     pretenureCount++;
                 }
             }
         }
     }
     for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
         if (shouldPretenure && zone->allocNurseryStrings && zone->tenuredStrings >= 30 * 1000) {
+            MOZ_ASSERT(session.isSome(), "discarding JIT code must be in an AutoTraceSession");
             CancelOffThreadIonCompile(zone);
             bool preserving = zone->isPreservingCode();
             zone->setPreservingCode(false);
             zone->discardJitCode(rt->defaultFreeOp());
             zone->setPreservingCode(preserving);
             for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
                 if (jit::JitCompartment* jitComp = c->jitCompartment()) {
                     jitComp->discardStubs();
@@ -787,16 +790,17 @@ js::Nursery::collect(JS::gcreason::Reaso
         disable();
     // Disable the nursery if the user changed the configuration setting.  The
     // nursery can only be re-enabled by resetting the configurationa and
     // restarting firefox.
     if (chunkCountLimit_ == 0)
         disable();
 
     endProfile(ProfileKey::Total);
+    session.reset(); // End the minor GC session, if running one.
     rt->gc.incMinorGcNumber();
 
     TimeDuration totalTime = profileDurations_[ProfileKey::Total];
     rt->addTelemetry(JS_TELEMETRY_GC_MINOR_US, totalTime.ToMicroseconds());
     rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON, reason);
     if (totalTime.ToMilliseconds() > 1.0)
         rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON_LONG, reason);
     rt->addTelemetry(JS_TELEMETRY_GC_NURSERY_BYTES, sizeOfHeapCommitted());
@@ -823,20 +827,20 @@ js::Nursery::collect(JS::gcreason::Reaso
                 }
             }
         }
     }
 }
 
 void
 js::Nursery::doCollection(JS::gcreason::Reason reason,
+                          AutoTraceSession& session,
                           TenureCountCache& tenureCounts)
 {
     JSRuntime* rt = runtime();
-    AutoTraceSession session(rt, JS::HeapState::MinorCollecting);
     AutoSetThreadIsPerformingGC performingGC;
     AutoStopVerifyingBarriers av(rt, false);
     AutoDisableProxyCheck disableStrictProxyChecking;
     mozilla::DebugOnly<AutoEnterOOMUnsafeRegion> oomUnsafeRegion;
 
     const size_t initialNurseryCapacity = spaceToEnd(maxChunkCount());
     const size_t initialNurseryUsedBytes = initialNurseryCapacity - freeSpace();
 
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -51,16 +51,17 @@ class Nursery;
 struct NurseryChunk;
 class HeapSlot;
 class JSONPrinter;
 
 void SetGCZeal(JSRuntime*, uint8_t, uint32_t);
 
 namespace gc {
 class AutoMaybeStartBackgroundAllocation;
+class AutoTraceSession;
 struct Cell;
 class MinorCollectionTracer;
 class RelocationOverlay;
 struct TenureCountCache;
 enum class AllocKind : uint8_t;
 class TenuredCell;
 } /* namespace gc */
 
@@ -512,17 +513,18 @@ class Nursery
     uintptr_t position() const { return position_; }
 
     JSRuntime* runtime() const { return runtime_; }
 
     /* Common internal allocator function. */
     void* allocate(size_t size);
 
     void doCollection(JS::gcreason::Reason reason,
-                        gc::TenureCountCache& tenureCounts);
+                      gc::AutoTraceSession& sesssion,
+                      gc::TenureCountCache& tenureCounts);
 
     /*
      * Move the object at |src| in the Nursery to an already-allocated cell
      * |dst| in Tenured.
      */
     void collectToFixedPoint(TenuringTracer& trc, gc::TenureCountCache& tenureCounts);
 
     /* Handle relocation of slots/elements pointers stored in Ion frames. */
--- a/js/src/tests/test262-update.py
+++ b/js/src/tests/test262-update.py
@@ -15,27 +15,27 @@ import shutil
 import sys
 
 from functools import partial
 from itertools import chain, imap
 
 # Skip all tests which use features not supported in SpiderMonkey.
 UNSUPPORTED_FEATURES = set([
                             "tail-call-optimization",
-                            "BigInt",
                             "class-fields-public",
                             "class-fields-private",
                             "regexp-dotall",
                             "regexp-lookbehind",
                             "regexp-named-groups",
                             "regexp-unicode-property-escapes",
                             "numeric-separator-literal",
                        ])
 FEATURE_CHECK_NEEDED = {
                          "Atomics": "!this.hasOwnProperty('Atomics')",
+                         "BigInt": "!this.hasOwnProperty('BigInt')",
                          "SharedArrayBuffer": "!this.hasOwnProperty('SharedArrayBuffer')",
                          "CannotSuspendMainAgent": "xulRuntime.shell",
                        }
 RELEASE_OR_BETA = set()
 
 @contextlib.contextmanager
 def TemporaryDirectory():
     tmpDir = tempfile.mkdtemp()
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/arithmetic.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/arithmetic.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asIntN arithmetic test cases
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/asIntN.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/asIntN.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asIntN property descriptor
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-errors.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-toprimitive.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bigint-tobigint.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-errors.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-toprimitive.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/bits-toindex.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asIntN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/length.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asIntN.length descriptor
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/name.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asIntN.name descriptor
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asIntN/order-of-steps.js
+++ b/js/src/tests/test262/built-ins/BigInt/asIntN/order-of-steps.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asIntN order of parameter type coercion
 info: |
   BigInt.asIntN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/arithmetic.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/arithmetic.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asUintN arithmetic test cases
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/asUintN.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/asUintN.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asUintN property descriptor
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-errors.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-toprimitive.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bigint-tobigint.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bigint parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-errors.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-toprimitive.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/bits-toindex.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: BigInt.asUintN type coercion for bits parameter
 esid: pending
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/length.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asUintN.length descriptor
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/name.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asUintN.name descriptor
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/asUintN/order-of-steps.js
+++ b/js/src/tests/test262/built-ins/BigInt/asUintN/order-of-steps.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Josh Wolfe. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: pending
 description: BigInt.asUintN order of parameter type coercion
 info: |
   BigInt.asUintN ( bits, bigint )
 
--- a/js/src/tests/test262/built-ins/BigInt/call-value-of-when-to-string-present.js
+++ b/js/src/tests/test262/built-ins/BigInt/call-value-of-when-to-string-present.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: ToPrimitive receives "hint Number" as parameter, then valueOf needs to be called
 esid: sec-bigint-constructor-number-value
 info: |
   1. If NewTarget is not undefined, throw a TypeError exception.
--- a/js/src/tests/test262/built-ins/BigInt/constructor-empty-string.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-empty-string.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Empty String should in BigInt should result into 0n
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-from-binary-string.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-from-binary-string.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: String should be parsed to BigInt according StringToBigInt
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-from-decimal-string.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-from-decimal-string.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: String should be parsed to BigInt according StringToBigInt
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-from-hex-string.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-from-hex-string.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Hexdecimal prefixed String should be parsed to BigInt according StringToBigInt
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-from-octal-string.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-from-octal-string.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Octal prefixed String should be parsed to BigInt according StringToBigInt
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-from-string-syntax-errors.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-from-string-syntax-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Invalid String into BigInt constructor should throw SyntaxError
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/constructor-trailing-leading-spaces.js
+++ b/js/src/tests/test262/built-ins/BigInt/constructor-trailing-leading-spaces.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Tariling/Leading spaces should be ignored in BigInt constructor should
 esid: sec-string-to-bigint
 info: |
   Apply the algorithm in 3.1.3.1 with the following changes:
--- a/js/src/tests/test262/built-ins/BigInt/infinity-throws-rangeerror.js
+++ b/js/src/tests/test262/built-ins/BigInt/infinity-throws-rangeerror.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: BigInt throws a RangeError if value is Infinity
 esid: sec-bigint-constructor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/issafeinteger-true.js
+++ b/js/src/tests/test262/built-ins/BigInt/issafeinteger-true.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Throws a TypeError if BigInt is called with a new target
 esid: sec-bigint-constructor
 info: |
   ...
--- a/js/src/tests/test262/built-ins/BigInt/length.js
+++ b/js/src/tests/test262/built-ins/BigInt/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint-constructor-number-value
 description: BigInt.length property descriptor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/name.js
+++ b/js/src/tests/test262/built-ins/BigInt/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint-constructor-number-value
 description: BigInt.name property descriptor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/nan-throws-rangeerror.js
+++ b/js/src/tests/test262/built-ins/BigInt/nan-throws-rangeerror.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: BigInt throws a RangeError if value is NaN
 esid: sec-bigint-constructor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/negative-infinity-throws.rangeerror.js
+++ b/js/src/tests/test262/built-ins/BigInt/negative-infinity-throws.rangeerror.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 The V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: BigInt throws a RangeError if value is Infinity
 esid: sec-bigint-constructor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/new-target-throws.js
+++ b/js/src/tests/test262/built-ins/BigInt/new-target-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Throws a TypeError if BigInt is called with a new target
 esid: sec-bigint-constructor
 info: |
   1. If NewTarget is not undefined, throw a TypeError exception.
--- a/js/src/tests/test262/built-ins/BigInt/non-integer-rangeerror.js
+++ b/js/src/tests/test262/built-ins/BigInt/non-integer-rangeerror.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Non integer number values will throw a RangeError
 esid: sec-bigint-constructor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/out-of-bounds-integer-rangeerror.js
+++ b/js/src/tests/test262/built-ins/BigInt/out-of-bounds-integer-rangeerror.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: BigInt throws a RangeError if value is not a safe integer.
 esid: sec-bigint-constructor
 info: |
   BigInt ( value )
--- a/js/src/tests/test262/built-ins/BigInt/parseInt/nonexistent.js
+++ b/js/src/tests/test262/built-ins/BigInt/parseInt/nonexistent.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: BigInt does not have a static parseInt function
 features: [BigInt]
 ---*/
 
--- a/js/src/tests/test262/built-ins/BigInt/prop-desc.js
+++ b/js/src/tests/test262/built-ins/BigInt/prop-desc.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 The V8 Project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint-constructor
 description: >
   Property descriptor of BigInt
 info: |
--- a/js/src/tests/test262/built-ins/BigInt/proto.js
+++ b/js/src/tests/test262/built-ins/BigInt/proto.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: The prototype of BigInt constructor is Function.prototype
 esid: sec-properties-of-the-bigint-constructor
 info: |
   The value of the [[Prototype]] internal slot of the BigInt constructor is the
--- a/js/src/tests/test262/built-ins/BigInt/prototype/Symbol.toStringTag.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/Symbol.toStringTag.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S. L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 esid: sec-bigint-@@tostringtag
 description: >
     `Symbol.toStringTag` property descriptor
 info: |
     The initial value of the @@toStringTag property is the String value
--- a/js/src/tests/test262/built-ins/BigInt/prototype/constructor.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/constructor.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.constructor
 description: BigInt.prototype.constructor property descriptor
 info: |
   BigInt.prototype.constructor
--- a/js/src/tests/test262/built-ins/BigInt/prototype/prop-desc.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/prop-desc.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: The property descriptor BigInt.prototype
 esid: sec-bigint.prototype
 info: |
   This property has the attributes { [[Writable]]: false, [[Enumerable]]: false,
--- a/js/src/tests/test262/built-ins/BigInt/prototype/proto.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/proto.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: The prototype of BigInt.prototype is Object.prototype
 esid: sec-properties-of-the-bigint-prototype-object
 info: |
   The value of the [[Prototype]] internal slot of the BigInt prototype object
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/length.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: BigInt.prototype.toString.length property descriptor
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/name.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: BigInt.prototype.toString.name property descriptor
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/prop-desc.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/prop-desc.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2016 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: BigInt.prototype.toString property descriptor
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/prototype-call.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/prototype-call.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: Direct toString on BigInt prototype
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/radix-2-to-36.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/radix-2-to-36.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: toString with radix between 2 and 36
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/radix-err.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/radix-err.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: toString with invalid radix
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/string-is-code-units-of-decimal-digits-only.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/string-is-code-units-of-decimal-digits-only.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright 2017 Rick Waldron. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-tostring-applied-to-the-bigint-type
 description: BigInt .toString() returns only decimal digits, does not include BigIntLiteralSuffix
 info: |
   ToString Applied to the BigInt Type
--- a/js/src/tests/test262/built-ins/BigInt/prototype/toString/thisbigintvalue-not-valid-throws.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/toString/thisbigintvalue-not-valid-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright 2017 Leo Balter. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.tostring
 description: Throws a TypeError if the this value is not a BigInt
 info: |
   BigInt.prototype.toString ( [ radix ] )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/length.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: BigInt.prototype.valueOf.length property descriptor
 info: |
   BigInt.prototype.valueOf ( )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/name.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: BigInt.prototype.valueOf.name property descriptor
 info: |
   BigInt.prototype.valueOf ( )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/prop-desc.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/prop-desc.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: BigInt.prototype.valueOf property descriptor
 info: |
   BigInt.prototype.valueOf ( )
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/return.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/return.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: >
   BigInt.prototype.valueOf returns the primitive BigInt value.
 info: |
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/this-value-invalid-object-throws.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/this-value-invalid-object-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: >
   Throws a TypeError if this is an Object without a [[BigIntData]] internal.
 info: |
--- a/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/this-value-invalid-primitive-throws.js
+++ b/js/src/tests/test262/built-ins/BigInt/prototype/valueOf/this-value-invalid-primitive-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Robin Templeton. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-bigint.prototype.valueof
 description: >
   Throws a TypeError if this is not a BigInt neither an Object.
 info: |
--- a/js/src/tests/test262/built-ins/BigInt/value-of-throws.js
+++ b/js/src/tests/test262/built-ins/BigInt/value-of-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Caio Lima. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 description: Throws exception in BigIntConstructor if valueOf/toString does that
 esid: sec-bigint-constructor-number-value
 info: |
   1. If NewTarget is not undefined, throw a TypeError exception.
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-after-toindex-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-after-toindex-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Detached buffer is only checked after ToIndex(requestIndex)
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-before-outofrange-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-before-outofrange-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Detached buffer is checked before out of range byteOffset's value
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/detached-buffer.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Throws a TypeError if buffer is detached
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/index-is-out-of-range.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/index-is-out-of-range.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Throws a RangeError if getIndex + elementSize > viewSize
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/length.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: DataView.prototype.getBigInt64.length property descriptor
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/name.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: DataView.prototype.getBigInt64.name property descriptor
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/negative-byteoffset-throws.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/negative-byteoffset-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Throws a RangeError if getIndex < 0
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset-symbol.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset-symbol.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Return abrupt from ToNumber(symbol byteOffset)
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Return abrupt from ToNumber(byteOffset)
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-value-clean-arraybuffer.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-value-clean-arraybuffer.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Return value from Buffer using a clean ArrayBuffer
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-values-custom-offset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-values-custom-offset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Return values from Buffer using a custom offset
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-values.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/return-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Return values from Buffer
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/this-has-no-dataview-internal.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/this-has-no-dataview-internal.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: >
   Throws a TypeError if this does not have a [[DataView]] internal slot
 info: |
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/this-is-not-object.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/this-is-not-object.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbigint64
 description: Throws a TypeError if this is not Object
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/to-boolean-littleendian.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/to-boolean-littleendian.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: Boolean littleEndian argument coerced in ToBoolean
 esid: sec-dataview.prototype.getbigint64
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-errors.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbigint64
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-toprimitive.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbigint64
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbigint64
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbigint64
 info: |
   DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-after-toindex-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-after-toindex-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Detached buffer is only checked after ToIndex(requestIndex)
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-before-outofrange-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-before-outofrange-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Detached buffer is checked before out of range byteOffset's value
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/detached-buffer.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Throws a TypeError if buffer is detached
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/index-is-out-of-range.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/index-is-out-of-range.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Throws a RangeError if getIndex + elementSize > viewSize
 features: [DataView, ArrayBuffer, BigInt, arrow-function]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/length.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: DataView.prototype.getBigUint64.length property descriptor
 includes: [propertyHelper.js]
 features: [DataView, ArrayBuffer, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/name.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/name.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: DataView.prototype.getBigUint64.name property descriptor
 includes: [propertyHelper.js]
 features: [DataView, ArrayBuffer, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/negative-byteoffset-throws.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/negative-byteoffset-throws.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Throws a RangeError if getIndex < 0
 features: [DataView, ArrayBuffer, BigInt, arrow-function]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset-symbol.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset-symbol.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Return abrupt from ToNumber(symbol byteOffset)
 features: [DataView, ArrayBuffer, Symbol, BigInt, arrow-function]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Return abrupt from ToNumber(byteOffset)
 features: [DataView, ArrayBuffer, BigInt, arrow-function]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-value-clean-arraybuffer.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-value-clean-arraybuffer.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Return value from Buffer using a clean ArrayBuffer
 features: [DataView, ArrayBuffer, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-values-custom-offset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-values-custom-offset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Return values from Buffer using a custom offset
 features: [DataView, ArrayBuffer, DataView.prototype.setUint8, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-values.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/return-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Return values from Buffer
 features: [DataView, ArrayBuffer, DataView.prototype.setUint8, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/this-has-no-dataview-internal.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/this-has-no-dataview-internal.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: >
   Throws a TypeError if this does not have a [[DataView]] internal slot
 features: [DataView, ArrayBuffer, Int8Array, BigInt, arrow-function]
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/this-is-not-object.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/this-is-not-object.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.getbiguint64
 description: Throws a TypeError if this is not Object
 features: [DataView, ArrayBuffer, Symbol, BigInt, arrow-function]
 ---*/
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/to-boolean-littleendian.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/to-boolean-littleendian.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: Boolean littleEndian argument coerced in ToBoolean
 esid: sec-dataview.prototype.getbiguint64
 features: [ArrayBuffer, BigInt, DataView, DataView.prototype.setUint8, Symbol]
 ---*/
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-errors.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-errors.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbiguint64
 features: [ArrayBuffer, BigInt, DataView, DataView.prototype.setUint8, Symbol, Symbol.toPrimitive, computed-property-names]
 ---*/
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-toprimitive.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-toprimitive.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbiguint64
 features: [ArrayBuffer, BigInt, DataView, DataView.prototype.setUint8, Symbol.toPrimitive, computed-property-names]
 ---*/
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-wrapped-values.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-wrapped-values.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbiguint64
 features: [ArrayBuffer, BigInt, DataView, DataView.prototype.setUint8, Symbol.toPrimitive, computed-property-names]
 ---*/
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 description: ToIndex conversions on byteOffset
 esid: sec-dataview.prototype.getbiguint64
 features: [ArrayBuffer, BigInt, DataView, DataView.prototype.setUint8]
 ---*/
 
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-bigint-value.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-bigint-value.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   Detached buffer is checked after ToBigInt(value)
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-toindex-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-toindex-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   Detached buffer is only checked after ToIndex(requestIndex)
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-before-outofrange-byteoffset.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-before-outofrange-byteoffset.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   Detached buffer is checked before out of range byteOffset's value
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/detached-buffer.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   Throws a TypeError if buffer is detached
 includes: [detachArrayBuffer.js]
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/index-check-before-value-conversion.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/index-check-before-value-conversion.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   RangeError exception for negative or non-integral index is thrown before
   the value conversion.
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/index-is-out-of-range.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/index-is-out-of-range.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 Igalia, S.L. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /*---
 esid: sec-dataview.prototype.setbigint64
 description: >
   Throws a RangeError if getIndex + elementSize > viewSize
 features: [DataView, ArrayBuffer, BigInt]
--- a/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/length.js
+++ b/js/src/tests/test262/built-ins/DataView/prototype/setBigInt64/length.js
@@ -1,9 +1,9 @@
-// |reftest| skip -- BigInt is not supported
+// |reftest| skip-if(!this.hasOwnProperty('BigInt')) -- BigInt is not enabled unconditionally
 // Copyright (C) 2017 I