Merge inbound to mozilla-central. a=merge
authordvarga <dvarga@mozilla.com>
Thu, 02 Aug 2018 01:09:38 +0300
changeset 484745 b72cd47198be
parent 484710 210796a7e6b4 (current diff)
parent 484744 560bed9dac99 (diff)
child 484746 3cb90f16402b
child 484766 f4c112eaaa75
child 484839 8b21457cfcd8
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
b72cd47198be / 63.0a1 / 20180801223951 / files
nightly linux64
b72cd47198be / 63.0a1 / 20180801223951 / files
nightly win32
b72cd47198be / 63.0a1 / 20180801223951 / files
nightly win64
b72cd47198be / 63.0a1 / 20180801223951 / files
nightly mac
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/base/content/browser.js
python/mozbuild/mozbuild/action/test_archive.py
toolkit/locales/en-US/crashreporter/crashes.dtd
toolkit/locales/en-US/crashreporter/crashes.properties
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1160,17 +1160,16 @@ pref("services.sync.prefs.sync.dom.event
 pref("services.sync.prefs.sync.extensions.personas.current", true);
 pref("services.sync.prefs.sync.extensions.update.enabled", true);
 pref("services.sync.prefs.sync.intl.accept_languages", true);
 pref("services.sync.prefs.sync.layout.spellcheckDefault", true);
 pref("services.sync.prefs.sync.lightweightThemes.selectedThemeID", true);
 pref("services.sync.prefs.sync.lightweightThemes.usedThemes", true);
 pref("services.sync.prefs.sync.network.cookie.cookieBehavior", true);
 pref("services.sync.prefs.sync.network.cookie.lifetimePolicy", true);
-pref("services.sync.prefs.sync.network.cookie.lifetime.days", true);
 pref("services.sync.prefs.sync.network.cookie.thirdparty.sessionOnly", true);
 pref("services.sync.prefs.sync.permissions.default.image", true);
 pref("services.sync.prefs.sync.pref.advanced.images.disable_button.view_image", true);
 pref("services.sync.prefs.sync.pref.advanced.javascript.disable_button.advanced", true);
 pref("services.sync.prefs.sync.pref.downloads.disable_button.edit_actions", true);
 pref("services.sync.prefs.sync.pref.privacy.disable_button.cookie_exceptions", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.cache", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2412,77 +2412,64 @@ function loadURI(uri, referrer, postData
  *
  * @param url
  *        A string that may begin with a keyword or an alias.
  *
  * @return {Promise}
  * @resolves { url, postData, mayInheritPrincipal }. If it's not possible
  *           to discern a keyword or an alias, url will be the input string.
  */
-function getShortcutOrURIAndPostData(url, callback = null) {
-  if (callback) {
-    Deprecated.warning("Please use the Promise returned by " +
-                       "getShortcutOrURIAndPostData() instead of passing a " +
-                       "callback",
-                       "https://bugzilla.mozilla.org/show_bug.cgi?id=1100294");
-  }
-  return (async function() {
-    let mayInheritPrincipal = false;
-    let postData = null;
-    // Split on the first whitespace.
-    let [keyword, param = ""] = url.trim().split(/\s(.+)/, 2);
-
-    if (!keyword) {
-      return { url, postData, mayInheritPrincipal };
-    }
-
-    let engine = Services.search.getEngineByAlias(keyword);
-    if (engine) {
-      let submission = engine.getSubmission(param, null, "keyword");
-      return { url: submission.uri.spec,
-               postData: submission.postData,
-               mayInheritPrincipal };
-    }
-
-    // A corrupt Places database could make this throw, breaking navigation
-    // from the location bar.
-    let entry = null;
-    try {
-      entry = await PlacesUtils.keywords.fetch(keyword);
-    } catch (ex) {
-      Cu.reportError(`Unable to fetch Places keyword "${keyword}": ${ex}`);
-    }
-    if (!entry || !entry.url) {
-      // This is not a Places keyword.
-      return { url, postData, mayInheritPrincipal };
-    }
-
-    try {
-      [url, postData] =
-        await BrowserUtils.parseUrlAndPostData(entry.url.href,
-                                               entry.postData,
-                                               param);
-      if (postData) {
-        postData = getPostDataStream(postData);
-      }
-
-      // Since this URL came from a bookmark, it's safe to let it inherit the
-      // current document's principal.
-      mayInheritPrincipal = true;
-    } catch (ex) {
-      // It was not possible to bind the param, just use the original url value.
-    }
-
+async function getShortcutOrURIAndPostData(url) {
+  let mayInheritPrincipal = false;
+  let postData = null;
+  // Split on the first whitespace.
+  let [keyword, param = ""] = url.trim().split(/\s(.+)/, 2);
+
+  if (!keyword) {
     return { url, postData, mayInheritPrincipal };
-  })().then(data => {
-    if (callback) {
-      callback(data);
-    }
-    return data;
-  });
+  }
+
+  let engine = Services.search.getEngineByAlias(keyword);
+  if (engine) {
+    let submission = engine.getSubmission(param, null, "keyword");
+    return { url: submission.uri.spec,
+             postData: submission.postData,
+             mayInheritPrincipal };
+  }
+
+  // A corrupt Places database could make this throw, breaking navigation
+  // from the location bar.
+  let entry = null;
+  try {
+    entry = await PlacesUtils.keywords.fetch(keyword);
+  } catch (ex) {
+    Cu.reportError(`Unable to fetch Places keyword "${keyword}": ${ex}`);
+  }
+  if (!entry || !entry.url) {
+    // This is not a Places keyword.
+    return { url, postData, mayInheritPrincipal };
+  }
+
+  try {
+    [url, postData] =
+      await BrowserUtils.parseUrlAndPostData(entry.url.href,
+                                             entry.postData,
+                                             param);
+    if (postData) {
+      postData = getPostDataStream(postData);
+    }
+
+    // Since this URL came from a bookmark, it's safe to let it inherit the
+    // current document's principal.
+    mayInheritPrincipal = true;
+  } catch (ex) {
+    // It was not possible to bind the param, just use the original url value.
+  }
+
+  return { url, postData, mayInheritPrincipal };
 }
 
 function getPostDataStream(aPostDataString,
                            aType = "application/x-www-form-urlencoded") {
   let dataStream = Cc["@mozilla.org/io/string-input-stream;1"]
                      .createInstance(Ci.nsIStringInputStream);
   dataStream.data = aPostDataString;
 
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -164,21 +164,16 @@ var whitelist = [
 
 whitelist = new Set(whitelist.filter(item =>
   ("isFromDevTools" in item) == isDevtools &&
   (!item.skipUnofficial || !AppConstants.MOZILLA_OFFICIAL) &&
   (!item.platforms || item.platforms.includes(AppConstants.platform))
 ).map(item => item.file));
 
 const ignorableWhitelist = new Set([
-  // These 2 files are unreferenced only when building without the crash
-  // reporter (eg. Linux x64 asan builds on treeherder)
-  "chrome://global/locale/crashes.dtd",
-  "chrome://global/locale/crashes.properties",
-
   // The following files are outside of the omni.ja file, so we only catch them
   // when testing on a non-packaged build.
 
   // toolkit/mozapps/extensions/nsBlocklistService.js
   "resource://app/blocklist.xml",
 
   // dom/media/gmp/GMPParent.cpp
   "resource://gre/gmp-clearkey/0.1/manifest.json",
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -129,16 +129,31 @@ def install_libgcc(gcc_dir, clang_dir):
     copy_tree(include_dir, clang_include_dir)
 
 
 def install_import_library(build_dir, clang_dir):
     shutil.copy2(os.path.join(build_dir, "lib", "clang.lib"),
                  os.path.join(clang_dir, "lib"))
 
 
+def install_asan_symbols(build_dir, clang_dir):
+    lib_path_pattern = os.path.join("lib", "clang", "*.*.*", "lib", "windows")
+    src_path = glob.glob(os.path.join(build_dir, lib_path_pattern,
+                                      "clang_rt.asan_dynamic-*.pdb"))
+    dst_path = glob.glob(os.path.join(clang_dir, lib_path_pattern))
+
+    if len(src_path) != 1:
+        raise Exception("Source path pattern did not resolve uniquely")
+
+    if len(src_path) != 1:
+        raise Exception("Destination path pattern did not resolve uniquely")
+
+    shutil.copy2(src_path[0], dst_path[0])
+
+
 def svn_co(source_dir, url, directory, revision):
     run_in(source_dir, ["svn", "co", "-q", "-r", revision, url, directory])
 
 
 def svn_update(directory, revision):
     run_in(directory, ["svn", "revert", "-q", "-R", "."])
     run_in(directory, ["svn", "update", "-q", "-r", revision])
 
@@ -221,16 +236,17 @@ def build_one_stage(cc, cxx, asm, ld, ar
     build_package(build_dir, cmake_args)
 
     if is_linux():
         install_libgcc(gcc_dir, inst_dir)
     # For some reasons the import library clang.lib of clang.exe is not
     # installed, so we copy it by ourselves.
     if is_windows():
         install_import_library(build_dir, inst_dir)
+        install_asan_symbols(build_dir, inst_dir)
 
 
 # Return the absolute path of a build tool.  We first look to see if the
 # variable is defined in the config file, and if so we make sure it's an
 # absolute path to an existing tool, otherwise we look for a program in
 # $PATH named "key".
 #
 # This expects the name of the key in the config file to match the name of
--- a/build/moz.build
+++ b/build/moz.build
@@ -45,16 +45,17 @@ if CONFIG['MOZ_DMD']:
 # by GDB when we debug executables there.
 FINAL_TARGET_FILES += ['/.gdbinit']
 FINAL_TARGET_PP_FILES += ['.gdbinit_python.in']
 OBJDIR_FILES += ['!/dist/bin/.gdbinit_python']
 
 # Install the clang-cl runtime library for ASAN next to the binaries we produce.
 if CONFIG['MOZ_ASAN'] and CONFIG['CC_TYPE'] == 'clang-cl':
     FINAL_TARGET_FILES += ['%' + CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]
+    FINAL_TARGET_FILES += ['%' + CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH'].replace(".dll", ".pdb")]
 
 if CONFIG['LLVM_SYMBOLIZER']:
     FINAL_TARGET_FILES += ['/' + CONFIG['LLVM_SYMBOLIZER']]
 
 if CONFIG['MOZ_APP_BASENAME']:
     appini_defines = {
         'TOPOBJDIR': TOPOBJDIR,
     }
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -9,16 +9,17 @@
 #include "nsDocShell.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIStandardURL.h"
 
 #include "ExpandedPrincipal.h"
 #include "nsNetUtil.h"
+#include "nsIURIWithSpecialOrigin.h"
 #include "nsScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 
 #include "mozilla/ContentPrincipal.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
@@ -406,16 +407,31 @@ BasePrincipal::CreateCodebasePrincipal(n
   bool inheritsPrincipal;
   nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
                                     &inheritsPrincipal);
   if (NS_FAILED(rv) || inheritsPrincipal) {
     return NullPrincipal::Create(aAttrs);
   }
 
   // Check whether the URI knows what its principal is supposed to be.
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+  nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = do_QueryInterface(aURI);
+  if (uriWithSpecialOrigin) {
+    nsCOMPtr<nsIURI> origin;
+    rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
+    }
+    MOZ_ASSERT(origin);
+    OriginAttributes attrs;
+    RefPtr<BasePrincipal> principal = CreateCodebasePrincipal(origin, attrs);
+    return principal.forget();
+  }
+#endif
+
   nsCOMPtr<nsIPrincipal> blobPrincipal;
   if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
                                                        getter_AddRefs(blobPrincipal))) {
     MOZ_ASSERT(blobPrincipal);
     RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
     return principal.forget();
   }
 
--- a/caps/ContentPrincipal.cpp
+++ b/caps/ContentPrincipal.cpp
@@ -11,16 +11,17 @@
 #include "nscore.h"
 #include "nsScriptSecurityManager.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "pratom.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIStandardURL.h"
+#include "nsIURIWithSpecialOrigin.h"
 #include "nsJSPrincipals.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIProtocolHandler.h"
 #include "nsError.h"
 #include "nsIContentSecurityPolicy.h"
@@ -265,16 +266,31 @@ ContentPrincipal::GetURI(nsIURI** aURI)
   return NS_OK;
 }
 
 bool
 ContentPrincipal::MayLoadInternal(nsIURI* aURI)
 {
   MOZ_ASSERT(aURI);
 
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+  nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = do_QueryInterface(aURI);
+  if (uriWithSpecialOrigin) {
+    nsCOMPtr<nsIURI> origin;
+    nsresult rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return false;
+    }
+    MOZ_ASSERT(origin);
+    OriginAttributes attrs;
+    RefPtr<BasePrincipal> principal = BasePrincipal::CreateCodebasePrincipal(origin, attrs);
+    return nsIPrincipal::Subsumes(principal);
+  }
+#endif
+
   nsCOMPtr<nsIPrincipal> blobPrincipal;
   if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
                                                        getter_AddRefs(blobPrincipal))) {
     MOZ_ASSERT(blobPrincipal);
     return nsIPrincipal::Subsumes(blobPrincipal);
   }
 
   // If this principal is associated with an addon, check whether that addon
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -9078,17 +9078,16 @@ exports.PSEUDO_ELEMENTS = [
   ":-moz-focus-outer",
   ":-moz-list-bullet",
   ":-moz-list-number",
   ":-moz-progress-bar",
   ":-moz-range-track",
   ":-moz-range-progress",
   ":-moz-range-thumb",
   ":-moz-meter-bar",
-  ":-moz-placeholder",
   ":placeholder",
   ":-moz-color-swatch"
 ];
 
 /**
  * A list of the preferences keys for whether a CSS property is enabled or not. This is
  * exposed for testing purposes.
  */
--- a/dom/base/CharacterData.cpp
+++ b/dom/base/CharacterData.cpp
@@ -438,18 +438,17 @@ CharacterData::ToCString(nsAString& aBuf
   }
 }
 #endif
 
 
 nsresult
 CharacterData::BindToTree(nsIDocument* aDocument,
                           nsIContent* aParent,
-                          nsIContent* aBindingParent,
-                          bool aCompileEventHandlers)
+                          nsIContent* aBindingParent)
 {
   MOZ_ASSERT(aParent || aDocument, "Must have document if no parent!");
   MOZ_ASSERT(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(),
              "Must have the same owner document");
   MOZ_ASSERT(!aParent || aDocument == aParent->GetUncomposedDoc(),
              "aDocument must be current doc of aParent");
   MOZ_ASSERT(!GetUncomposedDoc() && !IsInUncomposedDoc(),
              "Already have a document.  Unbind first!");
--- a/dom/base/CharacterData.h
+++ b/dom/base/CharacterData.h
@@ -138,18 +138,17 @@ public:
     // Batch possible DOMSubtreeModified events.
     mozAutoSubtreeModified subtree(OwnerDoc(), nullptr);
     return SetNodeValue(aTextContent, aError);
   }
 
   // Implementation for nsIContent
   nsresult BindToTree(nsIDocument* aDocument,
                       nsIContent* aParent,
-                      nsIContent* aBindingParent,
-                      bool aCompileEventHandlers) override;
+                      nsIContent* aBindingParent) override;
 
   void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override;
 
   already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) final
   {
     return nullptr;
   }
 
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -58,19 +58,19 @@ public:
   {
     Init();
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override
+  nsresult BindToTree(nsIDocument* aDocument,
+                      nsIContent* aParent,
+                      nsIContent* aBindingParent) override
   {
     NS_ASSERTION(false, "Trying to bind a fragment to a tree");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override
   {
     NS_ASSERTION(false, "Trying to unbind a fragment from a tree");
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1597,18 +1597,17 @@ EditableInclusiveDescendantCount(nsICont
     return htmlElem->EditableInclusiveDescendantCount();
   }
 
   return aContent->EditableDescendantCount();
 }
 
 nsresult
 Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                    nsIContent* aBindingParent,
-                    bool aCompileEventHandlers)
+                    nsIContent* aBindingParent)
 {
   MOZ_ASSERT(aParent || aDocument, "Must have document if no parent!");
   MOZ_ASSERT((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()),
              "Must have the same owner document");
   MOZ_ASSERT(!aParent || aDocument == aParent->GetUncomposedDoc(),
              "aDocument must be current doc of aParent");
   MOZ_ASSERT(!GetUncomposedDoc(), "Already have a document.  Unbind first!");
   // Note that as we recurse into the kids, they'll have a non-null parent.  So
@@ -1762,18 +1761,17 @@ Element::BindToTree(nsIDocument* aDocume
         binding->PrototypeBinding()->ChromeOnlyContent());
     }
   }
 
   // Now recurse into our kids
   nsresult rv;
   for (nsIContent* child = GetFirstChild(); child;
        child = child->GetNextSibling()) {
-    rv = child->BindToTree(aDocument, this, aBindingParent,
-                           aCompileEventHandlers);
+    rv = child->BindToTree(aDocument, this, aBindingParent);
     NS_ENSURE_SUCCESS(rv, rv);
 
     editableDescendantCount += EditableInclusiveDescendantCount(child);
   }
 
   if (aDocument) {
     // Update our editable descendant count because we don't keep track of it
     // for content that is not in the uncomposed document.
@@ -1810,21 +1808,20 @@ Element::BindToTree(nsIDocument* aDocume
     // anything... need to fix that.
     // If MayHaveStyle() is true, we must be an nsStyledElement
     static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false, false);
   }
 
   // Call BindToTree on shadow root children.
   if (ShadowRoot* shadowRoot = GetShadowRoot()) {
     shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
+    MOZ_ASSERT(shadowRoot->GetBindingParent() == this);
     for (nsIContent* child = shadowRoot->GetFirstChild(); child;
          child = child->GetNextSibling()) {
-      rv = child->BindToTree(nullptr, shadowRoot,
-                             shadowRoot->GetBindingParent(),
-                             aCompileEventHandlers);
+      rv = child->BindToTree(nullptr, shadowRoot, this);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // FIXME(emilio): Why is this needed? The element shouldn't even be styled in
   // the first place, we should style it properly eventually.
   //
   // Also, if this _is_ needed, then it's wrong and should use GetComposedDoc()
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -659,23 +659,24 @@ public:
   }
   void RemoveManuallyManagedStates(EventStates aStates)
   {
     MOZ_ASSERT(MANUALLY_MANAGED_STATES.HasAllStates(aStates),
                "Should only be removing manually-managed states here");
     RemoveStates(aStates);
   }
 
-  virtual void UpdateEditableState(bool aNotify) override;
+  void UpdateEditableState(bool aNotify) override;
 
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true) override;
+  nsresult BindToTree(nsIDocument* aDocument,
+                      nsIContent* aParent,
+                      nsIContent* aBindingParent) override;
+
+  void UnbindFromTree(bool aDeep = true,
+                      bool aNullParent = true) override;
 
   /**
    * Normalizes an attribute name and returns it as a nodeinfo if an attribute
    * with that name exists. This method is intended for character case
    * conversion if the content object is case insensitive (e.g. HTML). Returns
    * the nodeinfo of the attribute with the specified name if one exists or
    * null otherwise.
    *
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -174,16 +174,17 @@
 #include "nsIScriptError.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
 #include "nsIStreamConverterService.h"
 #include "nsIStringBundle.h"
 #include "nsIURI.h"
+#include "nsIURIWithSpecialOrigin.h"
 #include "nsIURL.h"
 #include "nsIWebNavigation.h"
 #include "nsIWindowMediator.h"
 #include "nsIXPConnect.h"
 #include "nsJSUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
@@ -6339,19 +6340,32 @@ nsContentUtils::GetUTFOrigin(nsIPrincipa
   return NS_OK;
 }
 
 /* static */
 nsresult
 nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin)
 {
   MOZ_ASSERT(aURI, "missing uri");
+  nsresult rv;
+
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+  // Check if either URI has a special origin.
+  nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = do_QueryInterface(aURI);
+  if (uriWithSpecialOrigin) {
+    nsCOMPtr<nsIURI> origin;
+    rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return GetUTFOrigin(origin, aOrigin);
+  }
+#endif
 
   bool isBlobURL = false;
-  nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
+  rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // For Blob URI, the path is the URL of the owning page.
   if (isBlobURL) {
     nsAutoCString path;
     rv = aURI->GetPathQueryRef(path);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -88,30 +88,31 @@ public:
    *                  aParent->GetUncomposedDoc() can be null, in which case
    *                  this must also be null).
    * @param aParent The new parent for the content node.  May be null if the
    *                node is being bound as a direct child of the document.
    * @param aBindingParent The new binding parent for the content node.
    *                       This is must either be non-null if a particular
    *                       binding parent is desired or match aParent's binding
    *                       parent.
-   * @param aCompileEventHandlers whether to initialize the event handlers in
-   *        the document (used by nsXULElement)
    * @note either aDocument or aParent must be non-null.  If both are null,
    *       this method _will_ crash.
    * @note This method must not be called by consumers of nsIContent on a node
    *       that is already bound to a tree.  Call UnbindFromTree first.
    * @note This method will handle rebinding descendants appropriately (eg
    *       changing their binding parent as needed).
    * @note This method does not add the content node to aParent's child list
    * @throws NS_ERROR_OUT_OF_MEMORY if that happens
+   *
+   * TODO(emilio): Should we move to nsIContent::BindToTree most of the
+   * FragmentOrElement / CharacterData duplicated code?
    */
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) = 0;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) = 0;
 
   /**
    * Unbind this content node from a tree.  This will set its current document
    * and binding parent to null.  In the typical case of a node being removed
    * from a parent, this will be called after it has been removed from the
    * parent's child list and after the nsIDocumentObserver notifications for
    * the removal have been dispatched.
    * @param aDeep Whether to recursively unbind the entire subtree rooted at
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1381,18 +1381,17 @@ nsINode::doInsertChildAt(nsIContent* aKi
   if (aIndex == 0) {
     mFirstChild = aKid;
   }
 
   nsIContent* parent = IsContent() ? AsContent() : nullptr;
 
   bool wasInXBLScope = ShouldUseXBLScope(aKid);
   rv = aKid->BindToTree(doc, parent,
-                        parent ? parent->GetBindingParent() : nullptr,
-                        true);
+                        parent ? parent->GetBindingParent() : nullptr);
   if (NS_SUCCEEDED(rv) && !wasInXBLScope && ShouldUseXBLScope(aKid)) {
     MOZ_ASSERT(ShouldUseXBLScope(this),
                "Why does the kid need to use an XBL scope?");
     rv = ReparentWrappersInSubtree(aKid);
   }
   if (NS_FAILED(rv)) {
     if (GetFirstChild() == aKid) {
       mFirstChild = aKid->GetNextSibling();
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -1493,18 +1493,17 @@ nsImageLoadingContent::HaveSize(imgIRequ
   // Query the image
   uint32_t status;
   nsresult rv = aImage->GetImageStatus(&status);
   return (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_SIZE_AVAILABLE));
 }
 
 void
 nsImageLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                  nsIContent* aBindingParent,
-                                  bool aCompileEventHandlers)
+                                  nsIContent* aBindingParent)
 {
   // We may be entering the document, so if our image should be tracked,
   // track it.
   if (!aDocument)
     return;
 
   TrackImage(mCurrentRequest);
   TrackImage(mPendingRequest);
--- a/dom/base/nsImageLoadingContent.h
+++ b/dom/base/nsImageLoadingContent.h
@@ -207,17 +207,17 @@ protected:
    * default implementation returns CORS_NONE unconditionally.
    */
   virtual mozilla::CORSMode GetCORSMode();
 
   virtual mozilla::net::ReferrerPolicy GetImageReferrerPolicy();
 
   // Subclasses are *required* to call BindToTree/UnbindFromTree.
   void BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                  nsIContent* aBindingParent, bool aCompileEventHandlers);
+                  nsIContent* aBindingParent);
   void UnbindFromTree(bool aDeep, bool aNullParent);
 
   nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
   void OnUnlockedDraw();
   nsresult OnImageIsAnimated(imgIRequest *aRequest);
 
   // The nsContentPolicyType we would use for this ImageLoadType
   static nsContentPolicyType PolicyTypeForLoad(ImageLoadType aImageLoadType);
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -89,21 +89,22 @@ nsJSUtils::CompileFunction(AutoJSAPI& js
 
   // Do the junk Gecko is supposed to do before calling into JSAPI.
   for (size_t i = 0; i < aScopeChain.length(); ++i) {
     JS::ExposeObjectToActiveJS(aScopeChain[i]);
   }
 
   // Compile.
   JS::Rooted<JSFunction*> fun(cx);
+  JS::SourceBufferHolder source(PromiseFlatString(aBody).get(), aBody.Length(),
+                                JS::SourceBufferHolder::NoOwnership);
   if (!JS::CompileFunction(cx, aScopeChain, aOptions,
                            PromiseFlatCString(aName).get(),
                            aArgCount, aArgArray,
-                           PromiseFlatString(aBody).get(),
-                           aBody.Length(), &fun))
+                           source, &fun))
   {
     return NS_ERROR_FAILURE;
   }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -595,21 +595,19 @@ nsObjectLoadingContent::SetupDocShell(ns
   }
 
   return docShell.forget();
 }
 
 nsresult
 nsObjectLoadingContent::BindToTree(nsIDocument* aDocument,
                                    nsIContent* aParent,
-                                   nsIContent* aBindingParent,
-                                   bool aCompileEventHandlers)
+                                   nsIContent* aBindingParent)
 {
-  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
-                                    aCompileEventHandlers);
+  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (aDocument) {
     aDocument->AddPlugin(this);
   }
   return NS_OK;
 }
 
 void
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -332,19 +332,19 @@ class nsObjectLoadingContent : public ns
 
     static void Traverse(nsObjectLoadingContent *tmp,
                          nsCycleCollectionTraversalCallback &cb);
 
     void CreateStaticClone(nsObjectLoadingContent* aDest) const;
 
     void DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner);
 
-    nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                        nsIContent* aBindingParent,
-                        bool aCompileEventHandler);
+    nsresult BindToTree(nsIDocument* aDocument,
+                        nsIContent* aParent,
+                        nsIContent* aBindingParent);
     void UnbindFromTree(bool aDeep = true,
                         bool aNullParent = true);
 
     /**
      * Return the content policy type used for loading the element.
      */
     virtual nsContentPolicyType GetContentPolicyType() const = 0;
 
--- a/dom/base/nsTextNode.cpp
+++ b/dom/base/nsTextNode.cpp
@@ -42,18 +42,17 @@ public:
     mNameSpaceID(aNameSpaceID),
     mAttrName(aAttrName)
   {
     NS_ASSERTION(mNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
     NS_ASSERTION(mAttrName, "Must have attr name");
   }
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
   virtual already_AddRefed<CharacterData>
     CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
@@ -132,21 +131,20 @@ nsTextNode::AppendTextForNormalize(const
   CharacterDataChangeInfo::Details details = {
     CharacterDataChangeInfo::Details::eMerge, aNextSibling
   };
   return SetTextInternal(mText.GetLength(), 0, aBuffer, aLength, aNotify, &details);
 }
 
 nsresult
 nsTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                       nsIContent* aBindingParent, bool aCompileEventHandlers)
+                       nsIContent* aBindingParent)
 {
   nsresult rv = CharacterData::BindToTree(aDocument, aParent,
-                                          aBindingParent,
-                                          aCompileEventHandlers);
+                                          aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SetDirectionFromNewTextNode(this);
 
   return NS_OK;
 }
 
 void nsTextNode::UnbindFromTree(bool aDeep, bool aNullParent)
@@ -231,24 +229,23 @@ NS_NewAttributeContent(nsNodeInfoManager
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(nsAttributeTextNode, nsTextNode,
                             nsIMutationObserver)
 
 nsresult
 nsAttributeTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+                                nsIContent* aBindingParent)
 {
   MOZ_ASSERT(aParent && aParent->GetParent(),
              "This node can't be a child of the document or of the document root");
 
   nsresult rv = nsTextNode::BindToTree(aDocument, aParent,
-                                       aBindingParent, aCompileEventHandlers);
+                                       aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ASSERTION(!mGrandparent, "We were already bound!");
   mGrandparent = aParent->GetParent()->AsElement();
   mGrandparent->AddMutationObserver(this);
 
   // Note that there is no need to notify here, since we have no
   // frame yet at this point.
--- a/dom/base/nsTextNode.h
+++ b/dom/base/nsTextNode.h
@@ -48,18 +48,17 @@ public:
   // nsINode
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   virtual already_AddRefed<CharacterData>
     CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
                   bool aCloneText) const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   nsresult AppendTextForNormalize(const char16_t* aBuffer, uint32_t aLength,
                                   bool aNotify, nsIContent* aNextSibling);
 
   // Need to have a copy here because including nsDocument.h in this file will
   // fail to build on Windows.
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -3257,56 +3257,16 @@ MOZ_ALWAYS_INLINE bool
 CallerSubsumes(JS::Handle<JS::Value> aValue)
 {
   if (!aValue.isObject()) {
     return true;
   }
   return CallerSubsumes(&aValue.toObject());
 }
 
-template<class T>
-inline bool
-WrappedJSToDictionary(JSContext* aCx, nsISupports* aObject, T& aDictionary)
-{
-  nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(aObject);
-  if (!wrappedObj) {
-    return false;
-  }
-
-  JS::Rooted<JSObject*> obj(aCx, wrappedObj->GetJSObject());
-  if (!obj) {
-    return false;
-  }
-
-  JSAutoRealmAllowCCW ar(aCx, obj);
-  JS::Rooted<JS::Value> v(aCx, JS::ObjectValue(*obj));
-  return aDictionary.Init(aCx, v);
-}
-
-template<class T>
-inline bool
-WrappedJSToDictionary(nsISupports* aObject, T& aDictionary)
-{
-  nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(aObject);
-  NS_ENSURE_TRUE(wrappedObj, false);
-  JS::Rooted<JSObject*> obj(RootingCx(), wrappedObj->GetJSObject());
-  NS_ENSURE_TRUE(obj, false);
-
-  nsIGlobalObject* global = xpc::NativeGlobal(obj);
-  NS_ENSURE_TRUE(global, false);
-
-  // we need this AutoEntryScript here because the spec requires us to execute
-  // getters when parsing a dictionary
-  AutoEntryScript aes(global, "WebIDL dictionary creation");
-
-  JS::Rooted<JS::Value> v(aes.cx(), JS::ObjectValue(*obj));
-  return aDictionary.Init(aes.cx(), v);
-}
-
-
 template<class T, class S>
 inline RefPtr<T>
 StrongOrRawPtr(already_AddRefed<S>&& aPtr)
 {
   return std::move(aPtr);
 }
 
 template<class T,
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -191,18 +191,17 @@ CallbackObject::CallSetup::CallSetup(Cal
         aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
           NS_LITERAL_CSTRING("Refusing to execute function from window "
                              "whose document is no longer active."));
         return;
       }
       globalObject = win;
     } else {
       // No DOM Window. Store the global.
-      JSObject* global = JS::GetNonCCWObjectGlobal(realCallback);
-      globalObject = xpc::NativeGlobal(global);
+      globalObject = xpc::NativeGlobal(realCallback);
       MOZ_ASSERT(globalObject);
     }
   }
 
   // Bail out if there's no useful global. This seems to happen intermittently
   // on gaia-ui tests, probably because nsInProcessTabChildGlobal is returning
   // null in some kind of teardown state.
   if (!globalObject->GetGlobalJSObject()) {
--- a/dom/html/HTMLAnchorElement.cpp
+++ b/dom/html/HTMLAnchorElement.cpp
@@ -112,24 +112,22 @@ HTMLAnchorElement::OnDNSPrefetchDeferred
 bool
 HTMLAnchorElement::HasDeferredDNSPrefetchRequest()
 {
   return HasFlag(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
 }
 
 nsresult
 HTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Prefetch links
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     doc->RegisterPendingLinkUpdate(this);
     TryDNSPrefetch();
   }
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -43,18 +43,17 @@ public:
 
   // Element
   virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
 
   // DOM memory reporter participant
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
   virtual bool IsLink(nsIURI** aURI) const override;
--- a/dom/html/HTMLAreaElement.cpp
+++ b/dom/html/HTMLAreaElement.cpp
@@ -87,23 +87,21 @@ HTMLAreaElement::RelList()
     mRelList = new nsDOMTokenList(this, nsGkAtoms::rel,
                                   HTMLAnchorElement::sSupportedRelValues);
   }
   return mRelList;
 }
 
 nsresult
 HTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   Link::ResetLinkState(false, Link::ElementHasHref());
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     doc->RegisterPendingLinkUpdate(this);
   }
   return rv;
 }
--- a/dom/html/HTMLAreaElement.h
+++ b/dom/html/HTMLAreaElement.h
@@ -41,18 +41,17 @@ public:
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   virtual EventStates IntrinsicState() const override;
 
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -287,22 +287,20 @@ HTMLBodyElement::IsEventAttributeNameInt
 {
   return nsContentUtils::IsEventAttributeName(aName,
                                               EventNameType_HTML |
                                               EventNameType_HTMLBodyOrFramesetOnly);
 }
 
 nsresult
 HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
   return mAttrsAndChildren.ForceMapped(this, OwnerDoc());
 }
 
 nsresult
 HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
                               const nsAttrValue* aOldValue,
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -131,18 +131,17 @@ public:
   virtual already_AddRefed<TextEditor> GetAssociatedEditor() override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
 
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   /**
    * Called when an attribute has just been changed
    */
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -313,22 +313,20 @@ HTMLButtonElement::PostHandleEvent(Event
     mForm->FlushPendingSubmission();
   } //if
 
   return rv;
 }
 
 nsresult
 HTMLButtonElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv =
-    nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent, aBindingParent,
-                                                  aCompileEventHandlers);
+    nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent, aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Update our state; we may now be the default submit element
   UpdateState(false);
 
   return NS_OK;
 }
 
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -57,18 +57,17 @@ public:
 
   // nsINode
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual void DoneCreatingElement() override;
 
   void UpdateBarredFromConstraintValidation();
   // Element
   EventStates IntrinsicState() const override;
   /**
--- a/dom/html/HTMLEmbedElement.cpp
+++ b/dom/html/HTMLEmbedElement.cpp
@@ -81,27 +81,24 @@ void
 HTMLEmbedElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
 {
   nsImageLoadingContent::AsyncEventRunning(aEvent);
 }
 
 nsresult
 HTMLEmbedElement::BindToTree(nsIDocument *aDocument,
                              nsIContent *aParent,
-                             nsIContent *aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent *aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
-                                          aBindingParent,
-                                          aCompileEventHandlers);
+                                          aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Don't kick off load from being bound to a plugin document - the plugin
   // document will call nsObjectLoadingContent::InitializeFromChannel() for the
   // initial load.
   nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
 
   if (!pluginDoc) {
--- a/dom/html/HTMLEmbedElement.h
+++ b/dom/html/HTMLEmbedElement.h
@@ -32,18 +32,17 @@ public:
   // EventTarget
   NS_IMETHOD PostHandleEvent(EventChainPostVisitor& aVisitor) override;
 #endif
 
   // EventTarget
   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent *aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
   virtual IMEState GetDesiredIMEState() override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom *aAttribute,
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -272,22 +272,20 @@ HTMLFormElement::ParseAttribute(int32_t 
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 nsresult
 HTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(aDocument));
   if (htmlDoc) {
     htmlDoc->AddedForm();
   }
 
   return rv;
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -94,18 +94,17 @@ public:
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   void WillHandleEvent(EventChainPostVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -543,26 +543,23 @@ HTMLImageElement::IsHTMLFocusable(bool a
 #endif
     (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
 
   return false;
 }
 
 nsresult
 HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
-                                    aCompileEventHandlers);
+  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (aParent) {
     UpdateFormOwner();
   }
 
   if (HaveSrcsetOrInPicture()) {
     if (aDocument && !mInDocResponsiveContent) {
       aDocument->AddResponsiveContent(this);
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -70,18 +70,17 @@ public:
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
 
   bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual EventStates IntrinsicState() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual void NodeInfoChanged(nsIDocument* aOldDoc) override;
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4598,26 +4598,23 @@ HTMLInputElement::MaybeLoadImage()
                            mSrcTriggeringPrincipal)) ||
        !LoadingEnabled())) {
     CancelImageRequests(true);
   }
 }
 
 nsresult
 HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
-                                                              aBindingParent,
-                                                              aCompileEventHandlers);
+                                                              aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
-                                    aCompileEventHandlers);
+  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (mType == NS_FORM_INPUT_IMAGE) {
     // Our base URI may have changed; claim that our URI changed, and the
     // nsImageLoadingContent will decide whether a new image load is warranted.
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
       // Mark channel as urgent-start before load image if the image load is
       // initaiated by a user interaction.
       mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -191,18 +191,17 @@ public:
                      EventChainPostVisitor& aVisitor) override;
   void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
   void StartRangeThumbDrag(WidgetGUIEvent* aEvent);
   void FinishRangeThumbDrag(WidgetGUIEvent* aEvent = nullptr);
   void CancelRangeThumbDrag(bool aIsForUserEvent = true);
   void SetValueOfRangeForUserEvent(Decimal aValue);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual void DoneCreatingElement() override;
 
   virtual EventStates IntrinsicState() const override;
 
   // Element
--- a/dom/html/HTMLLegendElement.cpp
+++ b/dom/html/HTMLLegendElement.cpp
@@ -67,22 +67,20 @@ HTMLLegendElement::GetAttributeChangeHin
   if (aAttribute == nsGkAtoms::align) {
     retval |= NS_STYLE_HINT_REFLOW;
   }
   return retval;
 }
 
 nsresult
 HTMLLegendElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   return nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                          aBindingParent,
-                                          aCompileEventHandlers);
+                                          aBindingParent);
 }
 
 void
 HTMLLegendElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -26,19 +26,19 @@ public:
 
   using nsGenericHTMLElement::Focus;
   virtual void Focus(ErrorResult& aError) override;
 
   virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) override;
 
   // nsIContent
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -122,24 +122,22 @@ bool
 HTMLLinkElement::HasDeferredDNSPrefetchRequest()
 {
   return HasFlag(HTML_LINK_DNS_PREFETCH_DEFERRED);
 }
 
 nsresult
 HTMLLinkElement::BindToTree(nsIDocument* aDocument,
                             nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (nsIDocument* doc = GetComposedDoc()) {
     doc->RegisterPendingLinkUpdate(this);
     TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
   }
 
   void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -44,18 +44,17 @@ public:
 
   // nsINode
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4533,21 +4533,20 @@ HTMLMediaElement::AfterMaybeChangeAttr(i
       DoLoad();
     }
   }
 }
 
 nsresult
 HTMLMediaElement::BindToTree(nsIDocument* aDocument,
                              nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(
-    aDocument, aParent, aBindingParent, aCompileEventHandlers);
+    aDocument, aParent, aBindingParent);
 
   mUnboundFromTree = false;
 
   if (aDocument) {
     // The preload action depends on the value of the autoplay attribute.
     // It's value may have changed, so update it.
     UpdatePreloadAction();
   }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -149,18 +149,17 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
                               nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual void DoneCreatingElement() override;
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable,
                                int32_t *aTabIndex) override;
   virtual int32_t TabIndexDefault() override;
 
--- a/dom/html/HTMLMenuItemElement.cpp
+++ b/dom/html/HTMLMenuItemElement.cpp
@@ -295,22 +295,20 @@ HTMLMenuItemElement::PostHandleEvent(Eve
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLMenuItemElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+                                nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
 
   if (NS_SUCCEEDED(rv) && aDocument && mType == CMD_TYPE_RADIO) {
     AddedToRadioGroup();
   }
 
   return rv;
 }
 
--- a/dom/html/HTMLMenuItemElement.h
+++ b/dom/html/HTMLMenuItemElement.h
@@ -31,19 +31,19 @@ public:
   // nsISupports
   NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLMenuItemElement,
                                        nsGenericHTMLElement)
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   virtual void DoneCreatingElement() override;
--- a/dom/html/HTMLMetaElement.cpp
+++ b/dom/html/HTMLMetaElement.cpp
@@ -75,22 +75,20 @@ HTMLMetaElement::AfterSetAttr(int32_t aN
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                             aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDocument &&
       AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport, eIgnoreCase)) {
     nsAutoString content;
     GetContent(content);
     nsContentUtils::ProcessViewportInfo(aDocument, content);
   }
 
--- a/dom/html/HTMLMetaElement.h
+++ b/dom/html/HTMLMetaElement.h
@@ -17,18 +17,17 @@ class HTMLMetaElement final : public nsG
 {
 public:
   explicit HTMLMetaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLMetaElement, nsGenericHTMLElement)
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -225,27 +225,24 @@ HTMLObjectElement::PostHandleEvent(Event
   return NS_OK;
 }
 
 #endif // #ifdef XP_MACOSX
 
 nsresult
 HTMLObjectElement::BindToTree(nsIDocument *aDocument,
                               nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent *aBindingParent)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+                                                     aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
-                                          aBindingParent,
-                                          aCompileEventHandlers);
+                                          aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Don't kick off load from being bound to a plugin document - the plugin
   // document will call nsObjectLoadingContent::InitializeFromChannel() for the
   // initial load.
   nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
 
   // If we already have all the children, start the load.
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -45,18 +45,17 @@ public:
 
   // Element
   virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
 
   // EventTarget
   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent *aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
   virtual IMEState GetDesiredIMEState() override;
 
   // Overriden nsIFormControl methods
   NS_IMETHOD Reset() override;
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -265,22 +265,20 @@ HTMLOptionElement::GetText(nsAString& aT
 void
 HTMLOptionElement::SetText(const nsAString& aText, ErrorResult& aRv)
 {
   aRv = nsContentUtils::SetNodeTextContent(this, aText, true);
 }
 
 nsresult
 HTMLOptionElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Our new parent might change :disabled/:enabled state.
   UpdateDisabledState(false);
 
   return NS_OK;
 }
 
--- a/dom/html/HTMLOptionElement.h
+++ b/dom/html/HTMLOptionElement.h
@@ -71,18 +71,17 @@ public:
 
   /**
    * Check our disabled content attribute and optgroup's (if it exists) disabled
    * state to decide whether our disabled flag should be toggled.
    */
   void UpdateDisabledState(bool aNotify);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   // nsIContent
   virtual EventStates IntrinsicState() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/html/HTMLOutputElement.cpp
+++ b/dom/html/HTMLOutputElement.cpp
@@ -114,22 +114,20 @@ HTMLOutputElement::IntrinsicState() cons
     }
   }
 
   return states;
 }
 
 nsresult
 HTMLOutputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+                                                     aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Unfortunately, we can actually end up having to change our state
   // as a result of being bound to a tree even from the parser: we
   // might end up a in a novalidate form, and unlike other form
   // controls that on its own is enough to make change ui-valid state.
   // So just go ahead and update our state now.
   UpdateState(false);
--- a/dom/html/HTMLOutputElement.h
+++ b/dom/html/HTMLOutputElement.h
@@ -42,18 +42,17 @@ public:
                               nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
 
   EventStates IntrinsicState() const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                               nsIContent* aBindingParent,
-                               bool aCompileEventHandlers) override;
+                               nsIContent* aBindingParent) override;
 
   // This function is called when a callback function from nsIMutationObserver
   // has to be used to update the defaultValue attribute.
   void DescendantsChanged();
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -49,22 +49,20 @@ HTMLScriptElement::~HTMLScriptElement()
 
 NS_IMPL_ISUPPORTS_INHERITED(HTMLScriptElement, nsGenericHTMLElement,
                             nsIScriptLoaderObserver,
                             nsIScriptElement,
                             nsIMutationObserver)
 
 nsresult
 HTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (GetComposedDoc()) {
     MaybeProcessScript();
   }
 
   return NS_OK;
 }
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -35,18 +35,17 @@ public:
   virtual bool GetScriptType(nsAString& type) override;
   virtual void GetScriptText(nsAString& text) override;
   virtual void GetScriptCharset(nsAString& charset) override;
   virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
   virtual CORSMode GetCORSMode() const override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
                               nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1103,22 +1103,20 @@ HTMLSelectElement::SelectSomething(bool 
     }
   }
 
   return false;
 }
 
 nsresult
 HTMLSelectElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
-                                                              aBindingParent,
-                                                              aCompileEventHandlers);
+                                                              aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is a disabled fieldset in the parent chain, the element is now
   // barred from constraint validation.
   // XXXbz is this still needed now that fieldset changes always call
   // FieldSetDisabledChanged?
   UpdateBarredFromConstraintValidation();
 
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -313,18 +313,17 @@ public:
   bool SetOptionsSelectedByIndex(int32_t aStartIndex,
                                  int32_t aEndIndex,
                                  uint32_t aOptionsMask);
 
   /**
    * Called when an attribute is about to be changed
    */
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                               nsIContent* aBindingParent,
-                               bool aCompileEventHandlers) override;
+                               nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -223,22 +223,20 @@ HTMLSharedElement::AfterSetAttr(int32_t 
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
                                             aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The document stores a pointer to its base URI and base target, which we may
   // need to update here.
   if (mNodeInfo->Equals(nsGkAtoms::base) &&
       aDocument) {
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
       SetBaseURIUsingFirstBaseWithHref(aDocument, this);
--- a/dom/html/HTMLSharedElement.h
+++ b/dom/html/HTMLSharedElement.h
@@ -32,18 +32,17 @@ public:
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
--- a/dom/html/HTMLSlotElement.cpp
+++ b/dom/html/HTMLSlotElement.cpp
@@ -46,24 +46,22 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLS
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLSlotElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLSlotElement)
 
 nsresult
 HTMLSlotElement::BindToTree(nsIDocument* aDocument,
                             nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow();
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   ShadowRoot* containingShadow = GetContainingShadow();
   if (containingShadow && !oldContainingShadow) {
     containingShadow->AddSlot(this);
   }
 
   return NS_OK;
--- a/dom/html/HTMLSlotElement.h
+++ b/dom/html/HTMLSlotElement.h
@@ -22,21 +22,20 @@ public:
   NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLSlotElement, slot)
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSlotElement, nsGenericHTMLElement)
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   // nsIContent
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true) override;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) override;
+  virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -138,23 +138,21 @@ HTMLSourceElement::AfterSetAttr(int32_t 
                                             aValue, aOldValue,
                                             aMaybeScriptedPrincipal,
                                             aNotify);
 }
 
 nsresult
 HTMLSourceElement::BindToTree(nsIDocument *aDocument,
                               nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent *aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                  aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (auto* media = HTMLMediaElement::FromNodeOrNull(aParent)) {
     media->NotifyAddedSource();
   }
 
   return NS_OK;
 }
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -31,18 +31,17 @@ public:
   NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLSourceElement, source)
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   // Override BindToTree() so that we can trigger a load when we add a
   // child source element.
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
 
   // If this element's media attr matches for its owner document.  Returns true
   // if no media attr was set.
   bool MatchesCurrentMedia();
 
   // True if a source tag would match the given media attribute for the
   // specified document. Used by the preloader to determine valid <source> tags
   // prior to DOM creation.
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -95,22 +95,20 @@ HTMLStyleElement::ContentChanged(nsICont
   mTriggeringPrincipal = nullptr;
   if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
     Unused << UpdateStyleSheetInternal(nullptr, nullptr);
   }
 }
 
 nsresult
 HTMLStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   void (HTMLStyleElement::*update)() = &HTMLStyleElement::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(
     NewRunnableMethod("dom::HTMLStyleElement::BindToTree", this, update));
 
   return rv;
 }
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -36,18 +36,17 @@ public:
   virtual void SetInnerHTML(const nsAString& aInnerHTML,
                             nsIPrincipal* aSubjectPrincipal,
                             mozilla::ErrorResult& aError) override;
   virtual void SetTextContentInternal(const nsAString& aTextContent,
                                       nsIPrincipal* aSubjectPrincipal,
                                       mozilla::ErrorResult& aError) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -1110,23 +1110,21 @@ HTMLTableElement::BuildInheritedAttribut
 void
 HTMLTableElement::ReleaseInheritedAttributes()
 {
   NS_IF_RELEASE(mTableInheritedAttributes);
 }
 
 nsresult
 HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   ReleaseInheritedAttributes();
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
   BuildInheritedAttributes();
   return NS_OK;
 }
 
 void
 HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -189,18 +189,17 @@ public:
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   /**
    * Called when an attribute is about to be changed
    */
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -906,22 +906,20 @@ HTMLTextAreaElement::IntrinsicState() co
     state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
   }
 
   return state;
 }
 
 nsresult
 HTMLTextAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+                                nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
-                                                              aBindingParent,
-                                                              aCompileEventHandlers);
+                                                              aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is a disabled fieldset in the parent chain, the element is now
   // barred from constraint validation and can't suffer from value missing.
   UpdateValueMissingValidityState();
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -99,18 +99,17 @@ public:
   NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
   virtual void GetValueFromSetRangeText(nsAString& aValue) override;
   virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
   NS_IMETHOD_(bool) HasCachedSelection() override;
 
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                               nsIContent* aBindingParent,
-                               bool aCompileEventHandlers) override;
+                               nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
--- a/dom/html/HTMLTitleElement.cpp
+++ b/dom/html/HTMLTitleElement.cpp
@@ -77,23 +77,21 @@ HTMLTitleElement::ContentRemoved(nsICont
                                  nsIContent* aPreviousSibling)
 {
   SendTitleChangeEvent(false);
 }
 
 nsresult
 HTMLTitleElement::BindToTree(nsIDocument *aDocument,
                              nsIContent *aParent,
-                             nsIContent *aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent *aBindingParent)
 {
   // Let this fall through.
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SendTitleChangeEvent(true);
 
   return NS_OK;
 }
 
 void
--- a/dom/html/HTMLTitleElement.h
+++ b/dom/html/HTMLTitleElement.h
@@ -36,18 +36,17 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent *aBindingParent) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
 
 protected:
   virtual ~HTMLTitleElement();
--- a/dom/html/HTMLTrackElement.cpp
+++ b/dom/html/HTMLTrackElement.cpp
@@ -345,23 +345,21 @@ HTMLTrackElement::LoadResource()
   }
 
   mChannel = channel;
 }
 
 nsresult
 HTMLTrackElement::BindToTree(nsIDocument* aDocument,
                              nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                  aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   LOG(LogLevel::Debug, ("Track Element bound to tree."));
   auto* parent = HTMLMediaElement::FromNodeOrNull(aParent);
   if (!parent) {
     return NS_OK;
   }
 
--- a/dom/html/HTMLTrackElement.h
+++ b/dom/html/HTMLTrackElement.h
@@ -97,18 +97,17 @@ public:
                               const nsAString& aValue,
                               nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   // Override BindToTree() so that we can trigger a load when we become
   // the child of a media element.
   virtual nsresult BindToTree(nsIDocument* aDocument,
                               nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   void DispatchTrackRunnable(const nsString& aEventName);
   void DispatchTrustedEvent(const nsAString& aName);
 
   void DropChannel();
 
   void NotifyShutdown();
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -413,22 +413,20 @@ nsGenericHTMLElement::EditableInclusiveD
 {
   bool isEditable = IsInComposedDoc() && HasFlag(NODE_IS_EDITABLE) &&
     GetContentEditableValue() == eTrue;
   return EditableDescendantCount() + isEditable;
 }
 
 nsresult
 nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                 nsIContent* aBindingParent,
-                                 bool aCompileEventHandlers)
+                                 nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
+                                                     aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     RegAccessKey();
     if (HasName() && CanHaveName(NodeInfo()->NameAtom())) {
       aDocument->
         AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
     }
@@ -1746,22 +1744,20 @@ nsGenericHTMLFormElement::GetDesiredIMES
     return nsGenericHTMLElement::GetDesiredIMEState();
   }
   return state;
 }
 
 nsresult
 nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
                                      nsIContent* aParent,
-                                     nsIContent* aBindingParent,
-                                     bool aCompileEventHandlers)
+                                     nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // An autofocus event has to be launched if the autofocus attribute is
   // specified and the element accept the autofocus attribute. In addition,
   // the document should not be already loaded and the "browser.autofocus"
   // preference should be 'true'.
   if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) &&
       nsContentUtils::AutoFocusEnabled() && aDocument) {
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -265,19 +265,19 @@ public:
    * Pass a reference to the image request, since the method may change the
    * value and we want to use the updated value.
    */
   MOZ_CAN_RUN_SCRIPT
   nsSize GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequest);
 
 public:
   // Implementation for nsIContent
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse) override
   {
     bool isFocusable = false;
     IsHTMLFocusable(aWithMouse, &isFocusable, aTabIndex);
     return isFocusable;
@@ -1007,18 +1007,17 @@ public:
   }
   virtual bool AllowDrop() override
   {
     return true;
   }
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual IMEState GetDesiredIMEState() override;
   virtual mozilla::EventStates IntrinsicState() const override;
 
   void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
   virtual nsresult PreHandleEvent(
                      mozilla::EventChainVisitor& aVisitor) override;
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -226,22 +226,20 @@ nsGenericHTMLFrameElement::LoadSrc()
   bool origSrc = !mSrcLoadHappened;
   mSrcLoadHappened = true;
   mFrameLoader->LoadFrame(origSrc);
 }
 
 nsresult
 nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
                                       nsIContent* aParent,
-                                      nsIContent* aBindingParent,
-                                      bool aCompileEventHandlers)
+                                      nsIContent* aBindingParent)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (IsInComposedDoc()) {
     NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                  "Missing a script blocker!");
 
     AUTO_PROFILER_LABEL("nsGenericHTMLFrameElement::BindToTree", OTHER);
 
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -54,18 +54,17 @@ public:
   NS_DECL_NSIDOMMOZBROWSERFRAME
   NS_DECL_NSIMOZBROWSERFRAME
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID)
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual void DestroyContent() override;
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest, bool aPreallocateChildren);
 
   virtual int32_t TabIndexDefault() override;
 
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -87,24 +87,22 @@ nsMathMLElement::nsMathMLElement(already
 : nsMathMLElementBase(aNodeInfo),
   ALLOW_THIS_IN_INITIALIZER_LIST(Link(this)),
   mIncrementScriptLevel(false)
 {
 }
 
 nsresult
 nsMathMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsMathMLElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     aDocument->RegisterPendingLinkUpdate(this);
   }
 
   // Set the bit in the document for telemetry.
   if (nsIDocument* doc = GetComposedDoc()) {
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -31,18 +31,17 @@ class nsMathMLElement final : public nsM
 public:
   explicit nsMathMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   explicit nsMathMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
   // Implementation of nsISupports is inherited from nsMathMLElementBase
   NS_DECL_ISUPPORTS_INHERITED
 
   nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                      nsIContent* aBindingParent,
-                      bool aCompileEventHandlers) override;
+                      nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
--- a/dom/script/ScriptLoadHandler.cpp
+++ b/dom/script/ScriptLoadHandler.cpp
@@ -114,41 +114,45 @@ ScriptLoadHandler::DecodeRawData(const u
                                  uint32_t aDataLength,
                                  bool aEndOfStream)
 {
   CheckedInt<size_t> needed = mDecoder->MaxUTF16BufferLength(aDataLength);
   if (!needed.isValid()) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  uint32_t haveRead = mRequest->ScriptText().length();
+  // Reference to the script source buffer which we will update.
+  ScriptLoadRequest::ScriptTextBuffer& scriptText = mRequest->ScriptText();
+
+  uint32_t haveRead = scriptText.length();
 
   CheckedInt<uint32_t> capacity = haveRead;
   capacity += needed.value();
 
-  if (!capacity.isValid() || !mRequest->ScriptText().reserve(capacity.value())) {
+  if (!capacity.isValid() || !scriptText.resize(capacity.value())) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   uint32_t result;
   size_t read;
   size_t written;
   bool hadErrors;
   Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
     MakeSpan(aData, aDataLength),
-    MakeSpan(mRequest->ScriptText().begin() + haveRead, needed.value()),
+    MakeSpan(scriptText.begin() + haveRead, needed.value()),
     aEndOfStream);
   MOZ_ASSERT(result == kInputEmpty);
   MOZ_ASSERT(read == aDataLength);
   MOZ_ASSERT(written <= needed.value());
   Unused << hadErrors;
 
   haveRead += written;
   MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
-  MOZ_ALWAYS_TRUE(mRequest->ScriptText().resizeUninitialized(haveRead));
+  MOZ_ALWAYS_TRUE(scriptText.resize(haveRead));
+  mRequest->mScriptTextLength = scriptText.length();
 
   return NS_OK;
 }
 
 bool
 ScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader* aLoader,
                                  const uint8_t* aData,
                                  uint32_t aDataLength,
--- a/dom/script/ScriptLoadRequest.cpp
+++ b/dom/script/ScriptLoadRequest.cpp
@@ -61,16 +61,17 @@ ScriptLoadRequest::ScriptLoadRequest(Scr
   , mInDeferList(false)
   , mInAsyncList(false)
   , mIsNonAsyncScriptInserted(false)
   , mIsXSLT(false)
   , mIsCanceled(false)
   , mWasCompiledOMT(false)
   , mIsTracking(false)
   , mOffThreadToken(nullptr)
+  , mScriptTextLength(0)
   , mScriptBytecode()
   , mBytecodeOffset(0)
   , mURI(aURI)
   , mLineNo(1)
   , mCORSMode(aCORSMode)
   , mIntegrity(aIntegrity)
   , mReferrer(aReferrer)
   , mReferrerPolicy(aReferrerPolicy)
@@ -161,26 +162,26 @@ ScriptLoadRequest::SetUnknownDataType()
   mScriptData.reset();
 }
 
 void
 ScriptLoadRequest::SetTextSource()
 {
   MOZ_ASSERT(IsUnknownDataType());
   mDataType = DataType::eTextSource;
-  mScriptData.emplace(VariantType<Vector<char16_t>>());
+  mScriptData.emplace(VariantType<ScriptTextBuffer>());
 }
 
 void
 ScriptLoadRequest::SetBinASTSource()
 {
 #ifdef JS_BUILD_BINAST
   MOZ_ASSERT(IsUnknownDataType());
   mDataType = DataType::eBinASTSource;
-  mScriptData.emplace(VariantType<Vector<uint8_t>>());
+  mScriptData.emplace(VariantType<BinASTSourceBuffer>());
 #else
   MOZ_CRASH("BinAST not supported");
 #endif
 }
 
 void
 ScriptLoadRequest::SetBytecode()
 {
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -166,31 +166,38 @@ public:
     return mDataType == DataType::eBytecode;
   }
 
   void SetUnknownDataType();
   void SetTextSource();
   void SetBinASTSource();
   void SetBytecode();
 
-  const Vector<char16_t>& ScriptText() const {
+  using ScriptTextBuffer = Vector<char16_t, 0, JSMallocAllocPolicy>;
+  using BinASTSourceBuffer = Vector<uint8_t>;
+
+  const ScriptTextBuffer& ScriptText() const
+  {
     MOZ_ASSERT(IsTextSource());
-    return mScriptData->as<Vector<char16_t>>();
-  }
-  Vector<char16_t>& ScriptText() {
-    MOZ_ASSERT(IsTextSource());
-    return mScriptData->as<Vector<char16_t>>();
+    return mScriptData->as<ScriptTextBuffer>();
   }
-  const Vector<uint8_t>& ScriptBinASTData() const {
-    MOZ_ASSERT(IsBinASTSource());
-    return mScriptData->as<Vector<uint8_t>>();
+  ScriptTextBuffer& ScriptText()
+  {
+    MOZ_ASSERT(IsTextSource());
+    return mScriptData->as<ScriptTextBuffer>();
   }
-  Vector<uint8_t>& ScriptBinASTData() {
+  const BinASTSourceBuffer& ScriptBinASTData() const
+  {
     MOZ_ASSERT(IsBinASTSource());
-    return mScriptData->as<Vector<uint8_t>>();
+    return mScriptData->as<BinASTSourceBuffer>();
+  }
+  BinASTSourceBuffer& ScriptBinASTData()
+  {
+    MOZ_ASSERT(IsBinASTSource());
+    return mScriptData->as<BinASTSourceBuffer>();
   }
 
   enum class ScriptMode : uint8_t {
     eBlocking,
     eDeferred,
     eAsync
   };
 
@@ -247,17 +254,21 @@ public:
 
   // Holds the top-level JSScript that corresponds to the current source, once
   // it is parsed, and planned to be saved in the bytecode cache.
   JS::Heap<JSScript*> mScript;
 
   // Holds script source data for non-inline scripts. Don't use nsString so we
   // can give ownership to jsapi. Holds either char16_t source text characters
   // or BinAST encoded bytes depending on mSourceEncoding.
-  Maybe<Variant<Vector<char16_t>, Vector<uint8_t>>> mScriptData;
+  Maybe<Variant<ScriptTextBuffer, BinASTSourceBuffer>> mScriptData;
+
+  // The length of script source text, set when reading completes. This is used
+  // since mScriptData is cleared when the source is passed to the JS engine.
+  size_t mScriptTextLength;
 
   // Holds the SRI serialized hash and the script bytecode for non-inline
   // scripts.
   mozilla::Vector<uint8_t> mScriptBytecode;
   uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
 
   const nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -486,18 +486,17 @@ ScriptLoader::CreateModuleScript(ModuleL
       rv = module ? NS_OK : NS_ERROR_FAILURE;
     } else {
       JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
 
       JS::CompileOptions options(cx);
       rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
 
       if (NS_SUCCEEDED(rv)) {
-        nsAutoString inlineData;
-        SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
+        SourceBufferHolder srcBuf = GetScriptSource(cx, aRequest);
         rv = nsJSUtils::CompileModule(cx, srcBuf, global, options, &module);
       }
     }
 
     MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
 
     RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
     aRequest->mModuleScript = moduleScript;
@@ -865,23 +864,16 @@ public:
 };
 
 void
 ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
 {
   MOZ_ASSERT(aRequest->IsReadyToRun());
 
   if (aRequest->IsTopLevel()) {
-    ModuleScript* moduleScript = aRequest->mModuleScript;
-    if (moduleScript && !moduleScript->HasErrorToRethrow()) {
-      if (!InstantiateModuleTree(aRequest)) {
-        aRequest->mModuleScript = nullptr;
-      }
-    }
-
     if (aRequest->mIsInline &&
         aRequest->mElement->GetParserCreated() == NOT_FROM_PARSER)
     {
       MOZ_ASSERT(!aRequest->isInList());
       nsContentUtils::AddScriptRunner(
         new ScriptRequestProcessor(this, aRequest));
     } else {
       MaybeMoveToLoadedList(aRequest);
@@ -1773,24 +1765,26 @@ OffThreadScriptLoaderCallback(JS::OffThr
 {
   RefPtr<NotifyOffThreadScriptLoadCompletedRunnable> aRunnable =
     dont_AddRef(static_cast<NotifyOffThreadScriptLoadCompletedRunnable*>(aCallbackData));
   aRunnable->SetToken(aToken);
   NotifyOffThreadScriptLoadCompletedRunnable::Dispatch(aRunnable.forget());
 }
 
 nsresult
-ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest)
+ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
+                                        bool* aCouldCompileOut)
 {
   MOZ_ASSERT_IF(!aRequest->IsModuleRequest(), aRequest->IsReadyToRun());
   MOZ_ASSERT(!aRequest->mWasCompiledOMT);
+  MOZ_ASSERT(aCouldCompileOut && !*aCouldCompileOut);
 
   // Don't off-thread compile inline scripts.
   if (aRequest->mIsInline) {
-    return NS_ERROR_FAILURE;
+    return NS_OK;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> globalObject = GetScriptGlobalObject();
   if (!globalObject) {
     return NS_ERROR_FAILURE;
   }
 
   AutoJSAPI jsapi;
@@ -1804,40 +1798,40 @@ ScriptLoader::AttemptAsyncScriptCompile(
 
   nsresult rv = FillCompileOptionsForRequest(jsapi, aRequest, global, &options);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (aRequest->IsTextSource()) {
     if (!JS::CanCompileOffThread(cx, options, aRequest->ScriptText().length())) {
-      return NS_ERROR_FAILURE;
+      return NS_OK;
     }
 #ifdef JS_BUILD_BINAST
   } else if (aRequest->IsBinASTSource()) {
     if (!JS::CanDecodeBinASTOffThread(cx, options, aRequest->ScriptBinASTData().length())) {
-      return NS_ERROR_FAILURE;
+      return NS_OK;
     }
 #endif
   } else {
     MOZ_ASSERT(aRequest->IsBytecode());
     size_t length = aRequest->mScriptBytecode.length() - aRequest->mBytecodeOffset;
     if (!JS::CanDecodeOffThread(cx, options, length)) {
-      return NS_ERROR_FAILURE;
+      return NS_OK;
     }
   }
 
   RefPtr<NotifyOffThreadScriptLoadCompletedRunnable> runnable =
     new NotifyOffThreadScriptLoadCompletedRunnable(aRequest, this);
 
   if (aRequest->IsModuleRequest()) {
     MOZ_ASSERT(aRequest->IsTextSource());
+    SourceBufferHolder srcBuf = GetScriptSource(cx, aRequest);
     if (!JS::CompileOffThreadModule(cx, options,
-                                    aRequest->ScriptText().begin(),
-                                    aRequest->ScriptText().length(),
+                                    srcBuf,
                                     OffThreadScriptLoaderCallback,
                                     static_cast<void*>(runnable))) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   } else if (aRequest->IsBytecode()) {
     if (!JS::DecodeOffThreadScript(cx, options,
                                    aRequest->mScriptBytecode,
                                    aRequest->mBytecodeOffset,
@@ -1853,93 +1847,110 @@ ScriptLoader::AttemptAsyncScriptCompile(
                                    aRequest->ScriptBinASTData().length(),
                                    OffThreadScriptLoaderCallback,
                                    static_cast<void*>(runnable))) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 #endif
   } else {
     MOZ_ASSERT(aRequest->IsTextSource());
+    SourceBufferHolder srcBuf = GetScriptSource(cx, aRequest);
     if (!JS::CompileOffThread(cx, options,
-                              aRequest->ScriptText().begin(),
-                              aRequest->ScriptText().length(),
+                              srcBuf,
                               OffThreadScriptLoaderCallback,
                               static_cast<void*>(runnable))) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   mDocument->BlockOnload();
 
   // Once the compilation is finished, an event would be added to the event loop
   // to call ScriptLoader::ProcessOffThreadRequest with the same request.
   aRequest->mProgress = ScriptLoadRequest::Progress::eCompiling;
 
+  *aCouldCompileOut = true;
   Unused << runnable.forget();
   return NS_OK;
 }
 
 nsresult
 ScriptLoader::CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest)
 {
   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
                "Processing requests when running scripts is unsafe.");
   NS_ASSERTION(!aRequest->mOffThreadToken,
                "Candidate for off-thread compile is already parsed off-thread");
   NS_ASSERTION(!aRequest->InCompilingStage(),
                "Candidate for off-thread compile is already in compiling stage.");
 
-  nsresult rv = AttemptAsyncScriptCompile(aRequest);
-  if (NS_SUCCEEDED(rv)) {
+  bool couldCompile = false;
+  nsresult rv = AttemptAsyncScriptCompile(aRequest, &couldCompile);
+  if (NS_FAILED(rv)) {
+    HandleLoadError(aRequest, rv);
     return rv;
   }
 
+  if (couldCompile) {
+    return NS_OK;
+  }
+
   return ProcessRequest(aRequest);
 }
 
 SourceBufferHolder
-ScriptLoader::GetScriptSource(ScriptLoadRequest* aRequest, nsAutoString& inlineData)
+ScriptLoader::GetScriptSource(JSContext* aCx, ScriptLoadRequest* aRequest)
 {
   // Return a SourceBufferHolder object holding the script's source text.
-  // |inlineData| is used to hold the text for inline objects.
+  // Ownership of the buffer is transferred to the resulting SourceBufferHolder.
 
   // If there's no script text, we try to get it from the element
   if (aRequest->mIsInline) {
-    // XXX This is inefficient - GetText makes multiple
-    // copies.
+    nsAutoString inlineData;
     aRequest->mElement->GetScriptText(inlineData);
-    return SourceBufferHolder(inlineData.get(),
-                              inlineData.Length(),
-                              SourceBufferHolder::NoOwnership);
+
+    size_t nbytes = inlineData.Length() * sizeof(char16_t);
+    JS::UniqueTwoByteChars chars(static_cast<char16_t*>(JS_malloc(aCx, nbytes)));
+    MOZ_RELEASE_ASSERT(chars);
+    memcpy(chars.get(), inlineData.get(), nbytes);
+    return SourceBufferHolder(std::move(chars), inlineData.Length());
   }
 
-  return SourceBufferHolder(aRequest->ScriptText().begin(),
-                            aRequest->ScriptText().length(),
-                            SourceBufferHolder::NoOwnership);
+  size_t length = aRequest->ScriptText().length();
+  return SourceBufferHolder(aRequest->ScriptText().extractOrCopyRawBuffer(),
+                            length,
+                            SourceBufferHolder::GiveOwnership);
 }
 
 nsresult
 ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest)
 {
   LOG(("ScriptLoadRequest (%p): Process request", aRequest));
 
   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
                "Processing requests when running scripts is unsafe.");
   NS_ASSERTION(aRequest->IsReadyToRun(),
                "Processing a request that is not ready to run.");
 
   NS_ENSURE_ARG(aRequest);
 
-  if (aRequest->IsModuleRequest() &&
-      !aRequest->AsModuleRequest()->mModuleScript)
-  {
-    // There was an error fetching a module script.  Nothing to do here.
-    LOG(("ScriptLoadRequest (%p):   Error loading request, firing error", aRequest));
-    FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
-    return NS_OK;
+  if (aRequest->IsModuleRequest()) {
+    ModuleLoadRequest* request = aRequest->AsModuleRequest();
+    if (request->mModuleScript && !request->mModuleScript->HasErrorToRethrow()) {
+      if (!InstantiateModuleTree(request)) {
+        request->mModuleScript = nullptr;
+      }
+    }
+
+    if (!request->mModuleScript) {
+      // There was an error fetching a module script.  Nothing to do here.
+      LOG(("ScriptLoadRequest (%p):   Error loading request, firing error", aRequest));
+      FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
+      return NS_OK;
+    }
   }
 
   nsCOMPtr<nsINode> scriptElem = do_QueryInterface(aRequest->mElement);
 
   nsCOMPtr<nsIDocument> doc;
   if (!aRequest->mIsInline) {
     doc = scriptElem->OwnerDoc();
   }
@@ -2181,17 +2192,17 @@ ScriptLoader::ShouldCacheBytecode(Script
 
   // If the script is too small/large, do not attempt at creating a bytecode
   // cache for this script, as the overhead of parsing it might not be worth the
   // effort.
   if (hasSourceLengthMin) {
     size_t sourceLength;
     size_t minLength;
     if (aRequest->IsTextSource()) {
-      sourceLength = aRequest->ScriptText().length();
+      sourceLength = aRequest->mScriptTextLength;
       minLength = sourceLengthMin;
     } else {
       MOZ_ASSERT(aRequest->IsBinASTSource());
       sourceLength = aRequest->ScriptBinASTData().length();
       minLength = binASTLengthMin;
     }
     if (sourceLength < minLength) {
       LOG(("ScriptLoadRequest (%p): Bytecode-cache: Script is too small.", aRequest));
@@ -2353,18 +2364,17 @@ ScriptLoader::EvaluateScript(ScriptLoadR
               LOG(("ScriptLoadRequest (%p): Compile And Exec", aRequest));
               if (aRequest->IsBinASTSource()) {
                 rv = exec.DecodeBinASTAndExec(options,
                                               aRequest->ScriptBinASTData().begin(),
                                               aRequest->ScriptBinASTData().length(),
                                               &script);
               } else {
                 MOZ_ASSERT(aRequest->IsTextSource());
-                nsAutoString inlineData;
-                SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
+                SourceBufferHolder srcBuf = GetScriptSource(cx, aRequest);
 
                 if (recordreplay::IsRecordingOrReplaying()) {
                   recordreplay::NoteContentParse(this, options.filename(), "application/javascript",
                                                  srcBuf.get(), srcBuf.length());
                 }
 
                 rv = exec.CompileAndExec(options, srcBuf, &script);
               }
@@ -3189,45 +3199,43 @@ ScriptLoader::PrepareLoadedRequest(Scrip
     // Fixup moz-extension: and resource: URIs, because the channel URI will
     // point to file:, which won't be allowed to load.
     if (uri && IsInternalURIScheme(uri)) {
       request->mBaseURL = uri;
     } else {
       channel->GetURI(getter_AddRefs(request->mBaseURL));
     }
 
-
     // Attempt to compile off main thread.
-    rv = AttemptAsyncScriptCompile(request);
-    if (NS_SUCCEEDED(rv)) {
-      return rv;
+    bool couldCompile = false;
+    rv = AttemptAsyncScriptCompile(request, &couldCompile);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (couldCompile) {
+      return NS_OK;
     }
 
     // Otherwise compile it right away and start fetching descendents.
     return ProcessFetchedModuleSource(request);
   }
 
   // The script is now loaded and ready to run.
   aRequest->SetReady();
 
   // If this is currently blocking the parser, attempt to compile it off-main-thread.
   if (aRequest == mParserBlockingRequest && NumberOfProcessors() > 1) {
     MOZ_ASSERT(!aRequest->IsModuleRequest());
-    nsresult rv = AttemptAsyncScriptCompile(aRequest);
-    if (rv == NS_OK) {
+    bool couldCompile = false;
+    nsresult rv = AttemptAsyncScriptCompile(aRequest, &couldCompile);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (couldCompile) {
       MOZ_ASSERT(aRequest->mProgress == ScriptLoadRequest::Progress::eCompiling,
                  "Request should be off-thread compiling now.");
       return NS_OK;
     }
 
-    // If off-thread compile errored, return the error.
-    if (rv != NS_ERROR_FAILURE) {
-      return rv;
-    }
-
     // If off-thread compile was rejected, continue with regular processing.
   }
 
   MaybeMoveToLoadedList(aRequest);
 
   return NS_OK;
 }
 
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -449,17 +449,18 @@ private:
                      nsresult aSRIStatus,
                      SRICheckDataVerifier* aSRIDataVerifier) const;
 
   nsresult SaveSRIHash(ScriptLoadRequest *aRequest,
                        SRICheckDataVerifier* aSRIDataVerifier) const;
 
   void ReportErrorToConsole(ScriptLoadRequest *aRequest, nsresult aResult) const;
 
-  nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
+  nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
+                                     bool* aCouldCompileOut);
   nsresult ProcessRequest(ScriptLoadRequest* aRequest);
   nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
   void FireScriptAvailable(nsresult aResult,
                            ScriptLoadRequest* aRequest);
   void FireScriptEvaluated(nsresult aResult,
                            ScriptLoadRequest* aRequest);
   nsresult EvaluateScript(ScriptLoadRequest* aRequest);
 
@@ -499,18 +500,18 @@ private:
                                 nsresult aStatus);
 
   void AddDeferRequest(ScriptLoadRequest* aRequest);
   void AddAsyncRequest(ScriptLoadRequest* aRequest);
   bool MaybeRemovedDeferRequests();
 
   void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
 
-  JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
-                                         nsAutoString& inlineData);
+  JS::SourceBufferHolder GetScriptSource(JSContext* aCx,
+                                         ScriptLoadRequest* aRequest);
 
   void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
   void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest* aRequest,
                                                       nsresult aResult);
 
   bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
 
   bool ModuleMapContainsURL(nsIURI* aURL) const;
--- a/dom/serviceworkers/ServiceWorkerScriptCache.cpp
+++ b/dom/serviceworkers/ServiceWorkerScriptCache.cpp
@@ -50,16 +50,20 @@ CreateCacheStorage(JSContext* aCx, nsIPr
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   MOZ_ASSERT(xpc, "This should never be null!");
   JS::Rooted<JSObject*> sandbox(aCx);
   aRv = xpc->CreateSandbox(aCx, aPrincipal, sandbox.address());
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
+  // This is called when the JSContext is not in a realm, so CreateSandbox
+  // returned an unwrapped global.
+  MOZ_ASSERT(JS_IsGlobalObject(sandbox));
+
   nsCOMPtr<nsIGlobalObject> sandboxGlobalObject = xpc::NativeGlobal(sandbox);
   if (!sandboxGlobalObject) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   // We assume private browsing is not enabled here.  The ScriptLoader
   // explicitly fails for private browsing so there should never be
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -207,24 +207,22 @@ void SVGAElement::SetText(const nsAStrin
   rv = nsContentUtils::SetNodeTextContent(this, aText, false);
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 SVGAElement::BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                        nsIContent *aBindingParent,
-                        bool aCompileEventHandlers)
+                        nsIContent *aBindingParent)
 {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = SVGAElementBase::BindToTree(aDocument, aParent,
-                                            aBindingParent,
-                                            aCompileEventHandlers);
+                                            aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     doc->RegisterPendingLinkUpdate(this);
   }
 
   return NS_OK;
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -44,18 +44,17 @@ public:
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent *aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual int32_t TabIndexDefault() override;
   virtual bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -156,24 +156,22 @@ SVGAnimationElement::GetSimpleDuration(E
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 SVGAnimationElement::BindToTree(nsIDocument* aDocument,
                                 nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers)
+                                nsIContent* aBindingParent)
 {
   MOZ_ASSERT(!mHrefTarget.get(),
              "Shouldn't have href-target yet (or it should've been cleared)");
   nsresult rv = SVGAnimationElementBase::BindToTree(aDocument, aParent,
-                                                    aBindingParent,
-                                                    aCompileEventHandlers);
+                                                    aBindingParent);
   NS_ENSURE_SUCCESS(rv,rv);
 
   // Add myself to the animation controller's master set of animation elements.
   if (nsIDocument* doc = GetComposedDoc()) {
     nsSMILAnimationController* controller = doc->GetAnimationController();
     if (controller) {
       controller->RegisterAnimationElement(this);
     }
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -39,18 +39,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAnimationElement,
                                            SVGAnimationElementBase)
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override = 0;
 
   // nsIContent specializations
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   // Element specializations
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
--- a/dom/svg/SVGFEImageElement.cpp
+++ b/dom/svg/SVGFEImageElement.cpp
@@ -151,26 +151,23 @@ SVGFEImageElement::MaybeLoadSVGImage()
       (NS_FAILED(LoadSVGImage(false, true)) ||
        !LoadingEnabled())) {
     CancelImageRequests(true);
   }
 }
 
 nsresult
 SVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+                              nsIContent* aBindingParent)
 {
   nsresult rv = SVGFEImageElementBase::BindToTree(aDocument, aParent,
-                                                  aBindingParent,
-                                                  aCompileEventHandlers);
+                                                  aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
-                                    aCompileEventHandlers);
+  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (mStringAttributes[HREF].IsExplicitlySet() ||
       mStringAttributes[XLINK_HREF].IsExplicitlySet()) {
     // FIXME: Bug 660963 it would be nice if we could just have
     // ClearBrokenState update our state and do it fast...
     ClearBrokenState();
     RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
     nsContentUtils::AddScriptRunner(
--- a/dom/svg/SVGFEImageElement.h
+++ b/dom/svg/SVGFEImageElement.h
@@ -59,18 +59,17 @@ public:
                          bool aPreallocateChildren) const override;
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual EventStates IntrinsicState() const override;
 
   NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) override;
 
   void MaybeLoadSVGImage();
 
   // WebIDL
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -182,26 +182,23 @@ SVGImageElement::MaybeLoadSVGImage()
       (NS_FAILED(LoadSVGImage(false, true)) ||
        !LoadingEnabled())) {
     CancelImageRequests(true);
   }
 }
 
 nsresult
 SVGImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   nsresult rv = SVGImageElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
-                                    aCompileEventHandlers);
+  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent);
 
   if (mStringAttributes[HREF].IsExplicitlySet() ||
       mStringAttributes[XLINK_HREF].IsExplicitlySet()) {
     // FIXME: Bug 660963 it would be nice if we could just have
     // ClearBrokenState update our state and do it fast...
     ClearBrokenState();
     RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
     nsContentUtils::AddScriptRunner(
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -46,18 +46,17 @@ public:
 
   // nsIContent interface
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual EventStates IntrinsicState() const override;
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* name) const override;
 
   // SVGGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
--- a/dom/svg/SVGMPathElement.cpp
+++ b/dom/svg/SVGMPathElement.cpp
@@ -77,24 +77,22 @@ SVGMPathElement::Href()
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 SVGMPathElement::BindToTree(nsIDocument* aDocument,
                             nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   MOZ_ASSERT(!mPathTracker.get(),
              "Shouldn't have href-target yet (or it should've been cleared)");
   nsresult rv = SVGMPathElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv,rv);
 
   if (aDocument) {
     const nsAttrValue* hrefAttrValue =
       HasAttr(kNameSpaceID_None, nsGkAtoms::href)
       ? mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_None)
       : mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink);
     if (hrefAttrValue) {
--- a/dom/svg/SVGMPathElement.h
+++ b/dom/svg/SVGMPathElement.h
@@ -40,18 +40,17 @@ public:
                                            SVGMPathElementBase)
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
   // nsIContent interface
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   // Element specializations
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -461,18 +461,17 @@ SVGSVGElement::GetTimedDocumentRoot()
   // invalid structure
   return nullptr;
 }
 //----------------------------------------------------------------------
 // nsSVGElement
 nsresult
 SVGSVGElement::BindToTree(nsIDocument* aDocument,
                           nsIContent* aParent,
-                          nsIContent* aBindingParent,
-                          bool aCompileEventHandlers)
+                          nsIContent* aBindingParent)
 {
   nsSMILAnimationController* smilController = nullptr;
 
   if (aDocument) {
     smilController = aDocument->GetAnimationController();
     if (smilController) {
       // SMIL is enabled in this document
       if (WillBeOutermostSVG(aParent, aBindingParent)) {
@@ -486,18 +485,17 @@ SVGSVGElement::BindToTree(nsIDocument* a
         // kick-start if we get promoted to be outermost later on.
         mTimedDocumentRoot = nullptr;
         mStartAnimationOnBindToTree = true;
       }
     }
   }
 
   nsresult rv = SVGGraphicsElement::BindToTree(aDocument, aParent,
-                                              aBindingParent,
-                                              aCompileEventHandlers);
+                                              aBindingParent);
   NS_ENSURE_SUCCESS(rv,rv);
 
   if (mTimedDocumentRoot && smilController) {
     rv = mTimedDocumentRoot->SetParent(smilController);
     if (mStartAnimationOnBindToTree) {
       mTimedDocumentRoot->Begin();
       mStartAnimationOnBindToTree = false;
     }
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -140,18 +140,17 @@ public:
   already_AddRefed<SVGTransform> CreateSVGTransformFromMatrix(SVGMatrix& matrix);
   using nsINode::GetElementById; // This does what we want
   uint16_t ZoomAndPan();
   void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
 
   // nsSVGElement overrides
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual nsSVGAnimatedTransformList*
     GetAnimatedTransformList(uint32_t aFlags = 0) override;
 
   // SVGSVGElement methods:
 
   // Returns true IFF our attributes are currently overridden by a <view>
   // element and that element's ID matches the passed-in string.
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -209,22 +209,20 @@ SVGScriptElement::GetStringInfo()
                               ArrayLength(sStringInfo));
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 SVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent* aBindingParent)
 {
   nsresult rv = SVGScriptElementBase::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
+                                                 aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     MaybeProcessScript();
   }
 
   return NS_OK;
 }
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -47,18 +47,17 @@ public:
   virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
   virtual CORSMode GetCORSMode() const override;
 
   // ScriptElement
   virtual bool HasScriptContent() override;
 
   // nsIContent specializations:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -60,22 +60,20 @@ SVGStyleElement::~SVGStyleElement()
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGStyleElement)
 
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 SVGStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
   nsresult rv = SVGStyleElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   void (SVGStyleElement::*update)() = &SVGStyleElement::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(
     NewRunnableMethod("dom::SVGStyleElement::BindToTree", this, update));
 
   return rv;
 }
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -35,18 +35,17 @@ protected:
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGStyleElement,
                                            SVGStyleElementBase)
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
--- a/dom/svg/SVGTitleElement.cpp
+++ b/dom/svg/SVGTitleElement.cpp
@@ -61,23 +61,21 @@ SVGTitleElement::ContentRemoved(nsIConte
                                 nsIContent* aPreviousSibling)
 {
   SendTitleChangeEvent(false);
 }
 
 nsresult
 SVGTitleElement::BindToTree(nsIDocument *aDocument,
                              nsIContent *aParent,
-                             nsIContent *aBindingParent,
-                             bool aCompileEventHandlers)
+                             nsIContent *aBindingParent)
 {
   // Let this fall through.
   nsresult rv = SVGTitleElementBase::BindToTree(aDocument, aParent,
-                                                aBindingParent,
-                                                aCompileEventHandlers);
+                                                aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SendTitleChangeEvent(true);
 
   return NS_OK;
 }
 
 void
--- a/dom/svg/SVGTitleElement.h
+++ b/dom/svg/SVGTitleElement.h
@@ -39,18 +39,17 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent *aBindingParent) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
 private:
   void SendTitleChangeEvent(bool aBound);
 };
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -111,20 +111,19 @@ SVGUseElement::Clone(mozilla::dom::NodeI
   }
 
   return NS_FAILED(rv1) ? rv1 : rv2;
 }
 
 nsresult
 SVGUseElement::BindToTree(nsIDocument* aDocument,
                           nsIContent* aParent,
-                          nsIContent* aBindingParent,
-                          bool aCompileEventHandlers)
+                          nsIContent* aBindingParent)
 {
-  nsresult rv = SVGUseElementBase::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers);
+  nsresult rv = SVGUseElementBase::BindToTree(aDocument, aParent, aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   TriggerReclone();
   return NS_OK;
 }
 
 void
 SVGUseElement::UnbindFromTree(bool aDeep, bool aNullParent)
--- a/dom/svg/SVGUseElement.h
+++ b/dom/svg/SVGUseElement.h
@@ -43,18 +43,17 @@ protected:
   virtual ~SVGUseElement();
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   NS_IMPL_FROMNODE_WITH_TAG(SVGUseElement, kNameSpaceID_SVG, use)
 
   nsresult BindToTree(nsIDocument* aDocument,
                       nsIContent* aParent,
-                      nsIContent* aBindingParent,
-                      bool aCompileEventHandlers) override;
+                      nsIContent* aBindingParent) override;
   void UnbindFromTree(bool aDeep = true,
                       bool aNullParent = true) override;
 
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGUseElement, SVGUseElementBase)
 
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -230,22 +230,20 @@ nsSVGElement::Init()
 //----------------------------------------------------------------------
 // Implementation
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                         nsIContent* aBindingParent,
-                         bool aCompileEventHandlers)
+                         nsIContent* aBindingParent)
 {
   nsresult rv = nsSVGElementBase::BindToTree(aDocument, aParent,
-                                             aBindingParent,
-                                             aCompileEventHandlers);
+                                             aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
   if (oldVal && oldVal->Type() == nsAttrValue::eCSSDeclaration) {
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -90,19 +90,19 @@ public:
 
   // nsISupports
   NS_INLINE_DECL_REFCOUNTING_INHERITED(nsSVGElement, nsSVGElementBase)
 
   void DidAnimateClass();
 
   // nsIContent interface methods
 
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+  virtual nsresult BindToTree(nsIDocument* aDocument,
+                              nsIContent* aParent,
+                              nsIContent* aBindingParent) override;
 
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   /**
    * We override the default to unschedule computation of Servo declaration blocks
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -1509,23 +1509,29 @@ CacheCreator::CreateCacheStorage(nsIPrin
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(!mCacheStorage);
   MOZ_ASSERT(aPrincipal);
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   MOZ_ASSERT(xpc, "This should never be null!");
 
-  mozilla::AutoSafeJSContext cx;
+  AutoJSAPI jsapi;
+  jsapi.Init();
+  JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> sandbox(cx);
   nsresult rv = xpc->CreateSandbox(cx, aPrincipal, sandbox.address());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  // The JSContext is not in a realm, so CreateSandbox returned an unwrapped
+  // global.
+  MOZ_ASSERT(JS_IsGlobalObject(sandbox));
+
   mSandboxGlobalObject = xpc::NativeGlobal(sandbox);
   if (NS_WARN_IF(!mSandboxGlobalObject)) {
     return NS_ERROR_FAILURE;
   }
 
   // If we're in private browsing mode, don't even try to create the
   // CacheStorage.  Instead, just fail immediately to terminate the
   // ServiceWorker load.
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -4860,18 +4860,19 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
       uint32_t lineNo = 0, dummyColumn = 0;
       info->mHandler->GetLocation(&filename, &lineNo, &dummyColumn);
 
       JS::CompileOptions options(aes.cx());
       options.setFileAndLine(filename, lineNo).setNoScriptRval(true);
 
       JS::Rooted<JS::Value> unused(aes.cx());
 
-      if (!JS::Evaluate(aes.cx(), options, script.BeginReading(),
-                        script.Length(), &unused) &&
+      JS::SourceBufferHolder srcBuf(script.BeginReading(), script.Length(),
+                                    JS::SourceBufferHolder::NoOwnership);
+      if (!JS::Evaluate(aes.cx(), options, srcBuf, &unused) &&
           !JS_IsExceptionPending(aCx)) {
         retval = false;
         break;
       }
     } else {
       ErrorResult rv;
       JS::Rooted<JS::Value> ignoredVal(aCx);
       callback->Call(GlobalScope(), info->mHandler->GetArgs(), &ignoredVal, rv,
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -198,30 +198,29 @@ nsXBLBinding::BindAnonymousContent(nsICo
   // element's document, assuming that the bound element is in a document
   // Note that we don't change the current doc of aAnonParent here, since that
   // quite simply does not matter.  aAnonParent is just a way of keeping refs
   // to all its kids, which are anonymous content from the point of view of
   // aElement.
   // (2) The children's parent back pointer should not be to this synthetic root
   // but should instead point to the enclosing parent element.
   nsIDocument* doc = aElement->GetUncomposedDoc();
-  bool allowScripts = AllowScripts();
 
   nsAutoScriptBlocker scriptBlocker;
   for (nsIContent* child = aAnonParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     child->UnbindFromTree();
     if (aChromeOnlyContent) {
       child->SetFlags(NODE_CHROME_ONLY_ACCESS |
                       NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS);
     }
     child->SetFlags(NODE_IS_ANONYMOUS_ROOT);
     nsresult rv =
-      child->BindToTree(doc, aElement, mBoundElement, allowScripts);
+      child->BindToTree(doc, aElement, mBoundElement);
     if (NS_FAILED(rv)) {
       // Oh, well... Just give up.
       // XXXbz This really shouldn't be a void method!
       child->UnbindFromTree();
       return;
     }
 
 #ifdef MOZ_XUL
--- a/dom/xml/XMLStylesheetProcessingInstruction.cpp
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -34,22 +34,20 @@ XMLStylesheetProcessingInstruction::~XML
 {
 }
 
 // nsIContent
 
 nsresult
 XMLStylesheetProcessingInstruction::BindToTree(nsIDocument* aDocument,
                                                nsIContent* aParent,
-                                               nsIContent* aBindingParent,
-                                               bool aCompileEventHandlers)
+                                               nsIContent* aBindingParent)
 {
   nsresult rv = ProcessingInstruction::BindToTree(aDocument, aParent,
-                                                  aBindingParent,
-                                                  aCompileEventHandlers);
+                                                  aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   void (XMLStylesheetProcessingInstruction::*update)() =
     &XMLStylesheetProcessingInstruction::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(NewRunnableMethod(
     "dom::XMLStylesheetProcessingInstruction::BindToTree", this, update));
 
   return rv;
--- a/dom/xml/XMLStylesheetProcessingInstruction.h
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -44,18 +44,17 @@ public:
                                            ProcessingInstruction)
 
   // nsINode
   virtual void SetNodeValueInternal(const nsAString& aNodeValue,
                                     mozilla::ErrorResult& aError) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   // nsIStyleSheetLinkingElement
   virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override;
 
   // nsStyleLinkElement
   void GetCharset(nsAString& aCharset) override;
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -2236,25 +2236,20 @@ XULDocument::OnStreamComplete(nsIStreamL
                                           mOffThreadCompileStringLength,
                                           JS::SourceBufferHolder::GiveOwnership);
             mOffThreadCompileStringBuf = nullptr;
             mOffThreadCompileStringLength = 0;
 
             rv = mCurrentScriptProto->Compile(srcBuf, uri, 1, this, this);
             if (NS_SUCCEEDED(rv) && !mCurrentScriptProto->HasScriptObject()) {
                 // We will be notified via OnOffThreadCompileComplete when the
-                // compile finishes. Keep the contents of the compiled script
-                // alive until the compilation finishes.
+                // compile finishes. The JS engine has taken ownership of the
+                // source buffer.
+                MOZ_RELEASE_ASSERT(!srcBuf.ownsChars());
                 mOffThreadCompiling = true;
-                // If the JS engine did not take the source buffer, then take
-                // it back here to ensure it remains alive.
-                mOffThreadCompileStringBuf = srcBuf.take();
-                if (mOffThreadCompileStringBuf) {
-                  mOffThreadCompileStringLength = srcBuf.length();
-                }
                 BlockOnload();
                 return NS_OK;
             }
         }
     }
 
     return OnScriptCompileComplete(mCurrentScriptProto->GetScriptObject(), rv);
 }
--- a/dom/xul/XULFrameElement.cpp
+++ b/dom/xul/XULFrameElement.cpp
@@ -144,20 +144,19 @@ XULFrameElement::SwapFrameLoaders(nsIFra
   }
 
   rv = loader->SwapWithOtherLoader(otherLoader, this, aOtherLoaderOwner);
 }
 
 nsresult
 XULFrameElement::BindToTree(nsIDocument* aDocument,
                             nsIContent* aParent,
-                            nsIContent* aBindingParent,
-                            bool aCompileEventHandlers)
+                            nsIContent* aBindingParent)
 {
-  nsresult rv = nsXULElement::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers);
+  nsresult rv = nsXULElement::BindToTree(aDocument, aParent, aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                  "Missing a script blocker!");
     // We're in a document now.  Kick off the frame load.
     LoadSrc();
   }
--- a/dom/xul/XULFrameElement.h
+++ b/dom/xul/XULFrameElement.h
@@ -59,18 +59,17 @@ public:
                         mozilla::ErrorResult& rv);
   void SwapFrameLoaders(XULFrameElement& aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
   void SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) override;
+                              nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual void DestroyContent() override;
 
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -193,18 +193,17 @@ nsXULElement::CreateFromPrototype(nsXULP
         }
 
         element->MakeHeavyweight(aPrototype);
         if (aIsScriptable) {
             // Check each attribute on the prototype to see if we need to do
             // any additional processing and hookup that would otherwise be
             // done 'automagically' by SetAttr().
             for (uint32_t i = 0; i < aPrototype->mNumAttributes; ++i) {
-                element->AddListenerFor(aPrototype->mAttributes[i].mName,
-                                        true);
+                element->AddListenerFor(aPrototype->mAttributes[i].mName);
             }
         }
 
         if (aIsRoot && aPrototype->mNodeInfo->Equals(nsGkAtoms::window)) {
             for (uint32_t i = 0; i < aPrototype->mNumAttributes; ++i) {
                 if (aPrototype->mAttributes[i].mName.Equals(nsGkAtoms::windowtype)) {
                     element->MaybeUpdatePrivateLifetime();
                 }
@@ -349,17 +348,17 @@ nsXULElement::Clone(mozilla::dom::NodeIn
                                                           attrValue,
                                                           &oldValueSet);
         } else {
             rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
                                                            attrValue,
                                                            &oldValueSet);
         }
         NS_ENSURE_SUCCESS(rv, rv);
-        element->AddListenerFor(*originalName, true);
+        element->AddListenerFor(*originalName);
         if (originalName->Equals(nsGkAtoms::id) &&
             !originalValue->IsEmptyString()) {
             element->SetHasID();
         }
         if (originalName->Equals(nsGkAtoms::_class)) {
             element->SetMayHaveClass();
         }
         if (originalName->Equals(nsGkAtoms::style)) {
@@ -569,28 +568,26 @@ nsXULElement::PerformAccesskey(bool aKey
     }
 
     return focused;
 }
 
 //----------------------------------------------------------------------
 
 void
-nsXULElement::AddListenerFor(const nsAttrName& aName,
-                             bool aCompileEventHandlers)
+nsXULElement::AddListenerFor(const nsAttrName& aName)
 {
     // If appropriate, add a popup listener and/or compile the event
     // handler. Called when we change the element's document, create a
     // new element, change an attribute's value, etc.
     // Eventlistenener-attributes are always in the null namespace
     if (aName.IsAtom()) {
         nsAtom *attr = aName.Atom();
         MaybeAddPopupListener(attr);
-        if (aCompileEventHandlers &&
-            nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
+        if (nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             nsAutoString value;
             GetAttr(kNameSpaceID_None, attr, value);
             SetEventHandler(attr, value, true);
         }
     }
 }
 
 void
@@ -674,30 +671,27 @@ NeedTooltipSupport(const nsXULElement& a
 
   return aXULElement.GetBoolAttr(nsGkAtoms::tooltip) ||
          aXULElement.GetBoolAttr(nsGkAtoms::tooltiptext);
 }
 
 nsresult
 nsXULElement::BindToTree(nsIDocument* aDocument,
                          nsIContent* aParent,
-                         nsIContent* aBindingParent,
-                         bool aCompileEventHandlers)
+                         nsIContent* aBindingParent)
 {
   if (!aBindingParent &&
       aDocument &&
       !aDocument->IsLoadedAsInteractiveData() &&
       !aDocument->AllowXULXBL() &&
       !aDocument->HasWarnedAbout(nsIDocument::eImportXULIntoContent)) {
     nsContentUtils::AddScriptRunner(new XULInContentErrorReporter(aDocument));
   }
 
-  nsresult rv = nsStyledElement::BindToTree(aDocument, aParent,
-                                            aBindingParent,
-                                            aCompileEventHandlers);
+  nsresult rv = nsStyledElement::BindToTree(aDocument, aParent, aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIDocument* doc = GetComposedDoc();
 #ifdef DEBUG
   if (doc && !doc->AllowXULXBL() && !doc->IsUnstyledDocument()) {
     // To save CPU cycles and memory, non-XUL documents only load the user
     // agent style sheet rules for a minimal set of XUL elements such as
     // 'scrollbar' that may be created implicitly for their content (those
@@ -2252,17 +2246,17 @@ nsXULPrototypeScript::Compile(JS::Source
     options.setSourceIsLazy(mOutOfLine);
     JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
     if (scope) {
       JS::ExposeObjectToActiveJS(scope);
     }
 
     if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aSrcBuf.length())) {
         if (!JS::CompileOffThread(cx, options,
-                                  aSrcBuf.get(), aSrcBuf.length(),
+                                  aSrcBuf,
                                   OffThreadScriptReceiverCallback,
                                   static_cast<void*>(aOffThreadReceiver))) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
         NotifyOffThreadScriptCompletedRunnable::NoteReceiver(aOffThreadReceiver);
     } else {
         JS::Rooted<JSScript*> script(cx);
         if (!JS::Compile(cx, options, aSrcBuf, &script))
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -357,19 +357,19 @@ public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
 
     // nsINode
     void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
     virtual nsresult PreHandleEvent(
                        mozilla::EventChainVisitor& aVisitor) override;
     // nsIContent
-    virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                                nsIContent* aBindingParent,
-                                bool aCompileEventHandlers) override;
+    virtual nsresult BindToTree(nsIDocument* aDocument,
+                                nsIContent* aParent,
+                                nsIContent* aBindingParent) override;
     virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
     virtual void DestroyContent() override;
 
 #ifdef DEBUG
     virtual void List(FILE* out, int32_t aIndent) const override;
     virtual void DumpContent(FILE* out, int32_t aIndent,bool aDumpAll) const override
     {
     }
@@ -667,18 +667,17 @@ protected:
 
     virtual mozilla::EventListenerManager*
       GetEventListenerManagerForAttr(nsAtom* aAttrName,
                                      bool* aDefer) override;
 
     /**
      * Add a listener for the specified attribute, if appropriate.
      */
-    void AddListenerFor(const nsAttrName& aName,
-                        bool aCompileEventHandlers);
+    void AddListenerFor(const nsAttrName& aName);
     void MaybeAddPopupListener(nsAtom* aLocalName);
 
     nsIWidget* GetWindowWidget();
 
     // attribute setters for widget
     nsresult HideWindowChrome(bool aShouldHide);
     void SetChromeMargins(const nsAttrValue* aValue);
     void ResetChromeMargins();
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
@@ -110,18 +110,19 @@ ElementDeletionObserver::ParentChainChan
       mNativeAnonNode = nullptr;
       NS_RELEASE_THIS();
       return;
     }
 
     // We're staying in the same document, just rebind the native anonymous
     // node so that the subtree root points to the right object etc.
     mNativeAnonNode->UnbindFromTree();
-    mNativeAnonNode->BindToTree(mObservedNode->GetUncomposedDoc(), mObservedNode,
-                                mObservedNode, true);
+    mNativeAnonNode->BindToTree(mObservedNode->GetUncomposedDoc(),
+                                mObservedNode,
+                                mObservedNode);
   }
 }
 
 void
 ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode)
 {
   NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedNode,
                "Wrong aNode!");
@@ -189,17 +190,17 @@ HTMLEditor::CreateAnonymousElement(nsAto
   }
 
   {
     nsAutoScriptBlocker scriptBlocker;
 
     // establish parenthood of the element
     newContentRaw->SetIsNativeAnonymousRoot();
     nsresult rv =
-      newContentRaw->BindToTree(doc, &aParentContent, &aParentContent, true);
+      newContentRaw->BindToTree(doc, &aParentContent, &aParentContent);
     if (NS_FAILED(rv)) {
       newContentRaw->UnbindFromTree();
       return nullptr;
     }
   }
 
   ManualNACPtr newContent(newContentRaw.forget());
 
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -33,26 +33,19 @@
 
 // values for mCookiesLifetimePolicy
 // 0 == accept normally
 // 1 == ask before accepting, no more supported, treated like ACCEPT_NORMALLY (Bug 606655).
 // 2 == downgrade to session
 // 3 == limit lifetime to N days
 static const uint32_t ACCEPT_NORMALLY = 0;
 static const uint32_t ACCEPT_SESSION = 2;
-static const uint32_t ACCEPT_FOR_N_DAYS = 3;
 
 static const bool kDefaultPolicy = true;
 static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
-static const char kCookiesLifetimeDays[] = "network.cookie.lifetime.days";
-
-static const char kCookiesPrefsMigrated[] = "network.cookie.prefsMigrated";
-// obsolete pref names for migration
-static const char kCookiesLifetimeEnabled[] = "network.cookie.lifetime.enabled";
-static const char kCookiesLifetimeBehavior[] = "network.cookie.lifetime.behavior";
 
 static const char kPermissionType[] = "cookie";
 
 NS_IMPL_ISUPPORTS(nsCookiePermission,
                   nsICookiePermission,
                   nsIObserver)
 
 bool
@@ -67,62 +60,37 @@ nsCookiePermission::Init()
   mThirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return false;
 
   // failure to access the pref service is non-fatal...
   nsCOMPtr<nsIPrefBranch> prefBranch =
       do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefBranch) {
     prefBranch->AddObserver(kCookiesLifetimePolicy, this, false);
-    prefBranch->AddObserver(kCookiesLifetimeDays, this, false);
     PrefChanged(prefBranch, nullptr);
-
-    // migration code for original cookie prefs
-    bool migrated;
-    rv = prefBranch->GetBoolPref(kCookiesPrefsMigrated, &migrated);
-    if (NS_FAILED(rv) || !migrated) {
-      bool lifetimeEnabled = false;
-      prefBranch->GetBoolPref(kCookiesLifetimeEnabled, &lifetimeEnabled);
-
-      // if they're limiting lifetime, use the appropriate limited lifetime pref
-      if (lifetimeEnabled) {
-        int32_t lifetimeBehavior;
-        prefBranch->GetIntPref(kCookiesLifetimeBehavior, &lifetimeBehavior);
-        if (lifetimeBehavior)
-          prefBranch->SetIntPref(kCookiesLifetimePolicy, ACCEPT_FOR_N_DAYS);
-        else
-          prefBranch->SetIntPref(kCookiesLifetimePolicy, ACCEPT_SESSION);
-      }
-      prefBranch->SetBoolPref(kCookiesPrefsMigrated, true);
-    }
   }
 
   return true;
 }
 
 void
 nsCookiePermission::PrefChanged(nsIPrefBranch *aPrefBranch,
                                 const char    *aPref)
 {
   int32_t val;
 
 #define PREF_CHANGED(_P) (!aPref || !strcmp(aPref, _P))
 
   if (PREF_CHANGED(kCookiesLifetimePolicy) &&
       NS_SUCCEEDED(aPrefBranch->GetIntPref(kCookiesLifetimePolicy, &val))) {
-    if (val != static_cast<int32_t>(ACCEPT_SESSION) && val != static_cast<int32_t>(ACCEPT_FOR_N_DAYS)) {
+    if (val != static_cast<int32_t>(ACCEPT_SESSION)) {
       val = ACCEPT_NORMALLY;
     }
     mCookiesLifetimePolicy = val;
   }
-
-  if (PREF_CHANGED(kCookiesLifetimeDays) &&
-      NS_SUCCEEDED(aPrefBranch->GetIntPref(kCookiesLifetimeDays, &val)))
-    // save cookie lifetime in seconds instead of days
-    mCookiesLifetimeSec = (int64_t)val * 24 * 60 * 60;
 }
 
 NS_IMETHODIMP
 nsCookiePermission::SetAccess(nsIURI         *aURI,
                               nsCookieAccess  aAccess)
 {
   // Lazily initialize ourselves
   if (!EnsureInitialized())
@@ -242,19 +210,16 @@ nsCookiePermission::CanSetCookie(nsIURI 
     int64_t delta = *aExpiry - currentTime;
 
     // We are accepting the cookie, but,
     // if it's not a session cookie, we may have to limit its lifetime.
     if (!*aIsSession && delta > 0) {
       if (mCookiesLifetimePolicy == ACCEPT_SESSION) {
         // limit lifetime to session
         *aIsSession = true;
-      } else if (delta > mCookiesLifetimeSec) {
-        // limit lifetime to specified time
-        *aExpiry = currentTime + mCookiesLifetimeSec;
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/extensions/cookie/nsCookiePermission.h
+++ b/extensions/cookie/nsCookiePermission.h
@@ -17,32 +17,30 @@ class nsCookiePermission : public nsICoo
                          , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOOKIEPERMISSION
   NS_DECL_NSIOBSERVER
 
   nsCookiePermission()
-    : mCookiesLifetimeSec(INT64_MAX)
-    , mCookiesLifetimePolicy(0) // ACCEPT_NORMALLY
+    : mCookiesLifetimePolicy(0) // ACCEPT_NORMALLY
     {}
 
   bool Init();
   void PrefChanged(nsIPrefBranch *, const char *);
 
 private:
   virtual ~nsCookiePermission() {}
 
   bool EnsureInitialized() { return (mPermMgr != nullptr && mThirdPartyUtil != nullptr) || Init(); };
 
   nsCOMPtr<nsIPermissionManager> mPermMgr;
   nsCOMPtr<mozIThirdPartyUtil> mThirdPartyUtil;
 
-  int64_t      mCookiesLifetimeSec;            // lifetime limit specified in seconds
   uint8_t      mCookiesLifetimePolicy;         // pref for how long cookies are stored
 };
 
 // {EF565D0A-AB9A-4A13-9160-0644CDFD859A}
 #define NS_COOKIEPERMISSION_CID \
  {0xEF565D0A, 0xAB9A, 0x4A13, {0x91, 0x60, 0x06, 0x44, 0xcd, 0xfd, 0x85, 0x9a }}
 
 #endif
--- a/gfx/2d/Rect.h
+++ b/gfx/2d/Rect.h
@@ -288,16 +288,23 @@ IntRectTyped<units> RoundedToInt(const R
   copy.Round();
   return IntRectTyped<units>(int32_t(copy.X()),
                              int32_t(copy.Y()),
                              int32_t(copy.Width()),
                              int32_t(copy.Height()));
 }
 
 template<class units>
+bool RectIsInt32Safe(const RectTyped<units>& aRect) {
+  float min = (float)std::numeric_limits<std::int32_t>::min();
+  float max = (float)std::numeric_limits<std::int32_t>::max();
+  return aRect.x > min && aRect.y > min && aRect.XMost() < max && aRect.YMost() < max;
+}
+
+template<class units>
 IntRectTyped<units> RoundedIn(const RectTyped<units>& aRect)
 {
   return IntRectTyped<units>::RoundIn(aRect);
 }
 
 template<class units>
 IntRectTyped<units> RoundedOut(const RectTyped<units>& aRect)
 {
new file mode 100644
--- /dev/null
+++ b/gfx/tests/reftest/1474722-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <style>
+    .shadowed {
+      box-shadow: 0 0 35px rgba(0, 0, 0, .9);
+      border: 1px solid lightgray;
+      margin: 0 2em;
+      float: left;
+    }
+  </style>
+</head>
+<body style = "overflow:hidden">
+<div class="shadowed" style="height: 200vh"> long shadow </div>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/tests/reftest/1474722.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <style>
+    .shadowed {
+      box-shadow: 0 0 35px rgba(0, 0, 0, .9);
+      border: 1px solid lightgray;
+      margin: 0 2em;
+      float: left;
+    }
+  </style>
+</head>
+<body style = "overflow:hidden">
+<div class="shadowed" style="height: 100000px"> long shadow </div>
+</body>
+</html>
\ No newline at end of file
--- a/gfx/tests/reftest/reftest.list
+++ b/gfx/tests/reftest/reftest.list
@@ -8,10 +8,11 @@ skip-if(Android) fuzzy-if(skiaContent,1,
 fuzzy(100,30) == 1149923.html 1149923-ref.html # use fuzzy due to few distorted pixels caused by border-radius
 == 1131264-1.svg pass.svg
 == 1419528.html 1419528-ref.html
 == 1424673.html 1424673-ref.html
 == 1429411.html 1429411-ref.html
 == 1435143.html 1435143-ref.html
 == 1444904.html 1444904-ref.html
 == 1451168.html 1451168-ref.html
+== 1461313.html 1461313-ref.html
 fuzzy(5-32,21908-26354) fuzzy-if(webrender,0-1,0-3) == 1463802.html 1463802-ref.html
-== 1461313.html 1461313-ref.html
+fuzzy(11,4) == 1474722.html 1474722-ref.html
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -589,16 +589,22 @@ GetBlur(gfxContext* aDestinationCtx,
   // Instead just render the blur ourself here as one image and send it over for printing.
   // TODO: May need to change this with the blob renderer in WR since it also records.
   Matrix destMatrix = aDestinationCtx->CurrentMatrix();
   bool useDestRect = !destMatrix.IsRectilinear() || destMatrix.HasNonIntegerTranslation() ||
                      aDestinationCtx->GetDrawTarget()->IsRecording();
   if (useDestRect) {
     minSize = aRectSize;
   }
+
+  int32_t maxTextureSize = gfxPlatform::MaxTextureSize();
+  if (minSize.width > maxTextureSize || minSize.height > maxTextureSize) {
+    return nullptr;
+  }
+
   aOutMinSize = minSize;
 
   DrawTarget* destDT = aDestinationCtx->GetDrawTarget();
 
   if (!useDestRect) {
     BlurCacheData* cached = gBlurCache->Lookup(minSize, aBlurRadius,
                                                aCornerRadii, aShadowColor,
                                                destDT->GetBackendType());
@@ -950,23 +956,17 @@ DrawMirroredMinBoxShadow(DrawTarget* aDe
 gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
                                const gfxRect& aRect,
                                const RectCornerRadii* aCornerRadii,
                                const gfxPoint& aBlurStdDev,
                                const Color& aShadowColor,
                                const gfxRect& aDirtyRect,
                                const gfxRect& aSkipRect)
 {
-  const double maxSize = (double)gfxPlatform::MaxTextureSize();
-  const double maxPos = (double)std::numeric_limits<std::int16_t>::max();
-  if (aRect.width > maxSize || aRect.height > maxSize ||
-      std::abs(aRect.x) > maxPos || std::abs(aRect.y) > maxPos) {
-    // The rectangle is huge, perhaps due to a very strong perspective or some other
-    // transform. We won't be able to blur something this big so give up now before
-    // overflowing or running into texture size limits later.
+  if (!RectIsInt32Safe(ToRect(aRect))) {
     return;
   }
 
   IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
   bool mirrorCorners = !aCornerRadii || aCornerRadii->AreRadiiSame();
 
   IntRect rect = RoundedToInt(ToRect(aRect));
   IntMargin blurMargin;
@@ -1015,27 +1015,22 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContex
     }
   }
 
   // A note about anti-aliasing and seems between adjacent parts:
   // We don't explicitly disable anti-aliasing in the DrawSurface calls above,
   // so if there's a transform on destDrawTarget that is not pixel-aligned,
   // there will be seams between adjacent parts of the box-shadow. It's hard to
   // avoid those without the use of an intermediate surface.
-  // You might think that we could avoid those by just turning of AA, but there
+  // You might think that we could avoid those by just turning off AA, but there
   // is a problem with that: Box-shadow rendering needs to clip out the
   // element's border box, and we'd like that clip to have anti-aliasing -
   // especially if the element has rounded corners! So we can't do that unless
   // we have a way to say "Please anti-alias the clip, but don't antialias the
   // destination rect of the DrawSurface call".
-  // On OS X there is an additional problem with turning off AA: CoreGraphics
-  // will not just fill the pixels that have their pixel center inside the
-  // filled shape. Instead, it will fill all the pixels which are partially
-  // covered by the shape. So for pixels on the edge between two adjacent parts,
-  // all those pixels will be painted to by both parts, which looks very bad.
 
   destDrawTarget->PopClip();
 }
 
 static already_AddRefed<Path>
 GetBoxShadowInsetPath(DrawTarget* aDrawTarget,
                       const Rect aOuterRect, const Rect aInnerRect,
                       const RectCornerRadii* aInnerClipRadii)
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -482,18 +482,19 @@ XPCShellEnvironment::EvaluateString(cons
 {
   AutoEntryScript aes(GetGlobalObject(),
                       "ipc XPCShellEnvironment::EvaluateString");
   JSContext* cx = aes.cx();
 
   JS::CompileOptions options(cx);
   options.setFileAndLine("typein", 0);
   JS::Rooted<JSScript*> script(cx);
-  if (!JS_CompileUCScript(cx, aString.get(), aString.Length(), options,
-                          &script))
+  JS::SourceBufferHolder srcBuf(aString.get(), aString.Length(),
+                                JS::SourceBufferHolder::NoOwnership);
+  if (!JS_CompileUCScript(cx, srcBuf, options, &script))
   {
      return false;
   }
 
   if (aResult) {
       aResult->Truncate();
   }
 
--- a/js/public/AllocPolicy.h
+++ b/js/public/AllocPolicy.h
@@ -21,31 +21,38 @@ extern MOZ_COLD JS_PUBLIC_API(void) JS_R
 
 namespace js {
 
 enum class AllocFunction {
     Malloc,
     Calloc,
     Realloc
 };
-/* Policy for using system memory functions and doing no error reporting. */
-class SystemAllocPolicy
+
+/* Base class allocation policies providing allocation methods. */
+class AllocPolicyBase
 {
   public:
     template <typename T> T* maybe_pod_malloc(size_t numElems) { return js_pod_malloc<T>(numElems); }
     template <typename T> T* maybe_pod_calloc(size_t numElems) { return js_pod_calloc<T>(numElems); }
     template <typename T> T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
         return js_pod_realloc<T>(p, oldSize, newSize);
     }
     template <typename T> T* pod_malloc(size_t numElems) { return maybe_pod_malloc<T>(numElems); }
     template <typename T> T* pod_calloc(size_t numElems) { return maybe_pod_calloc<T>(numElems); }
     template <typename T> T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
         return maybe_pod_realloc<T>(p, oldSize, newSize);
     }
     template <typename T> void free_(T* p, size_t numElems = 0) { js_free(p); }
+};
+
+/* Policy for using system memory functions and doing no error reporting. */
+class SystemAllocPolicy : public AllocPolicyBase
+{
+  public:
     void reportAllocOverflow() const {}
     bool checkSimulatedOOM() const {
         return !js::oom::ShouldFailWithOOM();
     }
 };
 
 MOZ_COLD JS_FRIEND_API(void) ReportOutOfMemory(JSContext* cx);
 
@@ -53,17 +60,17 @@ MOZ_COLD JS_FRIEND_API(void) ReportOutOf
  * Allocation policy that calls the system memory functions and reports errors
  * to the context. Since the JSContext given on construction is stored for
  * the lifetime of the container, this policy may only be used for containers
  * whose lifetime is a shorter than the given JSContext.
  *
  * FIXME bug 647103 - rewrite this in terms of temporary allocation functions,
  * not the system ones.
  */
-class TempAllocPolicy
+class TempAllocPolicy : public AllocPolicyBase
 {
     JSContext* const cx_;
 
     /*
      * Non-inline helper to call JSRuntime::onOutOfMemory with minimal
      * code bloat.
      */
     JS_FRIEND_API(void*) onOutOfMemory(AllocFunction allocFunc, size_t nbytes,
@@ -76,49 +83,34 @@ class TempAllocPolicy
             return nullptr;
         return static_cast<T*>(onOutOfMemory(allocFunc, bytes, reallocPtr));
     }
 
   public:
     MOZ_IMPLICIT TempAllocPolicy(JSContext* cx) : cx_(cx) {}
 
     template <typename T>
-    T* maybe_pod_malloc(size_t numElems) {
-        return js_pod_malloc<T>(numElems);
-    }
-
-    template <typename T>
-    T* maybe_pod_calloc(size_t numElems) {
-        return js_pod_calloc<T>(numElems);
-    }
-
-    template <typename T>
-    T* maybe_pod_realloc(T* prior, size_t oldSize, size_t newSize) {
-        return js_pod_realloc<T>(prior, oldSize, newSize);
-    }
-
-    template <typename T>
     T* pod_malloc(size_t numElems) {
-        T* p = maybe_pod_malloc<T>(numElems);
+        T* p = this->maybe_pod_malloc<T>(numElems);
         if (MOZ_UNLIKELY(!p))
             p = onOutOfMemoryTyped<T>(AllocFunction::Malloc, numElems);
         return p;
     }
 
     template <typename T>
     T* pod_calloc(size_t numElems) {
-        T* p = maybe_pod_calloc<T>(numElems);
+        T* p = this->maybe_pod_calloc<T>(numElems);
         if (MOZ_UNLIKELY(!p))
             p = onOutOfMemoryTyped<T>(AllocFunction::Calloc, numElems);
         return p;
     }
 
     template <typename T>
     T* pod_realloc(T* prior, size_t oldSize, size_t newSize) {
-        T* p2 = maybe_pod_realloc<T>(prior, oldSize, newSize);
+        T* p2 = this->maybe_pod_realloc<T>(prior, oldSize, newSize);
         if (MOZ_UNLIKELY(!p2))
             p2 = onOutOfMemoryTyped<T>(AllocFunction::Realloc, newSize, prior);
         return p2;
     }
 
     template <typename T>
     void free_(T* p, size_t numElems = 0) {
         js_free(p);
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -229,17 +229,22 @@ impl Runtime {
         } else {
             (script_utf16.as_ptr(), script_utf16.len() as c_uint)
         };
         assert!(!ptr.is_null());
         unsafe {
             let _ac = AutoCompartment::with_obj(self.cx(), glob.get());
             let options = CompileOptionsWrapper::new(self.cx(), filename_cstr.as_ptr(), line_num);
 
-            if !JS::Evaluate2(self.cx(), options.ptr, ptr as *const u16, len as _, rval) {
+            let mut srcBuf = JS::SourceBufferHolder {
+                data_: ptr,
+                length_: len as _,
+                ownsChars_: false
+            };
+            if !JS::Evaluate(self.cx(), options.ptr, &mut srcBuf, rval) {
                 debug!("...err!");
                 panic::maybe_resume_unwind();
                 Err(())
             } else {
                 // we could return the script result but then we'd have
                 // to root it and so forth and, really, who cares?
                 debug!("...ok!");
                 Ok(())
--- a/js/src/NamespaceImports.h
+++ b/js/src/NamespaceImports.h
@@ -33,17 +33,17 @@ class UTF8CharsZ;
 using AutoValueVector = AutoVector<Value>;
 using AutoIdVector = AutoVector<jsid>;
 using AutoObjectVector = AutoVector<JSObject*>;
 
 using ValueVector = JS::GCVector<JS::Value>;
 using IdVector = JS::GCVector<jsid>;
 using ScriptVector = JS::GCVector<JSScript*>;
 
-class MOZ_STACK_CLASS SourceBufferHolder;
+class SourceBufferHolder;
 
 class HandleValueArray;
 
 class ObjectOpResult;
 class PropertyResult;
 
 enum class SymbolCode: uint32_t;
 
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -986,17 +986,17 @@ EnqueuePromiseReactionJob(JSContext* cx,
         if (!cx->compartment()->wrap(cx, &promise))
             return false;
     }
 
     // Using objectFromIncumbentGlobal, we can derive the incumbent global by
     // unwrapping and then getting the global. This is very convoluted, but
     // much better than having to store the original global as a private value
     // because we couldn't wrap it to store it as a normal JS value.
-    RootedObject global(cx);
+    Rooted<GlobalObject*> global(cx);
     if (JSObject* objectFromIncumbentGlobal = reaction->getAndClearIncumbentGlobalObject()) {
         objectFromIncumbentGlobal = CheckedUnwrap(objectFromIncumbentGlobal);
         MOZ_ASSERT(objectFromIncumbentGlobal);
         global = &objectFromIncumbentGlobal->nonCCWGlobal();
     }
 
     // Note: the global we pass here might be from a different compartment
     // than job and promise. While it's somewhat unusual to pass objects
@@ -1719,17 +1719,17 @@ EnqueuePromiseResolveThenableJob(JSConte
 
     // Store the data array on the reaction job.
     job->setExtendedSlot(ThenableJobSlot_JobData, ObjectValue(*data));
 
     // At this point the promise is guaranteed to be wrapped into the job's
     // compartment.
     RootedObject promise(cx, &promiseToResolve.toObject());
 
-    RootedObject incumbentGlobal(cx, cx->runtime()->getIncumbentGlobal(cx));
+    Rooted<GlobalObject*> incumbentGlobal(cx, cx->runtime()->getIncumbentGlobal(cx));
     return cx->runtime()->enqueuePromiseJob(cx, job, promise, incumbentGlobal);
 }
 
 /**
  * Tells the embedding to enqueue a Promise resolve thenable built-in job,
  * based on two parameters:
  * promiseToResolve - The promise to resolve, obviously.
  * thenable - The thenable to resolve the Promise with.
@@ -1747,17 +1747,17 @@ EnqueuePromiseResolveThenableBuiltinJob(
                                              gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
     if (!job)
         return false;
 
     // Store the promise and the thenable on the reaction job.
     job->setExtendedSlot(BuiltinThenableJobSlot_Promise, ObjectValue(*promiseToResolve));
     job->setExtendedSlot(BuiltinThenableJobSlot_Thenable, ObjectValue(*thenable));
 
-    RootedObject incumbentGlobal(cx, cx->runtime()->getIncumbentGlobal(cx));
+    Rooted<GlobalObject*> incumbentGlobal(cx, cx->runtime()->getIncumbentGlobal(cx));
     return cx->runtime()->enqueuePromiseJob(cx, job, promiseToResolve, incumbentGlobal);
 }
 
 static MOZ_MUST_USE bool
 AddDummyPromiseReactionForDebugger(JSContext* cx, Handle<PromiseObject*> promise,
                                    HandleObject dependentPromise);
 
 static MOZ_MUST_USE bool
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -5170,17 +5170,18 @@ js::TestingFunctionArgumentToScript(JSCo
         size_t len = GetLinearStringLength(linearStr);
         AutoStableStringChars linearChars(cx);
         if (!linearChars.initTwoByte(cx, linearStr))
             return nullptr;
         const char16_t* chars = linearChars.twoByteRange().begin().get();
 
         RootedScript script(cx);
         CompileOptions options(cx);
-        if (!JS::Compile(cx, options, chars, len, &script))
+        SourceBufferHolder source(chars, len, SourceBufferHolder::NoOwnership);
+        if (!JS::Compile(cx, options, source, &script))
             return nullptr;
         return script;
     }
 
     RootedFunction fun(cx, JS_ValueToFunction(cx, v));
     if (!fun)
         return nullptr;
 
--- a/js/src/jit/RegisterSets.h
+++ b/js/src/jit/RegisterSets.h
@@ -911,17 +911,20 @@ class SpecializedRegSet<Accessors, Regis
     void takeUnchecked(AnyRegister reg) {
         if (reg.isFloat())
             takeUnchecked(reg.fpu());
         else
             takeUnchecked(reg.gpr());
     }
 
     void take(Register reg) {
-        MOZ_ASSERT(this->has(reg));
+#ifdef DEBUG
+        bool hasReg = this->has(reg);
+        MOZ_ASSERT(hasReg);
+#endif
         takeUnchecked(reg);
     }
     void take(FloatRegister reg) {
         MOZ_ASSERT(this->has(reg));
         takeUnchecked(reg);
     }
     void take(AnyRegister reg) {
         if (reg.isFloat())
--- a/js/src/jsapi-tests/testCompileNonSyntactic.cpp
+++ b/js/src/jsapi-tests/testCompileNonSyntactic.cpp
@@ -79,35 +79,41 @@ testCompile(bool nonSyntactic)
     // Check explicit non-syntactic compilation first to make sure it doesn't
     // modify our options object.
     CHECK(CompileForNonSyntacticScope(cx, options, buf, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
     CHECK(CompileForNonSyntacticScope(cx, options, src, length, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
-    CHECK(CompileForNonSyntacticScope(cx, options, src_16, length, &script));
-    CHECK_EQUAL(script->hasNonSyntacticScope(), true);
+    {
+        JS::SourceBufferHolder srcBuf(src_16, length, JS::SourceBufferHolder::NoOwnership);
+        CHECK(CompileForNonSyntacticScope(cx, options, srcBuf, &script));
+        CHECK_EQUAL(script->hasNonSyntacticScope(), true);
+    }
 
 
     CHECK(Compile(cx, options, buf, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
     CHECK(Compile(cx, options, src, length, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
-    CHECK(Compile(cx, options, src_16, length, &script));
-    CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
+    {
+        JS::SourceBufferHolder srcBuf(src_16, length, JS::SourceBufferHolder::NoOwnership);
+        CHECK(Compile(cx, options, srcBuf, &script));
+        CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
+    }
 
 
     options.forceAsync = true;
     OffThreadTask task;
     OffThreadToken* token;
 
-    CHECK(CompileOffThread(cx, options, src_16, length,
-                           task.OffThreadCallback, &task));
+    SourceBufferHolder srcBuf(src_16, length, SourceBufferHolder::NoOwnership);
+    CHECK(CompileOffThread(cx, options, srcBuf, task.OffThreadCallback, &task));
     CHECK(token = task.waitUntilDone(cx));
     CHECK(script = FinishOffThreadScript(cx, token));
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
     return true;
 }
 END_TEST(testCompileScript);
--- a/js/src/jsapi-tests/testErrorLineOfContext.cpp
+++ b/js/src/jsapi-tests/testErrorLineOfContext.cpp
@@ -35,17 +35,18 @@ eval(const char16_t* chars, size_t len, 
 {
     JS::RealmOptions globalOptions;
     JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
 						   JS::FireOnNewGlobalHook, globalOptions));
     CHECK(global);
 
     JSAutoRealm ar(cx, global);
     JS::CompileOptions options(cx);
-    return JS::Evaluate(cx, options, chars, len, rval);
+    JS::SourceBufferHolder srcBuf(chars, len, JS::SourceBufferHolder::NoOwnership);
+    return JS::Evaluate(cx, options, srcBuf, rval);
 }
 
 template<size_t N>
 bool
 testLineOfContextHasNoLineTerminator(const char16_t (&chars)[N], char16_t expectedLast)
 {
     JS::RootedValue rval(cx);
     CHECK(!eval(chars, N - 1, &rval));
--- a/js/src/jsapi-tests/testJSEvaluateScript.cpp
+++ b/js/src/jsapi-tests/testJSEvaluateScript.cpp
@@ -12,18 +12,19 @@ BEGIN_TEST(testJSEvaluateScript)
     CHECK(obj);
 
     static const char16_t src[] = u"var x = 5;";
 
     JS::RootedValue retval(cx);
     JS::CompileOptions opts(cx);
     JS::AutoObjectVector scopeChain(cx);
     CHECK(scopeChain.append(obj));
+    JS::SourceBufferHolder srcBuf(src, ArrayLength(src) - 1, JS::SourceBufferHolder::NoOwnership);
     CHECK(JS::Evaluate(cx, scopeChain, opts.setFileAndLine(__FILE__, __LINE__),
-                       src, ArrayLength(src) - 1, &retval));
+                       srcBuf, &retval));
 
     bool hasProp = true;
     CHECK(JS_AlreadyHasOwnProperty(cx, obj, "x", &hasProp));
     CHECK(hasProp);
 
     hasProp = false;
     CHECK(JS_HasProperty(cx, global, "x", &hasProp));
     CHECK(!hasProp);
--- a/js/src/jsapi-tests/testMutedErrors.cpp
+++ b/js/src/jsapi-tests/testMutedErrors.cpp
@@ -49,17 +49,18 @@ eval(const char* asciiChars, bool mutedE
     JSAutoRealm ar(cx, global);
     CHECK(JS::InitRealmStandardClasses(cx));
 
 
     JS::CompileOptions options(cx);
     options.setMutedErrors(mutedErrors)
            .setFileAndLine("", 0);
 
-    return JS::Evaluate(cx, options, chars.get(), len, rval);
+    JS::SourceBufferHolder srcBuf(chars.get(), len, JS::SourceBufferHolder::NoOwnership);
+    return JS::Evaluate(cx, options, srcBuf, rval);
 }
 
 bool
 testOuter(const char* asciiChars)
 {
     CHECK(testInner(asciiChars, false));
     CHECK(testInner(asciiChars, true));
     return true;
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -67,37 +67,40 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, 
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
     JS::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, code_size, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, code_size, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &script));
     return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
     JS::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, 0, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, 0, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &script));
     return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
     JS::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, code_size, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, code_size, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &script));
     return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile";
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1261,17 +1261,17 @@ JS::CurrentGlobalOrNull(JSContext* cx)
     if (!cx->realm())
         return nullptr;
     return cx->global();
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::GetNonCCWObjectGlobal(JSObject* obj)
 {
-    AssertHeapIsIdle();
+    AssertHeapIsIdleOrIterating();
     MOZ_DIAGNOSTIC_ASSERT(!IsCrossCompartmentWrapper(obj));
     return &obj->nonCCWGlobal();
 }
 
 JS_PUBLIC_API(bool)
 JS::detail::ComputeThis(JSContext* cx, Value* vp, MutableHandleObject thisObject)
 {
     AssertHeapIsIdle();
@@ -4004,35 +4004,28 @@ Compile(JSContext* cx, const ReadOnlyCom
     CHECK_REQUEST(cx);
 
     script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
     return !!script;
 }
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-        const char16_t* chars, size_t length, MutableHandleScript script)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    return ::Compile(cx, options, srcBuf, script);
-}
-
-static bool
-Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* bytes, size_t length, MutableHandleScript script)
 {
-    UniqueTwoByteChars chars;
+    char16_t* chars;
     if (options.utf8)
-        chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
+        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
     else
-        chars.reset(InflateString(cx, bytes, length));
+        chars = InflateString(cx, bytes, length);
     if (!chars)
         return false;
 
-    return ::Compile(cx, options, chars.get(), length, script);
+    SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
+    return ::Compile(cx, options, source, script);
 }
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         FILE* fp, MutableHandleScript script)
 {
     FileContents buffer(cx);
     if (!ReadCompleteFile(cx, fp, buffer))
@@ -4064,23 +4057,16 @@ bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             const char* bytes, size_t length, JS::MutableHandleScript script)
 {
     return ::Compile(cx, options, bytes, length, script);
 }
 
 bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-            const char16_t* chars, size_t length, JS::MutableHandleScript script)
-{
-    return ::Compile(cx, options, chars, length, script);
-}
-
-bool
-JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             FILE* file, JS::MutableHandleScript script)
 {
     return ::Compile(cx, options, file, script);
 }
 
 bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             const char* filename, JS::MutableHandleScript script)
@@ -4103,26 +4089,16 @@ JS::CompileForNonSyntacticScope(JSContex
 {
     CompileOptions options(cx, optionsArg);
     options.setNonSyntacticScope(true);
     return ::Compile(cx, options, bytes, length, script);
 }
 
 bool
 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-                                const char16_t* chars, size_t length,
-                                JS::MutableHandleScript script)
-{
-    CompileOptions options(cx, optionsArg);
-    options.setNonSyntacticScope(true);
-    return ::Compile(cx, options, chars, length, script);
-}
-
-bool
-JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
                                 FILE* file, JS::MutableHandleScript script)
 {
     CompileOptions options(cx, optionsArg);
     options.setNonSyntacticScope(true);
     return ::Compile(cx, options, file, script);
 }
 
 bool
@@ -4234,21 +4210,21 @@ JS_PUBLIC_API(bool)
 JS::CanDecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
 {
     return CanDoOffThread(cx, options, length, OffThread::DecodeBinAST);
 }
 #endif
 
 JS_PUBLIC_API(bool)
 JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
-                     const char16_t* chars, size_t length,
+                     JS::SourceBufferHolder& srcBuf,
                      OffThreadCompileCallback callback, void* callbackData)
 {
-    MOZ_ASSERT(CanCompileOffThread(cx, options, length));
-    return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
+    MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
+    return StartOffThreadParseScript(cx, options, srcBuf, callback, callbackData);
 }
 
 JS_PUBLIC_API(JSScript*)
 JS::FinishOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
     return HelperThreadState().finishScriptParseTask(cx, token);
@@ -4259,21 +4235,21 @@ JS::CancelOffThreadScript(JSContext* cx,
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
     HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Script, token);
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                           const char16_t* chars, size_t length,
+                           JS::SourceBufferHolder& srcBuf,
                            OffThreadCompileCallback callback, void* callbackData)
 {
-    MOZ_ASSERT(CanCompileOffThread(cx, options, length));
-    return StartOffThreadParseModule(cx, options, chars, length, callback, callbackData);
+    MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
+    return StartOffThreadParseModule(cx, options, srcBuf, callback, callbackData);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
     return HelperThreadState().finishModuleParseTask(cx, token);
@@ -4356,20 +4332,20 @@ JS::CancelMultiOffThreadScriptsDecoder(J
 JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
                  const JS::CompileOptions& options, MutableHandleScript script)
 {
     return ::Compile(cx, options, ascii, length, script);
 }
 
 JS_PUBLIC_API(bool)
-JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
+JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                    const JS::CompileOptions& options, MutableHandleScript script)
 {
-    return ::Compile(cx, options, chars, length, script);
+    return ::Compile(cx, options, srcBuf, script);
 }
 
 JS_PUBLIC_API(bool)
 JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4580,39 +4556,29 @@ JS::CompileFunction(JSContext* cx, AutoO
     return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
                            scope, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                     const ReadOnlyCompileOptions& options,
                     const char* name, unsigned nargs, const char* const* argnames,
-                    const char16_t* chars, size_t length, MutableHandleFunction fun)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
+                    const char* bytes, size_t length, MutableHandleFunction fun)
+{
+    char16_t* chars;
+    if (options.utf8)
+        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
+    else
+        chars = InflateString(cx, bytes, length);
+    if (!chars)
+        return false;
+
+    SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
     return CompileFunction(cx, envChain, options, name, nargs, argnames,
-                           srcBuf, fun);
-}
-
-JS_PUBLIC_API(bool)
-JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
-                    const ReadOnlyCompileOptions& options,
-                    const char* name, unsigned nargs, const char* const* argnames,
-                    const char* bytes, size_t length, MutableHandleFunction fun)
-{
-    UniqueTwoByteChars chars;
-    if (options.utf8)
-        chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
-    else
-        chars.reset(InflateString(cx, bytes, length));
-    if (!chars)
-        return false;
-
-    return CompileFunction(cx, envChain, options, name, nargs, argnames,
-                           chars.get(), length, fun);
+                           source, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
                             HandleObject element, HandleString elementAttrName)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
@@ -4781,25 +4747,16 @@ Evaluate(JSContext* cx, AutoObjectVector
 {
     RootedObject env(cx);
     RootedScope scope(cx);
     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
         return false;
     return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
 }
 
-static bool
-Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-         const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-  SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-  RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
-  return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
-}
-
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
              const char* bytes, size_t length, MutableHandleValue rval)
 {
     char16_t* chars;
     if (options.utf8)
         chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
     else
@@ -4841,31 +4798,16 @@ JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
              SourceBufferHolder& srcBuf, MutableHandleValue rval)
 {
     return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-             const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-    return ::Evaluate(cx, optionsArg, chars, length, rval);
-}
-
-JS_PUBLIC_API(bool)
-JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
-             const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
-}
-
-JS_PUBLIC_API(bool)
-JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
              const char* filename, MutableHandleValue rval)
 {
     return ::Evaluate(cx, optionsArg, filename, rval);
 }
 
 JS_PUBLIC_API(JS::ModuleResolveHook)
 JS::GetModuleResolveHook(JSRuntime* rt)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -373,37 +373,38 @@ namespace JS {
  *
  * Example use:
  *
  *    size_t length = 512;
  *    char16_t* chars = js_pod_malloc<char16_t>(length);
  *    JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
  *    JS::Compile(cx, options, srcBuf);
  */
-class MOZ_STACK_CLASS SourceBufferHolder final
+class SourceBufferHolder final
 {
   public:
     enum Ownership {
       NoOwnership,
       GiveOwnership
     };
 
     SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership)
       : data_(data),
         length_(dataLength),
         ownsChars_(ownership == GiveOwnership)
     {
-        // Ensure that null buffers properly return an unowned, empty,
-        // null-terminated string.
-        static const char16_t NullChar_ = 0;
-        if (!get()) {
-            data_ = &NullChar_;
-            length_ = 0;
-            ownsChars_ = false;
-        }
+        fixEmptyBuffer();
+    }
+
+    SourceBufferHolder(UniqueTwoByteChars&& data, size_t dataLength)
+      : data_(data.release()),
+        length_(dataLength),
+        ownsChars_(true)
+    {
+        fixEmptyBuffer();
     }
 
     SourceBufferHolder(SourceBufferHolder&& other)
       : data_(other.data_),
         length_(other.length_),
         ownsChars_(other.ownsChars_)
     {
         other.data_ = nullptr;
@@ -443,16 +444,27 @@ class MOZ_STACK_CLASS SourceBufferHolder
         ownsChars_ = false;
         return const_cast<char16_t*>(data_);
     }
 
   private:
     SourceBufferHolder(SourceBufferHolder&) = delete;
     SourceBufferHolder& operator=(SourceBufferHolder&) = delete;
 
+    void fixEmptyBuffer() {
+        // Ensure that null buffers properly return an unowned, empty,
+        // null-terminated string.
+        static const char16_t NullChar_ = 0;
+        if (!get()) {
+            data_ = &NullChar_;
+            length_ = 0;
+            ownsChars_ = false;
+        }
+    }
+
     const char16_t* data_;
     size_t length_;
     bool ownsChars_;
 };
 
 struct TranscodeSource;
 
 } /* namespace JS */
@@ -1312,16 +1324,34 @@ JS_free(JSContext* cx, void* p);
  * performance optimization as specified by the given JSFreeOp instance.
  */
 extern JS_PUBLIC_API(void)
 JS_freeop(JSFreeOp* fop, void* p);
 
 extern JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext* cx, size_t nbytes);
 
+/*
+ * A replacement for MallocAllocPolicy that allocates in the JS heap and adds no
+ * extra behaviours.
+ *
+ * This is currently used for allocating source buffers for parsing. Since these
+ * are temporary and will not be freed by GC, the memory is not tracked by the
+ * usual accounting.
+ */
+class JS_PUBLIC_API(JSMallocAllocPolicy) : public js::AllocPolicyBase
+{
+public:
+    void reportAllocOverflow() const {}
+
+    MOZ_MUST_USE bool checkSimulatedOOM() const {
+        return true;
+    }
+};
+
 /**
  * Set the size of the native stack that should not be exceed. To disable
  * stack size checking pass 0.
  *
  * SpiderMonkey allows for a distinction between system code (such as GCs, which
  * may incidentally be triggered by script but are not strictly performed on
  * behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals),
  * and untrusted script. Each kind of code may have a different stack quota,
@@ -3181,17 +3211,17 @@ extern JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
                  const JS::CompileOptions& options,
                  JS::MutableHandleScript script);
 
 /**
  * |script| will always be set. On failure, it will be set to nullptr.
  */
 extern JS_PUBLIC_API(bool)
-JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
+JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                    const JS::CompileOptions& options,
                    JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(JSObject*)
 JS_GetGlobalFromScript(JSScript* script);
 
 extern JS_PUBLIC_API(const char*)
 JS_GetScriptFilename(JSScript* script);
@@ -3596,40 +3626,32 @@ Compile(JSContext* cx, const ReadOnlyCom
         SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* bytes, size_t length, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-        const char16_t* chars, size_t length, JS::MutableHandleScript script);
-
-extern JS_PUBLIC_API(bool)
-Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         FILE* file, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* filename, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             const char* bytes, size_t length, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
-                            const char16_t* chars, size_t length, JS::MutableHandleScript script);
-
-extern JS_PUBLIC_API(bool)
-CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             FILE* file, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             const char* filename, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
@@ -3651,28 +3673,28 @@ CanDecodeOffThread(JSContext* cx, const 
  *
  * The characters passed in to CompileOffThread must remain live until the
  * callback is invoked, and the resulting script will be rooted until the call
  * to FinishOffThreadScript.
  */
 
 extern JS_PUBLIC_API(bool)
 CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
-                 const char16_t* chars, size_t length,
+                 JS::SourceBufferHolder& srcBuf,
                  OffThreadCompileCallback callback, void* callbackData);
 
 extern JS_PUBLIC_API(JSScript*)
 FinishOffThreadScript(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(void)
 CancelOffThreadScript(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(bool)
 CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                       const char16_t* chars, size_t length,
+                       JS::SourceBufferHolder& srcBuf,
                        OffThreadCompileCallback callback, void* callbackData);
 
 extern JS_PUBLIC_API(JSObject*)
 FinishOffThreadModule(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(void)
 CancelOffThreadModule(JSContext* cx, OffThreadToken* token);
 
@@ -3710,25 +3732,16 @@ CancelMultiOffThreadScriptsDecoder(JSCon
  * scope chain used for the function will consist of With wrappers for those
  * objects, followed by the current global of the compartment cx is in.  This
  * global must not be explicitly included in the scope chain.
  */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                 const ReadOnlyCompileOptions& options,
                 const char* name, unsigned nargs, const char* const* argnames,
-                const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
-
-/**
- * Same as above, but taking a SourceBufferHolder for the function body.
- */
-extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& envChain,
-                const ReadOnlyCompileOptions& options,
-                const char* name, unsigned nargs, const char* const* argnames,
                 SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
 
 /**
  * Same as above, but taking a const char * for the function body.
  */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                 const ReadOnlyCompileOptions& options,
@@ -3833,32 +3846,16 @@ Evaluate(JSContext* cx, const ReadOnlyCo
  * the global object on it; that's implicit.  It needs to contain the other
  * objects that should end up on the script's scope chain.
  */
 extern JS_PUBLIC_API(bool)
 Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
          SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
 
 /**
- * Evaluate the given character buffer in the scope of the current global of cx.
- */
-extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
-         const char16_t* chars, size_t length, JS::MutableHandleValue rval);
-
-/**
- * As above, but providing an explicit scope chain.  envChain must not include
- * the global object on it; that's implicit.  It needs to contain the other
- * objects that should end up on the script's scope chain.
- */
-extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
-         const char16_t* chars, size_t length, JS::MutableHandleValue rval);
-
-/**
  * Evaluate the given byte buffer in the scope of the current global of cx.
  */
 extern JS_PUBLIC_API(bool)
 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
          const char* bytes, size_t length, JS::MutableHandleValue rval);
 
 /**
  * Evaluate the given file in the scope of the current global of cx.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1980,20 +1980,22 @@ Evaluate(JSContext* cx, unsigned argc, V
             }
 
             if (loadBytecode) {
                 JS::TranscodeResult rv = JS::DecodeScript(cx, loadBuffer, &script);
                 if (!ConvertTranscodeResultToJSException(cx, rv))
                     return false;
             } else {
                 mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
+                JS::SourceBufferHolder srcBuf(chars.begin().get(), chars.length(),
+                                              JS::SourceBufferHolder::NoOwnership);
                 if (envChain.length() == 0) {
-                    (void) JS::Compile(cx, options, chars.begin().get(), chars.length(), &script);
+                    (void) JS::Compile(cx, options, srcBuf, &script);
                 } else {
-                    (void) JS::CompileForNonSyntacticScope(cx, options, chars.begin().get(), chars.length(), &script);
+                    (void) JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script);
                 }
             }
 
             if (!script)
                 return false;
         }
 
         if (displayURL && !script->scriptSource()->hasDisplayURL()) {
@@ -2182,33 +2184,33 @@ Run(JSContext* cx, unsigned argc, Value*
     str = FileAsString(cx, str);
     if (!str)
         return false;
 
     AutoStableStringChars chars(cx);
     if (!chars.initTwoByte(cx, str))
         return false;
 
-    const char16_t* ucbuf = chars.twoByteRange().begin().get();
-    size_t buflen = str->length();
+    JS::SourceBufferHolder srcBuf(chars.twoByteRange().begin().get(), str->length(),
+                                  JS::SourceBufferHolder::NoOwnership);
 
     RootedScript script(cx);
     int64_t startClock = PRMJ_Now();
     {
         /* FIXME: This should use UTF-8 (bug 987069). */
         JSAutoByteString filename(cx, str);
         if (!filename)
             return false;
 
         JS::CompileOptions options(cx);
         options.setIntroductionType("js shell run")
                .setFileAndLine(filename.ptr(), 1)
                .setIsRunOnce(true)
                .setNoScriptRval(true);
-        if (!JS_CompileUCScript(cx, ucbuf, buflen, options, &script))
+        if (!JS_CompileUCScript(cx, srcBuf, options, &script))
             return false;
     }
 
     if (!JS_ExecuteScript(cx, script))
         return false;
 
     int64_t endClock = PRMJ_Now();
 
@@ -3544,17 +3546,18 @@ EvalInContext(JSContext* cx, unsigned ar
         sobj = ToWindowIfWindowProxy(sobj);
 
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportErrorASCII(cx, "Invalid scope argument to evalcx");
             return false;
         }
         JS::CompileOptions opts(cx);
         opts.setFileAndLine(filename.get(), lineno);
-        if (!JS::Evaluate(cx, opts, src, srclen, args.rval())) {
+        JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
+        if (!JS::Evaluate(cx, opts, srcBuf, args.rval())) {
             return false;
         }
     }
 
     if (!cx->compartment()->wrap(cx, args.rval()))
         return false;
 
     return true;
@@ -3647,17 +3650,19 @@ WorkerMain(WorkerInput* input)
         JSAutoRealm ar(cx, global);
 
         JS::CompileOptions options(cx);
         options.setFileAndLine("<string>", 1)
                .setIsRunOnce(true);
 
         AutoReportException are(cx);
         RootedScript script(cx);
-        if (!JS::Compile(cx, options, input->chars.get(), input->length, &script))
+        JS::SourceBufferHolder srcBuf(input->chars.get(), input->length,
+                                      JS::SourceBufferHolder::NoOwnership);
+        if (!JS::Compile(cx, options, srcBuf, &script))
             break;
         RootedValue result(cx);
         JS_ExecuteScript(cx, script, &result);
     } while (0);
 
     KillWatchdog(cx);
     JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
 }
@@ -4233,18 +4238,20 @@ Compile(JSContext* cx, unsigned argc, Va
         return false;
 
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell compile")
            .setFileAndLine("<string>", 1)
            .setIsRunOnce(true)
            .setNoScriptRval(true);
     RootedScript script(cx);
-    const char16_t* chars = stableChars.twoByteRange().begin().get();
-    bool ok = JS_CompileUCScript(cx, chars, scriptContents->length(), options, &script);
+    JS::SourceBufferHolder srcBuf(stableChars.twoByteRange().begin().get(),
+                                  scriptContents->length(),
+                                  JS::SourceBufferHolder::NoOwnership);
+    bool ok = JS_CompileUCScript(cx, srcBuf, options, &script);
     args.rval().setUndefined();
     return ok;
 }
 
 static bool
 ParseModule(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -4731,17 +4738,19 @@ OffThreadCompileScript(JSContext* cx, un
         return false;
     }
 
     OffThreadJob* job = NewOffThreadJob(cx, ScriptKind::Script,
                                         OffThreadJob::Source(std::move(ownedChars)));
     if (!job)
         return false;
 
-    if (!JS::CompileOffThread(cx, options, job->sourceChars(), length,
+    JS::SourceBufferHolder srcBuf(job->sourceChars(), length,
+                                  JS::SourceBufferHolder::NoOwnership);
+    if (!JS::CompileOffThread(cx, options, srcBuf,
                               OffThreadCompileScriptCallback, job))
     {
         job->cancel();
         DeleteOffThreadJob(cx, job);
         return false;
     }
 
     args.rval().setInt32(job->id);
@@ -4817,17 +4826,19 @@ OffThreadCompileModule(JSContext* cx, un
         return false;
     }
 
     OffThreadJob* job = NewOffThreadJob(cx, ScriptKind::Module,
                                         OffThreadJob::Source(std::move(ownedChars)));
     if (!job)
         return false;
 
-    if (!JS::CompileOffThreadModule(cx, options, job->sourceChars(), length,
+    JS::SourceBufferHolder srcBuf(job->sourceChars(), length,
+                                  JS::SourceBufferHolder::NoOwnership);
+    if (!JS::CompileOffThreadModule(cx, options, srcBuf,
                                     OffThreadCompileScriptCallback, job))
     {
         job->cancel();
         DeleteOffThreadJob(cx, job);
         return false;
     }
 
     args.rval().setInt32(job->id);
@@ -6681,25 +6692,26 @@ EntryPoints(JSContext* cx, unsigned argc
         if (!code.isUndefined()) {
             RootedString codeString(cx, ToString(cx, code));
             if (!codeString || !codeString->ensureFlat(cx))
                 return false;
 
             AutoStableStringChars stableChars(cx);
             if (!stableChars.initTwoByte(cx, codeString))
                 return false;
-            const char16_t* chars = stableChars.twoByteRange().begin().get();
-            size_t length = codeString->length();
+            JS::SourceBufferHolder srcBuf(stableChars.twoByteRange().begin().get(),
+                                          codeString->length(),
+                                          JS::SourceBufferHolder::NoOwnership);
 
             CompileOptions options(cx);
             options.setIntroductionType("entryPoint eval")
                    .setFileAndLine("entryPoint eval", 1);
 
             js::shell::ShellAutoEntryMonitor sarep(cx);
-            if (!JS::Evaluate(cx, options, chars, length, &dummy))
+            if (!JS::Evaluate(cx, options, srcBuf, &dummy))
                 return false;
             return sarep.buildResult(cx, args.rval());
         }
     }
 
     JS_ReportErrorASCII(cx, "bad 'params' object");
     return false;
 }
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -477,52 +477,50 @@ ParseTask::trace(JSTracer* trc)
 size_t
 ParseTask::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
     return options.sizeOfExcludingThis(mallocSizeOf) +
            alloc.sizeOfExcludingThis(mallocSizeOf) +
            errors.sizeOfExcludingThis(mallocSizeOf);
 }
 
-ScriptParseTask::ScriptParseTask(JSContext* cx, const char16_t* chars, size_t length,
+ScriptParseTask::ScriptParseTask(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                                  JS::OffThreadCompileCallback callback, void* callbackData)
   : ParseTask(ParseTaskKind::Script, cx, callback, callbackData),
-    data(TwoByteChars(chars, length))
+    data(std::move(srcBuf))
 {}
 
 void
 ScriptParseTask::parse(JSContext* cx)
 {
-    SourceBufferHolder srcBuf(data.begin().get(), data.length(), SourceBufferHolder::NoOwnership);
     Rooted<ScriptSourceObject*> sourceObject(cx);
 
     ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
 
     JSScript* script = frontend::CompileGlobalScript(cx, alloc, scopeKind,
-                                                     options, srcBuf,
+                                                     options, data,
                                                      /* sourceObjectOut = */ &sourceObject.get());
     if (script)
         scripts.infallibleAppend(script);
     if (sourceObject)
         sourceObjects.infallibleAppend(sourceObject);
 }
 
-ModuleParseTask::ModuleParseTask(JSContext* cx, const char16_t* chars, size_t length,
+ModuleParseTask::ModuleParseTask(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                                  JS::OffThreadCompileCallback callback, void* callbackData)
   : ParseTask(ParseTaskKind::Module, cx, callback, callbackData),
-    data(TwoByteChars(chars, length))
+    data(std::move(srcBuf))
 {}
 
 void
 ModuleParseTask::parse(JSContext* cx)
 {
-    SourceBufferHolder srcBuf(data.begin().get(), data.length(), SourceBufferHolder::NoOwnership);
     Rooted<ScriptSourceObject*> sourceObject(cx);
 
-    ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject.get());
+    ModuleObject* module = frontend::CompileModule(cx, options, data, alloc, &sourceObject.get());
     if (module) {
         scripts.infallibleAppend(module->script());
         if (sourceObject)
             sourceObjects.infallibleAppend(sourceObject);
     }
 }
 
 ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range,
@@ -820,33 +818,33 @@ StartOffThreadParseTask(JSContext* cx, P
         return false;
 
     createdForHelper.forget();
     return true;
 }
 
 bool
 js::StartOffThreadParseScript(JSContext* cx, const ReadOnlyCompileOptions& options,
-                              const char16_t* chars, size_t length,
+                              JS::SourceBufferHolder& srcBuf,
                               JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    auto task = cx->make_unique<ScriptParseTask>(cx, chars, length, callback, callbackData);
+    auto task = cx->make_unique<ScriptParseTask>(cx, srcBuf, callback, callbackData);
     if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
     Unused << task.release();
     return true;
 }
 
 bool
 js::StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                              const char16_t* chars, size_t length,
+                              JS::SourceBufferHolder& srcBuf,
                               JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    auto task = cx->make_unique<ModuleParseTask>(cx, chars, length, callback, callbackData);
+    auto task = cx->make_unique<ModuleParseTask>(cx, srcBuf, callback, callbackData);
     if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
     Unused << task.release();
     return true;
 }
 
 bool
--- a/js/src/vm/HelperThreads.h
+++ b/js/src/vm/HelperThreads.h
@@ -586,22 +586,22 @@ void
 CancelOffThreadParses(JSRuntime* runtime);
 
 /*
  * Start a parse/emit cycle for a stream of source. The characters must stay
  * alive until the compilation finishes.
  */
 bool
 StartOffThreadParseScript(JSContext* cx, const ReadOnlyCompileOptions& options,
-                          const char16_t* chars, size_t length,
+                          JS::SourceBufferHolder& srcBuf,
                           JS::OffThreadCompileCallback callback, void* callbackData);
 
 bool
 StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                          const char16_t* chars, size_t length,
+                          JS::SourceBufferHolder& srcBuf,
                           JS::OffThreadCompileCallback callback, void* callbackData);
 
 bool
 StartOffThreadDecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
                            const JS::TranscodeRange& range,
                            JS::OffThreadCompileCallback callback, void* callbackData);
 
 #if defined(JS_BUILD_BINAST)
@@ -717,28 +717,28 @@ struct ParseTask : public mozilla::Linke
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
     }
 };
 
 struct ScriptParseTask : public ParseTask
 {
-    JS::TwoByteChars data;
+    JS::SourceBufferHolder data;
 
-    ScriptParseTask(JSContext* cx, const char16_t* chars, size_t length,
+    ScriptParseTask(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                     JS::OffThreadCompileCallback callback, void* callbackData);
     void parse(JSContext* cx) override;
 };
 
 struct ModuleParseTask : public ParseTask
 {
-    JS::TwoByteChars data;
+    JS::SourceBufferHolder data;
 
-    ModuleParseTask(JSContext* cx, const char16_t* chars, size_t length,
+    ModuleParseTask(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                     JS::OffThreadCompileCallback callback, void* callbackData);
     void parse(JSContext* cx) override;
 };
 
 struct ScriptDecodeTask : public ParseTask
 {
     const JS::TranscodeRange range;
 
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -2169,26 +2169,25 @@ JSObject::changeToSingleton(JSContext* c
  * to its outer window and end up with the wrong global. Plain objects don't
  * have this problem, so we use the global's Object.prototype. The code using
  * it - e.g. EnqueuePromiseReactionJob - can then unwrap the object and get
  * its global without fear of unwrapping too far.
  */
 bool
 js::GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj)
 {
-    RootedObject globalObj(cx, cx->runtime()->getIncumbentGlobal(cx));
+    Rooted<GlobalObject*> globalObj(cx, cx->runtime()->getIncumbentGlobal(cx));
     if (!globalObj) {
         obj.set(nullptr);
         return true;
     }
 
     {
         AutoRealm ar(cx, globalObj);
-        Handle<GlobalObject*> global = globalObj.as<GlobalObject>();
-        obj.set(GlobalObject::getOrCreateObjectPrototype(cx, global));
+        obj.set(GlobalObject::getOrCreateObjectPrototype(cx, globalObj));
         if (!obj)
             return false;
     }
 
     // The object might be from a different compartment, so wrap it.
     if (obj && !cx->compartment()->wrap(cx, obj))
         return false;
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -615,37 +615,42 @@ FreeOp::~FreeOp()
 }
 
 bool
 FreeOp::isDefaultFreeOp() const
 {
     return runtime_ && runtime_->defaultFreeOp() == this;
 }
 
-JSObject*
+GlobalObject*
 JSRuntime::getIncumbentGlobal(JSContext* cx)
 {
     // If the embedding didn't set a callback for getting the incumbent
     // global, the currently active global is used.
     if (!cx->getIncumbentGlobalCallback) {
         if (!cx->compartment())
             return nullptr;
         return cx->global();
     }
 
-    return cx->getIncumbentGlobalCallback(cx);
+    if (JSObject* obj = cx->getIncumbentGlobalCallback(cx)) {
+        MOZ_ASSERT(obj->is<GlobalObject>(),
+                   "getIncumbentGlobalCallback must return a global!");
+        return &obj->as<GlobalObject>();
+    }
+
+    return nullptr;
 }
 
 bool
 JSRuntime::enqueuePromiseJob(JSContext* cx, HandleFunction job, HandleObject promise,
-                             HandleObject incumbentGlobal)
+                             Handle<GlobalObject*> incumbentGlobal)
 {
     MOZ_ASSERT(cx->enqueuePromiseJobCallback,
                "Must set a callback using JS::SetEnqueuePromiseJobCallback before using Promises");
-    MOZ_ASSERT_IF(incumbentGlobal, !IsWrapper(incumbentGlobal) && !IsWindowProxy(incumbentGlobal));
 
     void* data = cx->enqueuePromiseJobCallbackData;
     RootedObject allocationSite(cx);
     if (promise) {
         RootedObject unwrappedPromise(cx, promise);
         // While the job object is guaranteed to be unwrapped, the promise
         // might be wrapped. See the comments in EnqueuePromiseReactionJob in
         // builtin/Promise.cpp for details.
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -326,19 +326,19 @@ struct JSRuntime : public js::MallocProv
     void setUseCounter(JSObject* obj, JSUseCounter counter);
 
     void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
 
   public:
     js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;
     js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback;
 
-    JSObject* getIncumbentGlobal(JSContext* cx);
+    js::GlobalObject* getIncumbentGlobal(JSContext* cx);
     bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job, js::HandleObject promise,
-                           js::HandleObject incumbentGlobal);
+                           js::Handle<js::GlobalObject*> incumbentGlobal);
     void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
     void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
 
     js::UnprotectedData<JS::RequestReadableStreamDataCallback> readableStreamDataRequestCallback;
     js::UnprotectedData<JS::WriteIntoReadRequestBufferCallback> readableStreamWriteIntoReadRequestCallback;
     js::UnprotectedData<JS::CancelReadableStreamCallback> readableStreamCancelCallback;
     js::UnprotectedData<JS::ReadableStreamClosedCallback> readableStreamClosedCallback;
     js::UnprotectedData<JS::ReadableStreamErroredCallback> readableStreamErroredCallback;
--- a/js/xpconnect/loader/ChromeScriptLoader.cpp
+++ b/js/xpconnect/loader/ChromeScriptLoader.cpp
@@ -126,29 +126,30 @@ OffThreadScriptLoaderCallback(JS::OffThr
     SystemGroup::Dispatch(TaskCategory::Other, scriptCompiler.forget());
 }
 
 bool
 AsyncScriptCompiler::StartCompile(JSContext* aCx)
 {
     Rooted<JSObject*> global(aCx, mGlobalObject->GetGlobalJSObject());
 
+    JS::SourceBufferHolder srcBuf(std::move(mScriptText), mScriptLength);
     if (JS::CanCompileOffThread(aCx, mOptions, mScriptLength)) {
-        if (!JS::CompileOffThread(aCx, mOptions, mScriptText.get(), mScriptLength,
+        if (!JS::CompileOffThread(aCx, mOptions, srcBuf,
                                   OffThreadScriptLoaderCallback,
                                   static_cast<void*>(this))) {
             return false;
         }
 
         NS_ADDREF(this);
         return true;
     }
 
     Rooted<JSScript*> script(aCx);
-    if (!JS::Compile(aCx, mOptions, mScriptText.get(), mScriptLength, &script)) {
+    if (!JS::Compile(aCx, mOptions, srcBuf, &script)) {
         return false;
     }
 
     Finish(aCx, script);
     return true;
 }
 
 NS_IMETHODIMP
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1844,18 +1844,19 @@ xpc::EvalInSandbox(JSContext* cx, Handle
         // This is clearly Gecko-specific and not in any spec.
         mozilla::dom::AutoEntryScript aes(priv, "XPConnect sandbox evaluation");
         JSContext* sandcx = aes.cx();
         JSAutoRealm ar(sandcx, sandbox);
 
         JS::CompileOptions options(sandcx);
         options.setFileAndLine(filenameBuf.get(), lineNo);
         MOZ_ASSERT(JS_IsGlobalObject(sandbox));
-        ok = JS::Evaluate(sandcx, options,
-                          PromiseFlatString(source).get(), source.Length(), &v);
+        JS::SourceBufferHolder buffer(PromiseFlatString(source).get(), source.Length(),
+                                      JS::SourceBufferHolder::NoOwnership);
+        ok = JS::Evaluate(sandcx, options, buffer, &v);
 
         // If the sandbox threw an exception, grab it off the context.
         if (aes.HasException()) {
             if (!aes.StealException(&exn)) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
         }
     }
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -124,17 +124,20 @@ const char* const XPCJSRuntime::mStrings
 class AsyncFreeSnowWhite : public Runnable
 {
 public:
   NS_IMETHOD Run() override
   {
       AUTO_PROFILER_LABEL("AsyncFreeSnowWhite::Run", GCCC);
 
       TimeStamp start = TimeStamp::Now();
-      bool hadSnowWhiteObjects = nsCycleCollector_doDeferredDeletion();
+      // 2 ms budget, given that kICCSliceBudget is only 3 ms
+      js::SliceBudget budget = js::SliceBudget(js::TimeBudget(2));
+      bool hadSnowWhiteObjects =
+        nsCycleCollector_doDeferredDeletionWithBudget(budget);
       Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING,
                             uint32_t((TimeStamp::Now() - start).ToMilliseconds()));
       if (hadSnowWhiteObjects && !mContinuation) {
           mContinuation = true;
           if (NS_FAILED(Dispatch())) {
               mActive = false;
           }
       } else {
@@ -159,17 +162,17 @@ public:
 
   nsresult Dispatch()
   {
       if (recordreplay::IsRecordingOrReplaying()) {
           recordreplay::ActivateTrigger(this);
           return NS_OK;
       }
       nsCOMPtr<nsIRunnable> self(this);
-      return NS_IdleDispatchToCurrentThread(self.forget(), 2500);
+      return NS_IdleDispatchToCurrentThread(self.forget(), 500);
   }
 
   void Start(bool aContinuation = false, bool aPurge = false)
   {
       if (mContinuation) {
           mContinuation = aContinuation;
       }
       mPurge = aPurge;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -544,18 +544,17 @@ nsXPCWrappedJSClass::DelegatedQueryInter
     }
 
     // QI on an XPCWrappedJS can run script, so we need an AutoEntryScript.
     // This is inherently Gecko-specific.
     // We check both nativeGlobal and nativeGlobal->GetGlobalJSObject() even
     // though we have derived nativeGlobal from the JS global, because we know
     // there are cases where this can happen. See bug 1094953.
     RootedObject obj(RootingCx(), self->GetJSObject());
-    nsIGlobalObject* nativeGlobal =
-      NativeGlobal(JS::GetNonCCWObjectGlobal(js::UncheckedUnwrap(obj)));
+    nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
     NS_ENSURE_TRUE(nativeGlobal, NS_ERROR_FAILURE);
     NS_ENSURE_TRUE(nativeGlobal->GetGlobalJSObject(), NS_ERROR_FAILURE);
     AutoEntryScript aes(nativeGlobal, "XPCWrappedJS QueryInterface",
                         /* aIsMainThread = */ true);
     XPCCallContext ccx(aes.cx());
     if (!ccx.IsValid()) {
         *aInstancePtr = nullptr;
         return NS_NOINTERFACE;
@@ -942,18 +941,17 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
     nsID  param_iid;
     const char* name = info->GetName();
     bool foundDependentParam;
 
     // We're about to call into script via an XPCWrappedJS, so we need an
     // AutoEntryScript. This is probably Gecko-specific at this point, and
     // definitely will be when we turn off XPConnect for the web.
     RootedObject obj(RootingCx(), wrapper->GetJSObject());
-    nsIGlobalObject* nativeGlobal =
-      NativeGlobal(JS::GetNonCCWObjectGlobal(js::UncheckedUnwrap(obj)));
+    nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
     AutoEntryScript aes(nativeGlobal, "XPCWrappedJS method call",
                         /* aIsMainThread = */ true);
     XPCCallContext ccx(aes.cx());
     if (!ccx.IsValid())
         return retval;
 
     JSContext* cx = ccx.GetJSContext();
 
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -498,20 +498,22 @@ PrivilegedJunkScope();
 /**
  * Shared compilation scope for XUL prototype documents and XBL
  * precompilation.
  */
 JSObject*
 CompilationScope();
 
 /**
- * Returns the nsIGlobalObject corresponding to |aObj|'s JS global.
+ * Returns the nsIGlobalObject corresponding to |obj|'s JS global. |obj| must
+ * not be a cross-compartment wrapper: CCWs are not associated with a single
+ * global.
  */
 nsIGlobalObject*
-NativeGlobal(JSObject* aObj);
+NativeGlobal(JSObject* obj);
 
 /**
  * Returns the nsIGlobalObject corresponding to |cx|'s JS global. Must not be
  * called when |cx| is not in a Realm.
  */
 nsIGlobalObject*
 CurrentNativeGlobal(JSContext* cx);
 
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -668,17 +668,17 @@ TransplantObjectRetainingXrayExpandos(JS
     }
 
     return newIdentity;
 }
 
 nsIGlobalObject*
 NativeGlobal(JSObject* obj)
 {
-    obj = js::GetGlobalForObjectCrossCompartment(obj);
+    obj = JS::GetNonCCWObjectGlobal(obj);
 
     // Every global needs to hold a native as its private or be a
     // WebIDL object with an nsISupports DOM object.
     MOZ_ASSERT((GetObjectClass(obj)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
                                              JSCLASS_HAS_PRIVATE)) ||
                dom::UnwrapDOMObjectToISupports(obj));
 
     nsISupports* native = dom::UnwrapDOMObjectToISupports(obj);
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1871,18 +1871,17 @@ nsCSSFrameConstructor::CreateGeneratedCo
 
   // If the parent is in a shadow tree, make sure we don't
   // bind with a document because shadow roots and its descendants
   // are not in document.
   nsIDocument* bindDocument =
     aOriginatingElement.HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
   rv = container->BindToTree(bindDocument,
                              &aOriginatingElement,
-                             &aOriginatingElement,
-                             true);
+                             &aOriginatingElement);
   if (NS_FAILED(rv)) {
     container->UnbindFromTree();
     return;
   }
 
   // Servo has already eagerly computed the style for the container, so we can
   // just stick the style on the element and avoid an additional traversal.
   //
@@ -4101,17 +4100,17 @@ nsCSSFrameConstructor::GetAnonymousConte
 
     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
 
     // If the parent is in a shadow tree, make sure we don't
     // bind with a document because shadow roots and its descendants
     // are not in document.
     nsIDocument* bindDocument =
       aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
-    rv = content->BindToTree(bindDocument, aParent, aParent, true);
+    rv = content->BindToTree(bindDocument, aParent, aParent);
     // If the anonymous content creator requested that the content should be
     // editable, honor its request.
     // We need to set the flag on the whole subtree, because existing
     // children's flags have already been set as part of the BindToTree operation.
     if (anonContentIsEditable) {
       NS_ASSERTION(aParentFrame->IsTextInputFrame(),
                    "We only expect this for anonymous content under a text control frame");
       SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
--- a/layout/style/nsCSSPseudoElementList.h
+++ b/layout/style/nsCSSPseudoElementList.h
@@ -85,15 +85,13 @@ CSS_PSEUDO_ELEMENT(mozProgressBar, ":-mo
 CSS_PSEUDO_ELEMENT(mozRangeTrack, ":-moz-range-track",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
 CSS_PSEUDO_ELEMENT(mozRangeProgress, ":-moz-range-progress",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
 CSS_PSEUDO_ELEMENT(mozRangeThumb, ":-moz-range-thumb",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
 CSS_PSEUDO_ELEMENT(mozMeterBar, ":-moz-meter-bar",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
-CSS_PSEUDO_ELEMENT(mozPlaceholder, ":-moz-placeholder",
-                   CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
 CSS_PSEUDO_ELEMENT(placeholder, ":placeholder",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
 CSS_PSEUDO_ELEMENT(mozColorSwatch, ":-moz-color-swatch",
                    CSS_PSEUDO_ELEMENT_SUPPORTS_STYLE_ATTRIBUTE |
                    CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE)
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -82,25 +82,21 @@ nsCSSPseudoElements::IsCSS2PseudoElement
                result == PseudoElementHasFlags(
                    GetPseudoType(aAtom, EnabledState::eIgnoreEnabledState),
                    CSS_PSEUDO_ELEMENT_IS_CSS2),
                "result doesn't match flags");
   return result;
 }
 
 /* static */ CSSPseudoElementType
-nsCSSPseudoElements::GetPseudoType(nsAtom *aAtom, EnabledState aEnabledState)
+nsCSSPseudoElements::GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState)
 {
   Maybe<uint32_t> index = nsStaticAtomUtils::Lookup(aAtom, sAtoms, sAtomsLen);
   if (index.isSome()) {
     auto type = static_cast<Type>(*index);
-    // ::moz-placeholder is an alias for ::placeholder
-    if (type == CSSPseudoElementType::mozPlaceholder) {
-      type = CSSPseudoElementType::placeholder;
-    }
     return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
   }
 
   if (nsCSSAnonBoxes::IsAnonBox(aAtom)) {
 #ifdef MOZ_XUL
     if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) {
       return Type::XULTree;
     }
--- a/layout/style/test/test_selectors.html
+++ b/layout/style/test/test_selectors.html
@@ -963,18 +963,18 @@ function run() {
     // Test serialization of pseudo-elements.
     should_serialize_to("p::first-letter", "p::first-letter");
     should_serialize_to("p:first-letter", "p::first-letter");
     should_serialize_to("div>p:first-letter", "div > p::first-letter");
     should_serialize_to("span +div:first-line", "span + div::first-line");
     should_serialize_to("input::placeholder", "input::placeholder");
     should_serialize_to("input:placeholder-shown", "input:placeholder-shown");
 
-    // Test serialization of non CSS2 pseudo-element.
-    should_serialize_to("input::-moz-placeholder", "input::-moz-placeholder");
+    // Test serialization of ::-moz-placeholder.
+    should_serialize_to("input::-moz-placeholder", "input::placeholder");
 
     // Test default namespaces, including inside :not().
     var html_default_ns = "@namespace url(http://www.w3.org/1999/xhtml);";
     var html_ns = "@namespace html url(http://www.w3.org/1999/xhtml);";
     var xul_default_ns = "@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);";
     var single_a = "<a id='a' href='data:text/plain,this_better_be_unvisited'></a>";
     var set_single = idset(['a']);
     var empty_set = idset([]);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2,16 +2,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/. */
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/DelayedInit.jsm");
+ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm");
 ChromeUtils.import("resource://gre/modules/Messaging.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/TelemetryController.jsm");
 
 if (AppConstants.ACCESSIBILITY) {
   ChromeUtils.defineModuleGetter(this, "AccessFu",
                                  "resource://gre/modules/accessibility/AccessFu.jsm");
@@ -384,16 +385,21 @@ var BrowserApp = {
       "Session:Forward",
       "Session:GetHistory",
       "Session:Navigate",
       "Session:Reload",
       "Session:Stop",
       "Telemetry:CustomTabsPing",
     ]);
 
+    // Initialize the default l10n resource sources for L10nRegistry.
+    let locales = Services.locale.getPackagedLocales();
+    const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
+    L10nRegistry.registerSource(greSource);
+
     // Provide compatibility for add-ons like QuitNow that send "Browser:Quit"
     // as an observer notification.
     Services.obs.addObserver((subject, topic, data) =>
         this.quit(data ? JSON.parse(data) : undefined), "Browser:Quit");
 
     Services.obs.addObserver(this, "android-get-pref");
     Services.obs.addObserver(this, "android-set-pref");
     Services.obs.addObserver(this, "gather-telemetry");
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -67,18 +67,16 @@ chrome.jar:
 % override chrome://global/locale/charsetMenu.properties chrome://browser/locale/overrides/charsetMenu.properties
 % override chrome://global/locale/commonDialogs.properties chrome://browser/locale/overrides/commonDialogs.properties
 % override chrome://global/locale/intl.properties chrome://browser/locale/overrides/intl.properties
 % override chrome://global/locale/intl.css chrome://browser/locale/overrides/intl.css
 % override chrome://global/locale/search/search.properties chrome://browser/locale/overrides/search/search.properties
 % override chrome://pluginproblem/locale/pluginproblem.dtd chrome://browser/locale/overrides/plugins/pluginproblem.dtd
 % override chrome://global/locale/aboutSupport.dtd chrome://browser/locale/overrides/global/aboutSupport.dtd
 % override chrome://global/locale/aboutSupport.properties chrome://browser/locale/overrides/global/aboutSupport.properties
-% override chrome://global/locale/crashes.dtd chrome://browser/locale/overrides/crashreporter/crashes.dtd
-% override chrome://global/locale/crashes.properties chrome://browser/locale/overrides/crashreporter/crashes.properties
 % override chrome://global/locale/mozilla.dtd chrome://browser/locale/overrides/global/mozilla.dtd
 % override chrome://global/locale/aboutTelemetry.dtd chrome://browser/locale/overrides/global/aboutTelemetry.dtd
 % override chrome://global/locale/aboutTelemetry.properties chrome://browser/locale/overrides/global/aboutTelemetry.properties
 % override chrome://global/locale/aboutWebrtc.properties chrome://browser/locale/overrides/global/aboutWebrtc.properties
 
 # overrides for dom l10n, also for en-US
 # keep this file list in sync with filter.py
 % override chrome://global/locale/global.dtd chrome://browser/locale/overrides/global.dtd
--- a/mobile/android/components/geckoview/GeckoViewStartup.js
+++ b/mobile/android/components/geckoview/GeckoViewStartup.js
@@ -1,17 +1,19 @@
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  FileSource: "resource://gre/modules/L10nRegistry.jsm",
   GeckoViewTelemetryController: "resource://gre/modules/GeckoViewTelemetryController.jsm",
   GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
+  L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
   Services: "resource://gre/modules/Services.jsm",
 });
 
 const {debug, warn} = GeckoViewUtils.initLogging("GeckoViewStartup", this);
 
 function GeckoViewStartup() {
 }
 
@@ -106,15 +108,20 @@ GeckoViewStartup.prototype = {
         }, {
           handler: _ => this.GeckoViewRemoteDebugger,
         });
 
         // This initializes Telemetry for GeckoView only in the parent process.
         // The Telemetry initialization for the content process is performed in
         // ContentProcessSingleton.js for consistency with Desktop Telemetry.
         GeckoViewTelemetryController.setup();
+
+        // Initialize the default l10n resource sources for L10nRegistry.
+        let locales = Services.locale.getPackagedLocales();
+        const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
+        L10nRegistry.registerSource(greSource);
         break;
       }
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GeckoViewStartup]);
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -195,41 +195,24 @@ public final class GeckoRuntimeSettings 
             return this;
         }
 
         /**
          * Set the cookie lifetime.
          *
          * @param lifetime The enforced cookie lifetime.
          *                 Use one of the {@link #COOKIE_LIFETIME_NORMAL COOKIE_LIFETIME_*} flags.
-         *                 Use {@link #cookieLifetimeDays} to set expiration
-         *                 days for {@link #COOKIE_LIFETIME_DAYS}.
          * @return The Builder instance.
          */
         public @NonNull Builder cookieLifetime(@CookieLifetime int lifetime) {
             mSettings.mCookieLifetime.set(lifetime);
             return this;
         }
 
         /**
-         * Set the expiration days for {@link #COOKIE_LIFETIME_DAYS}.
-         *
-         * @param days Limit lifetime to N days. Only enforced for {@link #COOKIE_LIFETIME_DAYS}.
-         * @return The Builder instance.
-         */
-        public @NonNull Builder cookieLifetimeDays(int days) {
-            if (mSettings.mCookieLifetime.get() != COOKIE_LIFETIME_DAYS) {
-                throw new IllegalStateException(
-                    "Setting expiration days for incompatible cookie lifetime");
-            }
-            mSettings.mCookieLifetimeDays.set(days);
-            return this;
-        }
-
-        /**
          * Set tracking protection blocking categories.
          *
          * @param categories The categories of trackers that should be blocked.
          *                   Use one or more of the
          *                   {@link TrackingProtectionDelegate#CATEGORY_AD TrackingProtectionDelegate.CATEGORY_*} flags.
          * @return This Builder instance.
          **/
         public @NonNull Builder trackingProtectionCategories(
@@ -297,35 +280,33 @@ public final class GeckoRuntimeSettings 
     /* package */ Pref<Boolean> mRemoteDebugging = new Pref<Boolean>(
         "devtools.debugger.remote-enabled", false);
     /* package */ Pref<Boolean> mWebFonts = new Pref<Boolean>(
         "browser.display.use_document_fonts", true);
     /* package */ Pref<Integer> mCookieBehavior = new Pref<Integer>(
         "network.cookie.cookieBehavior", COOKIE_ACCEPT_ALL);
     /* package */ Pref<Integer> mCookieLifetime = new Pref<Integer>(
         "network.cookie.lifetimePolicy", COOKIE_LIFETIME_NORMAL);
-    /* package */ Pref<Integer> mCookieLifetimeDays = new Pref<Integer>(
-        "network.cookie.lifetime.days", 90);
     /* package */ Pref<String> mTrackingProtection = new Pref<String>(
         "urlclassifier.trackingTable",
         TrackingProtection.buildPrefValue(
             TrackingProtectionDelegate.CATEGORY_TEST |
             TrackingProtectionDelegate.CATEGORY_ANALYTIC |
             TrackingProtectionDelegate.CATEGORY_SOCIAL |
             TrackingProtectionDelegate.CATEGORY_AD));
     /* package */ Pref<Boolean> mConsoleOutput = new Pref<Boolean>(
         "geckoview.console.enabled", false);
 
     /* package */ boolean mNativeCrashReporting;
     /* package */ boolean mJavaCrashReporting;
     /* package */ int mCrashReportingJobId;
     /* package */ boolean mDebugPause;
 
     private final Pref<?>[] mPrefs = new Pref<?>[] {
-        mCookieBehavior, mCookieLifetime, mCookieLifetimeDays, mConsoleOutput,
+        mCookieBehavior, mCookieLifetime, mConsoleOutput,
         mJavaScript, mRemoteDebugging, mTrackingProtection, mWebFonts
     };
 
     /* package */ GeckoRuntimeSettings() {
         this(null);
     }
 
     /* package */ GeckoRuntimeSettings(final @Nullable GeckoRuntimeSettings settings) {
@@ -556,57 +537,29 @@ public final class GeckoRuntimeSettings 
      *
      * @return The assigned lifetime, as one of {@link #COOKIE_LIFETIME_NORMAL COOKIE_LIFETIME_*} flags.
      */
     public @CookieBehavior int getCookieLifetime() {
         return mCookieLifetime.get();
     }
 
     /**
-     * Get the enforced lifetime expiration days.
-     *
-     * Note: This is only enforced for {@link #COOKIE_LIFETIME_DAYS}.
-     *
-     * @return The enforced expiration days.
-     */
-    public int getCookieLifetimeDays() {
-        return mCookieLifetimeDays.get();
-    }
-
-    /**
      * Set the cookie lifetime.
      *
      * @param lifetime The enforced cookie lifetime.
      *                 Use one of the {@link #COOKIE_LIFETIME_NORMAL COOKIE_LIFETIME_*} flags.
-     *                 Use {@link #setCookieLifetimeDays} to set expiration
-     *                 days for {@link #COOKIE_LIFETIME_DAYS}.
      * @return This GeckoRuntimeSettings instance.
      */
     public @NonNull GeckoRuntimeSettings setCookieLifetime(
             @CookieLifetime int lifetime) {
         mCookieLifetime.set(lifetime);
         return this;
     }
 
     /**
-     * Set the expiration days for {@link #COOKIE_LIFETIME_DAYS}.
-     *
-     * @param days Limit lifetime to N days. Only enforced for {@link #COOKIE_LIFETIME_DAYS}.
-     * @return This GeckoRuntimeSettings instance.
-     */
-    public @NonNull GeckoRuntimeSettings setCookieLifetimeDays(int days) {
-        if (mCookieLifetime.get() != COOKIE_LIFETIME_DAYS) {
-            throw new IllegalStateException(
-                "Setting expiration days for incompatible cookie lifetime");
-        }
-        mCookieLifetimeDays.set(days);
-        return this;
-    }
-
-    /**
      * Get the set tracking protection blocking categories.
      *
      * @return categories The categories of trackers that are set to be blocked.
      *                    Use one or more of the
      *                    {@link TrackingProtectionDelegate#CATEGORY_AD TrackingProtectionDelegate.CATEGORY_*} flags.
      **/
     public @TrackingProtectionDelegate.Category int getTrackingProtectionCategories() {
         return TrackingProtection.listToCategory(mTrackingProtection.get());
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -17,16 +17,17 @@
 [@AB_CD@]
 @BINPATH@/@PREF_DIR@/mobile-l10n.js
 @BINPATH@/update.locale
 #ifdef MOZ_UPDATER
 @BINPATH@/updater.ini
 #endif
 @BINPATH@/dictionaries/*
 @BINPATH@/hyphenation/*
+@BINPATH@/localization/*
 
 [assets destdir="assets/@ANDROID_CPU_ARCH@"]
 #ifndef MOZ_STATIC_JS
 @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
 #endif
 #ifdef MOZ_DMD
 @BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
 #endif
--- a/mobile/android/locales/filter.py
+++ b/mobile/android/locales/filter.py
@@ -24,22 +24,24 @@ def test(mod, path, entity=None):
             "chrome/global/charsetMenu.properties",
             "chrome/global/commonDialogs.properties",
             "chrome/global/intl.properties",
             "chrome/global/intl.css",
             "chrome/search/search.properties",
             "chrome/pluginproblem/pluginproblem.dtd",
             "chrome/global/aboutSupport.dtd",
             "chrome/global/aboutSupport.properties",
-            "crashreporter/crashes.dtd",
-            "crashreporter/crashes.properties",
             "chrome/global/mozilla.dtd",
             "chrome/global/aboutTelemetry.dtd",
             "chrome/global/aboutTelemetry.properties",
-            "chrome/global/aboutWebrtc.properties"):
+            "chrome/global/aboutWebrtc.properties",
+        ):
+            return "error"
+        if re.match(r"crashreporter/[^/]*.ftl", path):
+            # error on crashreporter/*.ftl
             return "error"
         return "ignore"
 
     if mod == "dom":
         # keep this file list in sync with jar.mn
         if path in (
             "chrome/global.dtd",
             "chrome/accessibility/AccessFu.properties",
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -45,27 +45,37 @@ relativesrcdir toolkit/locales:
   locale/@AB_CD@/browser/overrides/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/browser/overrides/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/browser/overrides/search/search.properties        (%chrome/search/search.properties)
 # plugins
   locale/@AB_CD@/browser/overrides/plugins/pluginproblem.dtd       (%chrome/pluginproblem/pluginproblem.dtd)
 # about:support
   locale/@AB_CD@/browser/overrides/global/aboutSupport.dtd         (%chrome/global/aboutSupport.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutSupport.properties  (%chrome/global/aboutSupport.properties)
-#about:crashes
-  locale/@AB_CD@/browser/overrides/crashreporter/crashes.dtd         (%crashreporter/crashes.dtd)
-  locale/@AB_CD@/browser/overrides/crashreporter/crashes.properties  (%crashreporter/crashes.properties)
 #about:mozilla
   locale/@AB_CD@/browser/overrides/global/mozilla.dtd                (%chrome/global/mozilla.dtd)
 #about:telemetry
   locale/@AB_CD@/browser/overrides/global/aboutTelemetry.dtd         (%chrome/global/aboutTelemetry.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutTelemetry.properties  (%chrome/global/aboutTelemetry.properties)
 #about:webrtc
   locale/@AB_CD@/browser/overrides/global/aboutWebrtc.properties  (%chrome/global/aboutWebrtc.properties)
 
 # overrides for dom l10n, also for en-US
 # keep this file list in sync with filter.py
 relativesrcdir dom/locales:
   locale/@AB_CD@/browser/overrides/global.dtd                  (%chrome/global.dtd)
   locale/@AB_CD@/browser/overrides/AccessFu.properties         (%chrome/accessibility/AccessFu.properties)
   locale/@AB_CD@/browser/overrides/dom/dom.properties          (%chrome/dom/dom.properties)
 #about:plugins
   locale/@AB_CD@/browser/overrides/plugins.properties          (%chrome/plugins.properties)
+
+# Fluent files
+# Note: All rules must be wildcards, as localized files are optional
+# Only run this if we're not en-US, as en-US is already built
+# by toolkit/locales/jar.mn.
+
+#define EN_US en-US
+#if AB_CD != EN_US
+[localization] @AB_CD@.jar:
+relativesrcdir toolkit/locales:
+#about:crashes
+  crashreporter                                    (%crashreporter/**/*.ftl)
+#endif
--- a/mobile/android/locales/l10n.toml
+++ b/mobile/android/locales/l10n.toml
@@ -197,16 +197,20 @@ exclude-multi-locale = [
     reference = "toolkit/locales/en-US/chrome/global/aboutSupport.dtd"
     l10n = "{l}toolkit/chrome/global/aboutSupport.dtd"
 
 [[paths]]
     reference = "toolkit/locales/en-US/chrome/global/aboutSupport.properties"
     l10n = "{l}toolkit/chrome/global/aboutSupport.properties"
 
 [[paths]]
+    reference = "toolkit/locales/en-US/crashreporter/*.ftl"
+    l10n = "{l}toolkit/crashreporter/*.ftl"
+
+[[paths]]
     reference = "toolkit/locales/en-US/crashreporter/crashes.dtd"
     l10n = "{l}toolkit/crashreporter/crashes.dtd"
 
 [[paths]]
     reference = "toolkit/locales/en-US/crashreporter/crashes.properties"
     l10n = "{l}toolkit/crashreporter/crashes.properties"
 
 [[paths]]
--- a/mobile/locales/filter.py
+++ b/mobile/locales/filter.py
@@ -24,22 +24,24 @@ def test(mod, path, entity=None):
             "chrome/global/charsetMenu.properties",
             "chrome/global/commonDialogs.properties",
             "chrome/global/intl.properties",
             "chrome/global/intl.css",
             "chrome/search/search.properties",
             "chrome/pluginproblem/pluginproblem.dtd",
             "chrome/global/aboutSupport.dtd",
             "chrome/global/aboutSupport.properties",
-            "crashreporter/crashes.dtd",
-            "crashreporter/crashes.properties",
             "chrome/global/mozilla.dtd",
             "chrome/global/aboutTelemetry.dtd",
             "chrome/global/aboutTelemetry.properties",
-            "chrome/global/aboutWebrtc.properties"):
+            "chrome/global/aboutWebrtc.properties",
+        ):
+            return "error"
+        if re.match(r"crashreporter/[^/]*.ftl", path):
+            # error on crashreporter/*.ftl
             return "error"
         return "ignore"
 
     if mod == "dom":
         # keep this file list in sync with jar.mn
         if path in (
             "chrome/global.dtd",
             "chrome/accessibility/AccessFu.properties",
@@ -47,17 +49,17 @@ def test(mod, path, entity=None):
             "chrome/plugins.properties"):
             return "error"
         return "ignore"
 
     if mod not in ("mobile", "mobile/android"):
         # we only have exceptions for mobile*
         return "error"
     if mod == "mobile/android":
-        if not entity:
+        if entity is None:
             if (re.match(r"mobile-l10n.js", path) or
                 re.match(r"defines.inc", path)):
                 return "ignore"
         if path == "defines.inc":
             if entity == "MOZ_LANGPACK_CONTRIBUTORS":
                 return "ignore"
         return "error"
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2238,19 +2238,24 @@ pref("network.proxy.proxy_over_tls",    
 pref("network.proxy.no_proxies_on",         "localhost, 127.0.0.1");
 pref("network.proxy.failover_timeout",      1800); // 30 minutes
 pref("network.online",                      true); //online/offline
 pref("network.cookie.thirdparty.sessionOnly", false);
 pref("network.cookie.thirdparty.nonsecureSessionOnly", false);
 pref("network.cookie.leave-secure-alone",   true);
 pref("network.cookie.same-site.enabled",    true); // Honor the SameSite cookie attribute
 pref("network.cookie.ipc.sync",             false);
-pref("network.cookie.lifetimePolicy",       0); // 0-accept, 2-acceptForSession, 3-acceptForNDays
-pref("network.cookie.prefsMigrated",        false);
-pref("network.cookie.lifetime.days",        90); // Ignored unless network.cookie.lifetimePolicy is 3.
+
+// Cookie lifetime policy. Possible values:
+// 0 - accept all cookies
+// 1 - deprecated. don't use it.
+// 2 - accept as session cookies
+// 3 - deprecated. don't use it.
+pref("network.cookie.lifetimePolicy",       0);
+
 // The interval in seconds to move the cookies in the child process.
 // Set to 0 to disable moving the cookies.
 pref("network.cookie.move.interval_sec",    10);
 
 pref("network.cookie.maxNumber", 3000);
 pref("network.cookie.maxPerHost", 180);
 
 // The PAC file to load.  Ignored unless network.proxy.type is 2.
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -121,16 +121,17 @@ XPIDL_SOURCES += [
     'nsITraceableChannel.idl',
     'nsITransport.idl',
     'nsIUDPSocket.idl',
     'nsIUploadChannel.idl',
     'nsIUploadChannel2.idl',
     'nsIURI.idl',
     'nsIURIClassifier.idl',
     'nsIURIMutator.idl',
+    'nsIURIWithSpecialOrigin.idl',
     'nsIURL.idl',
     'nsIURLParser.idl',
     'nsPILoadGroupInternal.idl',
     'nsPISocketTransportService.idl',
 ]
 
 if CONFIG['MOZ_TOOLKIT_SEARCH']:
     XPIDL_SOURCES += [
new file mode 100644
--- /dev/null
+++ b/netwerk/base/nsIURIWithSpecialOrigin.idl
@@ -0,0 +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 nsIURI;
+
+/**
+ * nsIURIWithSpecialOrigin is implemented by URIs need to supply an origin that
+ * does not match the spec. This is exclusively used in comm-central's Mailnews module.
+ */
+[scriptable, builtinclass, uuid(4f65569b-d6fc-4580-94d9-21e775658a2a)]
+interface nsIURIWithSpecialOrigin : nsISupports
+{
+    /**
+     * Special origin.
+     */
+    readonly attribute nsIURI origin;
+};
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -56,16 +56,17 @@
 #include "nsISocketProviderService.h"
 #include "nsIStandardURL.h"
 #include "nsIStreamLoader.h"
 #include "nsIIncrementalStreamLoader.h"
 #include "nsIStreamTransportService.h"
 #include "nsStringStream.h"
 #include "nsISyncStreamListener.h"
 #include "nsITransport.h"
+#include "nsIURIWithSpecialOrigin.h"
 #include "nsIURLParser.h"
 #include "nsIUUIDGenerator.h"
 #include "nsIViewSourceChannel.h"
 #include "nsInterfaceRequestorAgg.h"
 #include "plstr.h"
 #include "nsINestedURI.h"
 #include "mozilla/dom/nsCSPUtils.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
@@ -2458,16 +2459,18 @@ NS_SecurityHashURI(nsIURI *aURI)
     return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI));
 }
 
 bool
 NS_SecurityCompareURIs(nsIURI *aSourceURI,
                        nsIURI *aTargetURI,
                        bool    aStrictFileOriginPolicy)
 {
+    nsresult rv;
+
     // Note that this is not an Equals() test on purpose -- for URIs that don't
     // support host/port, we want equality to basically be object identity, for
     // security purposes.  Otherwise, for example, two javascript: URIs that
     // are otherwise unrelated could end up "same origin", which would be
     // unfortunate.
     if (aSourceURI && aSourceURI == aTargetURI)
     {
         return true;
@@ -2477,31 +2480,54 @@ NS_SecurityCompareURIs(nsIURI *aSourceUR
     {
         return false;
     }
 
     // If either URI is a nested URI, get the base URI
     nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
     nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
 
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+    // Check if either URI has a special origin.
+    nsCOMPtr<nsIURI> origin;
+    nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = do_QueryInterface(sourceBaseURI);
+    if (uriWithSpecialOrigin) {
+      rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return false;
+      }
+      MOZ_ASSERT(origin);
+      sourceBaseURI = origin;
+    }
+    uriWithSpecialOrigin = do_QueryInterface(targetBaseURI);
+    if (uriWithSpecialOrigin) {
+      rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return false;
+      }
+      MOZ_ASSERT(origin);
+      targetBaseURI = origin;
+    }
+#endif
+
     nsCOMPtr<nsIPrincipal> sourceBlobPrincipal;
     if (BlobURLProtocolHandler::GetBlobURLPrincipal(sourceBaseURI,
                                                     getter_AddRefs(sourceBlobPrincipal))) {
       nsCOMPtr<nsIURI> sourceBlobOwnerURI;
-      nsresult rv = sourceBlobPrincipal->GetURI(getter_AddRefs(sourceBlobOwnerURI));
+      rv = sourceBlobPrincipal->GetURI(getter_AddRefs(sourceBlobOwnerURI));
       if (NS_SUCCEEDED(rv)) {
         sourceBaseURI = sourceBlobOwnerURI;
       }
     }
 
     nsCOMPtr<nsIPrincipal> targetBlobPrincipal;
     if (BlobURLProtocolHandler::GetBlobURLPrincipal(targetBaseURI,
                                                     getter_AddRefs(targetBlobPrincipal))) {
       nsCOMPtr<nsIURI> targetBlobOwnerURI;
-      nsresult rv = targetBlobPrincipal->GetURI(getter_AddRefs(targetBlobOwnerURI));
+      rv = targetBlobPrincipal->GetURI(getter_AddRefs(targetBlobOwnerURI));
       if (NS_SUCCEEDED(rv)) {
         targetBaseURI = targetBlobOwnerURI;
       }
     }
 
     if (!sourceBaseURI || !targetBaseURI)
         return false;
 
@@ -2535,17 +2561,17 @@ NS_SecurityCompareURIs(nsIURI *aSourceUR
         sourceFileURL->GetFile(getter_AddRefs(sourceFile));
         targetFileURL->GetFile(getter_AddRefs(targetFile));
 
         if (!sourceFile || !targetFile)
             return false;
 
         // Otherwise they had better match
         bool filesAreEqual = false;
-        nsresult rv = sourceFile->Equals(targetFile, &filesAreEqual);
+        rv = sourceFile->Equals(targetFile, &filesAreEqual);
         return NS_SUCCEEDED(rv) && filesAreEqual;
     }
 
 #if IS_ORIGIN_IS_FULL_SPEC_DEFINED
     bool hasFlag;
     if (NS_FAILED(NS_URIChainHasFlags(targetBaseURI,
         nsIProtocolHandler::ORIGIN_IS_FULL_SPEC, &hasFlag)) ||
         hasFlag)
--- a/netwerk/cookie/nsICookieService.idl
+++ b/netwerk/cookie/nsICookieService.idl
@@ -91,17 +91,17 @@ interface nsICookieService : nsISupports
                                               // eTLD already has at least one cookie
 
   /*
    * Possible values for the "network.cookie.lifetimePolicy" preference.
    */
   const uint32_t ACCEPT_NORMALLY   = 0; // accept normally
   // Value = 1 is considered the same as 0 (See Bug 606655).
   const uint32_t ACCEPT_SESSION    = 2; // downgrade to session
-  const uint32_t ACCEPT_FOR_N_DAYS = 3; // limit lifetime to N days
+  // Value = 3 is considered the same as 0
 
   /*
    * Get the complete cookie string associated with the URI.
    *
    * @param aURI
    *        The URI of the document for which cookies are being queried.
    *        file:// URIs (i.e. with an empty host) are allowed, but any other
    *        scheme must have a non-empty host. A trailing dot in the host
--- a/netwerk/test/TestCookie.cpp
+++ b/netwerk/test/TestCookie.cpp
@@ -25,19 +25,16 @@
 
 using mozilla::Unused;
 
 static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID);
 static NS_DEFINE_CID(kPrefServiceCID,   NS_PREFSERVICE_CID);
 
 // various pref strings
 static const char kCookiesPermissions[] = "network.cookie.cookieBehavior";
-static const char kCookiesLifetimeEnabled[] = "network.cookie.lifetime.enabled";
-static const char kCookiesLifetimeDays[] = "network.cookie.lifetime.days";
-static const char kCookiesLifetimeCurrentSession[] = "network.cookie.lifetime.behavior";
 static const char kCookiesMaxPerHost[] = "network.cookie.maxPerHost";
 static const char kCookieLeaveSecurityAlone[] = "network.cookie.leave-secure-alone";
 
 #define OFFSET_ONE_WEEK int64_t(604800) * PR_USEC_PER_SEC
 #define OFFSET_ONE_DAY int64_t(86400) * PR_USEC_PER_SEC
 
 //Set server time or expiry time
 void
@@ -176,19 +173,16 @@ CheckResult(const char *aLhs, uint32_t a
 
 void
 InitPrefs(nsIPrefBranch *aPrefBranch)
 {
     // init some relevant prefs, so the tests don't go awry.
     // we use the most restrictive set of prefs we can;
     // however, we don't test third party blocking here.
     aPrefBranch->SetIntPref(kCookiesPermissions, 0); // accept all
-    aPrefBranch->SetBoolPref(kCookiesLifetimeEnabled, true);
-    aPrefBranch->SetIntPref(kCookiesLifetimeCurrentSession, 0);
-    aPrefBranch->SetIntPref(kCookiesLifetimeDays, 1);
     aPrefBranch->SetBoolPref(kCookieLeaveSecurityAlone, true);
     // Set the base domain limit to 50 so we have a known value.
     aPrefBranch->SetIntPref(kCookiesMaxPerHost, 50);
 }
 
 
 TEST(TestCookie,TestCookieMain)
 {
new file mode 100644
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1476034_aboutcrashes.py
@@ -0,0 +1,35 @@
+# coding=utf8
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from __future__ import absolute_import
+import fluent.syntax.ast as FTL
+from fluent.migrate.helpers import transforms_from
+
+
+def migrate(ctx):
+    """Bug 1476034 - about:crashes localization migration from DTD to Fluent"""
+
+    ctx.add_transforms(
+        "toolkit/crashreporter/aboutcrashes.ftl",
+        "toolkit/crashreporter/aboutcrashes.ftl",
+        transforms_from(
+"""
+crash-reports-title = { COPY("toolkit/crashreporter/crashes.dtd", "crashReports.title") }
+
+clear-all-reports-label = { COPY("toolkit/crashreporter/crashes.dtd", "clearAllReports.label") }
+delete-confirm-title = { COPY("toolkit/crashreporter/crashes.properties", "deleteconfirm.title") }
+delete-confirm-description = { COPY("toolkit/crashreporter/crashes.properties", "deleteconfirm.description") }
+
+crashes-unsubmitted-label = { COPY("toolkit/crashreporter/crashes.dtd", "crashesUnsubmitted.label") }
+id-heading = { COPY("toolkit/crashreporter/crashes.dtd", "id.heading") }
+date-crashed-heading = { COPY("toolkit/crashreporter/crashes.dtd", "dateCrashed.heading") }
+
+crashes-submitted-label = { COPY("toolkit/crashreporter/crashes.dtd", "crashesSubmitted.label") }
+date-submitted-heading = { COPY("toolkit/crashreporter/crashes.dtd", "dateSubmitted.heading") }
+
+no-reports-label = { COPY("toolkit/crashreporter/crashes.dtd", "noReports.label") }
+no-config-label = { COPY("toolkit/crashreporter/crashes.dtd", "noConfig.label") }
+""")
+    )
--- a/servo/components/style/gecko/pseudo_element.rs
+++ b/servo/components/style/gecko/pseudo_element.rs
@@ -157,25 +157,16 @@ impl PseudoElement {
     }
 
     /// Whether this pseudo-element is precomputed.
     #[inline]
     pub fn is_precomputed(&self) -> bool {
         self.is_anon_box() && !self.is_tree_pseudo_element()
     }
 
-    /// Covert non-canonical pseudo-element to canonical one, and keep a
-    /// canonical one as it is.
-    pub fn canonical(&self) -> PseudoElement {
-        match *self {
-            PseudoElement::MozPlaceholder => PseudoElement::Placeholder,
-            _ => self.clone(),
-        }
-    }
-
     /// Property flag that properties must have to apply to this pseudo-element.
     #[inline]
     pub fn property_restriction(&self) -> Option<PropertyFlags> {
         match *self {
             PseudoElement::FirstLetter => Some(PropertyFlags::APPLIES_TO_FIRST_LETTER),
             PseudoElement::FirstLine => Some(PropertyFlags::APPLIES_TO_FIRST_LINE),
             PseudoElement::Placeholder => Some(PropertyFlags::APPLIES_TO_PLACEHOLDER),
             _ => None,
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -229,16 +229,19 @@ impl PseudoElement {
             "${pseudo.value[1:]}" => {
                 return Some(${pseudo_element_variant(pseudo)})
             }
             % endfor
             // Alias "-moz-selection" to "selection" at parse time.
             "-moz-selection" => {
                 return Some(PseudoElement::Selection);
             }
+            "-moz-placeholder" => {
+                return Some(PseudoElement::Placeholder);
+            }
             _ => {
                 // FIXME: -moz-tree check should probably be
                 // ascii-case-insensitive.
                 if name.starts_with("-moz-tree-") {
                     return PseudoElement::tree_pseudo_element(name, Box::new([]))
                 }
             }
         }
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -2262,17 +2262,17 @@ impl<'le> ::selectors::Element for Gecko
         &self,
         pseudo_element: &PseudoElement,
         _context: &mut MatchingContext<Self::Impl>,
     ) -> bool {
         // TODO(emilio): I believe we could assert we are a pseudo-element and
         // match the proper pseudo-element, given how we rulehash the stuff
         // based on the pseudo.
         match self.implemented_pseudo_element() {
-            Some(ref pseudo) => *pseudo == pseudo_element.canonical(),
+            Some(ref pseudo) => *pseudo == *pseudo_element,
             None => false,
         }
     }
 
     #[inline]
     fn is_link(&self) -> bool {
         self.state()
             .intersects(NonTSPseudoClass::AnyLink.state_flag())
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -893,17 +893,16 @@ impl Stylist {
         pseudo: &PseudoElement,
         is_probe: bool,
         rule_inclusion: RuleInclusion,
         matching_fn: Option<&Fn(&PseudoElement) -> bool>,
     ) -> Option<CascadeInputs>
     where
         E: TElement,
     {
-        let pseudo = pseudo.canonical();
         debug_assert!(pseudo.is_lazy());
 
         // Apply the selector flags. We should be in sequential mode
         // already, so we can directly apply the parent flags.
         let mut set_selector_flags = |element: &E, flags: ElementSelectorFlags| {
             if cfg!(feature = "servo") {
                 // Servo calls this function from the worker, but only for internal
                 // pseudos, so we should never generate selector flags here.
@@ -1887,31 +1886,31 @@ impl ElementAndPseudoRules {
         pseudo_element: Option<&PseudoElement>,
         quirks_mode: QuirksMode,
     ) -> Result<(), FailedAllocationError> {
         debug_assert!(pseudo_element.map_or(true, |pseudo| !pseudo.is_precomputed()));
 
         let map = match pseudo_element {
             None => &mut self.element_map,
             Some(pseudo) => self.pseudos_map
-                .get_or_insert_with(&pseudo.canonical(), || Box::new(SelectorMap::new())),
+                .get_or_insert_with(pseudo, || Box::new(SelectorMap::new())),
         };
 
         map.insert(rule, quirks_mode)
     }
 
     fn clear(&mut self) {
         self.element_map.clear();
         self.pseudos_map.clear();
     }
 
     #[inline]
     fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
         match pseudo {
-            Some(pseudo) => self.pseudos_map.get(&pseudo.canonical()).map(|p| &**p),
+            Some(pseudo) => self.pseudos_map.get(pseudo).map(|p| &**p),
             None => Some(&self.element_map),
         }
     }
 
     /// Measures heap usage.
     #[cfg(feature = "gecko")]
     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
         sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
@@ -2185,17 +2184,17 @@ impl CascadeData {
                         if let Some(pseudo) = pseudo_element {
                             if pseudo.is_precomputed() {
                                 debug_assert!(selector.is_universal());
                                 debug_assert!(matches!(origin, Origin::UserAgent));
 
                                 precomputed_pseudo_element_decls
                                     .as_mut()
                                     .expect("Expected precomputed declarations for the UA level")
-                                    .get_or_insert_with(&pseudo.canonical(), Vec::new)
+                                    .get_or_insert_with(pseudo, Vec::new)
                                     .push(ApplicableDeclarationBlock::new(
                                         StyleSource::from_rule(locked.clone()),
                                         self.rules_source_order,
                                         CascadeLevel::UANormal,
                                         selector.specificity(),
                                         0,
                                     ));
                                 continue;
--- a/taskcluster/scripts/misc/fetch-content
+++ b/taskcluster/scripts/misc/fetch-content
@@ -1,33 +1,45 @@
 #!/usr/bin/python3 -u
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import argparse
+import bz2
 import concurrent.futures
+import gzip
 import hashlib
+import lzma
 import multiprocessing
 import os
 import pathlib
-import re
 import subprocess
 import sys
 import tempfile
 import time
 import urllib.request
 
+try:
+    import zstandard
+except ImportError:
+    zstandard = None
+
 
 ARTIFACT_URL = ('https://queue.taskcluster.net/v1/task/{task}/artifacts/'
                 '{artifact}')
 
 CONCURRENCY = multiprocessing.cpu_count()
 
 
+def log(msg):
+    print(msg, file=sys.stderr)
+    sys.stderr.flush()
+
+
 class IntegrityError(Exception):
     """Represents an integrity error when downloading a URL."""
 
 
 def stream_download(url, sha256=None, size=None):
     """Download a URL to a generator, optionally with content verification.
 
     If ``sha256`` or ``size`` are defined, the downloaded URL will be
@@ -35,17 +47,17 @@ def stream_download(url, sha256=None, si
     raised if expectations do not match.
 
     Because verification cannot occur until the file is completely downloaded
     it is recommended for consumers to not do anything meaningful with the
     data if content verification is being used. To securely handle retrieved
     content, it should be streamed to a file or memory and only operated
     on after the generator is exhausted without raising.
     """
-    print('downloading %s' % url)
+    log('Downloading %s' % url)
 
     h = hashlib.sha256()
     length = 0
 
     t0 = time.time()
     with urllib.request.urlopen(url) as fh:
         while True:
             chunk = fh.read(65536)
@@ -55,29 +67,29 @@ def stream_download(url, sha256=None, si
             h.update(chunk)
             length += len(chunk)
 
             yield chunk
 
     duration = time.time() - t0
     digest = h.hexdigest()
 
-    print('%s resolved to %d bytes with sha256 %s in %.3fs' % (
+    log('%s resolved to %d bytes with sha256 %s in %.3fs' % (
         url, length, digest, duration))
 
     if size:
         if size == length:
-            print('verified size of %s' % url)
+            log('Verified size of %s' % url)
         else:
             raise IntegrityError('size mismatch on %s: wanted %d; got %d' % (
                 url, size, length))
 
     if sha256:
         if digest == sha256:
-            print('verified sha256 integrity of %s' % url)
+            log('Verified sha256 integrity of %s' % url)
         else:
             raise IntegrityError('sha256 mismatch on %s: wanted %s; got %s' % (
                 url, sha256, digest))
 
 
 def download_to_path(url, path, sha256=None, size=None):
     """Download a URL to a filesystem path, possibly with verification."""
 
@@ -86,99 +98,147 @@ def download_to_path(url, path, sha256=N
     # bad data.
     try:
         path.unlink()
     except FileNotFoundError:
         pass
 
     tmp = path.with_name('%s.tmp' % path.name)
 
-    print('downloading %s to %s' % (url, tmp))
+    log('Downloading %s to %s' % (url, tmp))
 
     try:
         with tmp.open('wb') as fh:
             for chunk in stream_download(url, sha256=sha256, size=size):
                 fh.write(chunk)
 
-        print('renaming to %s' % path)
+        log('Renaming to %s' % path)
         tmp.rename(path)
     except IntegrityError:
         tmp.unlink()
         raise
 
 
 def gpg_verify_path(path: pathlib.Path, public_key_data: bytes,
                     signature_data: bytes):
     """Verify that a filesystem path verifies using GPG.
 
     Takes a Path defining a file to verify. ``public_key_data`` contains
     bytes with GPG public key data. ``signature_data`` contains a signed
     GPG document to use with ``gpg --verify``.
     """
-    print('validating GPG signature of %s' % path)
-    print('GPG key data:\n%s' % public_key_data.decode('ascii'))
+    log('Validating GPG signature of %s' % path)
+    log('GPG key data:\n%s' % public_key_data.decode('ascii'))
 
     with tempfile.TemporaryDirectory() as td:
         try:
             # --batch since we're running unattended.
             gpg_args = ['gpg', '--homedir', td, '--batch']
 
-            print('importing GPG key...')
+            log('Importing GPG key...')
             subprocess.run(gpg_args + ['--import'],
                            input=public_key_data,
                            check=True)
 
-            print('verifying GPG signature...')
+            log('Verifying GPG signature...')
             subprocess.run(gpg_args + ['--verify', '-', '%s' % path],
                            input=signature_data,
                            check=True)
 
-            print('GPG signature verified!')
+            log('GPG signature verified!')
         finally:
             # There is a race between the agent self-terminating and
             # shutil.rmtree() from the temporary directory cleanup that can
             # lead to exceptions. Kill the agent before cleanup to prevent this.
             env = dict(os.environ)
             env['GNUPGHOME'] = td
             subprocess.run(['gpgconf', '--kill', 'gpg-agent'], env=env)
 
 
-def extract_archive(path, dest_dir):
+def archive_type(path: pathlib.Path):
+    """Attempt to identify a path as an extractable archive."""
+    if path.suffixes[-2:-1] == ['.tar']:
+        return 'tar'
+    elif path.suffix == '.zip':
+        return 'zip'
+    else:
+        return None
+
+
+def extract_archive(path, dest_dir, typ):
     """Extract an archive to a destination directory."""
 
-    if re.search('\.tar\..*$', path.name):
-        args = ['tar', 'xaf', str(path)]
-    elif path.name.endswith('.zip'):
+    # We pipe input to the decompressor program so that we can apply
+    # custom decompressors that the program may not know about.
+
+    if typ == 'tar':
+        if path.suffix == '.bz2':
+            ifh = bz2.open(str(path), 'rb')
+        elif path.suffix == '.gz':
+            ifh = gzip.open(str(path), 'rb')
+        elif path.suffix == '.xz':
+            ifh = lzma.open(str(path), 'rb')
+        elif path.suffix == '.zst':
+            if not zstandard:
+                raise ValueError('zstandard Python package not available')
+            dctx = zstandard.ZstdDecompressor()
+            ifh = dctx.stream_reader(path.open('rb'))
+        elif path.suffix == '.tar':
+            ifh = path.open('rb')
+        else:
+            raise ValueError('unknown archive format for tar file: %s' % path)
+
+        args = ['tar', 'xf', '-']
+        pipe_stdin = True
+    elif typ == 'zip':
+        # unzip from stdin has wonky behavior. We don't use a pipe for it.
+        ifh = os.devnull
         args = ['unzip', str(path)]
+        pipe_stdin = False
     else:
-        print('%s is unknown archive format; ignoring' % path)
-        return False
+        raise ValueError('unknown archive format: %s' % path)
+
+    log('Extracting %s to %s using %r' % (path, dest_dir, args))
+    t0 = time.time()
+
+    with ifh, subprocess.Popen(args, cwd=str(dest_dir), bufsize=0,
+                               stdin=subprocess.PIPE) as p:
+        while True:
+            if not pipe_stdin:
+                break
 
-    print('extracting %s to %s using %r' % (path, dest_dir, args))
-    t0 = time.time()
-    subprocess.check_call(args, cwd=str(dest_dir), bufsize=0)
-    print('%s extracted in %.3fs' % (path, time.time() - t0))
-    return True
+            chunk = ifh.read(131072)
+            if not chunk:
+                break
+
+            p.stdin.write(chunk)
+
+    if p.returncode:
+        raise Exception('%r exited %d' % (args, p.returncode))
+
+    log('%s extracted in %.3fs' % (path, time.time() - t0))
 
 
 def fetch_and_extract(url, dest_dir, sha256=None, size=None):
     """Fetch a URL and extract it to a destination path.
 
     If the downloaded URL is an archive, it is extracted automatically
     and the archive is deleted. Otherwise the file remains in place in
     the destination directory.
     """
 
     basename = url.split('/')[-1]
     dest_path = dest_dir / basename
 
     download_to_path(url, dest_path, sha256=sha256, size=size)
 
-    if extract_archive(dest_path, dest_dir):
-        print('removing %s' % dest_path)
+    typ = archive_type(dest_path)
+    if typ:
+        extract_archive(dest_path, dest_dir, typ)
+        log('Removing %s' % dest_path)
         dest_path.unlink()
 
 
 def fetch_urls(downloads):
     """Fetch URLs pairs to a pathlib.Path."""
     with concurrent.futures.ThreadPoolExecutor(CONCURRENCY) as e:
         fs = []
 
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_webdriver.js
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/testharness_webdriver.js
@@ -12,12 +12,14 @@ window.setMessageListener = function(fun
 };
 
 window.setMessageListener(function(event) {
   window.message_queue.push(event);
 });
 
 window.win = window.open("%(abs_url)s", "%(window_id)s");
 
-window.timer = setTimeout(function() {
-  window.win.timeout();
-  window.win.close();
-}, %(timeout)s);
+if (%(timeout)s != null) {
+  window.timer = setTimeout(function() {
+    window.win.timeout();
+    window.win.close();
+  }, %(timeout)s);
+}
--- a/toolkit/crashreporter/content/crashes.css
+++ b/toolkit/crashreporter/content/crashes.css
@@ -14,17 +14,17 @@ table {
   margin: 0 auto;
   padding-bottom: 2em;
 }
 th {
   font-size: 130%;
   text-align: left;
   white-space: nowrap;
 }
-th[chromedir="rtl"] {
+th:-moz-locale-dir(rtl) {
   text-align: right;
 }
 /* name */
 th:first-child {
   padding-inline-end: 2em;
 }
 /* submitted */
 th:last-child {
@@ -46,17 +46,17 @@ td:last-child {
   width: 0;
   padding-inline-start: .5em;
   white-space: nowrap;
 }
 
 #clear-reports {
   float: right;
 }
-#clear-reports[chromedir="rtl"] {
+#clear-reports:-moz-locale-dir(rtl) {
   float: left;
 }
 
 .submitting {
   background-image: url(chrome://global/skin/icons/loading.png);
   background-repeat: no-repeat;
   background-position: right;
   background-size: 16px;
--- a/toolkit/crashreporter/content/crashes.js
+++ b/toolkit/crashreporter/content/crashes.js
@@ -125,22 +125,21 @@ function populateReportList() {
       document.getElementById("unsubmitted").appendChild(row);
     } else {
       document.getElementById("submitted").appendChild(row);
     }
   }
 }
 
 var clearReports = async function() {
-  let bundle = Services.strings.createBundle("chrome://global/locale/crashes.properties");
-
-  if (!Services.
-         prompt.confirm(window,
-                        bundle.GetStringFromName("deleteconfirm.title"),
-                        bundle.GetStringFromName("deleteconfirm.description"))) {
+  const [title, description] = await document.l10n.formatValues([
+    {id: "delete-confirm-title"},
+    {id: "delete-confirm-description"},
+  ]);
+  if (!Services.prompt.confirm(window, title, description)) {
     return;
   }
 
   let cleanupFolder = async function(path, filter) {
     let iterator = new OS.File.DirectoryIterator(path);
     try {
       await iterator.forEach(async function(aEntry) {
         if (!filter || (await filter(aEntry))) {
--- a/toolkit/crashreporter/content/crashes.xhtml
+++ b/toolkit/crashreporter/content/crashes.xhtml
@@ -1,56 +1,51 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
-[
-  <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
-  <!ENTITY % crashesDTD SYSTEM "chrome://global/locale/crashes.dtd">
-  %globalDTD;
-  %crashesDTD;
-]>
+<!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
+<link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
 <link rel="stylesheet" type="text/css" href="chrome://global/content/crashes.css"/>
 <link rel="stylesheet" media="screen, projection" type="text/css"
       href="chrome://global/skin/in-content/common.css"/>
 <script type="application/javascript" src="chrome://global/content/crashes.js"/>
+<script type="text/javascript" src="chrome://global/content/l10n.js"/>
 
-<title>&crashReports.title;</title>
-</head><body dir="&locale.dir;">
-<button chromedir="&locale.dir;" id="clear-reports">&clearAllReports.label;</button>
+<title data-l10n-id="crash-reports-title"></title>
+</head><body>
+<button id="clear-reports" data-l10n-id="clear-all-reports-label"></button>
 <div id="reportList">
   <div id="reportListUnsubmitted">
-    <h1>&crashesUnsubmitted.label;</h1>
+    <h1 data-l10n-id="crashes-unsubmitted-label"></h1>
     <table>
       <thead>
         <tr>
-          <th chromedir="&locale.dir;">&id.heading;</th>
-          <th chromedir="&locale.dir;" colspan="2">&dateCrashed.heading;</th>
+          <th data-l10n-id="id-heading"></th>
+          <th colspan="2" data-l10n-id="date-crashed-heading"></th>
         </tr>
       </thead>
       <tbody id="unsubmitted">
       </tbody>
     </table>
   </div>
   <div id="reportListSubmitted">
-    <h1>&crashesSubmitted.label;</h1>
+    <h1 data-l10n-id="crashes-submitted-label"></h1>
     <table>
       <thead>
         <tr>
-          <th chromedir="&locale.dir;">&id.heading;</th>
-          <th chromedir="&locale.dir;" colspan="2">&dateSubmitted.heading;</th>
+          <th data-l10n-id="id-heading"></th>
+          <th colspan="2" data-l10n-id="date-submitted-heading"></th>
         </tr>
       </thead>
       <tbody id="submitted">
       </tbody>
     </table>
   </div>
 </div>
-<p id="noReports" style="display: none">&noReports.label;</p>
-<p id="noConfig" style="display: none">&noConfig.label;</p>
+<p id="noReports" style="display: none" data-l10n-id="no-reports-label"></p>
+<p id="noConfig" style="display: none" data-l10n-id="no-config-label"></p>
 </body>
 </html>
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -8,17 +8,17 @@
 <!ENTITY aboutSupport.pageSubtitle "
   This page contains technical information that might be useful when you’re
   trying to solve a problem. If you are looking for answers to common questions
   about &brandShortName;, check out our <a id='supportLink'>support website</a>.
 ">
 
 <!ENTITY aboutSupport.crashes.title "Crash Reports">
 <!-- LOCALIZATION NOTE (aboutSupport.crashes.id):
-This is likely the same like id.heading in crashes.dtd. -->
+This is likely the same like id.heading in aboutcrashes.ftl. -->
 <!ENTITY aboutSupport.crashes.id "Report ID">
 <!ENTITY aboutSupport.crashes.sendDate "Submitted">
 <!ENTITY aboutSupport.crashes.allReports "All Crash Reports">
 <!ENTITY aboutSupport.crashes.noConfig "This application has not been configured to display crash reports.">
 
 <!ENTITY aboutSupport.extensionsTitle "Extensions">
 <!ENTITY aboutSupport.extensionName "Name">
 <!ENTITY aboutSupport.extensionEnabled "Enabled">
new file mode 100644
--- /dev/null
+++ b/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
@@ -0,0 +1,19 @@
+# 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/-
+
+crash-reports-title = Crash Reports
+
+clear-all-reports-label = Remove All Reports
+delete-confirm-title = Are you sure?
+delete-confirm-description = This will delete all reports and cannot be undone.
+
+crashes-unsubmitted-label = Unsubmitted Crash Reports
+id-heading = Report ID
+date-crashed-heading = Date Crashed
+
+crashes-submitted-label = Submitted Crash Reports
+date-submitted-heading = Date Submitted
+
+no-reports-label = No crash reports have been submitted.
+no-config-label = This application has not been configured to display crash reports. The preference <code>breakpad.reportURL</code> must be set.
deleted file mode 100644
--- a/toolkit/locales/en-US/crashreporter/crashes.dtd
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY crashReports.title         "Crash Reports">
-<!ENTITY crashesUnsubmitted.label   "Unsubmitted Crash Reports">
-<!ENTITY crashesSubmitted.label     "Submitted Crash Reports">
-<!ENTITY id.heading                 "Report ID">
-<!ENTITY dateCrashed.heading        "Date Crashed">
-<!ENTITY dateSubmitted.heading      "Date Submitted">
-<!ENTITY noReports.label            "No crash reports have been submitted.">
-<!ENTITY noConfig.label             "This application has not been configured to display crash reports. The preference <code>breakpad.reportURL</code> must be set.">
-<!ENTITY clearAllReports.label      "Remove All Reports">
deleted file mode 100644
--- a/toolkit/locales/en-US/crashreporter/crashes.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-deleteconfirm.title=Are you sure?
-deleteconfirm.description=This will delete all reports and cannot be undone.
-
--- a/toolkit/locales/jar.mn
+++ b/toolkit/locales/jar.mn
@@ -1,14 +1,15 @@
 #filter substitution
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 [localization] @AB_CD@.jar:
+  crashreporter                                    (%crashreporter/**/*.ftl)
   toolkit                                          (%toolkit/**/*.ftl)
 
 @AB_CD@.jar:
 % locale global @AB_CD@ %locale/@AB_CD@/global/
   locale/@AB_CD@/global/aboutAbout.dtd                  (%chrome/global/aboutAbout.dtd)
   locale/@AB_CD@/global/aboutReader.properties          (%chrome/global/aboutReader.properties)
   locale/@AB_CD@/global/aboutRights.dtd                 (%chrome/global/aboutRights.dtd)
   locale/@AB_CD@/global/aboutNetworking.dtd             (%chrome/global/aboutNetworking.dtd)
@@ -71,18 +72,16 @@
   locale/@AB_CD@/global/resetProfile.properties         (%chrome/global/resetProfile.properties)
   locale/@AB_CD@/global/dialog.properties               (%chrome/global/dialog.properties)
   locale/@AB_CD@/global/tree.dtd                        (%chrome/global/tree.dtd)
   locale/@AB_CD@/global/textcontext.dtd                 (%chrome/global/textcontext.dtd)
   locale/@AB_CD@/global/videocontrols.dtd               (%chrome/global/videocontrols.dtd)
   locale/@AB_CD@/global/viewSource.properties           (%chrome/global/viewSource.properties)
   locale/@AB_CD@/global/wizard.dtd                      (%chrome/global/wizard.dtd)
   locale/@AB_CD@/global/wizard.properties               (%chrome/global/wizard.properties)
-  locale/@AB_CD@/global/crashes.dtd                     (%crashreporter/crashes.dtd)
-  locale/@AB_CD@/global/crashes.properties              (%crashreporter/crashes.properties)
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/unix/ os=LikeUnix os=Android
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/mac/ os=Darwin
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/win/ os=WINNT
   locale/@AB_CD@/global-platform/mac/platformKeys.properties  (%chrome/global-platform/mac/platformKeys.properties)
   locale/@AB_CD@/global-platform/unix/platformKeys.properties (%chrome/global-platform/unix/platformKeys.properties)
   locale/@AB_CD@/global-platform/win/platformKeys.properties  (%chrome/global-platform/win/platformKeys.properties)
   locale/@AB_CD@/global-platform/mac/intl.properties          (%chrome/global-platform/mac/intl.properties)
   locale/@AB_CD@/global-platform/unix/intl.properties         (%chrome/global-platform/unix/intl.properties)
--- a/tools/code-coverage/nsCodeCoverage.cpp
+++ b/tools/code-coverage/nsCodeCoverage.cpp
@@ -39,17 +39,17 @@ private:
   uint32_t mCount;
 };
 
 nsresult Request(JSContext* cx, Promise** aPromise, RequestType requestType)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(cx));
+  nsIGlobalObject* global = xpc::CurrentNativeGlobal(cx);
   if (NS_WARN_IF(!global)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult result;
   RefPtr<Promise> promise = Promise::Create(global, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
--- a/widget/windows/JumpListBuilder.cpp
+++ b/widget/windows/JumpListBuilder.cpp
@@ -180,19 +180,17 @@ NS_IMETHODIMP JumpListBuilder::GetMaxLis
 NS_IMETHODIMP JumpListBuilder::InitListBuild(JSContext* aCx,
                                              Promise** aPromise)
 {
   ReentrantMonitorAutoEnter lock(mMonitor);
   if (!mJumpListMgr) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsIGlobalObject* globalObject =
-    xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
-
+  nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
   if (NS_WARN_IF(!globalObject)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult result;
   RefPtr<Promise> promise = Promise::Create(globalObject, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -204,16 +204,17 @@ class PromiseJobRunnable final : public 
 {
 public:
   PromiseJobRunnable(JS::HandleObject aCallback,
                      JS::HandleObject aAllocationSite,
                      nsIGlobalObject* aIncumbentGlobal)
     :mCallback(
        new PromiseJobCallback(aCallback, aAllocationSite, aIncumbentGlobal))
   {
+    MOZ_ASSERT(js::IsFunctionObject(aCallback));
   }
 
   virtual ~PromiseJobRunnable()
   {
   }
 
 protected:
   virtual void Run(AutoSlowOperation& aAso) override
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -1348,16 +1348,17 @@ public:
 
   void Suspect(void* aPtr, nsCycleCollectionParticipant* aCp,
                nsCycleCollectingAutoRefCnt* aRefCnt);
   void SuspectNurseryEntries();
   uint32_t SuspectedCount();
   void ForgetSkippable(js::SliceBudget& aBudget, bool aRemoveChildlessNodes,
                        bool aAsyncSnowWhiteFreeing);
   bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
+  bool FreeSnowWhiteWithBudget(js::SliceBudget& aBudget);
 
   // This method assumes its argument is already canonicalized.
   void RemoveObjectFromGraph(void* aPtr);
 
   void PrepareForGarbageCollection();
   void FinishAnyCurrentCollection();
 
   bool Collect(ccType aCCType,
@@ -2710,59 +2711,90 @@ class SnowWhiteKiller : public TraceCall
   };
 
   // Segments are 4 KiB on 32-bit and 8 KiB on 64-bit.
   static const size_t kSegmentSize = sizeof(void*) * 1024;
   typedef SegmentedVector<SnowWhiteObject, kSegmentSize, InfallibleAllocPolicy>
     ObjectsVector;
 
 public:
-  explicit SnowWhiteKiller(nsCycleCollector* aCollector)
+  SnowWhiteKiller(nsCycleCollector* aCollector, js::SliceBudget* aBudget)
     : mCollector(aCollector)
     , mObjects(kSegmentSize)
+    , mBudget(aBudget)
+    , mSawSnowWhiteObjects(false)
   {
     MOZ_ASSERT(mCollector, "Calling SnowWhiteKiller after nsCC went away");
   }
 
+  explicit SnowWhiteKiller(nsCycleCollector* aCollector)
+    : SnowWhiteKiller(aCollector, nullptr)
+  {
+  }
+
   ~SnowWhiteKiller()
   {
     for (auto iter = mObjects.Iter(); !iter.Done(); iter.Next()) {
       SnowWhiteObject& o = iter.Get();
-      if (!o.mRefCnt->get() && !o.mRefCnt->IsInPurpleBuffer()) {
-        mCollector->RemoveObjectFromGraph(o.mPointer);
-        o.mRefCnt->stabilizeForDeletion();
-        {
-          JS::AutoEnterCycleCollection autocc(mCollector->Runtime()->Runtime());
-          o.mParticipant->Trace(o.mPointer, *this, nullptr);
-        }
-        o.mParticipant->DeleteCycleCollectable(o.mPointer);
+      MaybeKillObject(o);
+    }
+  }
+
+  void
+  MaybeKillObject(SnowWhiteObject& aObject)
+  {
+    if (!aObject.mRefCnt->get() && !aObject.mRefCnt->IsInPurpleBuffer()) {
+      mCollector->RemoveObjectFromGraph(aObject.mPointer);
+      aObject.mRefCnt->stabilizeForDeletion();
+      {
+        JS::AutoEnterCycleCollection autocc(mCollector->Runtime()->Runtime());
+        aObject.mParticipant->Trace(aObject.mPointer, *this, nullptr);
       }
+      aObject.mParticipant->DeleteCycleCollectable(aObject.mPointer);
     }
   }
 
   bool
   Visit(nsPurpleBuffer& aBuffer, nsPurpleBufferEntry* aEntry)
   {
+    if (mBudget) {
+      if (mBudget->isOverBudget()) {
+        return false;
+      }
+      mBudget->step();
+    }
+
     MOZ_ASSERT(aEntry->mObject, "Null object in purple buffer");
     if (!aEntry->mRefCnt->get()) {
+      mSawSnowWhiteObjects = true;
       void* o = aEntry->mObject;
       nsCycleCollectionParticipant* cp = aEntry->mParticipant;
       ToParticipant(o, &cp);
       SnowWhiteObject swo = { o, cp, aEntry->mRefCnt };
-      mObjects.InfallibleAppend(swo);
+      if (!mBudget) {
+        mObjects.InfallibleAppend(swo);
+      }
       aBuffer.Remove(aEntry);
+      if (mBudget) {
+        MaybeKillObject(swo);
+      }
     }
     return true;
   }
 
   bool HasSnowWhiteObjects() const
   {
     return !mObjects.IsEmpty();
   }
 
+  bool SawSnowWhiteObjects() const
+  {
+    return mSawSnowWhiteObjects;
+  }
+
   virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
                      void* aClosure) const override
   {
     const JS::Value& val = aValue->unbarrieredGet();
     if (val.isGCThing() && ValueIsGrayCCThing(val)) {
       MOZ_ASSERT(!js::gc::IsInsideNursery(val.toGCThing()));
       mCollector->GetJSPurpleBuffer()->mValues.InfallibleAppend(val);
     }
@@ -2812,16 +2844,18 @@ public:
   virtual void Trace(JS::Heap<JSFunction*>* aFunction, const char* aName,
                      void* aClosure) const override
   {
   }
 
 private:
   RefPtr<nsCycleCollector> mCollector;
   ObjectsVector mObjects;
+  js::SliceBudget* mBudget;
+  bool mSawSnowWhiteObjects;
 };
 
 class RemoveSkippableVisitor : public SnowWhiteKiller
 {
 public:
   RemoveSkippableVisitor(nsCycleCollector* aCollector,
                          js::SliceBudget& aBudget,
                          bool aRemoveChildlessNodes,
@@ -2920,16 +2954,33 @@ nsCycleCollector::FreeSnowWhite(bool aUn
                           visitor.HasSnowWhiteObjects();
     if (!visitor.HasSnowWhiteObjects()) {
       break;
     }
   } while (aUntilNoSWInPurpleBuffer);
   return hadSnowWhiteObjects;
 }
 
+bool
+nsCycleCollector::FreeSnowWhiteWithBudget(js::SliceBudget& aBudget)
+{
+  CheckThreadSafety();
+
+  if (mFreeingSnowWhite) {
+    return false;
+  }
+
+  AutoRestore<bool> ar(mFreeingSnowWhite);
+  mFreeingSnowWhite = true;
+
+  SnowWhiteKiller visitor(this, &aBudget);
+  mPurpleBuf.VisitEntries(visitor);
+  return visitor.SawSnowWhiteObjects();;
+}
+
 void
 nsCycleCollector::ForgetSkippable(js::SliceBudget& aBudget,
                                   bool aRemoveChildlessNodes,
                                   bool aAsyncSnowWhiteFreeing)
 {
   CheckThreadSafety();
 
   mozilla::Maybe<mozilla::AutoGlobalTimelineMarker> marker;
@@ -4315,16 +4366,29 @@ nsCycleCollector_doDeferredDeletion()
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
   MOZ_ASSERT(data->mContext);
 
   return data->mCollector->FreeSnowWhite(false);
 }
 
+bool
+nsCycleCollector_doDeferredDeletionWithBudget(js::SliceBudget& aBudget)
+{
+  CollectorData* data = sCollectorData.get();
+
+  // We should have started the cycle collector by now.
+  MOZ_ASSERT(data);
+  MOZ_ASSERT(data->mCollector);
+  MOZ_ASSERT(data->mContext);
+
+  return data->mCollector->FreeSnowWhiteWithBudget(aBudget);
+}
+
 already_AddRefed<nsICycleCollectorLogSink>
 nsCycleCollector_createLogSink()
 {
   nsCOMPtr<nsICycleCollectorLogSink> sink = new nsCycleCollectorLogSinkToFile();
   return sink.forget();
 }
 
 void
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -38,16 +38,17 @@ void nsCycleCollector_forgetSkippable(js
 void nsCycleCollector_prepareForGarbageCollection();
 
 // If an incremental cycle collection is in progress, finish it.
 void nsCycleCollector_finishAnyCurrentCollection();
 
 void nsCycleCollector_dispatchDeferredDeletion(bool aContinuation = false,
                                                bool aPurge = false);
 bool nsCycleCollector_doDeferredDeletion();
+bool nsCycleCollector_doDeferredDeletionWithBudget(js::SliceBudget& aBudget);
 
 already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink();
 
 void nsCycleCollector_collect(nsICycleCollectorListener* aManualListener);
 
 void nsCycleCollector_collectSlice(js::SliceBudget& budget,
                                    bool aPreferShorterSlices = false);