merge mozilla-central to autoland. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Mon, 09 Oct 2017 23:56:28 +0200
changeset 427868 12293a4b3e23904229f8afd3e56805ffe072fde4
parent 427867 7e960acfd90c6a709e1cb157a5f9bf63b1a1349f (current diff)
parent 427818 2ed5e7fbf39e949693d8a7455d6313b14a7aeaf6 (diff)
child 427869 035d3125ca2f0e5eeb25a04be9faeaffd156546b
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersmerge, merge
milestone58.0a1
merge mozilla-central to autoland. r=merge a=merge
browser/components/extensions/test/browser/browser-common.ini
testing/marionette/sync.js
testing/web-platform/meta/domxpath/interfaces.html.ini
--- a/browser/base/content/test/alerts/browser.ini
+++ b/browser/base/content/test/alerts/browser.ini
@@ -6,8 +6,9 @@ support-files =
 [browser_notification_close.js]
 skip-if = os == 'win' # Bug 1227785
 [browser_notification_do_not_disturb.js]
 skip-if = (os == 'win' && bits == 32) # Bug 1352791
 [browser_notification_open_settings.js]
 [browser_notification_remove_permission.js]
 [browser_notification_replace.js]
 [browser_notification_tab_switching.js]
+skip-if = os == "win" || os == "linux" # Bug 1243263
--- a/browser/base/content/test/urlbar/browser_urlbar_remove_match.js
+++ b/browser/base/content/test/urlbar/browser_urlbar_remove_match.js
@@ -20,9 +20,12 @@ add_task(async function test_remove_hist
   EventUtils.synthesizeKey("VK_DOWN", {});
   Assert.equal(gURLBar.popup.richlistbox.selectedIndex, 1);
   let options = AppConstants.platform == "macosx" ? { shiftKey: true } : {};
   EventUtils.synthesizeKey("VK_DELETE", options);
   await promiseVisitRemoved;
   await BrowserTestUtils.waitForCondition(
     () => !gURLBar.popup.richlistbox.children.some(c => !c.collapsed && c.getAttribute("ac-value") == TEST_URL),
     "Waiting for the result to disappear");
+
+  gURLBar.popup.hidePopup();
+  await promisePopupHidden(gURLBar.popup);
 });
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -127,16 +127,17 @@ skip-if = debug || asan # Bug 1354681
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
 [browser_ext_slow_script.js]
 skip-if = !e10s || debug || asan
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_audio.js]
 [browser_ext_tabs_captureVisibleTab.js]
 [browser_ext_tabs_create.js]
+skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
 [browser_ext_tabs_create_invalid_url.js]
 [browser_ext_tabs_detectLanguage.js]
 [browser_ext_tabs_discarded.js]
 [browser_ext_tabs_duplicate.js]
 [browser_ext_tabs_events.js]
 [browser_ext_tabs_executeScript.js]
 [browser_ext_tabs_executeScript_good.js]
 [browser_ext_tabs_executeScript_bad.js]
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -1035,21 +1035,22 @@ Experiments.Experiments.prototype = {
    */
   async _loadFromCache() {
     this._log.trace("_loadFromCache");
     let path = this._cacheFilePath;
     try {
       let result = await loadJSONAsync(path, { compression: "lz4" });
       this._populateFromCache(result);
     } catch (e) {
+      this._experiments = new Map();
       if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
         // No cached manifest yet.
-        this._experiments = new Map();
+        this._log.trace("_loadFromCache - no cached manifest yet");
       } else {
-        throw e;
+        this._log.error("_loadFromCache - caught error", e);
       }
     }
   },
 
   _populateFromCache(data) {
     this._log.trace("populateFromCache() - data: " + JSON.stringify(data));
 
     // If the user has a newer cache version than we can understand, we fail
--- a/browser/experiments/test/xpcshell/test_cache.js
+++ b/browser/experiments/test/xpcshell/test_cache.js
@@ -388,8 +388,24 @@ add_task(async function test_expiration(
   await experiments.updateManifest();
   validateCache([...experiments._experiments.keys()], [EXPERIMENT2_ID]);
 
   // Cleanup.
   await experiments._toggleExperimentsEnabled(false);
   await promiseRestartManager();
   await removeCacheFile();
 });
+
+add_task(async function test_invalid_cache() {
+  // Save uncompressed data to the cache file to trigger a loading error.
+  let encoder = new TextEncoder();
+  let data = encoder.encode("foo");
+
+  let path = OS.Path.join(OS.Constants.Path.profileDir, "experiments.json");
+  let options = { tmpPath: path + ".tmp" };
+  await OS.File.writeAtomic(path, data, options);
+
+  // Trigger loading from the cache. This should not throw and gracefully recover.
+  let experiments = new Experiments.Experiments(gPolicy);
+  let list = await experiments.getExperiments();
+
+  Assert.deepEqual(list, [], "The experiments cache should be empty.");
+});
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -809,20 +809,18 @@ NetworkMonitor.prototype = {
     let channel = subject.QueryInterface(Ci.nsIHttpChannel);
 
     if (!matchRequest(channel, this.filters)) {
       return;
     }
 
     this.interceptedChannels.add(subject);
 
-    // On e10s, we never receive http-on-examine-cached-response, so fake one.
-    if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
-      this._httpResponseExaminer(channel, "http-on-examine-cached-response");
-    }
+    // Service workers never fire http-on-examine-cached-response, so fake one.
+    this._httpResponseExaminer(channel, "http-on-examine-cached-response");
   },
 
   /**
    * Observe notifications for the http-on-examine-response topic, coming from
    * the nsIObserverService.
    *
    * @private
    * @param nsIHttpChannel subject
--- a/devtools/shared/webconsole/test/test_console_serviceworker.html
+++ b/devtools/shared/webconsole/test/test_console_serviceworker.html
@@ -92,21 +92,16 @@ let expectedConsoleCalls = [
       filename: /helper_serviceworker/,
       arguments: ['fetch event: ' + SCOPE_FRAME_URL],
     },
     {
       level: "log",
       filename: /helper_serviceworker/,
       arguments: ['fetch event: ' + SCOPE_FRAME_URL2],
     },
-    {
-      level: "log",
-      filename: /helper_serviceworker/,
-      arguments: ['message event: ' + MESSAGE],
-    },
 ];
 let consoleCalls = [];
 
 let startTest = Task.async(function*() {
   removeEventListener("load", startTest);
 
   yield new Promise(resolve => {
     SpecialPowers.pushPrefEnv({"set": [
@@ -164,20 +159,19 @@ let onAttach = Task.async(function*(stat
     yield forceReloadFrame(currentFrame);
     ok(!currentFrame.contentWindow.navigator.serviceWorker.controller,
        'current frame should not be controlled after force refresh');
     is(currentFrame.contentWindow.location.toString(), SCOPE_FRAME_URL,
        'current frame should still have in-scope location URL even though it got 404');
 
     // Now postMessage() the service worker to trigger its message event
     // handler.  This will generate 1 or 2 to console.log() statements
-    // depending on if the worker thread needs to spin up again.  Although we
-    // don't have a controlled or registering document in both cases, we still
-    // could get console calls since we only flush reports when the channel is
-    // finally destroyed.
+    // depending on if the worker thread needs to spin up again.  In either
+    // case, though, we should not get any console calls because we don't
+    // have a controlled or registering document.
     info("Completed force refresh.  Messaging service worker.");
     yield messageServiceWorker(currentFrame.contentWindow, SCOPE, MESSAGE);
 
     info("Done messaging service worker.  Unregistering service worker.");
     yield unregisterServiceWorker(currentFrame.contentWindow);
 
     info('Service worker unregistered.  Checking console calls.');
     state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -15061,17 +15061,17 @@ nsDocShell::ShouldPrepareForIntercept(ns
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
 {
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (!swm) {
-    aChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
+    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
     return NS_OK;
   }
 
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = aChannel->GetChannel(getter_AddRefs(channel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDocument> doc;
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -508,20 +508,20 @@ WebGLContext::InitAndValidateGL(FailureR
                                      mGLMaxVertexAttribs);
         *out_failReason = { "FEATURE_FAILURE_WEBGL_V_ATRB", reason };
         return false;
     }
 
     // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
     // even though the hardware supports much more.  The
     // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
-    gl->GetUIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
-    mGLMaxCombinedTextureImageUnits = mGLMaxTextureUnits;
+    mGLMaxCombinedTextureImageUnits = gl->GetIntAs<GLuint>(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+    mGLMaxTextureUnits = mGLMaxCombinedTextureImageUnits;
 
-    if (mGLMaxTextureUnits < 8) {
+    if (mGLMaxCombinedTextureImageUnits < 8) {
         const nsPrintfCString reason("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %u is < 8!",
                                      mGLMaxTextureUnits);
         *out_failReason = { "FEATURE_FAILURE_WEBGL_T_UNIT", reason };
         return false;
     }
 
     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1290,34 +1290,35 @@ EventStateManager::DispatchCrossProcessE
   case eTouchEventClass: {
     // Let the child process synthesize a mouse event if needed, and
     // ensure we don't synthesize one in this process.
     *aStatus = nsEventStatus_eConsumeNoDefault;
     remote->SendRealTouchEvent(*aEvent->AsTouchEvent());
     return;
   }
   case eDragEventClass: {
-    if (remote->Manager()->IsContentParent()) {
-      remote->Manager()->AsContentParent()->MaybeInvokeDragSession(remote);
+    RefPtr<TabParent> tabParent = remote;
+    if (tabParent->Manager()->IsContentParent()) {
+      tabParent->Manager()->AsContentParent()->MaybeInvokeDragSession(tabParent);
     }
 
     nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
     uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
     uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
     if (dragSession) {
       dragSession->DragEventDispatchedToChildProcess();
       dragSession->GetDragAction(&action);
       nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
       dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
       if (initialDataTransfer) {
         initialDataTransfer->GetDropEffectInt(&dropEffect);
       }
     }
 
-    remote->SendRealDragEvent(*aEvent->AsDragEvent(), action, dropEffect);
+    tabParent->SendRealDragEvent(*aEvent->AsDragEvent(), action, dropEffect);
     return;
   }
   case ePluginEventClass: {
     *aStatus = nsEventStatus_eConsumeNoDefault;
     remote->SendPluginEvent(*aEvent->AsPluginEvent());
     return;
   }
   default: {
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -867,50 +867,56 @@ FetchDriver::AsyncOnChannelRedirect(nsIC
   nsCOMPtr<nsIHttpChannel> oldHttpChannel = do_QueryInterface(aOldChannel);
   nsAutoCString tRPHeaderCValue;
   if (oldHttpChannel) {
     Unused << oldHttpChannel->GetResponseHeader(NS_LITERAL_CSTRING("referrer-policy"),
                                                 tRPHeaderCValue);
   }
 
   // "HTTP-redirect fetch": step 14 "Append locationURL to request's URL list."
-  nsCOMPtr<nsIURI> uri;
-  MOZ_ALWAYS_SUCCEEDS(aNewChannel->GetURI(getter_AddRefs(uri)));
+  // However, ignore internal redirects here.  We don't want to flip
+  // Response.redirected to true if an internal redirect occurs.  These
+  // should be transparent to script.
+  if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
+    nsCOMPtr<nsIURI> uri;
+    MOZ_ALWAYS_SUCCEEDS(aNewChannel->GetURI(getter_AddRefs(uri)));
 
-  nsCOMPtr<nsIURI> uriClone;
-  nsresult rv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
-  if(NS_WARN_IF(NS_FAILED(rv))){
-    return rv;
-  }
-  nsCString spec;
-  rv = uriClone->GetSpec(spec);
-  if(NS_WARN_IF(NS_FAILED(rv))){
-    return rv;
-  }
-  nsCString fragment;
-  rv = uri->GetRef(fragment);
-  if(NS_WARN_IF(NS_FAILED(rv))){
-    return rv;
+    nsCOMPtr<nsIURI> uriClone;
+    nsresult rv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
+    if(NS_WARN_IF(NS_FAILED(rv))){
+      return rv;
+    }
+    nsCString spec;
+    rv = uriClone->GetSpec(spec);
+    if(NS_WARN_IF(NS_FAILED(rv))){
+      return rv;
+    }
+    nsCString fragment;
+    rv = uri->GetRef(fragment);
+    if(NS_WARN_IF(NS_FAILED(rv))){
+      return rv;
+    }
+
+    mRequest->AddURL(spec, fragment);
   }
 
-  mRequest->AddURL(spec, fragment);
   NS_ConvertUTF8toUTF16 tRPHeaderValue(tRPHeaderCValue);
   // updates request’s associated referrer policy according to the
   // Referrer-Policy header (if any).
   if (!tRPHeaderValue.IsEmpty()) {
     net::ReferrerPolicy net_referrerPolicy =
       nsContentUtils::GetReferrerPolicyFromHeader(tRPHeaderValue);
     if (net_referrerPolicy != net::RP_Unset) {
       mRequest->SetReferrerPolicy(net_referrerPolicy);
       // Should update channel's referrer policy
       if (httpChannel) {
-        rv = FetchUtil::SetRequestReferrer(mPrincipal,
-                                           mDocument,
-                                           httpChannel,
-                                           mRequest);
+        nsresult rv = FetchUtil::SetRequestReferrer(mPrincipal,
+                                                    mDocument,
+                                                    httpChannel,
+                                                    mRequest);
         NS_ENSURE_SUCCESS(rv, rv);
       }
     }
   }
 
   aCallback->OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -196,16 +196,20 @@ public:
   void SetCharset(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::charset, aValue, rv);
   }
   void GetName(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::name, aValue);
   }
+  void GetName(nsAString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::name, aValue);
+  }
   void SetName(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::name, aValue, rv);
   }
   void GetRev(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::rev, aValue);
   }
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -27,16 +27,18 @@ public:
   explicit HTMLBodyElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLBodyElement, body);
+
   // Event listener stuff; we need to declare only the ones we need to
   // forward to window that don't come from nsIDOMHTMLBodyElement.
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
 #define WINDOW_EVENT_HELPER(name_, type_)                               \
   type_* GetOn##name_();                                                \
   void SetOn##name_(type_* handler);
 #define WINDOW_EVENT(name_, id_, type_, struct_)                        \
   WINDOW_EVENT_HELPER(name_, EventHandlerNonNull)
@@ -107,16 +109,20 @@ public:
   void SetBgColor(const nsAString& aBgColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
   }
   void GetBackground(DOMString& aBackground)
   {
     GetHTMLAttr(nsGkAtoms::background, aBackground);
   }
+  void GetBackground(nsAString& aBackground)
+  {
+    GetHTMLAttr(nsGkAtoms::background, aBackground);
+  }
   void SetBackground(const nsAString& aBackground, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::background, aBackground, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -1523,16 +1523,21 @@ CSPReportRedirectSink::~CSPReportRedirec
 }
 
 NS_IMETHODIMP
 CSPReportRedirectSink::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
                                               nsIChannel* aNewChannel,
                                               uint32_t aRedirFlags,
                                               nsIAsyncVerifyRedirectCallback* aCallback)
 {
+  if (aRedirFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
+    aCallback->OnRedirectVerifyCallback(NS_OK);
+    return NS_OK;
+  }
+
   // cancel the old channel so XHR failure callback happens
   nsresult rv = aOldChannel->Cancel(NS_ERROR_ABORT);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // notify an observer that we have blocked the report POST due to a redirect,
   // used in testing, do this async since we're in an async call now to begin with
   nsCOMPtr<nsIURI> uri;
   rv = aOldChannel->GetURI(getter_AddRefs(uri));
--- a/dom/smil/nsSMILCompositor.h
+++ b/dom/smil/nsSMILCompositor.h
@@ -29,19 +29,19 @@ public:
   typedef nsSMILTargetIdentifier KeyType;
   typedef const KeyType& KeyTypeRef;
   typedef const KeyType* KeyTypePointer;
 
   explicit nsSMILCompositor(KeyTypePointer aKey)
    : mKey(*aKey),
      mForceCompositing(false)
   { }
-  nsSMILCompositor(const nsSMILCompositor& toCopy)
-    : mKey(toCopy.mKey),
-      mAnimationFunctions(toCopy.mAnimationFunctions),
+  nsSMILCompositor(nsSMILCompositor&& toMove)
+    : mKey(mozilla::Move(toMove.mKey)),
+      mAnimationFunctions(mozilla::Move(toMove.mAnimationFunctions)),
       mForceCompositing(false)
   { }
   ~nsSMILCompositor() { }
 
   // PLDHashEntryHdr methods
   KeyTypeRef GetKey() const { return mKey; }
   bool KeyEquals(KeyTypePointer aKey) const;
   static KeyTypePointer KeyToPointer(KeyTypeRef aKey) { return &aKey; }
--- a/dom/smil/nsSMILNullType.cpp
+++ b/dom/smil/nsSMILNullType.cpp
@@ -3,16 +3,23 @@
 /* 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 "nsSMILNullType.h"
 #include "nsSMILValue.h"
 #include "nsDebug.h"
 
+/*static*/ nsSMILNullType*
+nsSMILNullType::Singleton()
+{
+  static nsSMILNullType sSingleton;
+  return &sSingleton;
+}
+
 nsresult
 nsSMILNullType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
   NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aSrc.mType == this, "Unexpected source type");
   aDest.mU    = aSrc.mU;
   aDest.mType = Singleton();
   return NS_OK;
--- a/dom/smil/nsSMILNullType.h
+++ b/dom/smil/nsSMILNullType.h
@@ -9,22 +9,17 @@
 
 #include "mozilla/Attributes.h"
 #include "nsISMILType.h"
 
 class nsSMILNullType : public nsISMILType
 {
 public:
   // Singleton for nsSMILValue objects to hold onto.
-  static nsSMILNullType*
-  Singleton()
-  {
-    static nsSMILNullType sSingleton;
-    return &sSingleton;
-  }
+  static nsSMILNullType* Singleton();
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void Init(nsSMILValue& aValue) const override {}
   virtual void Destroy(nsSMILValue& aValue) const override {}
   virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const override;
 
--- a/dom/webidl/XPathEvaluator.webidl
+++ b/dom/webidl/XPathEvaluator.webidl
@@ -4,16 +4,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 [Constructor]
 interface XPathEvaluator {
   // Based on nsIDOMXPathEvaluator
   [NewObject, Throws]
   XPathExpression createExpression(DOMString expression,
-                                   XPathNSResolver? resolver);
+                                   optional XPathNSResolver? resolver = null);
   [Pure]
   Node createNSResolver(Node nodeResolver);
   [Throws]
-  XPathResult evaluate(DOMString expression, Node contextNode,
-                       XPathNSResolver? resolver, unsigned short type,
-                       object? result);
+  XPathResult evaluate(DOMString expression,
+                       Node contextNode,
+                       optional XPathNSResolver? resolver = null,
+                       optional unsigned short type = 0 /* XPathResult.ANY_TYPE */,
+                       optional object? result = null);
 };
--- a/dom/webidl/XPathExpression.webidl
+++ b/dom/webidl/XPathExpression.webidl
@@ -4,19 +4,22 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 interface XPathExpression {
   // The result specifies a specific result object which may be reused and
   // returned by this method. If this is specified as null or it's not an
   // XPathResult object, a new result object will be constructed and returned.
   [Throws]
-  XPathResult evaluate(Node contextNode, unsigned short type, object? result);
+  XPathResult evaluate(Node contextNode,
+                       optional unsigned short type = 0  /* XPathResult.ANY_TYPE */,
+                       optional object? result = null);
 
   // The result specifies a specific result object which may be reused and
   // returned by this method. If this is specified as null or it's not an
   // XPathResult object, a new result object will be constructed and returned.
   [Throws, ChromeOnly]
   XPathResult evaluateWithContext(Node contextNode,
                                   unsigned long contextPosition,
                                   unsigned long contextSize,
-                                  unsigned short type, object? result);
+                                  optional unsigned short type = 0  /* XPathResult.ANY_TYPE */,
+                                  optional object? result = null);
 };
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -110,17 +110,17 @@ CancelChannelRunnable::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // TODO: When bug 1204254 is implemented, this time marker should be moved to
   // the point where the body of the network request is complete.
   mChannel->SetHandleFetchEventEnd(TimeStamp::Now());
   mChannel->SaveTimeStamps();
 
-  mChannel->Cancel(mStatus);
+  mChannel->CancelInterception(mStatus);
   mRegistration->MaybeScheduleUpdate();
   return NS_OK;
 }
 
 FetchEvent::FetchEvent(EventTarget* aOwner)
   : ExtendableEvent(aOwner)
   , mPreventDefaultLineNumber(0)
   , mPreventDefaultColumnNumber(0)
@@ -194,53 +194,53 @@ public:
 
     nsCOMPtr<nsIChannel> underlyingChannel;
     nsresult rv = mChannel->GetChannel(getter_AddRefs(underlyingChannel));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(underlyingChannel, NS_ERROR_UNEXPECTED);
     nsCOMPtr<nsILoadInfo> loadInfo = underlyingChannel->GetLoadInfo();
 
     if (!loadInfo || !CSPPermitsResponse(loadInfo)) {
-      mChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
+      mChannel->CancelInterception(NS_ERROR_CONTENT_BLOCKED);
       return NS_OK;
     }
 
     ChannelInfo channelInfo;
     if (mInternalResponse->GetChannelInfo().IsInitialized()) {
       channelInfo = mInternalResponse->GetChannelInfo();
     } else {
       // We are dealing with a synthesized response here, so fall back to the
       // channel info for the worker script.
       channelInfo = mWorkerChannelInfo;
     }
     rv = mChannel->SetChannelInfo(&channelInfo);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
+      mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
       return NS_OK;
     }
 
     rv = mChannel->SynthesizeStatus(mInternalResponse->GetUnfilteredStatus(),
                                     mInternalResponse->GetUnfilteredStatusText());
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
+      mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
       return NS_OK;
     }
 
     AutoTArray<InternalHeaders::Entry, 5> entries;
     mInternalResponse->UnfilteredHeaders()->GetEntries(entries);
     for (uint32_t i = 0; i < entries.Length(); ++i) {
        mChannel->SynthesizeHeader(entries[i].mName, entries[i].mValue);
     }
 
     auto castLoadInfo = static_cast<LoadInfo*>(loadInfo.get());
     castLoadInfo->SynthesizeServiceWorkerTainting(mInternalResponse->GetTainting());
 
     rv = mChannel->FinishSynthesizedResponse(mResponseURLSpec);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
+      mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
       return NS_OK;
     }
 
     TimeStamp timeStamp = TimeStamp::Now();
     mChannel->SetHandleFetchEventEnd(timeStamp);
     mChannel->SetFinishSynthesizedResponseEnd(timeStamp);
     mChannel->SaveTimeStamps();
 
new file mode 100644
--- /dev/null
+++ b/dom/xml/crashtests/1405878.xml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <body>
+    <select>
+      <script>document.documentElement.offsetHeight</script>
+    <option>Hello there</option>
+    </select>
+    <script>
+      document.querySelector("body").style.display = "inline";
+    </script>
+  </body>
+</html>
--- a/dom/xml/crashtests/crashtests.list
+++ b/dom/xml/crashtests/crashtests.list
@@ -5,8 +5,9 @@ load 382636-2.svg
 load 382636-3.xhtml
 load 382636-4.xul # Throws (bug 455856)
 load 420429.xul
 load 431703-1.xhtml
 load 453278.html
 load 803586.xhtml
 load 994740-1.xhtml
 load 1038887.xhtml
+load 1405878.xml
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -1065,38 +1065,42 @@ nsXMLContentSink::HandleEndElement(const
                 content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_MathML &&
                 content->NodeInfo()->Equals(debugTagAtom)) ||
                (debugNameSpaceID == kNameSpaceID_SVG &&
                 content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_SVG &&
                 content->NodeInfo()->Equals(debugTagAtom)) ||
                isTemplateElement, "Wrong element being closed");
 #endif
 
+  // Make sure to notify on our kids before we call out to any other code that
+  // might reenter us and call FlushTags, in a state in which we've already
+  // popped "content" from the stack but haven't notified on its kids yet.
+  int32_t stackLen = mContentStack.Length();
+  if (mNotifyLevel >= stackLen) {
+    if (numFlushed < content->GetChildCount()) {
+      NotifyAppend(content, numFlushed);
+    }
+    mNotifyLevel = stackLen - 1;
+  }
+
   result = CloseElement(content);
 
   if (mCurrentHead == content) {
     mCurrentHead = nullptr;
   }
 
   if (mDocElement == content) {
     // XXXbz for roots that don't want to be appended on open, we
     // probably need to deal here.... (and stop appending them on open).
     mState = eXMLContentSinkState_InEpilog;
 
     // We might have had no occasion to start layout yet.  Do so now.
     MaybeStartLayout(false);
   }
 
-  int32_t stackLen = mContentStack.Length();
-  if (mNotifyLevel >= stackLen) {
-    if (numFlushed < content->GetChildCount()) {
-      NotifyAppend(content, numFlushed);
-    }
-    mNotifyLevel = stackLen - 1;
-  }
   DidAddContent();
 
   if (content->IsSVGElement(nsGkAtoms::svg)) {
     FlushTags();
     nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(content);
     if (NS_FAILED(content->OwnerDoc()->Dispatch(TaskCategory::Other,
                                                 event.forget()))) {
       NS_WARNING("failed to dispatch svg load dispatcher");
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -107,19 +107,19 @@ public:
 
   class PermissionHashKey : public nsRefPtrHashKey<PermissionKey>
   {
   public:
     explicit PermissionHashKey(const PermissionKey* aPermissionKey)
       : nsRefPtrHashKey<PermissionKey>(aPermissionKey)
     {}
 
-    PermissionHashKey(const PermissionHashKey& toCopy)
-      : nsRefPtrHashKey<PermissionKey>(toCopy)
-      , mPermissions(toCopy.mPermissions)
+    PermissionHashKey(PermissionHashKey&& toCopy)
+      : nsRefPtrHashKey<PermissionKey>(mozilla::Move(toCopy))
+      , mPermissions(mozilla::Move(toCopy.mPermissions))
     {}
 
     bool KeyEquals(const PermissionKey* aKey) const
     {
       return *aKey == *GetKey();
     }
 
     static PLDHashNumber HashKey(const PermissionKey* aKey)
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -161,22 +161,22 @@ static gfx::IntRect ContainerVisibleRect
   gfx::IntRect surfaceRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
   return surfaceRect;
 }
 
 
 /* all of the per-layer prepared data we need to maintain */
 struct PreparedLayer
 {
-  PreparedLayer(LayerComposite *aLayer,
+  PreparedLayer(Layer *aLayer,
                 RenderTargetIntRect aClipRect,
                 Maybe<gfx::Polygon>&& aGeometry)
   : mLayer(aLayer), mClipRect(aClipRect), mGeometry(Move(aGeometry)) {}
 
-  LayerComposite* mLayer;
+  RefPtr<Layer> mLayer;
   RenderTargetIntRect mClipRect;
   Maybe<Polygon> mGeometry;
 };
 
 /* all of the prepared data that we need in RenderLayer() */
 struct PreparedData
 {
   RefPtr<CompositingRenderTarget> mTmpTarget;
@@ -230,17 +230,18 @@ ContainerPrepare(ContainerT* aContainer,
         CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
         continue;
       }
     }
 
     CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
 
     layerToRender->Prepare(clipRect);
-    aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender, clipRect,
+    aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender->GetLayer(),
+                                                               clipRect,
                                                                Move(layer.geometry)));
   }
 
   CULLING_LOG("Preparing container layer %p\n", aContainer->GetLayer());
 
   /**
    * Setup our temporary surface for rendering the contents of this container.
    */
@@ -408,17 +409,17 @@ RenderLayers(ContainerT* aContainer, Lay
              const Maybe<gfx::Polygon>& aGeometry)
 {
   Compositor* compositor = aManager->GetCompositor();
 
   for (size_t i = 0u; i < aContainer->mPrepared->mLayers.Length(); i++) {
     PreparedLayer& preparedData = aContainer->mPrepared->mLayers[i];
 
     const gfx::IntRect clipRect = preparedData.mClipRect.ToUnknownRect();
-    LayerComposite* layerToRender = preparedData.mLayer;
+    LayerComposite* layerToRender = static_cast<LayerComposite*>(preparedData.mLayer->ImplData());
     const Maybe<gfx::Polygon>& childGeometry = preparedData.mGeometry;
 
     Layer* layer = layerToRender->GetLayer();
 
     if (layerToRender->HasStaleCompositor()) {
       continue;
     }
 
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -15,25 +15,22 @@ StackingContextHelper::StackingContextHe
   : mBuilder(nullptr)
   , mScale(1.0f, 1.0f)
 {
   // mOrigin remains at 0,0
 }
 
 StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
                                              wr::DisplayListBuilder& aBuilder,
-                                             nsDisplayListBuilder* aDisplayListBuilder,
-                                             nsDisplayItem* aItem,
-                                             nsDisplayList* aDisplayList,
+                                             const nsTArray<wr::WrFilterOp>& aFilters,
                                              const gfx::Matrix4x4* aBoundTransform,
                                              uint64_t aAnimationsId,
                                              float* aOpacityPtr,
                                              gfx::Matrix4x4* aTransformPtr,
                                              gfx::Matrix4x4* aPerspectivePtr,
-                                             const nsTArray<wr::WrFilterOp>& aFilters,
                                              const gfx::CompositionOp& aMixBlendMode,
                                              bool aBackfaceVisible)
   : mBuilder(&aBuilder)
   , mScale(1.0f, 1.0f)
 {
   bool is2d = !aTransformPtr || (aTransformPtr->Is2D() && !aPerspectivePtr);
   if (aTransformPtr) {
     mTransform = *aTransformPtr;
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -25,25 +25,22 @@ class WebRenderLayer;
  * This is a helper class that pushes/pops a stacking context, and manages
  * some of the coordinate space transformations needed.
  */
 class MOZ_RAII StackingContextHelper
 {
 public:
   StackingContextHelper(const StackingContextHelper& aParentSC,
                         wr::DisplayListBuilder& aBuilder,
-                        nsDisplayListBuilder* aDisplayListBuilder,
-                        nsDisplayItem* aItem,
-                        nsDisplayList* aDisplayList,
-                        const gfx::Matrix4x4* aBoundTransform,
-                        uint64_t aAnimationsId,
-                        float* aOpacityPtr,
-                        gfx::Matrix4x4* aTransformPtr,
+                        const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
+                        const gfx::Matrix4x4* aBoundTransform = nullptr,
+                        uint64_t aAnimationsId = 0,
+                        float* aOpacityPtr = nullptr,
+                        gfx::Matrix4x4* aTransformPtr = nullptr,
                         gfx::Matrix4x4* aPerspectivePtr = nullptr,
-                        const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
                         const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
                         bool aBackfaceVisible = true);
   // This version of the constructor should only be used at the root level
   // of the tree, so that we have a StackingContextHelper to pass down into
   // the RenderLayer traversal, but don't actually want it to push a stacking
   // context on the display list builder.
   StackingContextHelper();
 
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -41,18 +41,21 @@ WebRenderCommandBuilder::BuildWebRenderC
 
     StackingContextHelper sc;
     mParentCommands.Clear();
     aScrollData = WebRenderScrollData();
     MOZ_ASSERT(mLayerScrollData.empty());
     mLastCanvasDatas.Clear();
     mLastAsr = nullptr;
 
-    CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc,
-                                           aBuilder, aResourceUpdates);
+    {
+      StackingContextHelper pageRootSc(sc, aBuilder);
+      CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder,
+                                             pageRootSc, aBuilder, aResourceUpdates);
+    }
 
     // Make a "root" layer data that has everything else as descendants
     mLayerScrollData.emplace_back();
     mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
     if (aDisplayListBuilder->IsBuildingLayerEventRegions()) {
       nsIPresShell* shell = aDisplayListBuilder->RootReferenceFrame()->PresContext()->PresShell();
       if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(shell)) {
         mLayerScrollData.back().SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -232,17 +232,17 @@ AssertGCThingIsNotAnObjectSubclass(js::g
  * keep the pointed-to GC thing alive.
  *
  * Heap<T> objects should only be used on the heap. GC references stored on the
  * C/C++ stack must use Rooted/Handle/MutableHandle instead.
  *
  * Type T must be a public GC pointer type.
  */
 template <typename T>
-class Heap : public js::HeapBase<T, Heap<T>>
+class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T, Heap<T>>
 {
     // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
     static_assert(js::IsHeapConstructibleType<T>::value,
                   "Type T must be a public GC pointer type");
   public:
     using ElementType = T;
 
     Heap() {
@@ -1168,16 +1168,24 @@ class JS_PUBLIC_API(ObjectPtr)
 
   public:
     using ElementType = JSObject*;
 
     ObjectPtr() : value(nullptr) {}
 
     explicit ObjectPtr(JSObject* obj) : value(obj) {}
 
+    ObjectPtr(const ObjectPtr& other) : value(other.value) {}
+
+    ObjectPtr(ObjectPtr&& other)
+      : value(other.value)
+    {
+        other.value = nullptr;
+    }
+
     /* Always call finalize before the destructor. */
     ~ObjectPtr() { MOZ_ASSERT(!value); }
 
     void finalize(JSRuntime* rt);
     void finalize(JSContext* cx);
 
     void init(JSObject* obj) { value = obj; }
 
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1423,24 +1423,35 @@ class HeapBase<JS::Value, Wrapper> : pub
  * If the Value is a GC pointer type, convert to that type and call |f| with
  * the pointer. If the Value is not a GC type, calls F::defaultValue.
  */
 template <typename F, typename... Args>
 auto
 DispatchTyped(F f, const JS::Value& val, Args&&... args)
   -> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
 {
-    if (val.isString())
-        return f(val.toString(), mozilla::Forward<Args>(args)...);
-    if (val.isObject())
-        return f(&val.toObject(), mozilla::Forward<Args>(args)...);
-    if (val.isSymbol())
-        return f(val.toSymbol(), mozilla::Forward<Args>(args)...);
-    if (MOZ_UNLIKELY(val.isPrivateGCThing()))
+    if (val.isString()) {
+        JSString* str = val.toString();
+        MOZ_ASSERT(gc::IsCellPointerValid(str));
+        return f(str, mozilla::Forward<Args>(args)...);
+    }
+    if (val.isObject()) {
+        JSObject* obj = &val.toObject();
+        MOZ_ASSERT(gc::IsCellPointerValid(obj));
+        return f(obj, mozilla::Forward<Args>(args)...);
+    }
+    if (val.isSymbol()) {
+        JS::Symbol* sym = val.toSymbol();
+        MOZ_ASSERT(gc::IsCellPointerValid(sym));
+        return f(sym, mozilla::Forward<Args>(args)...);
+    }
+    if (MOZ_UNLIKELY(val.isPrivateGCThing())) {
+        MOZ_ASSERT(gc::IsCellPointerValid(val.toGCThing()));
         return DispatchTyped(f, val.toGCCellPtr(), mozilla::Forward<Args>(args)...);
+    }
     MOZ_ASSERT(!val.isGCThing());
     return F::defaultValue(val);
 }
 
 template <class S> struct VoidDefaultAdaptor { static void defaultValue(const S&) {} };
 template <class S> struct IdentityDefaultAdaptor { static S defaultValue(const S& v) {return v;} };
 template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(const S&) { return v; } };
 
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -467,40 +467,40 @@ PromiseHasAnyFlag(PromiseObject& promise
 {
     return promise.getFixedSlot(PromiseSlot_Flags).toInt32() & flag;
 }
 
 static bool ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp);
 static bool RejectPromiseFunction(JSContext* cx, unsigned argc, Value* vp);
 
 // ES2016, 25.4.1.3.
-static MOZ_MUST_USE bool
+static MOZ_MUST_USE MOZ_ALWAYS_INLINE bool
 CreateResolvingFunctions(JSContext* cx, HandleObject promise,
                          MutableHandleObject resolveFn,
                          MutableHandleObject rejectFn)
 {
-    RootedAtom funName(cx, cx->names().empty);
-    RootedFunction resolve(cx, NewNativeFunction(cx, ResolvePromiseFunction, 1, funName,
-                                                 gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
-    if (!resolve)
+    HandlePropertyName funName = cx->names().empty;
+    resolveFn.set(NewNativeFunction(cx, ResolvePromiseFunction, 1, funName,
+                                    gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
+    if (!resolveFn)
         return false;
 
-    RootedFunction reject(cx, NewNativeFunction(cx, RejectPromiseFunction, 1, funName,
-                                                 gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
-    if (!reject)
+    rejectFn.set(NewNativeFunction(cx, RejectPromiseFunction, 1, funName,
+                                   gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
+    if (!rejectFn)
         return false;
 
-    resolve->setExtendedSlot(ResolveFunctionSlot_Promise, ObjectValue(*promise));
-    resolve->setExtendedSlot(ResolveFunctionSlot_RejectFunction, ObjectValue(*reject));
-
-    reject->setExtendedSlot(RejectFunctionSlot_Promise, ObjectValue(*promise));
-    reject->setExtendedSlot(RejectFunctionSlot_ResolveFunction, ObjectValue(*resolve));
-
-    resolveFn.set(resolve);
-    rejectFn.set(reject);
+    JSFunction* resolveFun = &resolveFn->as<JSFunction>();
+    JSFunction* rejectFun = &rejectFn->as<JSFunction>();
+
+    resolveFun->initExtendedSlot(ResolveFunctionSlot_Promise, ObjectValue(*promise));
+    resolveFun->initExtendedSlot(ResolveFunctionSlot_RejectFunction, ObjectValue(*rejectFun));
+
+    rejectFun->initExtendedSlot(RejectFunctionSlot_Promise, ObjectValue(*promise));
+    rejectFun->initExtendedSlot(RejectFunctionSlot_ResolveFunction, ObjectValue(*resolveFun));
 
     return true;
 }
 
 static void ClearResolutionFunctionSlots(JSFunction* resolutionFun);
 static MOZ_MUST_USE bool RejectMaybeWrappedPromise(JSContext *cx, HandleObject promiseObj,
                                                    HandleValue reason);
 
@@ -1460,58 +1460,61 @@ ClearResolutionFunctionSlots(JSFunction*
     resolve->setExtendedSlot(ResolveFunctionSlot_Promise, UndefinedValue());
     resolve->setExtendedSlot(ResolveFunctionSlot_RejectFunction, UndefinedValue());
 
     reject->setExtendedSlot(RejectFunctionSlot_Promise, UndefinedValue());
     reject->setExtendedSlot(RejectFunctionSlot_ResolveFunction, UndefinedValue());
 }
 
 // ES2016, 25.4.3.1. steps 3-7.
-static MOZ_MUST_USE PromiseObject*
+static MOZ_MUST_USE MOZ_ALWAYS_INLINE PromiseObject*
 CreatePromiseObjectInternal(JSContext* cx, HandleObject proto /* = nullptr */,
                             bool protoIsWrapped /* = false */, bool informDebugger /* = true */)
 {
     // Step 3.
-    Rooted<PromiseObject*> promise(cx);
     // Enter the unwrapped proto's compartment, if that's different from
     // the current one.
     // All state stored in a Promise's fixed slots must be created in the
     // same compartment, so we get all of that out of the way here.
     // (Except for the resolution functions, which are created below.)
     mozilla::Maybe<AutoCompartment> ac;
     if (protoIsWrapped)
         ac.emplace(cx, proto);
 
-    promise = NewObjectWithClassProto<PromiseObject>(cx, proto);
+    PromiseObject* promise = NewObjectWithClassProto<PromiseObject>(cx, proto);
     if (!promise)
         return nullptr;
 
     // Step 4.
-    promise->setFixedSlot(PromiseSlot_Flags, Int32Value(0));
+    promise->initFixedSlot(PromiseSlot_Flags, Int32Value(0));
 
     // Steps 5-6.
     // Omitted, we allocate our single list of reaction records lazily.
 
     // Step 7.
     // Implicit, the handled flag is unset by default.
 
+    if (MOZ_LIKELY(!ShouldCaptureDebugInfo(cx)))
+        return promise;
+
     // Store an allocation stack so we can later figure out what the
     // control flow was for some unexpected results. Frightfully expensive,
     // but oh well.
-    if (ShouldCaptureDebugInfo(cx)) {
-        PromiseDebugInfo* debugInfo = PromiseDebugInfo::create(cx, promise);
-        if (!debugInfo)
-            return nullptr;
-    }
+
+    Rooted<PromiseObject*> promiseRoot(cx, promise);
+
+    PromiseDebugInfo* debugInfo = PromiseDebugInfo::create(cx, promiseRoot);
+    if (!debugInfo)
+        return nullptr;
 
     // Let the Debugger know about this Promise.
     if (informDebugger)
-        Debugger::onNewPromise(cx, promise);
-
-    return promise;
+        Debugger::onNewPromise(cx, promiseRoot);
+
+    return promiseRoot;
 }
 
 // ES2016, 25.4.3.1.
 static bool
 PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
@@ -1583,17 +1586,17 @@ PromiseConstructor(JSContext* cx, unsign
 
     if (needsWrapping) {
         if (!cx->compartment()->wrap(cx, &proto))
             return false;
     } else {
         if (!GetPrototypeFromBuiltinConstructor(cx, args, &proto))
             return false;
     }
-    Rooted<PromiseObject*> promise(cx, PromiseObject::create(cx, executor, proto, needsWrapping));
+    PromiseObject* promise = PromiseObject::create(cx, executor, proto, needsWrapping);
     if (!promise)
         return false;
 
     // Step 11.
     args.rval().setObject(*promise);
     if (needsWrapping)
         return cx->compartment()->wrap(cx, args.rval());
     return true;
@@ -1634,24 +1637,26 @@ PromiseObject::create(JSContext* cx, Han
     // (maybe wrapped) Promise constructor was called. They contain checks and
     // can unwrap the Promise if required.
     RootedObject resolveFn(cx);
     RootedObject rejectFn(cx);
     if (!CreateResolvingFunctions(cx, promiseObj, &resolveFn, &rejectFn))
         return nullptr;
 
     // Need to wrap the resolution functions before storing them on the Promise.
+    MOZ_ASSERT(promise->getFixedSlot(PromiseSlot_RejectFunction).isUndefined(),
+               "Slot must be undefined so initFixedSlot can be used");
     if (needsWrapping) {
         AutoCompartment ac(cx, promise);
         RootedObject wrappedRejectFn(cx, rejectFn);
         if (!cx->compartment()->wrap(cx, &wrappedRejectFn))
             return nullptr;
-        promise->setFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*wrappedRejectFn));
+        promise->initFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*wrappedRejectFn));
     } else {
-        promise->setFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*rejectFn));
+        promise->initFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*rejectFn));
     }
 
     // Step 9.
     bool success;
     {
         FixedInvokeArgs<2> args(cx);
 
         args[0].setObject(*resolveFn);
@@ -2396,16 +2401,25 @@ Promise_static_species(JSContext* cx, un
 
 // ES2016, 25.4.5.1, implemented in Promise.js.
 
 static PromiseReactionRecord*
 NewReactionRecord(JSContext* cx, HandleObject resultPromise, HandleValue onFulfilled,
                   HandleValue onRejected, HandleObject resolve, HandleObject reject,
                   HandleObject incumbentGlobalObject)
 {
+    // Either of the following conditions must be met:
+    //   * resultPromise is a PromiseObject
+    //   * resolve and reject are callable
+    // except for Async Generator, there resultPromise can be nullptr.
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), resolve);
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(resolve));
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), reject);
+    MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(reject));
+
     Rooted<PromiseReactionRecord*> reaction(cx, NewObjectWithClassProto<PromiseReactionRecord>(cx));
     if (!reaction)
         return nullptr;
 
     assertSameCompartment(cx, resultPromise);
     assertSameCompartment(cx, onFulfilled);
     assertSameCompartment(cx, onRejected);
     assertSameCompartment(cx, resolve);
@@ -3103,17 +3117,17 @@ BlockOnPromise(JSContext* cx, HandleValu
         RootedObject resultPromise(cx, blockedPromise_);
         RootedObject resolveFun(cx);
         RootedObject rejectFun(cx);
 
         // By default, the blocked promise is added as an extra entry to the
         // rejected promises list.
         bool addToDependent = true;
 
-        if (C == PromiseCtor) {
+        if (C == PromiseCtor && resultPromise->is<PromiseObject>()) {
             addToDependent = false;
         } else {
             // 25.4.5.3., step 4.
             if (!NewPromiseCapability(cx, C, &resultPromise, &resolveFun, &rejectFun, true))
                 return false;
         }
 
         // 25.4.5.3., step 5.
@@ -3162,22 +3176,24 @@ BlockOnPromise(JSContext* cx, HandleValu
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
             return false;
         }
         ac.emplace(cx, unwrappedPromiseObj);
         if (!cx->compartment()->wrap(cx, &blockedPromise))
             return false;
     }
 
-    // If the object to depend on isn't a, maybe-wrapped, Promise instance,
-    // we ignore it. All this does is lose some small amount of debug
-    // information in scenarios that are highly unlikely to occur in useful
-    // code.
+    // If either the object to depend on or the object that gets blocked isn't
+    // a, maybe-wrapped, Promise instance, we ignore it. All this does is lose
+    // some small amount of debug information in scenarios that are highly
+    // unlikely to occur in useful code.
     if (!unwrappedPromiseObj->is<PromiseObject>())
         return true;
+    if (!blockedPromise_->is<PromiseObject>())
+        return true;
 
     Rooted<PromiseObject*> promise(cx, &unwrappedPromiseObj->as<PromiseObject>());
     return AddPromiseReaction(cx, promise, UndefinedHandleValue, UndefinedHandleValue,
                               blockedPromise, nullptr, nullptr, nullptr);
 }
 
 static MOZ_MUST_USE bool
 AddPromiseReaction(JSContext* cx, Handle<PromiseObject*> promise,
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -278,17 +278,17 @@ template <>
 struct InternalBarrierMethods<Value>
 {
     static bool isMarkable(const Value& v) { return v.isGCThing(); }
 
     static void preBarrier(const Value& v) {
         DispatchTyped(PreBarrierFunctor<Value>(), v);
     }
 
-    static void postBarrier(Value* vp, const Value& prev, const Value& next) {
+    static MOZ_ALWAYS_INLINE void postBarrier(Value* vp, const Value& prev, const Value& next) {
         MOZ_ASSERT(!CurrentThreadIsIonCompiling());
         MOZ_ASSERT(vp);
 
         // If the target needs an entry, add it.
         js::gc::StoreBuffer* sb;
         if (next.isObject() && (sb = reinterpret_cast<gc::Cell*>(&next.toObject())->storeBuffer())) {
             // If we know that the prev has already inserted an entry, we can
             // skip doing the lookup to add the new entry. Note that we cannot
@@ -313,18 +313,21 @@ template <>
 struct InternalBarrierMethods<jsid>
 {
     static bool isMarkable(jsid id) { return JSID_IS_GCTHING(id); }
     static void preBarrier(jsid id) { DispatchTyped(PreBarrierFunctor<jsid>(), id); }
     static void postBarrier(jsid* idp, jsid prev, jsid next) {}
 };
 
 // Base class of all barrier types.
+//
+// This is marked non-memmovable since post barriers added by derived classes
+// can add pointers to class instances to the store buffer.
 template <typename T>
-class BarrieredBase
+class MOZ_NON_MEMMOVABLE BarrieredBase
 {
   protected:
     // BarrieredBase is not directly instantiable.
     explicit BarrieredBase(const T& v) : value(v) {}
 
     // BarrieredBase subclasses cannot be copy constructed by default.
     BarrieredBase(const BarrieredBase<T>& other) = default;
 
@@ -364,17 +367,17 @@ class WriteBarrieredBase : public Barrie
     // Obviously this is dangerous unless you know the barrier is not needed.
     void unsafeSet(const T& v) { this->value = v; }
 
     // For users who need to manually barrier the raw types.
     static void writeBarrierPre(const T& v) { InternalBarrierMethods<T>::preBarrier(v); }
 
   protected:
     void pre() { InternalBarrierMethods<T>::preBarrier(this->value); }
-    void post(const T& prev, const T& next) {
+    MOZ_ALWAYS_INLINE void post(const T& prev, const T& next) {
         InternalBarrierMethods<T>::postBarrier(&this->value, prev, next);
     }
 };
 
 /*
  * PreBarriered only automatically handles pre-barriers. Post-barriers must be
  * manually implemented when using this class. GCPtr and HeapPtr should be used
  * in all cases that do not require explicit low-level control of moving
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2711,16 +2711,17 @@ template void
 StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>::trace(StoreBuffer*, TenuringTracer&);
 } // namespace gc
 } // namespace js
 
 void
 js::gc::StoreBuffer::SlotsEdge::trace(TenuringTracer& mover) const
 {
     NativeObject* obj = object();
+    MOZ_ASSERT(IsCellPointerValid(obj));
 
     // Beware JSObject::swap exchanging a native object for a non-native one.
     if (!obj->isNative())
         return;
 
     if (IsInsideNursery(obj))
         return;
 
@@ -2783,16 +2784,17 @@ TraceBufferedCells(TenuringTracer& mover
     }
 }
 
 void
 js::gc::StoreBuffer::traceWholeCells(TenuringTracer& mover)
 {
     for (ArenaCellSet* cells = bufferWholeCell; cells; cells = cells->next) {
         Arena* arena = cells->arena;
+        MOZ_ASSERT(IsCellPointerValid(arena));
 
         MOZ_ASSERT(arena->bufferedCells() == cells);
         arena->bufferedCells() = &ArenaCellSet::Empty;
 
         JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind());
         switch (kind) {
           case JS::TraceKind::Object:
             TraceBufferedCells<JSObject>(mover, arena, cells);
@@ -2812,16 +2814,17 @@ js::gc::StoreBuffer::traceWholeCells(Ten
 }
 
 void
 js::gc::StoreBuffer::CellPtrEdge::trace(TenuringTracer& mover) const
 {
     if (!*edge)
         return;
 
+    MOZ_ASSERT(IsCellPointerValid(*edge));
     MOZ_ASSERT((*edge)->getTraceKind() == JS::TraceKind::Object);
     mover.traverse(reinterpret_cast<JSObject**>(edge));
 }
 
 void
 js::gc::StoreBuffer::ValueEdge::trace(TenuringTracer& mover) const
 {
     if (deref())
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -77,19 +77,22 @@ Zone::~Zone()
     JSRuntime* rt = runtimeFromAnyThread();
     if (this == rt->gc.systemZone)
         rt->gc.systemZone = nullptr;
 
     js_delete(debuggers.ref());
     js_delete(jitZone_.ref());
 
 #ifdef DEBUG
-    // Avoid assertion destroying the weak map list if the embedding leaked GC things.
-    if (!rt->gc.shutdownCollectedEverything())
+    // Avoid assertions failures warning that not everything has been destroyed
+    // if the embedding leaked GC things.
+    if (!rt->gc.shutdownCollectedEverything()) {
         gcWeakMapList().clear();
+        regExps.clear();
+    }
 #endif
 }
 
 bool
 Zone::init(bool isSystemArg)
 {
     isSystem = isSystemArg;
     return uniqueIds().init() &&
--- a/js/src/jit-test/tests/wasm/import-export.js
+++ b/js/src/jit-test/tests/wasm/import-export.js
@@ -614,40 +614,87 @@ assertEq(e.call(), 1090);
     if (!options['baseline.enable'])
         return;
 
     let baselineTrigger = options['baseline.warmup.trigger'];
 
     let valueToConvert = 0;
     function ffi(n) { if (n == 1337) { return valueToConvert }; return 42; }
 
-    // Baseline compile ffi.
-    for (let i = baselineTrigger + 1; i --> 0;)
+    function sum(a, b, c) {
+        if (a === 1337)
+            return valueToConvert;
+        return (a|0) + (b|0) + (c|0) | 0;
+    }
+
+    // Baseline compile ffis.
+    for (let i = baselineTrigger + 1; i --> 0;) {
         ffi(i);
+        sum((i%2)?i:undefined,
+            (i%3)?i:undefined,
+            (i%4)?i:undefined);
+    }
 
-    let imports = { a: { ffi }};
+    let imports = {
+        a: {
+            ffi,
+            sum
+        }
+    };
 
     i = wasmEvalText(`(module
         (import $ffi "a" "ffi" (param i32) (result i32))
-        (func $foo (export "foo") (param i32) (result i32)
+
+        (import $missingOneArg "a" "sum" (param i32) (param i32) (result i32))
+        (import $missingTwoArgs "a" "sum" (param i32) (result i32))
+        (import $missingThreeArgs "a" "sum" (result i32))
+
+        (func (export "foo") (param i32) (result i32)
          get_local 0
-         call $ffi)
+         call $ffi
+        )
+
+        (func (export "missThree") (result i32)
+         call $missingThreeArgs
+        )
+
+        (func (export "missTwo") (param i32) (result i32)
+         get_local 0
+         call $missingTwoArgs
+        )
+
+        (func (export "missOne") (param i32) (param i32) (result i32)
+         get_local 0
+         get_local 1
+         call $missingOneArg
+        )
     )`, imports).exports;
 
-    // Enable the jit exit.
+    // Enable the jit exit for each JS callee.
     assertEq(i.foo(0), 42);
 
-    // Test the jit exit.
+    assertEq(i.missThree(), 0);
+    assertEq(i.missTwo(42), 42);
+    assertEq(i.missOne(13, 37), 50);
+
+    // Test the jit exit under normal conditions.
     assertEq(i.foo(0), 42);
     assertEq(i.foo(1337), 0);
 
+    // Test the arguments rectifier.
+    assertEq(i.missThree(), 0);
+    assertEq(i.missTwo(-1), -1);
+    assertEq(i.missOne(23, 10), 33);
+
     // Test OOL coercion.
     valueToConvert = 2**31;
     assertEq(i.foo(1337), -(2**31));
 
     // Test OOL error path.
     valueToConvert = { valueOf() { throw new Error('make ffi great again'); } }
     assertErrorMessage(() => i.foo(1337), Error, "make ffi great again");
 
     valueToConvert = { toString() { throw new Error('a FFI to believe in'); } }
     assertErrorMessage(() => i.foo(1337), Error, "a FFI to believe in");
+
+    // Test the error path in the arguments rectifier.
+    assertErrorMessage(() => i.missTwo(1337), Error, "a FFI to believe in");
 })();
-
--- a/js/src/jit-test/tests/wasm/profiling.js
+++ b/js/src/jit-test/tests/wasm/profiling.js
@@ -326,63 +326,97 @@ for (let type of ['f32', 'f64']) {
         return;
 
     setJitCompilerOption("baseline.warmup.trigger", 10);
 
     enableGeckoProfiling();
 
     var m = new Module(wasmTextToBinary(`(module
         (import $ffi "a" "ffi" (param i32) (result i32))
-        (func $foo (export "foo") (param i32) (result i32)
+
+        (import $missingOneArg "a" "sumTwo" (param i32) (result i32))
+
+        (func (export "foo") (param i32) (result i32)
          get_local 0
          call $ffi)
+
+        (func (export "id") (param i32) (result i32)
+         get_local 0
+         call $missingOneArg
+        )
     )`));
 
     var valueToConvert = 0;
     function ffi(n) {
         new Error().stack; // enter VM to clobber FP register.
         if (n == 1337) { return valueToConvert };
         return 42;
     }
 
+    function sumTwo(a, b) {
+        return (a|0)+(b|0)|0;
+    }
+
     // Baseline compile ffi.
-    for (var i = 20; i --> 0;)
+    for (var i = 20; i --> 0;) {
         ffi(i);
+        sumTwo(i-1, i+1);
+    }
 
-    var imports = { a: { ffi }};
+    var imports = {
+        a: {
+            ffi,
+            sumTwo
+        }
+    };
 
     var i = new Instance(m, imports).exports;
 
     // Enable the jit exit.
     assertEq(i.foo(0), 42);
+    assertEq(i.id(13), 13);
 
+    // Test normal conditions.
     enableSingleStepProfiling();
     assertEq(i.foo(0), 42);
-    assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "<,1,>",
+    assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>",
         // Losing stack information while the JIT func prologue sets profiler
         // virtual FP.
         "",
         // Callee time.
-        "<,1,>",
+        "<,2,>",
         // Losing stack information while we're exiting JIT func epilogue and
         // recovering wasm FP.
         "",
         // Back into the jit exit (frame info has been recovered).
-        "<,1,>",
+        "<,2,>",
         // Normal unwinding.
-        "1,>", ">", ""]);
+        "2,>", ">", ""]);
+
+    // Test rectifier frame.
+    enableSingleStepProfiling();
+    assertEq(i.id(100), 100);
+    assertEqStacks(disableSingleStepProfiling(), ["", ">", "3,>", "<,3,>",
+        // Rectifier frame time is spent here (lastProfilingFrame has not been
+        // set).
+        "",
+        "<,3,>",
+        // Rectifier frame unwinding time is spent here.
+        "",
+        "<,3,>",
+        "3,>", ">", ""]);
 
     // Test OOL coercion path.
     valueToConvert = 2**31;
 
     enableSingleStepProfiling();
     assertEq(i.foo(1337), -(2**31));
-    assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "<,1,>", "", "<,1,>", "",
+    assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>", "", "<,2,>", "",
         // Back into the jit exit (frame info has been recovered).
         // Inline conversion fails, we skip to the OOL path, call from there
         // and get back to the jit exit.
-        "<,1,>",
+        "<,2,>",
         // Normal unwinding.
-        "1,>", ">", ""]);
+        "2,>", ">", ""]);
 
     disableGeckoProfiling();
     setJitCompilerOption("baseline.warmup.trigger", prevOptions["baseline.warmup.trigger"]);
 })();
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -389,21 +389,23 @@ struct BaselineStackBuilder
 #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
       defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
       defined(JS_CODEGEN_X64)
         // On X64, ARM, ARM64, and MIPS, the frame pointer save location depends on
         // the caller of the rectifier frame.
         BufferPointer<RectifierFrameLayout> priorFrame =
             pointerAtStackOffset<RectifierFrameLayout>(priorOffset);
         FrameType priorType = priorFrame->prevType();
-        MOZ_ASSERT(priorType == JitFrame_IonJS || priorType == JitFrame_BaselineStub);
+        MOZ_ASSERT(priorType == JitFrame_WasmToJSJit ||
+                   priorType == JitFrame_IonJS ||
+                   priorType == JitFrame_BaselineStub);
 
-        // If the frame preceding the rectifier is an IonJS frame, then once again
-        // the frame pointer does not matter.
-        if (priorType == JitFrame_IonJS)
+        // If the frame preceding the rectifier is an IonJS or WasmToJSJit
+        // entry frame, then once again the frame pointer does not matter.
+        if (priorType == JitFrame_IonJS || priorType == JitFrame_WasmToJSJit)
             return nullptr;
 
         // Otherwise, the frame preceding the rectifier is a BaselineStub frame.
         //  let X = STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
         //      X + RectifierFrameLayout::Size()
         //        + ((RectifierFrameLayout*) X)->prevFrameLocalSize()
         //        - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
         size_t extraOffset = RectifierFrameLayout::Size() + priorFrame->prevFrameLocalSize() +
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -275,16 +275,25 @@ JitRuntime::initialize(JSContext* cx, Au
             return false;
 
         JitSpew(JitSpew_Codegen, "# Emitting invalidator");
         invalidator_ = generateInvalidator(cx);
         if (!invalidator_)
             return false;
     }
 
+    // The arguments rectifier has to use the same frame layout as the function
+    // frames it rectifies.
+    static_assert(mozilla::IsBaseOf<JitFrameLayout, RectifierFrameLayout>::value,
+                  "a rectifier frame can be used with jit frame");
+    static_assert(mozilla::IsBaseOf<JitFrameLayout, WasmToJSJitFrameLayout>::value,
+                  "wasm frames simply are jit frames");
+    static_assert(sizeof(JitFrameLayout) == sizeof(WasmToJSJitFrameLayout),
+                  "thus a rectifier frame can be used with a wasm frame");
+
     JitSpew(JitSpew_Codegen, "# Emitting sequential arguments rectifier");
     argumentsRectifier_ = generateArgumentsRectifier(cx, &argumentsRectifierReturnAddr_.writeRef());
     if (!argumentsRectifier_)
         return false;
 
     JitSpew(JitSpew_Codegen, "# Emitting EnterJIT sequence");
     enterJIT_ = generateEnterJIT(cx, EnterJitOptimized);
     if (!enterJIT_)
--- a/js/src/jit/JSJitFrameIter.cpp
+++ b/js/src/jit/JSJitFrameIter.cpp
@@ -639,16 +639,27 @@ JSJitProfilingFrameIterator::fixBaseline
 void
 JSJitProfilingFrameIterator::operator++()
 {
     JitFrameLayout* frame = framePtr();
     moveToNextFrame(frame);
 }
 
 void
+JSJitProfilingFrameIterator::moveToWasmFrame(CommonFrameLayout* frame)
+{
+    // No previous js jit frame, this is a transition frame, used to
+    // pass a wasm iterator the correct value of FP.
+    returnAddressToFp_ = nullptr;
+    fp_ = GetPreviousRawFrame<uint8_t*>(frame);
+    type_ = JitFrame_WasmToJSJit;
+    MOZ_ASSERT(!done());
+}
+
+void
 JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
 {
     /*
      * fp_ points to a Baseline or Ion frame.  The possible call-stacks
      * patterns occurring between this frame and a previous Ion or Baseline
      * frame are as follows:
      *
      * <Baseline-Or-Ion>
@@ -661,16 +672,18 @@ JSJitProfilingFrameIterator::moveToNextF
      * ^--- WasmToJSJit <---- (other wasm frames, not handled by this iterator)
      * |
      * ^--- Argument Rectifier
      * |    ^
      * |    |
      * |    ^--- Ion
      * |    |
      * |    ^--- Baseline Stub <---- Baseline
+     * |    |
+     * |    ^--- WasmToJSJit <--- (other wasm frames)
      * |
      * ^--- Entry Frame (From C++)
      *      Exit Frame (From previous JitActivation)
      *      ^
      *      |
      *      ^--- Ion
      *      |
      *      ^--- Baseline
@@ -721,37 +734,38 @@ JSJitProfilingFrameIterator::moveToNextF
                 GetPreviousRawFrame<BaselineStubFrameLayout*>(rectFrame);
             returnAddressToFp_ = stubFrame->returnAddress();
             fp_ = ((uint8_t*) stubFrame->reverseSavedFramePtr())
                     + jit::BaselineFrame::FramePointerOffset;
             type_ = JitFrame_BaselineJS;
             return;
         }
 
+        if (rectPrevType == JitFrame_WasmToJSJit) {
+            moveToWasmFrame(rectFrame);
+            return;
+        }
+
         MOZ_CRASH("Bad frame type prior to rectifier frame.");
     }
 
     if (prevType == JitFrame_IonICCall) {
         IonICCallFrameLayout* callFrame =
             GetPreviousRawFrame<IonICCallFrameLayout*>(frame);
 
         MOZ_ASSERT(callFrame->prevType() == JitFrame_IonJS);
 
         returnAddressToFp_ = callFrame->returnAddress();
         fp_ = GetPreviousRawFrame<uint8_t*>(callFrame);
         type_ = JitFrame_IonJS;
         return;
     }
 
     if (prevType == JitFrame_WasmToJSJit) {
-        // No previous js jit frame, this is a transition frame, used to pass
-        // a wasm iterator the correct value of FP.
-        returnAddressToFp_ = nullptr;
-        fp_ = GetPreviousRawFrame<uint8_t*>(frame);
-        type_ = JitFrame_WasmToJSJit;
+        moveToWasmFrame(frame);
         return;
     }
 
     if (prevType == JitFrame_CppToJSJit) {
         // No previous frame, set to null to indicate that
         // JSJitProfilingFrameIterator is done().
         returnAddressToFp_ = nullptr;
         fp_ = nullptr;
--- a/js/src/jit/JSJitFrameIter.h
+++ b/js/src/jit/JSJitFrameIter.h
@@ -292,16 +292,17 @@ class JSJitProfilingFrameIterator
 
     inline JitFrameLayout* framePtr();
     inline JSScript* frameScript();
     MOZ_MUST_USE bool tryInitWithPC(void* pc);
     MOZ_MUST_USE bool tryInitWithTable(JitcodeGlobalTable* table, void* pc, JSRuntime* rt,
                                        bool forLastCallSite);
     void fixBaselineReturnAddress();
 
+    void moveToWasmFrame(CommonFrameLayout* frame);
     void moveToNextFrame(CommonFrameLayout* frame);
 
   public:
     JSJitProfilingFrameIterator(JSContext* cx,
                               const JS::ProfilingFrameIterator::RegisterState& state);
     explicit JSJitProfilingFrameIterator(void* exitFrame);
 
     void operator++();
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -440,21 +440,21 @@ class JitFrameLayout : public CommonFram
 class RectifierFrameLayout : public JitFrameLayout
 {
   public:
     static inline size_t Size() {
         return sizeof(RectifierFrameLayout);
     }
 };
 
-class WasmFrameLayout : public JitFrameLayout
+class WasmToJSJitFrameLayout : public JitFrameLayout
 {
   public:
     static inline size_t Size() {
-        return sizeof(WasmFrameLayout);
+        return sizeof(WasmToJSJitFrameLayout);
     }
 };
 
 class IonICCallFrameLayout : public CommonFrameLayout
 {
   protected:
     // Pointer to root the stub's JitCode.
     JitCode* stubCode_;
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1650,16 +1650,32 @@ MacroAssembler::generateBailoutTail(Regi
             addToStackPtr(Imm32(ExitFrameLayout::SizeWithFooter()));
 
             jump(jitcodeReg);
         }
     }
 }
 
 void
+MacroAssembler::assertRectifierFrameParentType(Register frameType)
+{
+#ifdef DEBUG
+    {
+        // Check the possible previous frame types here.
+        Label checkOk;
+        branch32(Assembler::Equal, frameType, Imm32(JitFrame_IonJS), &checkOk);
+        branch32(Assembler::Equal, frameType, Imm32(JitFrame_BaselineStub), &checkOk);
+        branch32(Assembler::Equal, frameType, Imm32(JitFrame_WasmToJSJit), &checkOk);
+        assumeUnreachable("Unrecognized frame type preceding RectifierFrame.");
+        bind(&checkOk);
+    }
+#endif
+}
+
+void
 MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, Label* failure)
 {
     loadPtr(Address(script, JSScript::offsetOfBaselineOrIonRaw()), dest);
     if (failure)
         branchTestPtr(Assembler::Zero, dest, dest, failure);
 }
 
 void
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1832,16 +1832,18 @@ class MacroAssembler : public MacroAssem
     // Result of the typeof operation. Falls back to slow-path for proxies.
     void typeOfObject(Register objReg, Register scratch, Label* slow,
                       Label* isObject, Label* isCallable, Label* isUndefined);
 
   public:
     // Generates code used to complete a bailout.
     void generateBailoutTail(Register scratch, Register bailoutInfo);
 
+    void assertRectifierFrameParentType(Register frameType);
+
   public:
 #ifndef JS_CODEGEN_ARM64
     // StackPointer manipulation functions.
     // On ARM64, the StackPointer is implemented as two synchronized registers.
     // Code shared across platforms must use these functions to be valid.
     template <typename T> inline void addToStackPtr(T t);
     template <typename T> inline void addStackPtrTo(T t);
 
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -1282,20 +1282,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
+    // a BaselineStub frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1330,42 +1330,40 @@ JitRuntime::generateProfilerExitFrameTai
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.ma_lsr(Imm32(FRAMESIZE_SHIFT), scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
+        masm.assertRectifierFrameParentType(scratch3);
+
         // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.ma_add(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         masm.ma_add(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
 
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1419,17 +1417,17 @@ JitRuntime::generateProfilerExitFrameTai
         //                       IonICCallFrameLayout::Size()
         masm.ma_add(scratch2, scratch3, scratch1);
         masm.addPtr(Imm32(IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -1123,42 +1123,40 @@ JitRuntime::generateProfilerExitFrameTai
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
+        masm.assertRectifierFrameParentType(scratch3);
+
         // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.addPtr(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         masm.addPtr(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
 
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1213,17 +1211,17 @@ JitRuntime::generateProfilerExitFrameTai
         //                       IonICCallFrameLayout::Size()
         masm.addPtr(scratch2, scratch3, scratch1);
         masm.addPtr(Imm32(IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/mips-shared/Architecture-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Architecture-mips-shared.cpp
@@ -8,62 +8,72 @@
 
 #include <fcntl.h>
 #include <unistd.h>
 
 #include "jit/RegisterSets.h"
 
 #define HWCAP_MIPS (1 << 28)
 #define HWCAP_LOONGSON (1 << 27)
+#define HWCAP_R2 (1 << 26)
 #define HWCAP_FPU (1 << 0)
 
 namespace js {
 namespace jit {
 
 static uint32_t
 get_mips_flags()
 {
     uint32_t flags = HWCAP_MIPS;
 
 #if defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
     flags |= HWCAP_FPU;
+    flags |= HWCAP_R2;
 #else
 # ifdef __linux__
     FILE* fp = fopen("/proc/cpuinfo", "r");
     if (!fp)
         return flags;
 
     char buf[1024];
     memset(buf, 0, sizeof(buf));
     fread(buf, sizeof(char), sizeof(buf) - 1, fp);
     fclose(fp);
     if (strstr(buf, "FPU"))
         flags |= HWCAP_FPU;
     if (strstr(buf, "Loongson"))
         flags |= HWCAP_LOONGSON;
+    if (strstr(buf, "mips32r2") || strstr(buf, "mips64r2"))
+        flags |= HWCAP_R2;
 # endif
 #endif // JS_SIMULATOR_MIPS32 || JS_SIMULATOR_MIPS64
     return flags;
 }
 
 static bool check_fpu()
 {
     return mips_private::Flags & HWCAP_FPU;
 }
 
 static bool check_loongson()
 {
     return mips_private::Flags & HWCAP_LOONGSON;
 }
 
+static bool check_r2()
+{
+    return mips_private::Flags & HWCAP_R2;
+}
+
 namespace mips_private {
     // Cache a local copy so we only have to read /proc/cpuinfo once.
     uint32_t Flags = get_mips_flags();
     bool hasFPU = check_fpu();;
     bool isLoongson = check_loongson();
+    bool hasR2 = check_r2();
 }
 
 Registers::Code
 Registers::FromName(const char* name)
 {
     for (size_t i = 0; i < Total; i++) {
         if (strcmp(GetName(i), name) == 0)
             return Code(i);
--- a/js/src/jit/mips-shared/Architecture-mips-shared.h
+++ b/js/src/jit/mips-shared/Architecture-mips-shared.h
@@ -309,21 +309,23 @@ class FloatRegisterMIPSShared
         return 63 - mozilla::CountLeadingZeroes64(x);
     }
 };
 
 namespace mips_private {
     extern uint32_t Flags;
     extern bool hasFPU;
     extern bool isLoongson;
+    extern bool hasR2;
 }
 
 inline uint32_t GetMIPSFlags() { return mips_private::Flags; }
 inline bool hasFPU() { return mips_private::hasFPU; }
 inline bool isLoongson() { return mips_private::isLoongson; }
+inline bool hasR2() { return mips_private::hasR2; }
 
 // MIPS doesn't have double registers that can NOT be treated as float32.
 inline bool
 hasUnaliasedDouble() {
     return false;
 }
 
 // On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need
--- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp
@@ -709,46 +709,51 @@ AssemblerMIPSShared::as_dsrav(Register r
     return writeInst(InstReg(op_special, rs, rt, rd, ff_dsrav).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_rotr(Register rd, Register rt, uint16_t sa)
 {
     MOZ_ASSERT(sa < 32);
     spew("rotr   %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_srl).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_drotr(Register rd, Register rt, uint16_t sa)
 {
     MOZ_ASSERT(sa < 32);
     spew("drotr  %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_dsrl).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_drotr32(Register rd, Register rt, uint16_t sa)
 {
     MOZ_ASSERT(31 < sa && sa < 64);
     spew("drotr32%3s,%3s, 0x%x", rd.name(), rt.name(), sa - 32);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special, rs_one, rt, rd, sa - 32, ff_dsrl32).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_rotrv(Register rd, Register rt, Register rs)
 {
     spew("rotrv  %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_srlv).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_drotrv(Register rd, Register rt, Register rs)
 {
     spew("drotrv %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_dsrlv).encode());
 }
 
 // Load and store instructions
 BufferOffset
 AssemblerMIPSShared::as_lb(Register rd, Register rs, int16_t off)
 {
     spew("lb     %3s, (0x%x)%2s", rd.name(), off, rs.name());
@@ -1071,101 +1076,111 @@ AssemblerMIPSShared::as_dclz(Register rd
 
 BufferOffset
 AssemblerMIPSShared::as_ins(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32);
     Register rd;
     rd = Register::FromCode(pos + size - 1);
     spew("ins    %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ins).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dins(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32);
     Register rd;
     rd = Register::FromCode(pos + size - 1);
     spew("dins   %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dins).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dinsm(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size >= 2 && size <= 64 && pos + size > 32 && pos + size <= 64);
     Register rd;
     rd = Register::FromCode(pos + size - 1 - 32);
     spew("dinsm  %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dinsm).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dinsu(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos >= 32 && pos < 64 && size >= 1 && size <= 32 && pos + size > 32 && pos + size <= 64);
     Register rd;
     rd = Register::FromCode(pos + size - 1 - 32);
     spew("dinsu  %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dinsu).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_ext(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32);
     Register rd;
     rd = Register::FromCode(size - 1);
     spew("ext    %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ext).encode());
 }
 
 // Sign extend
 BufferOffset
 AssemblerMIPSShared::as_seb(Register rd, Register rt)
 {
     spew("seb    %3s,%3s", rd.name(), rt.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, zero, rt, rd, 16, ff_bshfl).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_seh(Register rd, Register rt)
 {
     spew("seh    %3s,%3s", rd.name(), rt.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, zero, rt, rd, 24, ff_bshfl).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dext(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 63);
     Register rd;
     rd = Register::FromCode(size - 1);
     spew("dext   %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dext).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dextm(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos < 32 && size > 32 && size <= 64 && pos + size > 32 && pos + size <= 64);
     Register rd;
     rd = Register::FromCode(size - 1 - 32);
     spew("dextm  %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
-   return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
+    MOZ_ASSERT(hasR2());
+    return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_dextu(Register rt, Register rs, uint16_t pos, uint16_t size)
 {
     MOZ_ASSERT(pos >= 32 && pos < 64 && size != 0 && size <= 32 && pos + size > 32 && pos + size <= 64);
     Register rd;
     rd = Register::FromCode(size - 1);
     spew("dextu  %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dextu).encode());
 }
 
 // FP instructions
 BufferOffset
 AssemblerMIPSShared::as_ld(FloatRegister fd, Register base, int32_t off)
 {
     MOZ_ASSERT(Imm16::IsInSignedRange(off));
@@ -1407,16 +1422,17 @@ AssemblerMIPSShared::as_truncws(FloatReg
     spew("trunc.w.s%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_s, zero, fs, fd, ff_trunc_w_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_truncls(FloatRegister fd, FloatRegister fs)
 {
     spew("trunc.l.s%3s,%3s", fd.name(), fs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_cop1, rs_s, zero, fs, fd, ff_trunc_l_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_ceilwd(FloatRegister fd, FloatRegister fs)
 {
     spew("ceil.w.d%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_ceil_w_fmt).encode());
@@ -1442,23 +1458,25 @@ AssemblerMIPSShared::as_truncwd(FloatReg
     spew("trunc.w.d%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_trunc_w_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_truncld(FloatRegister fd, FloatRegister fs)
 {
     spew("trunc.l.d%3s,%3s", fd.name(), fs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_trunc_l_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_cvtdl(FloatRegister fd, FloatRegister fs)
 {
     spew("cvt.d.l%3s,%3s", fd.name(), fs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_d_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_cvtds(FloatRegister fd, FloatRegister fs)
 {
     spew("cvt.d.s%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_s, zero, fs, fd, ff_cvt_d_fmt).encode());
@@ -1477,16 +1495,17 @@ AssemblerMIPSShared::as_cvtsd(FloatRegis
     spew("cvt.s.d%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_cvt_s_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_cvtsl(FloatRegister fd, FloatRegister fs)
 {
     spew("cvt.s.l%3s,%3s", fd.name(), fs.name());
+    MOZ_ASSERT(hasR2());
     return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_s_fmt).encode());
 }
 
 BufferOffset
 AssemblerMIPSShared::as_cvtsw(FloatRegister fd, FloatRegister fs)
 {
     spew("cvt.s.w%3s,%3s", fd.name(), fs.name());
     return writeInst(InstReg(op_cop1, rs_w, zero, fs, fd, ff_cvt_s_fmt).encode());
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -1575,17 +1575,17 @@ CodeGeneratorMIPSShared::visitCopySignF(
 
     Register lhsi = ToRegister(ins->getTemp(0));
     Register rhsi = ToRegister(ins->getTemp(1));
 
     masm.moveFromFloat32(lhs, lhsi);
     masm.moveFromFloat32(rhs, rhsi);
 
     // Combine.
-    masm.as_ins(rhsi, lhsi, 0, 31);
+    masm.ma_ins(rhsi, lhsi, 0, 31);
 
     masm.moveToFloat32(rhsi, output);
 }
 
 void
 CodeGeneratorMIPSShared::visitCopySignD(LCopySignD* ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->getOperand(0));
@@ -1595,17 +1595,17 @@ CodeGeneratorMIPSShared::visitCopySignD(
     Register lhsi = ToRegister(ins->getTemp(0));
     Register rhsi = ToRegister(ins->getTemp(1));
 
     // Manipulate high words of double inputs.
     masm.moveFromDoubleHi(lhs, lhsi);
     masm.moveFromDoubleHi(rhs, rhsi);
 
     // Combine.
-    masm.as_ins(rhsi, lhsi, 0, 31);
+    masm.ma_ins(rhsi, lhsi, 0, 31);
 
     masm.moveToDoubleHi(rhsi, output);
 }
 
 void
 CodeGeneratorMIPSShared::visitValue(LValue* value)
 {
     const ValueOperand out = ToOutValue(value);
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
@@ -24,23 +24,23 @@ void
 MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest)
 {
     moveToFloat32(src, dest);
 }
 
 void
 MacroAssembler::move8SignExtend(Register src, Register dest)
 {
-    as_seb(dest, src);
+    ma_seb(dest, src);
 }
 
 void
 MacroAssembler::move16SignExtend(Register src, Register dest)
 {
-    as_seh(dest, src);
+    ma_seh(dest, src);
 }
 
 // ===============================================================
 // Logical instructions
 
 void
 MacroAssembler::not32(Register reg)
 {
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -66,23 +66,37 @@ void
 MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Imm32 shift)
 {
     as_sra(rd, rt, shift.value % 32);
 }
 
 void
 MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Imm32 shift)
 {
-    as_rotr(rd, rt, shift.value % 32);
+    if (hasR2()) {
+        as_rotr(rd, rt, shift.value % 32);
+    } else {
+        ScratchRegisterScope scratch(asMasm());
+        as_srl(scratch, rt, shift.value % 32);
+        as_sll(rd, rt, (32 - (shift.value % 32)) % 32);
+        as_or(rd, rd, scratch);
+    }
 }
 
 void
 MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Imm32 shift)
 {
-    as_rotr(rd, rt, 32 - (shift.value % 32));
+    if (hasR2()) {
+        as_rotr(rd, rt, (32 - (shift.value % 32)) % 32);
+    } else {
+        ScratchRegisterScope scratch(asMasm());
+        as_srl(scratch, rt, (32 - (shift.value % 32)) % 32);
+        as_sll(rd, rt, shift.value % 32);
+        as_or(rd, rd, scratch);
+    }
 }
 
 void
 MacroAssemblerMIPSShared::ma_sll(Register rd, Register rt, Register shift)
 {
     as_sllv(rd, rt, shift);
 }
 
@@ -96,38 +110,116 @@ void
 MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Register shift)
 {
     as_srav(rd, rt, shift);
 }
 
 void
 MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Register shift)
 {
-    as_rotrv(rd, rt, shift);
+    if (hasR2()) {
+        as_rotrv(rd, rt, shift);
+    } else {
+        ScratchRegisterScope scratch(asMasm());
+        ma_negu(scratch, shift);
+        as_sllv(scratch, rt, scratch);
+        as_srlv(rd, rt, shift);
+        as_or(rd, rd, scratch);
+    }
 }
 
 void
 MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Register shift)
 {
-    ma_negu(ScratchRegister, shift);
-    as_rotrv(rd, rt, ScratchRegister);
+    ScratchRegisterScope scratch(asMasm());
+    ma_negu(scratch, shift);
+    if (hasR2()) {
+        as_rotrv(rd, rt, scratch);
+    } else {
+        as_srlv(rd, rt, scratch);
+        as_sllv(scratch, rt, shift);
+        as_or(rd, rd, scratch);
+    }
 }
 
 void
 MacroAssemblerMIPSShared::ma_negu(Register rd, Register rs)
 {
     as_subu(rd, zero, rs);
 }
 
 void
 MacroAssemblerMIPSShared::ma_not(Register rd, Register rs)
 {
     as_nor(rd, rs, zero);
 }
 
+// Bit extract/insert
+void
+MacroAssemblerMIPSShared::ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size) {
+    MOZ_ASSERT(pos < 32);
+    MOZ_ASSERT(pos + size < 33);
+
+    if (hasR2()) {
+        as_ext(rt, rs, pos, size);
+    } else {
+        int shift_left = 32 - (pos + size);
+        as_sll(rt, rs, shift_left);
+        int shift_right = 32 - size;
+        if (shift_right > 0) {
+            as_srl(rt, rt, shift_right);
+        }
+    }
+}
+
+void
+MacroAssemblerMIPSShared::ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size) {
+    MOZ_ASSERT(pos < 32);
+    MOZ_ASSERT(pos + size <= 32);
+    MOZ_ASSERT(size != 0);
+
+    if (hasR2()) {
+        as_ins(rt, rs, pos, size);
+    } else {
+        ScratchRegisterScope scratch(asMasm());
+        SecondScratchRegisterScope scratch2(asMasm());
+        ma_subu(scratch, zero, Imm32(1));
+        as_srl(scratch, scratch, 32 - size);
+        as_and(scratch2, rs, scratch);
+        as_sll(scratch2, scratch2, pos);
+        as_sll(scratch, scratch, pos);
+        as_nor(scratch, scratch, zero);
+        as_and(scratch, rt, scratch);
+        as_or(rt, scratch2, scratch);
+    }
+}
+
+// Sign extend
+void
+MacroAssemblerMIPSShared::ma_seb(Register rd, Register rt)
+{
+    if (hasR2()) {
+        as_seb(rd, rt);
+    } else {
+        as_sll(rd, rt, 24);
+        as_sra(rd, rd, 24);
+    }
+}
+
+void
+MacroAssemblerMIPSShared::ma_seh(Register rd, Register rt)
+{
+    if (hasR2()) {
+        as_seh(rd, rt);
+    } else {
+        as_sll(rd, rt, 16);
+        as_sra(rd, rd, 16);
+    }
+}
+
 // And.
 void
 MacroAssemblerMIPSShared::ma_and(Register rd, Register rs)
 {
     as_and(rd, rd, rs);
 }
 
 void
@@ -479,17 +571,17 @@ MacroAssemblerMIPSShared::ma_load_unalig
 
     switch (size) {
       case SizeHalfWord:
         as_lbu(dest, base, lowOffset);
         if (extension != ZeroExtend)
             as_lbu(temp, base, hiOffset);
         else
             as_lb(temp, base, hiOffset);
-        as_ins(dest, temp, 8, 24);
+        ma_ins(dest, temp, 8, 24);
         break;
       case SizeWord:
         as_lwl(dest, base, hiOffset);
         as_lwr(dest, base, lowOffset);
 #ifdef JS_CODEGEN_MIPS64
         if (extension != ZeroExtend)
             as_dext(dest, dest, 0, 32);
 #endif
@@ -622,17 +714,17 @@ MacroAssemblerMIPSShared::ma_store_unali
         base = ScratchRegister;
         lowOffset = Imm16(0).encode();
         hiOffset = Imm16(size / 8 - 1).encode();
     }
 
     switch (size) {
       case SizeHalfWord:
         as_sb(data, base, lowOffset);
-        as_ext(temp, data, 8, 8);
+        ma_ext(temp, data, 8, 8);
         as_sb(temp, base, hiOffset);
         break;
       case SizeWord:
         as_swl(data, base, hiOffset);
         as_swr(data, base, lowOffset);
         break;
       case SizeDouble:
         as_sdl(data, base, hiOffset);
@@ -1238,20 +1330,20 @@ MacroAssemblerMIPSShared::atomicFetchOpM
 
     as_sllv(valueTemp, value, offsetTemp);
     if (output != InvalidReg) {
         as_and(output, flagTemp, maskTemp);
         as_srlv(output, output, offsetTemp);
         if (signExtend) {
             switch (nbytes) {
             case 1:
-                as_seb(output, output);
+                ma_seb(output, output);
                 break;
             case 2:
-                as_seh(output, output);
+                ma_seh(output, output);
                 break;
             case 4:
                 break;
             default:
                 MOZ_CRASH("NYI");
             }
         }
     }
@@ -1413,20 +1505,20 @@ MacroAssemblerMIPSShared::compareExchang
     as_sync(0);
 
     bind(&end);
 
     as_srlv(output, output, offsetTemp);
     if (signExtend) {
         switch (nbytes) {
         case 1:
-            as_seb(output, output);
+            ma_seb(output, output);
             break;
         case 2:
-            as_seh(output, output);
+            ma_seh(output, output);
             break;
         case 4:
             break;
         default:
             MOZ_CRASH("NYI");
         }
     }
 }
@@ -1764,24 +1856,24 @@ MacroAssembler::comment(const char* msg)
 
 
 void
 MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     as_truncwd(ScratchFloat32Reg, input);
     as_cfc1(ScratchRegister, Assembler::FCSR);
     moveFromFloat32(ScratchFloat32Reg, output);
-    as_ext(ScratchRegister, ScratchRegister, 6, 1);
+    ma_ext(ScratchRegister, ScratchRegister, 6, 1);
     ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
 }
 
 
 void
 MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     as_truncws(ScratchFloat32Reg, input);
     as_cfc1(ScratchRegister, Assembler::FCSR);
     moveFromFloat32(ScratchFloat32Reg, output);
-    as_ext(ScratchRegister, ScratchRegister, 6, 1);
+    ma_ext(ScratchRegister, ScratchRegister, 6, 1);
     ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
 }
 
 //}}} check_macroassembler_style
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -80,16 +80,24 @@ class MacroAssemblerMIPSShared : public 
     void ma_ror(Register rd, Register rt, Register shift);
     void ma_rol(Register rd, Register rt, Register shift);
 
     // Negate
     void ma_negu(Register rd, Register rs);
 
     void ma_not(Register rd, Register rs);
 
+    // Bit extract/insert
+    void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
+    void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
+
+    // Sign extend
+    void ma_seb(Register rd, Register rt);
+    void ma_seh(Register rd, Register rt);
+
     // and
     void ma_and(Register rd, Register rs);
     void ma_and(Register rd, Imm32 imm);
     void ma_and(Register rd, Register rs, Imm32 imm);
 
     // or
     void ma_or(Register rd, Register rs);
     void ma_or(Register rd, Imm32 imm);
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -422,31 +422,31 @@ JitRuntime::generateInvalidator(JSContex
 }
 
 JitCode*
 JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
 {
     MacroAssembler masm(cx);
     masm.pushReturnAddress();
 
-    // ArgumentsRectifierReg contains the |nargs| pushed onto the current
-    // frame. Including |this|, there are (|nargs| + 1) arguments to copy.
-    MOZ_ASSERT(ArgumentsRectifierReg == s3);
-
     Register numActArgsReg = t6;
     Register calleeTokenReg = t7;
     Register numArgsReg = t5;
 
-    // Copy number of actual arguments into numActArgsReg
+    // Load the number of actual arguments into numActArgsReg
     masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfNumActualArgs()),
                  numActArgsReg);
 
     // Load the number of |undefined|s to push into t1.
     masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfCalleeToken()),
                  calleeTokenReg);
+
+    // Copy the number of actual arguments into s3.
+    masm.mov(numActArgsReg, s3);
+
     masm.mov(calleeTokenReg, numArgsReg);
     masm.andPtr(Imm32(CalleeTokenMask), numArgsReg);
     masm.load16ZeroExtend(Address(numArgsReg, JSFunction::offsetOfNargs()), numArgsReg);
 
     masm.as_subu(t1, numArgsReg, s3);
 
     // Get the topmost argument.
     masm.ma_sll(t0, s3, Imm32(3)); // t0 <- nargs * 8
@@ -1261,20 +1261,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
+    // a BaselineStub frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1309,42 +1309,40 @@ JitRuntime::generateProfilerExitFrameTai
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.ma_srl(scratch1, scratch3, Imm32(FRAMESIZE_SHIFT));
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
+        masm.assertRectifierFrameParentType(scratch3);
+
         // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_addu(scratch3, scratch2, scratch1);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         masm.as_addu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
 
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1398,17 +1396,17 @@ JitRuntime::generateProfilerExitFrameTai
         //                       IonICCallFrameLayout::Size()
         masm.as_addu(scratch1, scratch2, scratch3);
         masm.addPtr(Imm32(IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/mips64/CodeGenerator-mips64.cpp
+++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp
@@ -678,17 +678,17 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
 
             masm.as_truncls(ScratchDoubleReg, input);
         }
 
         // Check that the result is in the uint64_t range.
         masm.moveFromDouble(ScratchDoubleReg, output);
         masm.as_cfc1(ScratchRegister, Assembler::FCSR);
         // extract invalid operation flag (bit 6) from FCSR
-        masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
+        masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
         masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
         masm.ma_or(SecondScratchReg, ScratchRegister);
         masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
 
         masm.ma_b(&done, ShortJump);
 
         // The input is greater than double(INT64_MAX).
         masm.bind(&isLarge);
@@ -698,17 +698,17 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
         } else {
             masm.as_subs(ScratchDoubleReg, input, ScratchDoubleReg);
             masm.as_truncls(ScratchDoubleReg, ScratchDoubleReg);
         }
 
         // Check that the result is in the uint64_t range.
         masm.moveFromDouble(ScratchDoubleReg, output);
         masm.as_cfc1(ScratchRegister, Assembler::FCSR);
-        masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
+        masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
         masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
         masm.ma_or(SecondScratchReg, ScratchRegister);
         masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
 
         masm.ma_li(ScratchRegister, Imm32(1));
         masm.ma_dins(output, ScratchRegister, Imm32(63), Imm32(1));
 
         masm.bind(&done);
@@ -719,17 +719,17 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
     // range [INT64_MIN; INT64_MAX + 1[, the Invalid Operation flag is set in the FCSR.
     if (fromType == MIRType::Double)
         masm.as_truncld(ScratchDoubleReg, input);
     else
         masm.as_truncls(ScratchDoubleReg, input);
 
     // Check that the result is in the int64_t range.
     masm.as_cfc1(output, Assembler::FCSR);
-    masm.as_ext(output, output, 6, 1);
+    masm.ma_ext(output, output, 6, 1);
     masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual);
 
     masm.bind(ool->rejoin());
     masm.moveFromDouble(ScratchDoubleReg, output);
 }
 
 void
 CodeGeneratorMIPS64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2573,30 +2573,30 @@ MacroAssembler::storeUnboxedValue(const 
 
 
 void
 MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     as_truncld(ScratchDoubleReg, input);
     moveFromDoubleHi(ScratchDoubleReg, output);
     as_cfc1(ScratchRegister, Assembler::FCSR);
-    as_ext(ScratchRegister, ScratchRegister, 6, 1);
+    ma_ext(ScratchRegister, ScratchRegister, 6, 1);
     ma_or(ScratchRegister, output);
     moveFromFloat32(ScratchDoubleReg, output);
     ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
 
 
 }
 
 void
 MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     as_truncls(ScratchDoubleReg, input);
     moveFromDoubleHi(ScratchDoubleReg, output);
     as_cfc1(ScratchRegister, Assembler::FCSR);
-    as_ext(ScratchRegister, ScratchRegister, 6, 1);
+    ma_ext(ScratchRegister, ScratchRegister, 6, 1);
     ma_or(ScratchRegister, output);
     moveFromFloat32(ScratchDoubleReg, output);
     ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
 
 }
 
 //}}} check_macroassembler_style
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -423,24 +423,20 @@ JitCode*
 JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
 {
     // Do not erase the frame pointer in this function.
 
     MacroAssembler masm(cx);
     masm.pushReturnAddress();
     // Caller:
     // [arg2] [arg1] [this] [[argc] [callee] [descr] [raddr]] <- sp
-    // '--- s3 ---'
-
-    // ArgumentsRectifierReg contains the |nargs| pushed onto the current
-    // frame. Including |this|, there are (|nargs| + 1) arguments to copy.
-    MOZ_ASSERT(ArgumentsRectifierReg == s3);
 
     // Add |this|, in the counter of known arguments.
-    masm.addPtr(Imm32(1), ArgumentsRectifierReg);
+    masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfNumActualArgs()), s3);
+    masm.addPtr(Imm32(1), s3);
 
     Register numActArgsReg = a6;
     Register calleeTokenReg = a7;
     Register numArgsReg = a5;
 
     // Load |nformals| into numArgsReg.
     masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfCalleeToken()),
                  calleeTokenReg);
@@ -1206,20 +1202,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
+    // a BaselineStub frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1254,42 +1250,40 @@ JitRuntime::generateProfilerExitFrameTai
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.ma_dsrl(scratch1, scratch3, Imm32(FRAMESIZE_SHIFT));
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
+        masm.assertRectifierFrameParentType(scratch3);
+
         // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_daddu(scratch3, scratch2, scratch1);
         masm.addPtr(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         masm.as_daddu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
 
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1343,17 +1337,17 @@ JitRuntime::generateProfilerExitFrameTai
         //                       IonICCallFrameLayout::Size()
         masm.as_daddu(scratch1, scratch2, scratch3);
         masm.addPtr(Imm32(IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -1175,20 +1175,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
+    // a BaselineStub frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1223,41 +1223,39 @@ JitRuntime::generateProfilerExitFrameTai
         masm.movePtr(scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
         masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
-        // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        masm.assertRectifierFrameParentType(scratch3);
+
+        // Check for either Ion or something else frame.
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         BaseIndex stubFrameSavedFramePtr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1309,17 +1307,17 @@ JitRuntime::generateProfilerExitFrameTai
         // lastProfilingFrame := ICCallFrame + ICCallFrame-Descriptor.Size +
         //                       IonICCallFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch3, TimesOne, IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -1209,20 +1209,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
+    // a BaselineStub frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1257,41 +1257,39 @@ JitRuntime::generateProfilerExitFrameTai
         masm.movePtr(scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
         masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
+        masm.assertRectifierFrameParentType(scratch3);
+
         // Check for either Ion or BaselineStub frame.
-        Label handle_Rectifier_BaselineStub;
-        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
-                      &handle_Rectifier_BaselineStub);
+        Label notIonFrame;
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), &notIonFrame);
 
         // Handle Rectifier <- IonJS
         // scratch3 := RectFrame[ReturnAddr]
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfReturnAddress()), scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
+        masm.bind(&notIonFrame);
+
+        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
+        // just an entry, jump there if we see it.
+        masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
+
         // Handle Rectifier <- BaselineStub <- BaselineJS
-        masm.bind(&handle_Rectifier_BaselineStub);
-#ifdef DEBUG
-        {
-            Label checkOk;
-            masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
-            masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
-            masm.bind(&checkOk);
-        }
-#endif
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
 
         BaseIndex stubFrameSavedFramePtr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() - (2 * sizeof(void*)));
@@ -1343,17 +1341,17 @@ JitRuntime::generateProfilerExitFrameTai
         // lastProfilingFrame := ICCallFrame + ICCallFrame-Descriptor.Size +
         //                       IonICCallFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch3, TimesOne, IonICCallFrameLayout::Size()), scratch1);
         masm.storePtr(scratch1, lastProfilingFrame);
         masm.ret();
     }
 
     //
-    // JitFrame_CppToJSJit / JitFrame_WasmJSToJit
+    // JitFrame_CppToJSJit / JitFrame_WasmToJSJit
     //
     // If at an entry frame, store null into both fields.
     // A fast-path wasm->jit transition frame is an entry frame from the point
     // of view of the JIT.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7520,29 +7520,16 @@ UnhideScriptedCaller(JSContext* cx)
     Activation* act = cx->activation();
     if (!act)
         return;
     act->unhideScriptedCaller();
 }
 
 } /* namespace JS */
 
-AutoGCRooter::AutoGCRooter(JSContext* cx, ptrdiff_t tag)
-  : AutoGCRooter(JS::RootingContext::get(cx), tag)
-{}
-
-AutoGCRooter::AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
-  : down(cx->autoGCRooters_),
-    tag_(tag),
-    stackTop(&cx->autoGCRooters_)
-{
-    MOZ_ASSERT(this != *stackTop);
-    *stackTop = this;
-}
-
 #ifdef JS_DEBUG
 JS_PUBLIC_API(void)
 JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2032,38 +2032,16 @@ JSFunction::needsNamedLambdaEnvironment(
     LexicalScope* scope = nonLazyScript()->maybeNamedLambdaScope();
     if (!scope)
         return false;
 
     return scope->hasEnvironment();
 }
 
 JSFunction*
-js::NewNativeFunction(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
-                      gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
-                      NewObjectKind newKind /* = SingletonObject */)
-{
-    MOZ_ASSERT(native);
-    return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
-                                nullptr, atom, nullptr, allocKind, newKind);
-}
-
-JSFunction*
-js::NewNativeConstructor(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
-                         gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
-                         NewObjectKind newKind /* = SingletonObject */,
-                         JSFunction::Flags flags /* = JSFunction::NATIVE_CTOR */)
-{
-    MOZ_ASSERT(native);
-    MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
-    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
-                                nullptr, allocKind, newKind);
-}
-
-JSFunction*
 js::NewScriptedFunction(JSContext* cx, unsigned nargs,
                         JSFunction::Flags flags, HandleAtom atom,
                         HandleObject proto /* = nullptr */,
                         gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
                         NewObjectKind newKind /* = GenericObject */,
                         HandleObject enclosingEnvArg /* = nullptr */)
 {
     RootedObject enclosingEnv(cx, enclosingEnvArg);
@@ -2087,36 +2065,26 @@ NewFunctionEnvironmentIsWellFormed(JSCon
 }
 #endif
 
 JSFunction*
 js::NewFunctionWithProto(JSContext* cx, Native native,
                          unsigned nargs, JSFunction::Flags flags, HandleObject enclosingEnv,
                          HandleAtom atom, HandleObject proto,
                          gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
-                         NewObjectKind newKind /* = GenericObject */,
-                         NewFunctionProtoHandling protoHandling /* = NewFunctionClassProto */)
+                         NewObjectKind newKind /* = GenericObject */)
 {
     MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
     MOZ_ASSERT_IF(native, !enclosingEnv);
     MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
 
-    RootedObject funobj(cx);
-    if (protoHandling == NewFunctionClassProto) {
-        funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
-                                         newKind);
-    } else {
-        funobj = NewObjectWithGivenTaggedProto(cx, &JSFunction::class_, AsTaggedProto(proto),
-                                               allocKind, newKind);
-    }
-    if (!funobj)
+    JSFunction* fun = NewObjectWithClassProto<JSFunction>(cx, proto, allocKind, newKind);
+    if (!fun)
         return nullptr;
 
-    RootedFunction fun(cx, &funobj->as<JSFunction>());
-
     if (allocKind == AllocKind::FUNCTION_EXTENDED)
         flags = JSFunction::Flags(flags | JSFunction::EXTENDED);
 
     /* Initialize all function members. */
     fun->setArgCount(uint16_t(nargs));
     fun->setFlags(flags);
     if (fun->isInterpreted()) {
         MOZ_ASSERT(!native);
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -682,59 +682,61 @@ extern bool
 Generator(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
 
+// If enclosingEnv is null, the function will have a null environment()
+// (yes, null, not the global).  In all cases, the global will be used as the
+// parent.
+
+extern JSFunction*
+NewFunctionWithProto(JSContext* cx, JSNative native, unsigned nargs,
+                     JSFunction::Flags flags, HandleObject enclosingEnv, HandleAtom atom,
+                     HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
+                     NewObjectKind newKind = GenericObject);
+
 // Allocate a new function backed by a JSNative.  Note that by default this
 // creates a singleton object.
-extern JSFunction*
+inline JSFunction*
 NewNativeFunction(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
                   gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
-                  NewObjectKind newKind = SingletonObject);
+                  NewObjectKind newKind = SingletonObject)
+{
+    MOZ_ASSERT(native);
+    return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
+                                nullptr, atom, nullptr, allocKind, newKind);
+}
 
 // Allocate a new constructor backed by a JSNative.  Note that by default this
 // creates a singleton object.
-extern JSFunction*
+inline JSFunction*
 NewNativeConstructor(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
                      gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                      NewObjectKind newKind = SingletonObject,
-                     JSFunction::Flags flags = JSFunction::NATIVE_CTOR);
+                     JSFunction::Flags flags = JSFunction::NATIVE_CTOR)
+{
+    MOZ_ASSERT(native);
+    MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
+    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
+                                nullptr, allocKind, newKind);
+}
 
 // Allocate a new scripted function.  If enclosingEnv is null, the
 // global will be used.  In all cases the parent of the resulting object will be
 // the global.
 extern JSFunction*
 NewScriptedFunction(JSContext* cx, unsigned nargs, JSFunction::Flags flags,
                     HandleAtom atom, HandleObject proto = nullptr,
                     gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                     NewObjectKind newKind = GenericObject,
                     HandleObject enclosingEnv = nullptr);
-
-// By default, if proto is nullptr, Function.prototype is used instead.i
-// If protoHandling is NewFunctionExactProto, and proto is nullptr, the created
-// function will use nullptr as its [[Prototype]] instead. If
-// enclosingEnv is null, the function will have a null environment()
-// (yes, null, not the global).  In all cases, the global will be used as the
-// parent.
-
-enum NewFunctionProtoHandling {
-    NewFunctionClassProto,
-    NewFunctionGivenProto
-};
-extern JSFunction*
-NewFunctionWithProto(JSContext* cx, JSNative native, unsigned nargs,
-                     JSFunction::Flags flags, HandleObject enclosingEnv, HandleAtom atom,
-                     HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
-                     NewObjectKind newKind = GenericObject,
-                     NewFunctionProtoHandling protoHandling = NewFunctionClassProto);
-
 extern JSAtom*
 IdToFunctionName(JSContext* cx, HandleId id,
                  FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
 
 extern JSAtom*
 NameToFunctionName(JSContext* cx, HandleAtom name,
                    FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
 
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -205,21 +205,100 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(Auto
   public:
     explicit AutoEnterCycleCollection(JSRuntime* rt) {}
     ~AutoEnterCycleCollection() {}
 #endif
 };
 
 class RootingContext;
 
+// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
+// instantiation of MapTypeToRootKind.
+template <>
+struct MapTypeToRootKind<void*> {
+    static const RootKind kind = RootKind::Traceable;
+};
+
+using RootedListHeads = mozilla::EnumeratedArray<RootKind, RootKind::Limit,
+                                                 Rooted<void*>*>;
+
+/*
+ * This list enumerates the different types of conceptual stacks we have in
+ * SpiderMonkey. In reality, they all share the C stack, but we allow different
+ * stack limits depending on the type of code running.
+ */
+enum StackKind
+{
+    StackForSystemCode,      // C++, such as the GC, running on behalf of the VM.
+    StackForTrustedScript,   // Script running with trusted principals.
+    StackForUntrustedScript, // Script running with untrusted principals.
+    StackKindCount
+};
+
+class JS_PUBLIC_API(AutoGCRooter);
+
+// Superclass of JSContext which can be used for rooting data in use by the
+// current thread but that does not provide all the functions of a JSContext.
+class RootingContext
+{
+    // Stack GC roots for Rooted GC heap pointers.
+    RootedListHeads stackRoots_;
+    template <typename T> friend class JS::Rooted;
+
+    // Stack GC roots for AutoFooRooter classes.
+    JS::AutoGCRooter* autoGCRooters_;
+    friend class JS::AutoGCRooter;
+
+  public:
+    RootingContext();
+
+    void traceStackRoots(JSTracer* trc);
+    void checkNoGCRooters();
+
+  protected:
+    // The remaining members in this class should only be accessed through
+    // JSContext pointers. They are unrelated to rooting and are in place so
+    // that inlined API functions can directly access the data.
+
+    /* The current compartment. */
+    JSCompartment*      compartment_;
+
+    /* The current zone. */
+    JS::Zone*           zone_;
+
+  public:
+    /* Limit pointer for checking native stack consumption. */
+    uintptr_t nativeStackLimit[StackKindCount];
+
+    static const RootingContext* get(const JSContext* cx) {
+        return reinterpret_cast<const RootingContext*>(cx);
+    }
+
+    static RootingContext* get(JSContext* cx) {
+        return reinterpret_cast<RootingContext*>(cx);
+    }
+
+    friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
+    friend JS::Zone* js::GetContextZone(const JSContext* cx);
+};
+
 class JS_PUBLIC_API(AutoGCRooter)
 {
   public:
-    AutoGCRooter(JSContext* cx, ptrdiff_t tag);
-    AutoGCRooter(RootingContext* cx, ptrdiff_t tag);
+    AutoGCRooter(JSContext* cx, ptrdiff_t tag)
+      : AutoGCRooter(JS::RootingContext::get(cx), tag)
+    {}
+    AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
+      : down(cx->autoGCRooters_),
+        tag_(tag),
+        stackTop(&cx->autoGCRooters_)
+    {
+        MOZ_ASSERT(this != *stackTop);
+        *stackTop = this;
+    }
 
     ~AutoGCRooter() {
         MOZ_ASSERT(this == *stackTop);
         *stackTop = down;
     }
 
     /* Implemented in gc/RootMarking.cpp. */
     inline void trace(JSTracer* trc);
@@ -257,84 +336,16 @@ class JS_PUBLIC_API(AutoGCRooter)
   private:
     AutoGCRooter ** const stackTop;
 
     /* No copy or assignment semantics. */
     AutoGCRooter(AutoGCRooter& ida) = delete;
     void operator=(AutoGCRooter& ida) = delete;
 };
 
-// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
-// instantiation of MapTypeToRootKind.
-template <>
-struct MapTypeToRootKind<void*> {
-    static const RootKind kind = RootKind::Traceable;
-};
-
-using RootedListHeads = mozilla::EnumeratedArray<RootKind, RootKind::Limit,
-                                                 Rooted<void*>*>;
-
-/*
- * This list enumerates the different types of conceptual stacks we have in
- * SpiderMonkey. In reality, they all share the C stack, but we allow different
- * stack limits depending on the type of code running.
- */
-enum StackKind
-{
-    StackForSystemCode,      // C++, such as the GC, running on behalf of the VM.
-    StackForTrustedScript,   // Script running with trusted principals.
-    StackForUntrustedScript, // Script running with untrusted principals.
-    StackKindCount
-};
-
-// Superclass of JSContext which can be used for rooting data in use by the
-// current thread but that does not provide all the functions of a JSContext.
-class RootingContext
-{
-    // Stack GC roots for Rooted GC heap pointers.
-    RootedListHeads stackRoots_;
-    template <typename T> friend class JS::Rooted;
-
-    // Stack GC roots for AutoFooRooter classes.
-    JS::AutoGCRooter* autoGCRooters_;
-    friend class JS::AutoGCRooter;
-
-  public:
-    RootingContext();
-
-    void traceStackRoots(JSTracer* trc);
-    void checkNoGCRooters();
-
-  protected:
-    // The remaining members in this class should only be accessed through
-    // JSContext pointers. They are unrelated to rooting and are in place so
-    // that inlined API functions can directly access the data.
-
-    /* The current compartment. */
-    JSCompartment*      compartment_;
-
-    /* The current zone. */
-    JS::Zone*           zone_;
-
-  public:
-    /* Limit pointer for checking native stack consumption. */
-    uintptr_t nativeStackLimit[StackKindCount];
-
-    static const RootingContext* get(const JSContext* cx) {
-        return reinterpret_cast<const RootingContext*>(cx);
-    }
-
-    static RootingContext* get(JSContext* cx) {
-        return reinterpret_cast<RootingContext*>(cx);
-    }
-
-    friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
-    friend JS::Zone* js::GetContextZone(const JSContext* cx);
-};
-
 } /* namespace JS */
 
 namespace js {
 
 /*
  * Inlinable accessors for JSContext.
  *
  * - These must not be available on the more restricted superclasses of
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -274,16 +274,20 @@ class RegExpZone
 
     bool empty() const { return set_.empty(); }
 
     RegExpShared* get(JSContext* cx, HandleAtom source, RegExpFlag flags);
 
     /* Like 'get', but compile 'maybeOpt' (if non-null). */
     RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt);
 
+#ifdef DEBUG
+    void clear() { set_.clear(); }
+#endif
+
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
 };
 
 class RegExpCompartment
 {
     /*
      * This is the template object where the result of re.exec() is based on,
      * if there is a result. This is used in CreateRegExpMatchResult to set
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -533,16 +533,17 @@ JitFrameIter::JitFrameIter(jit::JitActiv
 void
 JitFrameIter::skipNonScriptedJSFrames()
 {
     if (isJSJit()) {
         // Stop at the first scripted frame.
         jit::JSJitFrameIter& frames = asJSJit();
         while (!frames.isScripted() && !frames.done())
             ++frames;
+        settle();
     }
 }
 
 bool
 JitFrameIter::done() const
 {
     if (!isSome())
         return true;
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -210,49 +210,57 @@ Instance::callImport(JSContext* cx, uint
     }
 
     // Don't enable jit entry when we have a pending ion builder.
     // Take the interpreter path which will link it and enable
     // the fast path on the next call.
     if (script->baselineScript()->hasPendingIonBuilder())
         return true;
 
-    // Currently we can't rectify arguments. Therefore disable if argc is too low.
-    if (importFun->nargs() > fi.sig().args().length())
-        return true;
-
     // Ensure the argument types are included in the argument TypeSets stored in
     // the TypeScript. This is necessary for Ion, because the import will use
     // the skip-arg-checks entry point.
     //
     // Note that the TypeScript is never discarded while the script has a
     // BaselineScript, so if those checks hold now they must hold at least until
     // the BaselineScript is discarded and when that happens the import is
     // patched back.
     if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
         return true;
-    for (uint32_t i = 0; i < importFun->nargs(); i++) {
+
+    const ValTypeVector& importArgs = fi.sig().args();
+
+    size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
+    for (uint32_t i = 0; i < numKnownArgs; i++) {
         TypeSet::Type type = TypeSet::UnknownType();
-        switch (fi.sig().args()[i]) {
+        switch (importArgs[i]) {
           case ValType::I32:   type = TypeSet::Int32Type(); break;
           case ValType::I64:   MOZ_CRASH("can't happen because of above guard");
           case ValType::F32:   type = TypeSet::DoubleType(); break;
           case ValType::F64:   type = TypeSet::DoubleType(); break;
           case ValType::I8x16: MOZ_CRASH("NYI");
           case ValType::I16x8: MOZ_CRASH("NYI");
           case ValType::I32x4: MOZ_CRASH("NYI");
           case ValType::F32x4: MOZ_CRASH("NYI");
           case ValType::B8x16: MOZ_CRASH("NYI");
           case ValType::B16x8: MOZ_CRASH("NYI");
           case ValType::B32x4: MOZ_CRASH("NYI");
         }
         if (!TypeScript::ArgTypes(script, i)->hasType(type))
             return true;
     }
 
+    // These arguments will be filled with undefined at runtime by the
+    // arguments rectifier: check that the imported function can handle
+    // undefined there.
+    for (uint32_t i = importArgs.length(); i < importFun->nargs(); i++) {
+        if (!TypeScript::ArgTypes(script, i)->hasType(TypeSet::UndefinedType()))
+            return true;
+    }
+
     // Let's optimize it!
     if (!script->baselineScript()->addDependentWasmImport(cx, *this, funcImportIndex))
         return false;
 
     import.code = jitExitCode;
     import.baselineScript = script->baselineScript();
     return true;
 }
@@ -446,16 +454,23 @@ Instance::init(JSContext* cx)
             const void* sigId;
             if (!lockedSigIdSet->allocateSigId(cx, sig, &sigId))
                 return false;
 
             *addressOfSigId(sig.id) = sigId;
         }
     }
 
+    if (!metadata(code_->bestTier()).funcImports.empty()) {
+        JitRuntime* jitRuntime = cx->runtime()->getJitRuntime(cx);
+        if (!jitRuntime)
+            return false;
+        jsJitArgsRectifier_ = jitRuntime->getArgumentsRectifier();
+    }
+
     return true;
 }
 
 Instance::~Instance()
 {
     compartment_->wasm.unregisterInstance(*this);
 
     const FuncImportVector& funcImports = metadata(code().stableTier()).funcImports;
@@ -503,16 +518,18 @@ Instance::tracePrivate(JSTracer* trc)
 {
     // This method is only called from WasmInstanceObject so the only reason why
     // TraceEdge is called is so that the pointer can be updated during a moving
     // GC. TraceWeakEdge may sound better, but it is less efficient given that
     // we know object_ is already marked.
     MOZ_ASSERT(!gc::IsAboutToBeFinalized(&object_));
     TraceEdge(trc, &object_, "wasm instance object");
 
+    TraceNullableEdge(trc, &jsJitArgsRectifier_, "wasm jit args rectifier");
+
     // OK to just do one tier here; though the tiers have different funcImports
     // tables, they share the tls object.
     for (const FuncImport& fi : metadata(code().stableTier()).funcImports)
         TraceNullableEdge(trc, &funcImportTls(fi).obj, "wasm import");
 
     for (const SharedTable& table : tables_)
         table->trace(trc);
 
--- a/js/src/wasm/WasmInstance.h
+++ b/js/src/wasm/WasmInstance.h
@@ -66,16 +66,17 @@ typedef UniquePtr<GlobalSegment> UniqueG
 // The instance's code may be shared among multiple instances provided none of
 // those instances are being debugged. Instances that are being debugged own
 // their code.
 
 class Instance
 {
     JSCompartment* const            compartment_;
     ReadBarrieredWasmInstanceObject object_;
+    GCPtrJitCode                    jsJitArgsRectifier_;
     const SharedCode                code_;
     const UniqueDebugState          debug_;
     const UniqueGlobalSegment       globals_;
     GCPtrWasmMemoryObject           memory_;
     SharedTableVector               tables_;
     bool                            enterFrameTrapsEnabled_;
 
     // Internal helpers:
@@ -117,16 +118,18 @@ class Instance
     const SharedTableVector& tables() const { return tables_; }
     SharedMem<uint8_t*> memoryBase() const;
     WasmMemoryObject* memory() const;
     size_t memoryLength() const;
     size_t memoryMappedSize() const;
     bool memoryAccessInGuardRegion(uint8_t* addr, unsigned numBytes) const;
     TlsData* tlsData() const { return globals_->tlsData(); }
 
+    static size_t offsetOfJSJitArgsRectifier() { return offsetof(Instance, jsJitArgsRectifier_); }
+
     // This method returns a pointer to the GC object that owns this Instance.
     // Instances may be reached via weak edges (e.g., Compartment::instances_)
     // so this perform a read-barrier on the returned object unless the barrier
     // is explicitly waived.
 
     WasmInstanceObject* object() const;
     WasmInstanceObject* objectUnbarriered() const;
 
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -18,16 +18,17 @@
 
 #include "wasm/WasmStubs.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/EnumeratedRange.h"
 
 #include "wasm/WasmCode.h"
 #include "wasm/WasmGenerator.h"
+#include "wasm/WasmInstance.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 using namespace js::wasm;
 
 using mozilla::ArrayLength;
@@ -705,63 +706,72 @@ GenerateImportJitExit(MacroAssembler& ma
     // JIT calls use the following stack layout (sp grows to the left):
     //   | retaddr | descriptor | callee | argc | this | arg1..N |
     // After the JIT frame, the global register (if present) is saved since the
     // JIT's ABI does not preserve non-volatile regs. Also, unlike most ABIs,
     // the JIT ABI requires that sp be JitStackAlignment-aligned *after* pushing
     // the return address.
     static_assert(WasmStackAlignment >= JitStackAlignment, "subsumes");
     unsigned sizeOfRetAddr = sizeof(void*);
-    unsigned sizeOfPreFrame = WasmFrameLayout::Size() - sizeOfRetAddr;
+    unsigned sizeOfPreFrame = WasmToJSJitFrameLayout::Size() - sizeOfRetAddr;
     unsigned sizeOfThisAndArgs = (1 + fi.sig().args().length()) * sizeof(Value);
     unsigned totalJitFrameBytes = sizeOfRetAddr + sizeOfPreFrame + sizeOfThisAndArgs;
     unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) -
                               sizeOfRetAddr;
     unsigned sizeOfThisAndArgsAndPadding = jitFramePushed - sizeOfPreFrame;
 
     GenerateJitExitPrologue(masm, jitFramePushed, offsets);
 
     // 1. Descriptor
     size_t argOffset = 0;
     uint32_t descriptor = MakeFrameDescriptor(sizeOfThisAndArgsAndPadding, JitFrame_WasmToJSJit,
-                                              WasmFrameLayout::Size());
+                                              WasmToJSJitFrameLayout::Size());
     masm.storePtr(ImmWord(uintptr_t(descriptor)), Address(masm.getStackPointer(), argOffset));
     argOffset += sizeof(size_t);
 
     // 2. Callee
     Register callee = ABINonArgReturnReg0;   // live until call
     Register scratch = ABINonArgReturnReg1;  // repeatedly clobbered
 
-    // 2.1. Get callee
+    // 2.1. Get JSFunction callee
     masm.loadWasmGlobalPtr(fi.tlsDataOffset() + offsetof(FuncImportTls, obj), callee);
 
     // 2.2. Save callee
     masm.storePtr(callee, Address(masm.getStackPointer(), argOffset));
     argOffset += sizeof(size_t);
 
-    // 2.3. Load callee executable entry point
-    masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee);
-    masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr);
-
     // 3. Argc
     unsigned argc = fi.sig().args().length();
     masm.storePtr(ImmWord(uintptr_t(argc)), Address(masm.getStackPointer(), argOffset));
     argOffset += sizeof(size_t);
     MOZ_ASSERT(argOffset == sizeOfPreFrame);
 
     // 4. |this| value
     masm.storeValue(UndefinedValue(), Address(masm.getStackPointer(), argOffset));
     argOffset += sizeof(Value);
 
     // 5. Fill the arguments
     unsigned offsetToCallerStackArgs = jitFramePushed + sizeof(Frame);
     FillArgumentArray(masm, fi.sig().args(), argOffset, offsetToCallerStackArgs, scratch, ToValue(true));
     argOffset += fi.sig().args().length() * sizeof(Value);
     MOZ_ASSERT(argOffset == sizeOfThisAndArgs + sizeOfPreFrame);
 
+    // 6. Check if we need to rectify arguments
+    masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch);
+
+    Label rectify;
+    masm.branch32(Assembler::Above, scratch, Imm32(fi.sig().args().length()), &rectify);
+
+    // 7. If we haven't rectified arguments, load callee executable entry point
+    masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee);
+    masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr);
+
+    Label rejoinBeforeCall;
+    masm.bind(&rejoinBeforeCall);
+
     AssertStackAlignment(masm, JitStackAlignment, sizeOfRetAddr);
     masm.callJitNoProfiler(callee);
 
     // The JIT callee clobbers all registers, including WasmTlsReg and
     // FramePointer, so restore those here. During this sequence of
     // instructions, FP can't be trusted by the profiling frame iterator.
     offsets->untrustedFPStart = masm.currentOffset();
     AssertStackAlignment(masm, JitStackAlignment, sizeOfRetAddr);
@@ -813,16 +823,25 @@ GenerateImportJitExit(MacroAssembler& ma
         MOZ_CRASH("Limit");
     }
 
     Label done;
     masm.bind(&done);
 
     GenerateJitExitEpilogue(masm, masm.framePushed(), offsets);
 
+    {
+        // Call the arguments rectifier.
+        masm.bind(&rectify);
+        masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, instance)), callee);
+        masm.loadPtr(Address(callee, Instance::offsetOfJSJitArgsRectifier()), callee);
+        masm.loadPtr(Address(callee, JitCode::offsetOfCode()), callee);
+        masm.jump(&rejoinBeforeCall);
+    }
+
     if (oolConvert.used()) {
         masm.bind(&oolConvert);
         masm.setFramePushed(nativeFramePushed);
 
         // Coercion calls use the following stack layout (sp grows to the left):
         //   | args | padding | Value argv[1] | padding | exit Frame |
         MIRTypeVector coerceArgTypes;
         JS_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6274,27 +6274,18 @@ nsDisplayOpacity::CreateWebRenderCommand
     aManager->WrBridge()->AddWebRenderParentCommand(anim);
     aManager->AddActiveCompositorAnimationId(animationsId);
   } else if (animationsId) {
     aManager->AddCompositorAnimationsIdForDiscard(animationsId);
     animationsId = 0;
   }
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
-  StackingContextHelper sc(aSc,
-                           aBuilder,
-                           aDisplayListBuilder,
-                           this,
-                           &mList,
-                           nullptr,
-                           animationsId,
-                           opacityForSC,
-                           nullptr,
-                           nullptr,
-                           filters);
+  StackingContextHelper sc(aSc, aBuilder, filters, nullptr, animationsId,
+                           opacityForSC);
 
   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(&mList,
                                                                     aDisplayListBuilder,
                                                                     sc,
                                                                     aBuilder,
                                                                     aResources);
   return true;
 }
@@ -6336,19 +6327,18 @@ nsDisplayBlendMode::GetLayerState(nsDisp
 bool
 nsDisplayBlendMode::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
                                             const StackingContextHelper& aSc,
                                             mozilla::layers::WebRenderLayerManager* aManager,
                                             nsDisplayListBuilder* aDisplayListBuilder)
 {
   nsTArray<mozilla::wr::WrFilterOp> filters;
-  StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
-                           &mList, nullptr, 0, nullptr, nullptr, nullptr,
-                           filters, nsCSSRendering::GetGFXBlendMode(mBlendMode));
+  StackingContextHelper sc(aSc, aBuilder, filters, nullptr, 0, nullptr, nullptr,
+                           nullptr, nsCSSRendering::GetGFXBlendMode(mBlendMode));
 
   return nsDisplayWrapList::CreateWebRenderCommands(aBuilder,aResources, sc,
                                                     aManager, aDisplayListBuilder);
 }
 
 // nsDisplayBlendMode uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
@@ -6466,18 +6456,17 @@ nsDisplayBlendContainer::GetLayerState(n
 
 bool
 nsDisplayBlendContainer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                  const StackingContextHelper& aSc,
                                                  mozilla::layers::WebRenderLayerManager* aManager,
                                                  nsDisplayListBuilder* aDisplayListBuilder)
 {
-  StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
-                           &mList, nullptr, 0, nullptr, nullptr);
+  StackingContextHelper sc(aSc, aBuilder);
 
   return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
                                                     aManager, aDisplayListBuilder);
 }
 
 nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
                                      nsIFrame* aFrame, nsDisplayList* aList,
                                      const ActiveScrolledRoot* aActiveScrolledRoot,
@@ -6573,18 +6562,18 @@ nsDisplayOwnLayer::CreateWebRenderComman
   // APZ is enabled and this is a scroll thumb, so we need to create and
   // set an animation id. That way APZ can move this scrollthumb around as
   // needed.
   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
   animationInfo.EnsureAnimationsId();
   mWrAnimationId = animationInfo.GetCompositorAnimationsId();
 
-  StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
-                           &mList, nullptr, mWrAnimationId, nullptr, nullptr);
+  StackingContextHelper sc(aSc, aBuilder, nsTArray<wr::WrFilterOp>(), nullptr,
+                           mWrAnimationId);
 
   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
                                              aManager, aDisplayListBuilder);
   return true;
 }
 
 bool
 nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
@@ -7126,18 +7115,17 @@ nsDisplayStickyPosition::CreateWebRender
   }
 
   // All the things inside this position:sticky item also have the main-thread
   // translation already applied, so we need to make sure that gets unapplied.
   // The easiest way to do it is to just create a new stacking context with an
   // adjusted origin and use that for the nested items. This way all the
   // ToRelativeLayoutRect calls on this StackingContextHelper object will
   // include the necessary adjustment.
-  StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
-                           &mList, nullptr, 0, nullptr, nullptr);
+  StackingContextHelper sc(aSc, aBuilder);
   sc.AdjustOrigin(scTranslation);
 
   // TODO: if, inside this nested command builder, we try to turn a gecko clip
   // chain into a WR clip chain, we might end up repushing the clip stack
   // without `id` which effectively throws out the sticky behaviour. The
   // repushing can happen because of the need to define a new clip while
   // particular things are on the stack
   nsDisplayOwnLayer::CreateWebRenderCommands(aBuilder, aResources, sc,
@@ -8051,25 +8039,22 @@ nsDisplayTransform::CreateWebRenderComma
   } else if (animationsId) {
     aManager->AddCompositorAnimationsIdForDiscard(animationsId);
     animationsId = 0;
   }
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            aBuilder,
-                           aDisplayListBuilder,
-                           this,
-                           mStoredList.GetChildren(),
+                           filters,
                            &newTransformMatrix,
                            animationsId,
                            nullptr,
                            transformForSC,
                            nullptr,
-                           filters,
                            gfx::CompositionOp::OP_OVER,
                            !BackfaceIsHidden());
 
   return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc,
                                              aManager, aDisplayListBuilder);
 }
 
 bool
@@ -8665,25 +8650,22 @@ nsDisplayPerspective::CreateWebRenderCom
                         NS_round(newOrigin.y),
                         0);
 
   gfx::Matrix4x4 transformForSC = gfx::Matrix4x4::Translation(roundedOrigin);
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            aBuilder,
-                           aDisplayListBuilder,
-                           this,
-                           mList.GetChildren(),
+                           filters,
                            nullptr,
                            0,
                            nullptr,
                            &transformForSC,
                            &perspectiveMatrix,
-                           filters,
                            gfx::CompositionOp::OP_OVER,
                            !BackfaceIsHidden());
 
   return mList.CreateWebRenderCommands(aBuilder, aResources, sc,
                                        aManager, aDisplayListBuilder);
 }
 
 int32_t
@@ -9404,27 +9386,17 @@ nsDisplayFilter::CreateWebRenderCommands
 
   nsTArray<mozilla::wr::WrFilterOp> wrFilters;
   const nsTArray<nsStyleFilter>& filters = mFrame->StyleEffects()->mFilters;
   nsTArray<layers::CSSFilter> cssFilters = nsTArray<layers::CSSFilter>(filters.Length());
   for (const nsStyleFilter& filter : filters) {
     wrFilters.AppendElement(wr::ToWrFilterOp(ToCSSFilter(filter)));
   }
 
-  StackingContextHelper sc(aSc,
-                           aBuilder,
-                           aDisplayListBuilder,
-                           this,
-                           &mList,
-                           nullptr,
-                           0,
-                           nullptr,
-                           nullptr,
-                           nullptr,
-                           wrFilters);
+  StackingContextHelper sc(aSc, aBuilder, wrFilters);
 
   nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, sc, aManager, aDisplayListBuilder);
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayFilter::PrintEffects(nsACString& aTo)
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1405878-1-ref.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <select>
+    <script>document.documentElement.offsetHeight</script>
+    <option>Hello there</option>
+    <script>document.documentElement.offsetHeight</script>
+  </select>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1405878-1.xml
@@ -0,0 +1,6 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <select>
+    <script>document.documentElement.offsetHeight</script>
+    <option>Hello there</option>
+  </select>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2037,10 +2037,11 @@ needs-focus != 1377447-1.html 1377447-2.
 == 1380224-1.html 1380224-1-ref.html
 == 1384065.html 1384065-ref.html
 == 1384275-1.html 1384275-1-ref.html
 == 1381821.html 1381821-ref.html
 == 1395650-1.html 1395650-1-ref.html
 == 1398500-1.html 1398500-1-ref.html
 == 1401317.html 1401317-ref.html
 == 1401992.html 1401992-ref.html
+== 1405878-1.xml 1405878-1-ref.xml
 == 1404057.html 1404057-ref.html
 != 1404057.html 1404057-noref.html
--- a/layout/reftests/css-blending/reftest.list
+++ b/layout/reftests/css-blending/reftest.list
@@ -1,37 +1,37 @@
 pref(layout.css.mix-blend-mode.enabled,true) == blend-canvas.html blend-canvas-ref.html
 pref(layout.css.mix-blend-mode.enabled,true) == blend-constant-background-color.html blend-constant-background-color-ref.html
 pref(layout.css.mix-blend-mode.enabled,true) fuzzy-if(webrender,1-1,7875-7875) == blend-gradient-background-color.html blend-gradient-background-color-ref.html
 pref(layout.css.mix-blend-mode.enabled,true) == blend-image.html blend-image-ref.html
-pref(layout.css.mix-blend-mode.enabled,true) fails-if(webrender) == blend-difference-stacking.html blend-difference-stacking-ref.html
+pref(layout.css.mix-blend-mode.enabled,true) == blend-difference-stacking.html blend-difference-stacking-ref.html
 
-fuzzy-if(skiaContent,1,30000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-alpha.html background-blending-alpha-ref.html
+fuzzy-if(skiaContent,1,30000) pref(layout.css.background-blend-mode.enabled,true) == background-blending-alpha.html background-blending-alpha-ref.html
 pref(layout.css.background-blend-mode.enabled,true) fuzzy-if(webrender,1-1,7875-7875) == background-blending-gradient-color.html background-blending-gradient-color-ref.html
 fuzzy-if(azureSkiaGL,3,7597) fuzzy-if(cocoaWidget,3,7597) fuzzy-if(d2d,1,3800) fuzzy-if(d3d11,1,4200) fuzzy-if(skiaContent,2,9450) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-gradient-gradient.html background-blending-gradient-gradient-ref.html
 fuzzy-if(azureSkiaGL,2,7174) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-gradient-image.html background-blending-gradient-color-ref.html
 fuzzy-if(azureSkia||d2d||gtkWidget,1,10000) pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-jpg.html background-blending-image-color-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-png.html background-blending-image-color-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-svg.html background-blending-image-color-ref.html
 fuzzy-if(azureSkiaGL,2,7174) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-image-gradient.html background-blending-gradient-color-ref.html
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-image-image.html background-blending-image-color-ref.html
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-isolation.html background-blending-isolation-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-image.html background-blending-image-color-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation.html background-blending-isolation-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-list-repeat.html background-blending-list-repeat-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-multiple-images.html background-blending-multiple-images-ref.html
 
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color-burn.html background-blending-color-burn-ref.svg
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color-dodge.html background-blending-color-dodge-ref.svg
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-color-burn.html background-blending-color-burn-ref.svg
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-color-dodge.html background-blending-color-dodge-ref.svg
 # need to investigate why these tests are fuzzy - first suspect is a possible color space conversion on some platforms; same for mix-blend-mode tests
 fuzzy-if(azureSkia||gtkWidget,2,9600) fuzzy-if(d2d,1,8000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color.html background-blending-color-ref.svg
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-darken.html background-blending-darken-ref.svg
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-difference.html background-blending-difference-ref.svg
-fuzzy-if(skiaContent,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-exclusion.html background-blending-exclusion-ref.svg
-fuzzy-if(cocoaWidget||d2d,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-hard-light.html background-blending-hard-light-ref.svg
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-difference.html background-blending-difference-ref.svg
+fuzzy-if(skiaContent,1,1600) pref(layout.css.background-blend-mode.enabled,true) == background-blending-exclusion.html background-blending-exclusion-ref.svg
+fuzzy-if(cocoaWidget||d2d,1,1600) pref(layout.css.background-blend-mode.enabled,true) == background-blending-hard-light.html background-blending-hard-light-ref.svg
 fuzzy-if(d2d,1,9600) fuzzy-if(azureSkia||gtkWidget,2,9600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-hue.html background-blending-hue-ref.svg
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-lighten.html background-blending-lighten-ref.svg
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-lighten.html background-blending-lighten-ref.svg
 fuzzy-if(d2d,1,8000) fuzzy-if(azureSkia||gtkWidget,2,9600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-luminosity.html background-blending-luminosity-ref.svg
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-multiply.html background-blending-multiply-ref.svg
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-normal.html background-blending-normal-ref.svg
 fuzzy-if(azureSkia||gtkWidget,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-overlay.html background-blending-overlay-ref.svg
 fuzzy-if(d2d,1,1600) fuzzy-if(azureSkia||gtkWidget,2,12800) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-saturation.html background-blending-saturation-ref.svg
 fuzzy-if(d2d||azureSkia||gtkWidget,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-screen.html background-blending-screen-ref.svg
 fuzzy-if(d2d||azureSkia||gtkWidget,10,4800) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-soft-light.html background-blending-soft-light-ref.svg
 
@@ -55,17 +55,17 @@ fuzzy(1,6800) == clipped-opacity-contain
 # Test 9
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-svg-as-data-uri.html background-blending-image-color-ref.html
 # Test 10
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-gif.html background-blending-image-color-gif-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-transform3d.html background-blending-image-color-ref.html
 
 # Test plan 5.3.2 Background layers do not blend with content outside the background (or behind the element) - tests 2 and 3
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation-parent-child-color.html background-blending-isolation-parent-child-ref.html
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-isolation-parent-child-image.html background-blending-isolation-parent-child-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation-parent-child-image.html background-blending-isolation-parent-child-ref.html
 
 # Test plan 5.3.6 background-blend-mode for an element with background-position
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-position-percentage.html background-blending-background-position-percentage-ref.html
 
 # Test plan 5.3.7 background-blend-mode for an element with background-size
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-size-contain.html background-blending-background-size-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-size-cover.html background-blending-background-size-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-size-percentage.html background-blending-background-size-ref.html
@@ -80,21 +80,21 @@ pref(layout.css.background-blend-mode.en
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-clip-padding-box.html background-blending-background-clip-padding-box-ref.html
 
 # Test plan 5.3.10 background-blend-mode for an element with background-origin
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-origin-border-box.html background-blending-background-origin-ref.html
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-origin-content-box.html background-blending-background-origin-ref.html
 
 # Test plan 5.3.11 background-blend-mode for an element with background-attachement
 pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-attachement-fixed.html background-blending-background-attachement-fixed-ref.html
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-background-attachement-fixed-scroll.html background-blending-background-attachement-fixed-scroll-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-attachement-fixed-scroll.html background-blending-background-attachement-fixed-scroll-ref.html
 
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blend-mode-body-image.html background-blend-mode-body-image-ref.html
-fuzzy-if(Android,4,768) fuzzy-if(gtkWidget,1,132) fuzzy-if(skiaContent,1,800) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blend-mode-body-transparent-image.html background-blend-mode-body-transparent-image-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blend-mode-body-image.html background-blend-mode-body-image-ref.html
+fuzzy-if(Android,4,768) fuzzy-if(gtkWidget,1,132) fuzzy-if(skiaContent,1,800) pref(layout.css.background-blend-mode.enabled,true) == background-blend-mode-body-transparent-image.html background-blend-mode-body-transparent-image-ref.html
 
-pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-moz-element.html background-blending-moz-element-ref.html
+pref(layout.css.background-blend-mode.enabled,true) == background-blending-moz-element.html background-blending-moz-element-ref.html
 
 fuzzy(1,40000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == mix-blend-mode-soft-light.html mix-blend-mode-soft-light-ref.html
 
 # Test plan 4.4.2 element with isolation:isolate creates an isolated group for blended children
-pref(layout.css.isolation.enabled,true) fails-if(webrender) == blend-isolation.html blend-isolation-ref.html
+pref(layout.css.isolation.enabled,true) == blend-isolation.html blend-isolation-ref.html
 
 pref(layout.css.background-blend-mode.enabled,true) == bug1281593.html bug1281593-ref.html
--- a/layout/reftests/font-face/reftest.list
+++ b/layout/reftests/font-face/reftest.list
@@ -173,17 +173,17 @@ pref(gfx.downloadable_fonts.woff2.enable
 
 # sanity tests for reflow behavior with downloadable fonts
 HTTP(..) == reflow-sanity-1.html reflow-sanity-1-ref.html
 HTTP(..) == reflow-sanity-1-data.html reflow-sanity-1-ref.html
 HTTP(..) == reflow-sanity-1.html reflow-sanity-1-data.html
 HTTP(..) == reflow-sanity-delay-1a.html reflow-sanity-1-ref.html
 HTTP(..) == reflow-sanity-delay-1b.html reflow-sanity-1-ref.html
 HTTP(..) == reflow-sanity-delay-1c.html reflow-sanity-1-ref.html
-HTTP(..) == reflow-sanity-delay-1-metrics.html reflow-sanity-1-ref.html
+skip-if(winWidget&&!isDebugBuild) HTTP(..) == reflow-sanity-delay-1-metrics.html reflow-sanity-1-ref.html
 
 # font-display
 skip-if(/^Linux\x20i686/.test(http.oscpu)) HTTP(..) == font-display-1.html font-display-1-ref.html # normal font load (~500ms)
 # ^ disabled due to intermittents due to timing issues -- Bug 1238222
 fuzzy-if(OSX==1010,3,5) HTTP(..) == font-display-2.html font-display-2-ref.html # font load takes 4500ms
 
 # Testing hack for Meiryo
 == meiryo-en.html meiryo-ja.html
--- a/layout/tables/celldata.h
+++ b/layout/tables/celldata.h
@@ -189,24 +189,35 @@ public:
 
   BCPixelSize GetCorner(mozilla::LogicalSide& aCornerOwner,
                         bool&                 aBevel) const;
 
   void SetCorner(BCPixelSize          aSubSize,
                  mozilla::LogicalSide aOwner,
                  bool                 aBevel);
 
-  bool IsIStartStart() const;
+  inline bool IsIStartStart() const
+  {
+    return (bool)mIStartStart;
+  }
 
-  void SetIStartStart(bool aValue);
+  inline void SetIStartStart(bool aValue)
+  {
+    mIStartStart = aValue;
+  }
 
-  bool IsBStartStart() const;
+  inline bool IsBStartStart() const
+  {
+    return (bool)mBStartStart;
+  }
 
-  void SetBStartStart(bool aValue);
-
+  inline void SetBStartStart(bool aValue)
+  {
+    mBStartStart = aValue;
+  }
 
 protected:
   BCPixelSize mIStartSize;    // size in pixels of iStart border
   BCPixelSize mBStartSize;    // size in pixels of bStart border
   BCPixelSize mCornerSubSize; // size of the largest border not in the
                               //   dominant plane (for example, if corner is
                               //   owned by the segment to its bStart or bEnd,
                               //   then the size is the max of the border
@@ -366,60 +377,61 @@ inline void CellData::SetOverlap(bool aO
       mBits &= ~OVERLAP;
     }
   }
 }
 
 inline BCData::BCData()
 {
   mIStartOwner = mBStartOwner = eCellOwner;
-  mIStartStart = mBStartStart = 1;
+  SetBStartStart(true);
+  SetIStartStart(true);
   mIStartSize = mCornerSubSize = mBStartSize = 0;
   mCornerSide = mozilla::eLogicalSideBStart;
   mCornerBevel = false;
 }
 
 inline BCData::~BCData()
 {
 }
 
 inline nscoord BCData::GetIStartEdge(BCBorderOwner& aOwner,
                                      bool&          aStart) const
 {
   aOwner = (BCBorderOwner)mIStartOwner;
-  aStart = (bool)mIStartStart;
+  aStart = IsIStartStart();
 
   return (nscoord)mIStartSize;
 }
 
 inline void BCData::SetIStartEdge(BCBorderOwner  aOwner,
                                   nscoord        aSize,
                                   bool           aStart)
 {
   mIStartOwner = aOwner;
   mIStartSize  = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
-  mIStartStart = aStart;
+  SetIStartStart(aStart);
 }
 
 inline nscoord BCData::GetBStartEdge(BCBorderOwner& aOwner,
                                      bool&          aStart) const
 {
   aOwner = (BCBorderOwner)mBStartOwner;
-  aStart = (bool)mBStartStart;
+  aStart = IsBStartStart();
 
   return (nscoord)mBStartSize;
 }
 
 inline void BCData::SetBStartEdge(BCBorderOwner  aOwner,
                                   nscoord        aSize,
                                   bool           aStart)
 {
   mBStartOwner = aOwner;
   mBStartSize  = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
-  mBStartStart = aStart;
+  SetBStartStart(aStart);
 }
 
 inline BCPixelSize BCData::GetCorner(mozilla::LogicalSide& aOwnerSide,
                                      bool&                 aBevel) const
 {
   aOwnerSide = mozilla::LogicalSide(mCornerSide);
   aBevel     = (bool)mCornerBevel;
   return mCornerSubSize;
@@ -429,29 +441,9 @@ inline void BCData::SetCorner(BCPixelSiz
                               mozilla::LogicalSide aOwnerSide,
                               bool                 aBevel)
 {
   mCornerSubSize = aSubSize;
   mCornerSide    = aOwnerSide;
   mCornerBevel   = aBevel;
 }
 
-inline bool BCData::IsIStartStart() const
-{
-  return (bool)mIStartStart;
-}
-
-inline void BCData::SetIStartStart(bool aValue)
-{
-  mIStartStart = aValue;
-}
-
-inline bool BCData::IsBStartStart() const
-{
-  return (bool)mBStartStart;
-}
-
-inline void BCData::SetBStartStart(bool aValue)
-{
-  mBStartStart = aValue;
-}
-
 #endif
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1307,18 +1307,18 @@ pref("dom.timeout.background_budget_rege
 pref("dom.timeout.background_throttling_max_budget", 50);
 // Time (in ms) that it takes to regenerate 1ms.
 pref("dom.timeout.foreground_budget_regeneration_rate", 1);
 // Maximum value (in ms) for the background budget. Only valid for
 // values greater than 0.
 pref("dom.timeout.foreground_throttling_max_budget", -1);
 // The maximum amount a timeout can be delayed by budget throttling
 pref("dom.timeout.budget_throttling_max_delay", 15000);
-// Turn off budget throttling by default
-pref("dom.timeout.enable_budget_timer_throttling", false);
+// Turn on budget throttling by default
+pref("dom.timeout.enable_budget_timer_throttling", true);
 
 // Don't use new input types
 pref("dom.experimental_forms", false);
 
 // Enable <input type=number>:
 pref("dom.forms.number", true);
 
 // Enable <input type=color> by default. It will be turned off for remaining
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -101,16 +101,38 @@ nsBaseChannel::Redirect(nsIChannel *newC
                         nsIChannelEventSink::REDIRECT_STS_UPGRADE));
 
     // nsBaseChannel hst no thing to do with HttpBaseChannel, we would not care
     // about referrer and remote address in this case
     nsCOMPtr<nsIRedirectHistoryEntry> entry =
       new nsRedirectHistoryEntry(uriPrincipal, nullptr, EmptyCString());
 
     newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
+
+    // Ensure the channel's loadInfo's result principal URI so that it's
+    // either non-null or updated to the redirect target URI.
+    // We must do this because in case the loadInfo's result principal URI
+    // is null, it would be taken from OriginalURI of the channel.  But we
+    // overwrite it with the whole redirect chain first URI before opening
+    // the target channel, hence the information would be lost.
+    // If the protocol handler that created the channel wants to use
+    // the originalURI of the channel as the principal URI, it has left
+    // the result principal URI on the load info null.
+    nsCOMPtr<nsIURI> resultPrincipalURI;
+
+    nsCOMPtr<nsILoadInfo> existingLoadInfo = newChannel->GetLoadInfo();
+    if (existingLoadInfo) {
+      existingLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
+    }
+    if (!resultPrincipalURI) {
+      newChannel->GetOriginalURI(getter_AddRefs(resultPrincipalURI));
+    }
+
+    newLoadInfo->SetResultPrincipalURI(resultPrincipalURI);
+
     newChannel->SetLoadInfo(newLoadInfo);
   }
   else {
     // the newChannel was created with a dummy loadInfo, we should clear
     // it in case the original channel does not have a loadInfo
     newChannel->SetLoadInfo(nullptr);
   }
 
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -63,17 +63,17 @@ interface nsIInterceptedChannel : nsISup
      */
     void finishSynthesizedResponse(in ACString finalURLSpec);
 
     /**
      * Cancel the pending intercepted request.
      * @return NS_ERROR_FAILURE if the response has already been synthesized or
      *         the original request has been instructed to continue.
      */
-    void cancel(in nsresult status);
+    void cancelInterception(in nsresult status);
 
     /**
      * The synthesized response body to be produced.
      */
     readonly attribute nsIOutputStream responseBody;
 
     /**
      * The underlying channel object that was intercepted.
--- a/netwerk/dns/nsIDNService.cpp
+++ b/netwerk/dns/nsIDNService.cpp
@@ -775,17 +775,16 @@ bool nsIDNService::isLabelSafe(const nsA
     // Check for mixed script
     Script script = GetScriptCode(ch);
     if (script != Script::COMMON &&
         script != Script::INHERITED &&
         script != lastScript) {
       if (illegalScriptCombo(script, savedScript)) {
         return false;
       }
-      lastScript = script;
     }
 
     // Check for mixed numbering systems
     auto genCat = GetGeneralCategory(ch);
     if (genCat == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) {
       uint32_t zeroCharacter = ch - GetNumericValue(ch);
       if (savedNumberingSystem == 0) {
         // If we encounter a decimal number, save the zero character from that
@@ -828,16 +827,20 @@ bool nsIDNService::isLabelSafe(const nsA
           }
           if (nScripts == -1) {
             return false;
           }
         }
       }
     }
 
+    if (script != Script::COMMON && script != Script::INHERITED) {
+      lastScript = script;
+    }
+
     // Simplified/Traditional Chinese check temporarily disabled -- bug 857481
 #if 0
 
     // Check for both simplified-only and traditional-only Chinese characters
     HanVariantType hanVariant = GetHanVariant(ch);
     if (hanVariant == HVT_SimplifiedOnly || hanVariant == HVT_TraditionalOnly) {
       if (savedHanVariant == HVT_NotHan) {
         savedHanVariant = hanVariant;
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -366,16 +366,46 @@ public: /* Necko internal use only... */
 
     void SetIsTrackingResource();
 
     const uint64_t& ChannelId() const
     {
       return mChannelId;
     }
 
+    void InternalSetUploadStream(nsIInputStream *uploadStream)
+    {
+      mUploadStream = uploadStream;
+    }
+
+    void SetUploadStreamHasHeaders(bool hasHeaders)
+    {
+      mUploadStreamHasHeaders = hasHeaders;
+    }
+
+    MOZ_MUST_USE nsresult
+    SetReferrerWithPolicyInternal(nsIURI *referrer, uint32_t referrerPolicy)
+    {
+      nsAutoCString spec;
+      nsresult rv = referrer->GetAsciiSpec(spec);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      mReferrer = referrer;
+      mReferrerPolicy = referrerPolicy;
+      rv = mRequestHead.SetHeader(nsHttp::Referer, spec);
+      return rv;
+    }
+
+    MOZ_MUST_USE nsresult SetTopWindowURI(nsIURI* aTopWindowURI)
+    {
+      mTopWindowURI = aTopWindowURI;
+      return NS_OK;
+    }
+
 protected:
   // Handle notifying listener, removing from loadgroup if request failed.
   void     DoNotifyListener();
   virtual void DoNotifyListenerCleanup() = 0;
 
   // drop reference to listener, its callbacks, and the progress sink
   virtual void ReleaseListeners();
 
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -3565,22 +3565,16 @@ HttpChannelChild::ForceIntercepted(bool 
                                    bool aPostRedirectChannelShouldUpgrade)
 {
   mShouldParentIntercept = true;
   mPostRedirectChannelShouldIntercept = aPostRedirectChannelShouldIntercept;
   mPostRedirectChannelShouldUpgrade = aPostRedirectChannelShouldUpgrade;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-HttpChannelChild::ForceIntercepted(uint64_t aInterceptionID)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 void
 HttpChannelChild::ForceIntercepted(nsIInputStream* aSynthesizedInput)
 {
   mSynthesizedInput = aSynthesizedInput;
   mSynthesizedResponse = true;
   mRedirectingForSubsequentSynthesizedResponse = true;
 }
 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -93,17 +93,16 @@ public:
   NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
                               const nsACString& aValue,
                               bool aMerge) override;
   NS_IMETHOD SetEmptyRequestHeader(const nsACString& aHeader) override;
   NS_IMETHOD RedirectTo(nsIURI *newURI) override;
   NS_IMETHOD GetProtocolVersion(nsACString& aProtocolVersion) override;
   // nsIHttpChannelInternal
   NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
-  NS_IMETHOD ForceIntercepted(uint64_t aInterceptionID) override;
   // nsISupportsPriority
   NS_IMETHOD SetPriority(int32_t value) override;
   // nsIClassOfService
   NS_IMETHOD SetClassFlags(uint32_t inFlags) override;
   NS_IMETHOD AddClassFlags(uint32_t inFlags) override;
   NS_IMETHOD ClearClassFlags(uint32_t inFlags) override;
   // nsIResumableChannel
   NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID) override;
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -108,17 +108,17 @@ HttpChannelParent::ActorDestroy(ActorDes
   // We may still have refcount>0 if nsHttpChannel hasn't called OnStopRequest
   // yet, but child process has crashed.  We must not try to send any more msgs
   // to child, or IPDL will kill chrome process, too.
   mIPCClosed = true;
 
   // If this is an intercepted channel, we need to make sure that any resources are
   // cleaned up to avoid leaks.
   if (mParentListener) {
-    mParentListener->ClearInterceptedChannel();
+    mParentListener->ClearInterceptedChannel(this);
   }
 
   CleanupBackgroundChannel();
 }
 
 bool
 HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
 {
@@ -230,18 +230,19 @@ HttpChannelParent::CleanupBackgroundChan
   if (mBgParent) {
     RefPtr<HttpBackgroundChannelParent> bgParent = mBgParent.forget();
     bgParent->OnChannelClosed();
     return;
   }
 
   // The nsHttpChannel may have a reference to this parent, release it
   // to avoid circular references.
-  if (mChannel) {
-    mChannel->SetWarningReporter(nullptr);
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
+  if (httpChannelImpl) {
+    httpChannelImpl->SetWarningReporter(nullptr);
   }
 
   if (!mPromise.IsEmpty()) {
     mRequest.DisconnectIfExists();
     mPromise.Reject(NS_ERROR_FAILURE, __func__);
 
     if (!mChannel) {
       return;
@@ -516,27 +517,30 @@ HttpChannelParent::DoAsyncOpen(  const U
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo,
                              nullptr, nullptr, aLoadFlags, ios);
   if (NS_FAILED(rv)) {
     return SendFailedAsyncOpen(rv);
   }
 
-  RefPtr<nsHttpChannel> httpChannel = do_QueryObject(channel, &rv);
+  RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(channel, &rv);
   if (NS_FAILED(rv)) {
     return SendFailedAsyncOpen(rv);
   }
 
   // Set the channelId allocated in child to the parent instance
   httpChannel->SetChannelId(aChannelId);
   httpChannel->SetTopLevelContentWindowId(aContentWindowId);
   httpChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
 
-  httpChannel->SetWarningReporter(this);
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(httpChannel);
+  if (httpChannelImpl) {
+    httpChannelImpl->SetWarningReporter(this);
+  }
   httpChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
     httpChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
   }
 
   if (doResumeAt)
     httpChannel->ResumeAt(startPos, entityID);
 
@@ -561,18 +565,18 @@ HttpChannelParent::DoAsyncOpen(  const U
     httpChannel->SetIsMainDocumentChannel(true);
   }
 
   for (uint32_t i = 0; i < requestHeaders.Length(); i++) {
     if (requestHeaders[i].mEmpty) {
       httpChannel->SetEmptyRequestHeader(requestHeaders[i].mHeader);
     } else {
       httpChannel->SetRequestHeader(requestHeaders[i].mHeader,
-                                 requestHeaders[i].mValue,
-                                 requestHeaders[i].mMerge);
+                                    requestHeaders[i].mValue,
+                                    requestHeaders[i].mMerge);
     }
   }
 
   RefPtr<HttpChannelParentListener> parentListener
     = new HttpChannelParentListener(this);
 
   httpChannel->SetRequestMethod(nsDependentCString(requestMethod.get()));
 
@@ -640,17 +644,17 @@ HttpChannelParent::DoAsyncOpen(  const U
       httpChannel->InternalSetUploadStream(stream);
     }
     httpChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
   }
 
   if (aSynthesizedResponseHead.type() == OptionalHttpResponseHead::TnsHttpResponseHead) {
     parentListener->SetupInterception(aSynthesizedResponseHead.get_nsHttpResponseHead());
     mWillSynthesizeResponse = true;
-    httpChannel->SetCouldBeSynthesized();
+    httpChannelImpl->SetCouldBeSynthesized();
 
     if (!aSecurityInfoSerialization.IsEmpty()) {
       nsCOMPtr<nsISupports> secInfo;
       NS_DeserializeObject(aSecurityInfoSerialization, getter_AddRefs(secInfo));
       rv = httpChannel->OverrideSecurityInfo(secInfo);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
   } else {
@@ -666,20 +670,24 @@ HttpChannelParent::DoAsyncOpen(  const U
     return SendFailedAsyncOpen(rv);
   }
 
   rv = cacheKey->SetData(aCacheKey);
   if (NS_FAILED(rv)) {
     return SendFailedAsyncOpen(rv);
   }
 
-  httpChannel->SetCacheKey(cacheKey);
-  httpChannel->PreferAlternativeDataType(aPreferredAlternativeType);
+  nsCOMPtr<nsICacheInfoChannel> cacheChannel =
+    do_QueryInterface(static_cast<nsIChannel*>(httpChannel.get()));
+  if (cacheChannel) {
+    cacheChannel->SetCacheKey(cacheKey);
+    cacheChannel->PreferAlternativeDataType(aPreferredAlternativeType);
 
-  httpChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
+    cacheChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
+  }
 
   httpChannel->SetContentType(aContentTypeHint);
 
   if (priority != nsISupportsPriority::PRIORITY_NORMAL) {
     httpChannel->SetPriority(priority);
   }
   if (classOfService) {
     httpChannel->SetClassFlags(classOfService);
@@ -809,24 +817,27 @@ HttpChannelParent::ConnectChannel(const 
     // no other way to tell the child side there were something wrong.
     Delete();
     return true;
   }
 
   LOG(("  found channel %p, rv=%08" PRIx32, channel.get(), static_cast<uint32_t>(rv)));
   mChannel = do_QueryObject(channel);
   if (!mChannel) {
-    LOG(("  but it's not nsHttpChannel"));
+    LOG(("  but it's not HttpBaseChannel"));
     Delete();
     return true;
   }
 
-  LOG(("  and it is nsHttpChannel %p", mChannel.get()));
+  LOG(("  and it is HttpBaseChannel %p", mChannel.get()));
 
-  mChannel->SetWarningReporter(this);
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
+  if (httpChannelImpl) {
+    httpChannelImpl->SetWarningReporter(this);
+  }
 
   nsCOMPtr<nsINetworkInterceptController> controller;
   NS_QueryNotificationCallbacks(channel, controller);
   RefPtr<HttpChannelParentListener> parentListener = do_QueryObject(controller);
   MOZ_ASSERT(parentListener);
   parentListener->SetupInterceptionAfterRedirect(shouldIntercept);
 
   if (mPBOverride != kPBOverride_Unset) {
@@ -1404,100 +1415,112 @@ HttpChannelParent::OnStartRequest(nsIReq
 {
   LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n",
        this, aRequest));
   MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnStartRequest if diverting is set!");
 
-  RefPtr<nsHttpChannel> chan = do_QueryObject(aRequest);
+  RefPtr<HttpBaseChannel> chan = do_QueryObject(aRequest);
   if (!chan) {
-    LOG(("  aRequest is not nsHttpChannel"));
-    NS_ERROR("Expecting only nsHttpChannel as aRequest in HttpChannelParent::OnStartRequest");
+    LOG(("  aRequest is not HttpBaseChannel"));
+    NS_ERROR("Expecting only HttpBaseChannel as aRequest in HttpChannelParent::OnStartRequest");
     return NS_ERROR_UNEXPECTED;
   }
 
   MOZ_ASSERT(mChannel == chan,
-             "HttpChannelParent getting OnStartRequest from a different nsHttpChannel instance");
+             "HttpChannelParent getting OnStartRequest from a different HttpBaseChannel instance");
 
   // Send down any permissions which are relevant to this URL if we are
   // performing a document load. We can't do that is mIPCClosed is set.
   if (!mIPCClosed) {
     PContentParent* pcp = Manager()->Manager();
     MOZ_ASSERT(pcp, "We should have a manager if our IPC isn't closed");
     DebugOnly<nsresult> rv =
       static_cast<ContentParent*>(pcp)->AboutToLoadHttpFtpWyciwygDocumentForChild(chan);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
   }
 
   nsHttpResponseHead *responseHead = chan->GetResponseHead();
   nsHttpRequestHead  *requestHead = chan->GetRequestHead();
   bool isFromCache = false;
-  chan->IsFromCache(&isFromCache);
   int32_t fetchCount = 0;
-  chan->GetCacheTokenFetchCount(&fetchCount);
   uint32_t expirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
-  chan->GetCacheTokenExpirationTime(&expirationTime);
   nsCString cachedCharset;
-  chan->GetCacheTokenCachedCharset(cachedCharset);
+
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(chan);
+
+  if (httpChannelImpl) {
+    httpChannelImpl->IsFromCache(&isFromCache);
+    httpChannelImpl->GetCacheTokenFetchCount(&fetchCount);
+    httpChannelImpl->GetCacheTokenExpirationTime(&expirationTime);
+    httpChannelImpl->GetCacheTokenCachedCharset(cachedCharset);
+  }
+
+  bool loadedFromApplicationCache = false;
 
-  bool loadedFromApplicationCache;
-  chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
-  if (loadedFromApplicationCache) {
-    mOfflineForeignMarker = chan->GetOfflineCacheEntryAsForeignMarker();
-    nsCOMPtr<nsIApplicationCache> appCache;
-    chan->GetApplicationCache(getter_AddRefs(appCache));
-    nsCString appCacheGroupId;
-    nsCString appCacheClientId;
-    appCache->GetGroupID(appCacheGroupId);
-    appCache->GetClientID(appCacheClientId);
-    if (mIPCClosed ||
-        !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
-    {
-      return NS_ERROR_UNEXPECTED;
+  if (httpChannelImpl) {
+    httpChannelImpl->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
+    if (loadedFromApplicationCache) {
+      mOfflineForeignMarker = httpChannelImpl->GetOfflineCacheEntryAsForeignMarker();
+      nsCOMPtr<nsIApplicationCache> appCache;
+      httpChannelImpl->GetApplicationCache(getter_AddRefs(appCache));
+      nsCString appCacheGroupId;
+      nsCString appCacheClientId;
+      appCache->GetGroupID(appCacheGroupId);
+      appCache->GetClientID(appCacheClientId);
+      if (mIPCClosed ||
+          !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
+      {
+        return NS_ERROR_UNEXPECTED;
+      }
     }
   }
 
   nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest);
   if (encodedChannel)
     encodedChannel->SetApplyConversion(false);
 
   // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
   // It could be already released by nsHttpChannel at that time.
   nsCOMPtr<nsISupports> cacheEntry;
-  chan->GetCacheToken(getter_AddRefs(cacheEntry));
-  mCacheEntry = do_QueryInterface(cacheEntry);
+  nsresult channelStatus = NS_OK;
+  uint32_t cacheKeyValue = 0;
+  nsAutoCString altDataType;
+
+  if (httpChannelImpl) {
+    httpChannelImpl->GetCacheToken(getter_AddRefs(cacheEntry));
+    mCacheEntry = do_QueryInterface(cacheEntry);
+
+    httpChannelImpl->GetStatus(&channelStatus);
 
-  nsresult channelStatus = NS_OK;
-  chan->GetStatus(&channelStatus);
+    nsCOMPtr<nsISupports> cacheKey;
+    httpChannelImpl->GetCacheKey(getter_AddRefs(cacheKey));
+    if (cacheKey) {
+      nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
+      if (!container) {
+        return NS_ERROR_ILLEGAL_VALUE;
+      }
+
+      nsresult rv = container->GetData(&cacheKeyValue);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+    }
+
+    httpChannelImpl->GetAlternativeDataType(altDataType);
+  }
 
   nsCString secInfoSerialization;
   UpdateAndSerializeSecurityInfo(secInfoSerialization);
 
   uint8_t redirectCount = 0;
   chan->GetRedirectCount(&redirectCount);
 
-  nsCOMPtr<nsISupports> cacheKey;
-  chan->GetCacheKey(getter_AddRefs(cacheKey));
-  uint32_t cacheKeyValue = 0;
-  if (cacheKey) {
-    nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
-    if (!container) {
-      return NS_ERROR_ILLEGAL_VALUE;
-    }
-
-    nsresult rv = container->GetData(&cacheKeyValue);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-  }
-
-  nsAutoCString altDataType;
-  chan->GetAlternativeDataType(altDataType);
   int64_t altDataLen = chan->GetAltDataLength();
 
   // !!! We need to lock headers and please don't forget to unlock them !!!
   requestHead->Enter();
   nsresult rv = NS_OK;
   if (mIPCClosed ||
       !SendOnStartRequest(channelStatus,
                           responseHead ? *responseHead : nsHttpResponseHead(),
@@ -1557,17 +1580,20 @@ HttpChannelParent::OnStopRequest(nsIRequ
   mChannel->GetEncodedBodySize(&timing.encodedBodySize);
   // decodedBodySize can be computed in the child process so it doesn't need
   // to be passed down.
   mChannel->GetProtocolVersion(timing.protocolVersion);
 
   mChannel->GetCacheReadStart(&timing.cacheReadStart);
   mChannel->GetCacheReadEnd(&timing.cacheReadEnd);
 
-  mChannel->SetWarningReporter(nullptr);
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
+  if (httpChannelImpl) {
+    httpChannelImpl->SetWarningReporter(nullptr);
+  }
 
   // Either IPC channel is closed or background channel
   // is ready to send OnStopRequest.
   MOZ_ASSERT(mIPCClosed || mBgParent);
 
   if (mIPCClosed ||
       !mBgParent || !mBgParent->OnStopRequest(aStatusCode, timing)) {
     return NS_ERROR_UNEXPECTED;
@@ -1592,19 +1618,21 @@ HttpChannelParent::OnDataAvailable(nsIRe
   MOZ_ASSERT(NS_IsMainThread());
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnDataAvailable if diverting is set!");
 
   nsresult channelStatus = NS_OK;
   mChannel->GetStatus(&channelStatus);
 
-  nsresult transportStatus =
-    (mChannel->IsReadingFromCache()) ? NS_NET_STATUS_READING
-                                     : NS_NET_STATUS_RECEIVING_FROM;
+  nsresult transportStatus = NS_NET_STATUS_RECEIVING_FROM;
+  RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
+  if (httpChannelImpl && httpChannelImpl->IsReadingFromCache()) {
+    transportStatus = NS_NET_STATUS_READING;
+  }
 
   static uint32_t const kCopyChunkSize = 128 * 1024;
   uint32_t toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
 
   nsCString data;
   if (!data.SetCapacity(toRead, fallible)) {
     LOG(("  out of memory!"));
     return NS_ERROR_OUT_OF_MEMORY;
@@ -1773,18 +1801,50 @@ HttpChannelParent::StartRedirect(uint32_
                                  nsIAsyncVerifyRedirectCallback* callback)
 {
   nsresult rv;
 
   LOG(("HttpChannelParent::StartRedirect [this=%p, registrarId=%" PRIu32 " "
        "newChannel=%p callback=%p]\n", this, registrarId, newChannel,
        callback));
 
-  if (mIPCClosed)
+  if (mIPCClosed) {
     return NS_BINDING_ABORTED;
+  }
+
+  // If this is an internal redirect for service worker interception, then
+  // hide it from the child process.  The original e10s interception code
+  // was not designed with this in mind and its not necessary to replace
+  // the HttpChannelChild/Parent objects in this case.
+  if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
+    nsCOMPtr<nsIInterceptedChannel> newIntercepted = do_QueryInterface(newChannel);
+    if (newIntercepted) {
+#ifdef DEBUG
+      // Note, InterceptedHttpChannel can also do an internal redirect
+      // for opaque response interception.  This should not actually
+      // happen here in e10s mode.
+      nsCOMPtr<nsIInterceptedChannel> oldIntercepted =
+        do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
+      MOZ_ASSERT(!oldIntercepted);
+#endif
+
+      // Re-link the HttpChannelParent to the new InterceptedHttpChannel.
+      nsCOMPtr<nsIChannel> linkedChannel;
+      rv = NS_LinkRedirectChannels(registrarId, this, getter_AddRefs(linkedChannel));
+      NS_ENSURE_SUCCESS(rv, rv);
+      MOZ_ASSERT(linkedChannel == newChannel);
+
+      // We immediately store the InterceptedHttpChannel as our nested
+      // mChannel.  None of the redirect IPC messaging takes place.
+      mChannel = do_QueryObject(newChannel);
+
+      callback->OnRedirectVerifyCallback(NS_OK);
+      return NS_OK;
+    }
+  }
 
   // Sending down the original URI, because that is the URI we have
   // to construct the channel from - this is the URI we've been actually
   // redirected to.  URI of the channel may be an inner channel URI.
   // URI of the channel will be reconstructed by the protocol handler
   // on the child process, no need to send it then.
   nsCOMPtr<nsIURI> newOriginalURI;
   newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
@@ -1793,17 +1853,17 @@ HttpChannelParent::StartRedirect(uint32_
   SerializeURI(newOriginalURI, uriParams);
 
   nsCString secInfoSerialization;
   UpdateAndSerializeSecurityInfo(secInfoSerialization);
 
   // If the channel is a HTTP channel, we also want to inform the child
   // about the parent's channelId attribute, so that both parent and child
   // share the same ID. Useful for monitoring channel activity in devtools.
-  uint64_t channelId;
+  uint64_t channelId = 0;
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
   if (httpChannel) {
     rv = httpChannel->GetChannelId(&channelId);
     NS_ENSURE_SUCCESS(rv, NS_BINDING_ABORTED);
   }
 
   nsHttpResponseHead *responseHead = mChannel->GetResponseHead();
   bool result = false;
@@ -1834,16 +1894,23 @@ HttpChannelParent::StartRedirect(uint32_
 }
 
 NS_IMETHODIMP
 HttpChannelParent::CompleteRedirect(bool succeeded)
 {
   LOG(("HttpChannelParent::CompleteRedirect [this=%p succeeded=%d]\n",
        this, succeeded));
 
+  // If this was an internal redirect for a service worker interception then
+  // we will not have a redirecting channel here.  Hide this redirect from
+  // the child.
+  if (!mRedirectChannel) {
+    return NS_OK;
+  }
+
   if (succeeded && !mIPCClosed) {
     // TODO: check return value: assume child dead if failed
     Unused << SendRedirect3Complete();
   }
 
   mRedirectChannel = nullptr;
   return NS_OK;
 }
@@ -1868,33 +1935,35 @@ HttpChannelParent::SuspendForDiversion()
 
   if (NS_WARN_IF(mDivertingFromChild)) {
     MOZ_ASSERT(!mDivertingFromChild, "Already suspended for diversion!");
     return NS_ERROR_UNEXPECTED;
   }
 
   // MessageDiversionStarted call will suspend mEventQ as many times as the
   // channel has been suspended, so that channel and this queue are in sync.
-  mChannel->MessageDiversionStarted(this);
+  nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
+    do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
+  divertChannel->MessageDiversionStarted(this);
 
   nsresult rv = NS_OK;
 
   // Try suspending the channel. Allow it to fail, since OnStopRequest may have
   // been called and thus the channel may not be pending.  If we've already
   // automatically suspended after synthesizing the response, then we don't
   // need to suspend again here.
   if (!mSuspendAfterSynthesizeResponse) {
     // We need to suspend only nsHttpChannel (i.e. we should not suspend
     // mEventQ). Therefore we call mChannel->SuspendInternal() and not
     // mChannel->Suspend().
     // We are suspending only nsHttpChannel here because we want to stop
     // OnDataAvailable until diversion is over. At the same time we should
     // send the diverted OnDataAvailable-s to the listeners and not queue them
     // in mEventQ.
-    rv = mChannel->SuspendInternal();
+    rv = divertChannel->SuspendInternal();
     MOZ_ASSERT(NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_AVAILABLE);
     mSuspendedForDiversion = NS_SUCCEEDED(rv);
   } else {
     // Take ownership of the automatic suspend that occurred after synthesizing
     // the response.
     mSuspendedForDiversion = true;
 
     // If mSuspendAfterSynthesizeResponse is true channel has been already
@@ -1939,21 +2008,23 @@ HttpChannelParent::ResumeForDiversion()
   LOG(("HttpChannelParent::ResumeForDiversion [this=%p]\n", this));
   MOZ_ASSERT(mChannel);
   if (NS_WARN_IF(!mDivertingFromChild)) {
     MOZ_ASSERT(mDivertingFromChild,
                "Cannot ResumeForDiversion if not diverting!");
     return NS_ERROR_UNEXPECTED;
   }
 
-  mChannel->MessageDiversionStop();
+  nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
+    do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
+  divertChannel->MessageDiversionStop();
 
   if (mSuspendedForDiversion) {
     // The nsHttpChannel will deliver remaining OnData/OnStop for the transfer.
-    nsresult rv = mChannel->ResumeInternal();
+    nsresult rv = divertChannel->ResumeInternal();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     mSuspendedForDiversion = false;
   }
 
   if (NS_WARN_IF(mIPCClosed || !DoSendDeleteSelf())) {
     return NS_ERROR_UNEXPECTED;
@@ -2099,17 +2170,19 @@ HttpChannelParent::NotifyDiversionFailed
   mChannel->ForcePending(false);
 
   bool isPending = false;
   nsresult rv = mChannel->IsPending(&isPending);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 
   // Resume only if we suspended earlier.
   if (mSuspendedForDiversion) {
-    mChannel->ResumeInternal();
+    nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
+      do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
+    divertChannel->ResumeInternal();
   }
   // Channel has already sent OnStartRequest to the child, so ensure that we
   // call it here if it hasn't already been called.
   if (!mDivertedOnStartRequest) {
     mChannel->ForcePending(true);
     mParentListener->OnStartRequest(mChannel, nullptr);
     mChannel->ForcePending(false);
   }
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -255,17 +255,17 @@ private:
   // DocumentChannelCleanup.
   void CleanupBackgroundChannel();
 
   friend class HttpBackgroundChannelParent;
   friend class DivertDataAvailableEvent;
   friend class DivertStopRequestEvent;
   friend class DivertCompleteEvent;
 
-  RefPtr<nsHttpChannel>       mChannel;
+  RefPtr<HttpBaseChannel>       mChannel;
   nsCOMPtr<nsICacheEntry>       mCacheEntry;
   nsCOMPtr<nsIAssociatedContentSecurity>  mAssociatedContentSecurity;
   bool mIPCClosed;                // PHttpChannel actor has been Closed()
 
   nsCOMPtr<nsIChannel> mRedirectChannel;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
 
   nsAutoPtr<class nsHttpChannel::OfflineCacheEntryAsForeignMarker> mOfflineForeignMarker;
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -24,16 +24,17 @@ namespace mozilla {
 namespace net {
 
 HttpChannelParentListener::HttpChannelParentListener(HttpChannelParent* aInitialChannel)
   : mNextListener(aInitialChannel)
   , mRedirectChannelId(0)
   , mSuspendedForDiversion(false)
   , mShouldIntercept(false)
   , mShouldSuspendIntercept(false)
+  , mInterceptCanceled(false)
 {
   LOG(("HttpChannelParentListener::HttpChannelParentListener [this=%p, next=%p]",
        this, aInitialChannel));
 }
 
 HttpChannelParentListener::~HttpChannelParentListener()
 {
 }
@@ -242,24 +243,29 @@ HttpChannelParentListener::OnRedirectRes
 
   if (activeRedirectingChannel) {
     activeRedirectingChannel->CompleteRedirect(succeeded);
   } else {
     succeeded = false;
   }
 
   if (succeeded) {
-    // Switch to redirect channel and delete the old one.
-    nsCOMPtr<nsIParentChannel> parent;
-    parent = do_QueryInterface(mNextListener);
-    MOZ_ASSERT(parent);
-    parent->Delete();
-    mNextListener = do_QueryInterface(redirectChannel);
-    MOZ_ASSERT(mNextListener);
-    redirectChannel->SetParentListener(this);
+    // Switch to redirect channel and delete the old one.  Only do this
+    // if we are actually changing channels.  During a service worker
+    // interception internal redirect we preserve the same HttpChannelParent.
+    if (!SameCOMIdentity(redirectChannel, mNextListener)) {
+      nsCOMPtr<nsIParentChannel> parent;
+      parent = do_QueryInterface(mNextListener);
+      MOZ_ASSERT(parent);
+      parent->Delete();
+      mInterceptCanceled = false;
+      mNextListener = do_QueryInterface(redirectChannel);
+      MOZ_ASSERT(mNextListener);
+      redirectChannel->SetParentListener(this);
+    }
   } else if (redirectChannel) {
     // Delete the redirect target channel: continue using old channel
     redirectChannel->Delete();
   }
 
   return NS_OK;
 }
 
@@ -315,16 +321,33 @@ public:
     mChannel->FinishSynthesizedResponse(EmptyCString());
     return NS_OK;
   }
 };
 
 NS_IMETHODIMP
 HttpChannelParentListener::ChannelIntercepted(nsIInterceptedChannel* aChannel)
 {
+  // Its possible for the child-side interception to complete and tear down
+  // the actor before we even get this parent-side interception notification.
+  // In this case we want to let the interception succeed, but then immediately
+  // cancel it.  If we return an error code from here then it might get
+  // propagated back to the child process where the interception did not encounter
+  // an error.  Therefore cancel the new channel asynchronously from a runnable.
+  if (mInterceptCanceled) {
+    nsCOMPtr<nsIRunnable> r =
+      NewRunnableMethod<nsresult>("HttpChannelParentListener::CancelInterception",
+                                  aChannel,
+                                  &nsIInterceptedChannel::CancelInterception,
+                                  NS_BINDING_ABORTED);
+    MOZ_ALWAYS_SUCCEEDS(
+      SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
+    return NS_OK;
+  }
+
   if (mShouldSuspendIntercept) {
     mInterceptedChannel = aChannel;
     return NS_OK;
   }
 
   nsAutoCString statusText;
   mSynthesizedResponseHead->StatusText(statusText);
   aChannel->SynthesizeStatus(mSynthesizedResponseHead->Status(), statusText);
@@ -376,16 +399,21 @@ HttpChannelParentListener::ResumeForDive
 }
 
 nsresult
 HttpChannelParentListener::DivertTo(nsIStreamListener* aListener)
 {
   MOZ_ASSERT(aListener);
   MOZ_RELEASE_ASSERT(mSuspendedForDiversion, "Must already be suspended!");
 
+  // Reset mInterceptCanceled back to false every time a new listener is set.
+  // We only want to cancel the interception if our current listener has
+  // signaled its cleaning up.
+  mInterceptCanceled = false;
+
   mNextListener = aListener;
 
   return ResumeForDiversion();
 }
 
 void
 HttpChannelParentListener::SetupInterception(const nsHttpResponseHead& aResponseHead)
 {
@@ -400,18 +428,27 @@ HttpChannelParentListener::SetupIntercep
   if (mShouldIntercept) {
     // When an interception occurs, this channel should suspend all further activity.
     // It will be torn down and recreated if necessary.
     mShouldSuspendIntercept = true;
   }
 }
 
 void
-HttpChannelParentListener::ClearInterceptedChannel()
+HttpChannelParentListener::ClearInterceptedChannel(nsIStreamListener* aListener)
 {
+  // Only cancel the interception if this is from our current listener.  We
+  // can get spurious calls here from other HttpChannelParent instances being
+  // destroyed asynchronously.
+  if (!SameCOMIdentity(mNextListener, aListener)) {
+    return;
+  }
   if (mInterceptedChannel) {
-    mInterceptedChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
+    mInterceptedChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
     mInterceptedChannel = nullptr;
   }
+  // Note that channel interception has been canceled.  If we got this before
+  // the interception even occured we will trigger the cancel later.
+  mInterceptCanceled = true;
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/HttpChannelParentListener.h
+++ b/netwerk/protocol/http/HttpChannelParentListener.h
@@ -47,17 +47,17 @@ public:
   explicit HttpChannelParentListener(HttpChannelParent* aInitialChannel);
 
   // For channel diversion from child to parent.
   MOZ_MUST_USE nsresult DivertTo(nsIStreamListener *aListener);
   MOZ_MUST_USE nsresult SuspendForDiversion();
 
   void SetupInterception(const nsHttpResponseHead& aResponseHead);
   void SetupInterceptionAfterRedirect(bool aShouldIntercept);
-  void ClearInterceptedChannel();
+  void ClearInterceptedChannel(nsIStreamListener* aListener);
 
 private:
   virtual ~HttpChannelParentListener();
 
   // Private partner function to SuspendForDiversion.
   MOZ_MUST_USE nsresult ResumeForDiversion();
 
   // Can be the original HttpChannelParent that created this object (normal
@@ -68,16 +68,20 @@ private:
   uint32_t mRedirectChannelId;
   // When set, no OnStart/OnData/OnStop calls should be received.
   bool mSuspendedForDiversion;
 
   // Set if this channel should be intercepted before it sets up the HTTP transaction.
   bool mShouldIntercept;
   // Set if this channel should suspend on interception.
   bool mShouldSuspendIntercept;
+  // Set if the channel interception has been canceled.  Can be set before
+  // interception first occurs.  In this case cancelation is deferred until
+  // the interception takes place.
+  bool mInterceptCanceled;
 
   nsAutoPtr<nsHttpResponseHead> mSynthesizedResponseHead;
 
   // Handle to the channel wrapper if this channel has been intercepted.
   nsCOMPtr<nsIInterceptedChannel> mInterceptedChannel;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelParentListener,
--- a/netwerk/protocol/http/InterceptedChannel.cpp
+++ b/netwerk/protocol/http/InterceptedChannel.cpp
@@ -208,225 +208,16 @@ InterceptedChannelBase::SecureUpgradeCha
 
   nsCOMPtr<nsIURI> upgradedURI;
   rv = NS_GetSecureUpgradedURI(uri, getter_AddRefs(upgradedURI));
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return upgradedURI.forget();
 }
 
-InterceptedChannelChrome::InterceptedChannelChrome(nsHttpChannel* aChannel,
-                                                   nsINetworkInterceptController* aController,
-                                                   nsICacheEntry* aEntry)
-: InterceptedChannelBase(aController)
-, mChannel(aChannel)
-, mSynthesizedCacheEntry(aEntry)
-{
-  nsresult rv = mChannel->GetApplyConversion(&mOldApplyConversion);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    mOldApplyConversion = false;
-  }
-}
-
-void
-InterceptedChannelChrome::NotifyController()
-{
-  // Intercepted responses should already be decoded.
-  mChannel->SetApplyConversion(false);
-
-  nsresult rv = mSynthesizedCacheEntry->OpenOutputStream(0, getter_AddRefs(mResponseBody));
-  NS_ENSURE_SUCCESS_VOID(rv);
-
-  DoNotifyController();
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::GetChannel(nsIChannel** aChannel)
-{
-  NS_IF_ADDREF(*aChannel = mChannel);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::ResetInterception()
-{
-  if (mClosed) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  mReportCollector->FlushConsoleReports(mChannel);
-
-  mSynthesizedCacheEntry->AsyncDoom(nullptr);
-  mSynthesizedCacheEntry = nullptr;
-
-  mChannel->SetApplyConversion(mOldApplyConversion);
-
-  nsCOMPtr<nsIURI> uri;
-  mChannel->GetURI(getter_AddRefs(uri));
-
-  nsresult rv = mChannel->StartRedirectChannelToURI(uri, nsIChannelEventSink::REDIRECT_INTERNAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mResponseBody->Close();
-  mResponseBody = nullptr;
-  mClosed = true;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::SynthesizeStatus(uint16_t aStatus, const nsACString& aReason)
-{
-  if (!mSynthesizedCacheEntry) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  return DoSynthesizeStatus(aStatus, aReason);
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::SynthesizeHeader(const nsACString& aName, const nsACString& aValue)
-{
-  if (!mSynthesizedCacheEntry) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  return DoSynthesizeHeader(aName, aValue);
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
-{
-  if (mClosed) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // Make sure the cache entry's output stream is always closed.  If the
-  // channel was intercepted with a null-body response then its possible
-  // the synthesis completed without a stream copy operation.
-  mResponseBody->Close();
-
-  mReportCollector->FlushConsoleReports(mChannel);
-
-  EnsureSynthesizedResponse();
-
-  // If the synthesized response is a redirect, then we want to respect
-  // the encoding of whatever is loaded as a result.
-  if (nsHttpChannel::WillRedirect(mSynthesizedResponseHead.ref())) {
-    nsresult rv = mChannel->SetApplyConversion(mOldApplyConversion);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  mChannel->MarkIntercepted();
-
-  // First we ensure the appropriate metadata is set on the synthesized cache entry
-  // (i.e. the flattened response head)
-
-  nsCOMPtr<nsISupports> securityInfo;
-  nsresult rv = mChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  uint32_t expirationTime = 0;
-  rv = DoUpdateExpirationTime(mChannel, mSynthesizedCacheEntry,
-                              mSynthesizedResponseHead.ref(),
-                              expirationTime);
-
-  rv = DoAddCacheEntryHeaders(mChannel, mSynthesizedCacheEntry,
-                              mChannel->GetRequestHead(),
-                              mSynthesizedResponseHead.ref(), securityInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIURI> originalURI;
-  mChannel->GetURI(getter_AddRefs(originalURI));
-
-  nsCOMPtr<nsIURI> responseURI;
-  if (!aFinalURLSpec.IsEmpty()) {
-    rv = NS_NewURI(getter_AddRefs(responseURI), aFinalURLSpec);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    responseURI = originalURI;
-  }
-
-  bool equal = false;
-  originalURI->Equals(responseURI, &equal);
-  if (!equal) {
-    rv =
-        mChannel->StartRedirectChannelToURI(responseURI, nsIChannelEventSink::REDIRECT_INTERNAL);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    bool usingSSL = false;
-    responseURI->SchemeIs("https", &usingSSL);
-
-    // Then we open a real cache entry to read the synthesized response from.
-    rv = mChannel->OpenCacheEntry(usingSSL);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mSynthesizedCacheEntry = nullptr;
-
-    if (!mChannel->AwaitingCacheCallbacks()) {
-      rv = mChannel->ContinueConnect();
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
-  mClosed = true;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::Cancel(nsresult aStatus)
-{
-  MOZ_ASSERT(NS_FAILED(aStatus));
-
-  if (mClosed) {
-    return NS_ERROR_FAILURE;
-  }
-
-  mReportCollector->FlushConsoleReports(mChannel);
-
-  // we need to use AsyncAbort instead of Cancel since there's no active pump
-  // to cancel which will provide OnStart/OnStopRequest to the channel.
-  nsresult rv = mChannel->AsyncAbort(aStatus);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mClosed = true;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::SetChannelInfo(dom::ChannelInfo* aChannelInfo)
-{
-  if (mClosed) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return aChannelInfo->ResurrectInfoOnChannel(mChannel);
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::GetInternalContentPolicyType(nsContentPolicyType* aPolicyType)
-{
-  NS_ENSURE_ARG(aPolicyType);
-  nsCOMPtr<nsILoadInfo> loadInfo;
-  nsresult rv = mChannel->GetLoadInfo(getter_AddRefs(loadInfo));
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (loadInfo) {
-    *aPolicyType = loadInfo->InternalContentPolicyType();
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::GetSecureUpgradedChannelURI(nsIURI** aURI)
-{
-  return mChannel->GetURI(aURI);
-}
-
 InterceptedChannelContent::InterceptedChannelContent(HttpChannelChild* aChannel,
                                                      nsINetworkInterceptController* aController,
                                                      InterceptStreamListener* aListener,
                                                      bool aSecureUpgrade)
 : InterceptedChannelBase(aController)
 , mChannel(aChannel)
 , mStreamListener(aListener)
 , mSecureUpgrade(aSecureUpgrade)
@@ -536,17 +327,17 @@ InterceptedChannelContent::FinishSynthes
   mResponseBody = nullptr;
   mStreamListener = nullptr;
   mClosed = true;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-InterceptedChannelContent::Cancel(nsresult aStatus)
+InterceptedChannelContent::CancelInterception(nsresult aStatus)
 {
   MOZ_ASSERT(NS_FAILED(aStatus));
 
   if (mClosed) {
     return NS_ERROR_FAILURE;
   }
 
   mReportCollector->FlushConsoleReports(mChannel);
--- a/netwerk/protocol/http/InterceptedChannel.h
+++ b/netwerk/protocol/http/InterceptedChannel.h
@@ -161,47 +161,16 @@ public:
   }
 
   NS_IMETHODIMP SaveTimeStamps() override;
 
   static already_AddRefed<nsIURI>
   SecureUpgradeChannelURI(nsIChannel* aChannel);
 };
 
-class InterceptedChannelChrome : public InterceptedChannelBase
-{
-  // The actual channel being intercepted.
-  RefPtr<nsHttpChannel> mChannel;
-
-  // Writeable cache entry for use when synthesizing a response in a parent process
-  nsCOMPtr<nsICacheEntry> mSynthesizedCacheEntry;
-
-  // When a channel is intercepted, content decoding is disabled since the
-  // ServiceWorker will have already extracted the decoded data. For parent
-  // process channels we need to preserve the earlier value in case
-  // ResetInterception is called.
-  bool mOldApplyConversion;
-public:
-  InterceptedChannelChrome(nsHttpChannel* aChannel,
-                           nsINetworkInterceptController* aController,
-                           nsICacheEntry* aEntry);
-
-  NS_IMETHOD ResetInterception() override;
-  NS_IMETHOD FinishSynthesizedResponse(const nsACString& aFinalURLSpec) override;
-  NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
-  NS_IMETHOD GetSecureUpgradedChannelURI(nsIURI** aURI) override;
-  NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
-  NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
-  NS_IMETHOD Cancel(nsresult aStatus) override;
-  NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
-  NS_IMETHOD GetInternalContentPolicyType(nsContentPolicyType *aInternalContentPolicyType) override;
-
-  virtual void NotifyController() override;
-};
-
 class InterceptedChannelContent : public InterceptedChannelBase
 {
   // The actual channel being intercepted.
   RefPtr<HttpChannelChild> mChannel;
 
   // Reader-side of the response body when synthesizing in a child proces
   nsCOMPtr<nsIInputStream> mSynthesizedInput;
 
@@ -218,17 +187,17 @@ public:
                             bool aSecureUpgrade);
 
   NS_IMETHOD ResetInterception() override;
   NS_IMETHOD FinishSynthesizedResponse(const nsACString& aFinalURLSpec) override;
   NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
   NS_IMETHOD GetSecureUpgradedChannelURI(nsIURI** aURI) override;
   NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
   NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
-  NS_IMETHOD Cancel(nsresult aStatus) override;
+  NS_IMETHOD CancelInterception(nsresult aStatus) override;
   NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
   NS_IMETHOD GetInternalContentPolicyType(nsContentPolicyType *aInternalContentPolicyType) override;
 
   virtual void NotifyController() override;
 };
 
 } // namespace net
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -0,0 +1,1054 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ *  License, v. 2.0. If a copy of the MPL was not distributed with this
+ *  file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InterceptedHttpChannel.h"
+#include "nsContentSecurityManager.h"
+#include "nsEscape.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS_INHERITED(InterceptedHttpChannel,
+                            HttpBaseChannel,
+                            nsIInterceptedChannel,
+                            nsIAsyncVerifyRedirectCallback,
+                            nsIRequestObserver,
+                            nsIStreamListener,
+                            nsIChannelWithDivertableParentListener,
+                            nsIThreadRetargetableRequest,
+                            nsIThreadRetargetableStreamListener)
+
+InterceptedHttpChannel::InterceptedHttpChannel(PRTime aCreationTime,
+                                               const TimeStamp& aCreationTimestamp,
+                                               const TimeStamp& aAsyncOpenTimestamp)
+  : HttpAsyncAborter<InterceptedHttpChannel>(this)
+  , mProgress(0)
+  , mProgressReported(0)
+  , mSynthesizedStreamLength(-1)
+  , mResumeStartPos(0)
+  , mSynthesizedOrReset(Invalid)
+  , mCallingStatusAndProgress(false)
+{
+  // Pre-set the creation and AsyncOpen times based on the original channel
+  // we are intercepting.  We don't want our extra internal redirect to mask
+  // any time spent processing the channel.
+  mChannelCreationTime = aCreationTime;
+  mChannelCreationTimestamp = aCreationTimestamp;
+  mAsyncOpenTime = aAsyncOpenTimestamp;
+}
+
+void
+InterceptedHttpChannel::ReleaseListeners()
+{
+  if (mLoadGroup) {
+    mLoadGroup->RemoveRequest(this, nullptr, mStatus);
+  }
+  HttpBaseChannel::ReleaseListeners();
+  mSynthesizedResponseHead.reset();
+  mRedirectChannel = nullptr;
+  mBodyReader = nullptr;
+  mBodyWriter = nullptr;
+  mReleaseHandle = nullptr;
+  mProgressSink = nullptr;
+  mPump = nullptr;
+  mParentChannel = nullptr;
+
+  MOZ_DIAGNOSTIC_ASSERT(!mIsPending);
+}
+
+nsresult
+InterceptedHttpChannel::SetupReplacementChannel(nsIURI *aURI,
+                                                nsIChannel *aChannel,
+                                                bool aPreserveMethod,
+                                                uint32_t aRedirectFlags)
+{
+  nsresult rv = HttpBaseChannel::SetupReplacementChannel(aURI, aChannel,
+                                                         aPreserveMethod,
+                                                         aRedirectFlags);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // While we can't resume an synthetic response, we can still propagate
+  // the resume params across redirects for other channels to handle.
+  if (mResumeStartPos > 0) {
+    nsCOMPtr<nsIResumableChannel> resumable = do_QueryInterface(aChannel);
+    if (!resumable) {
+      return NS_ERROR_NOT_RESUMABLE;
+    }
+
+    resumable->ResumeAt(mResumeStartPos, mResumeEntityId);
+  }
+
+  return NS_OK;
+}
+
+bool
+InterceptedHttpChannel::ShouldRedirect() const
+{
+  // Determine if the synthetic response requires us to perform a real redirect.
+  return nsHttpChannel::WillRedirect(mResponseHead) &&
+         !mLoadInfo->GetDontFollowRedirects();
+}
+
+nsresult
+InterceptedHttpChannel::FollowSyntheticRedirect()
+{
+  // Perform a real redirect based on the synthetic response.
+
+  nsCOMPtr<nsIIOService> ioService;
+  nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString location;
+  rv = mResponseHead->GetHeader(nsHttp::Location, location);
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+  // make sure non-ASCII characters in the location header are escaped.
+  nsAutoCString locationBuf;
+  if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII, locationBuf)) {
+    location = locationBuf;
+  }
+
+  if (NS_WARN_IF(mRedirectionLimit == 0)) {
+    return NS_ERROR_REDIRECT_LOOP;
+  }
+
+  nsCOMPtr<nsIURI> redirectURI;
+  rv = ioService->NewURI(nsDependentCString(location.get()),
+                         nullptr,
+                         mURI,
+                         getter_AddRefs(redirectURI));
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_CORRUPTED_CONTENT);
+
+  uint32_t redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
+  if (nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
+    redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
+  }
+
+  bool rewriteToGET = ShouldRewriteRedirectToGET(mResponseHead->Status(),
+                                                 mRequestHead.ParsedMethod());
+
+  nsCOMPtr<nsIChannel> newChannel;
+  nsCOMPtr<nsILoadInfo> redirectLoadInfo =
+    CloneLoadInfoForRedirect(redirectURI, redirectFlags);
+  rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
+                             redirectURI,
+                             redirectLoadInfo,
+                             nullptr, // aLoadGroup
+                             nullptr, // aCallbacks
+                             mLoadFlags,
+                             ioService);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = SetupReplacementChannel(redirectURI, newChannel, !rewriteToGET,
+                               redirectFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mRedirectChannel = newChannel.forget();
+
+  rv = gHttpHandler->AsyncOnChannelRedirect(this, mRedirectChannel, redirectFlags);
+
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    OnRedirectVerifyCallback(rv);
+  }
+
+  return rv;
+}
+
+nsresult
+InterceptedHttpChannel::RedirectForOpaqueResponse(nsIURI* aResponseURI)
+{
+  // Perform an internal redirect to another InterceptedHttpChannel using
+  // the given cross-origin response URL.  The resulting channel will then
+  // process the synthetic response as normal.  This extra redirect is
+  // performed so that listeners treat the result as unsafe cross-origin
+  // data.
+
+  nsresult rv = NS_OK;
+
+  RefPtr<InterceptedHttpChannel> newChannel =
+    CreateForSynthesis(mResponseHead, mBodyReader,
+                       mChannelCreationTime, mChannelCreationTimestamp,
+                       mAsyncOpenTime);
+
+  rv = newChannel->Init(aResponseURI, mCaps,
+                        static_cast<nsProxyInfo*>(mProxyInfo.get()),
+                        mProxyResolveFlags, mProxyURI, mChannelId);
+
+  uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
+
+  nsCOMPtr<nsILoadInfo> redirectLoadInfo =
+    CloneLoadInfoForRedirect(aResponseURI, flags);
+  newChannel->SetLoadInfo(redirectLoadInfo);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = SetupReplacementChannel(aResponseURI, newChannel, true, flags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mRedirectChannel = newChannel;
+
+  rv = gHttpHandler->AsyncOnChannelRedirect(this, mRedirectChannel, flags);
+
+  if (NS_FAILED(rv)) {
+    OnRedirectVerifyCallback(rv);
+  }
+
+  return rv;
+}
+
+nsresult
+InterceptedHttpChannel::StartPump()
+{
+  MOZ_DIAGNOSTIC_ASSERT(!mPump);
+  MOZ_DIAGNOSTIC_ASSERT(mBodyReader);
+
+  // We don't support resuming an intercepted channel.  We can't guarantee the
+  // ServiceWorker will always return the same data and we can't rely on the
+  // http cache code to detect changes.  For now, just force the channel to
+  // NS_ERROR_NOT_RESUMABLE which should cause the front-end to recreate the
+  // channel without calling ResumeAt().
+  //
+  // It would also be possible to convert this information to a range request,
+  // but its unclear if we should do that for ServiceWorker FetchEvents.  See:
+  //
+  //  https://github.com/w3c/ServiceWorker/issues/1201
+  if (mResumeStartPos > 0) {
+    return NS_ERROR_NOT_RESUMABLE;
+  }
+
+  // For progress we trust the content-length for the "maximum" size.
+  // We can't determine the full size from the stream itself since
+  // we may only receive the data incrementally.  We can't trust
+  // Available() here.
+  // TODO: We could implement an nsIFixedLengthInputStream interface and
+  //       QI to it here.  This would let us determine the total length
+  //       for streams that support it.  See bug 1388774.
+  Unused << GetContentLength(&mSynthesizedStreamLength);
+
+  nsresult rv = nsInputStreamPump::Create(getter_AddRefs(mPump),
+                                          mBodyReader,
+                                          0, 0, true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = mPump->AsyncRead(this, mListenerContext);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uint32_t suspendCount = mSuspendCount;
+  while (suspendCount--) {
+    mPump->Suspend();
+  }
+
+  return rv;
+}
+
+nsresult
+InterceptedHttpChannel::OpenRedirectChannel()
+{
+  nsresult rv = NS_OK;
+
+  // Make sure to do this after we received redirect veto answer,
+  // i.e. after all sinks had been notified
+  mRedirectChannel->SetOriginalURI(mOriginalURI);
+
+  // open new channel
+  if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+    MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+    rv = mRedirectChannel->AsyncOpen2(mListener);
+  }
+  else {
+    rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+  }
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mStatus = NS_BINDING_REDIRECTED;
+
+  return rv;
+}
+
+void
+InterceptedHttpChannel::MaybeCallStatusAndProgress()
+{
+  // OnStatus() and OnProgress() must only be called on the main thread.  If
+  // we are on a separate thread, then we maybe need to schedule a runnable
+  // to call them asynchronousnly.
+  if (!NS_IsMainThread()) {
+    // Check to see if we are already trying to call OnStatus/OnProgress
+    // asynchronously.  If we are, then don't queue up another runnable.
+    // We don't want to flood the main thread.
+    if (mCallingStatusAndProgress) {
+      return;
+    }
+    mCallingStatusAndProgress = true;
+
+    nsCOMPtr<nsIRunnable> r =
+      NewRunnableMethod("InterceptedHttpChannel::MaybeCallStatusAndProgress",
+                        this,
+                        &InterceptedHttpChannel::MaybeCallStatusAndProgress);
+    MOZ_ALWAYS_SUCCEEDS(
+      SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
+
+    return;
+  }
+
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // We are about to capture out progress position.  Clear the flag we use
+  // to de-duplicate progress report runnables.  We want any further progress
+  // updates to trigger another runnable.  We do this before capture the
+  // progress value since we're using atomics and not a mutex lock.
+  mCallingStatusAndProgress = false;
+
+  // Capture the current status from our atomic count.
+  int64_t progress = mProgress;
+
+  MOZ_DIAGNOSTIC_ASSERT(progress >= mProgressReported);
+
+  // Do nothing if we've already made the calls for this amount of progress
+  // or if the channel is not configured for these calls.  Note, the check
+  // for mProgressSink here means we will not fire any spurious late calls
+  // after ReleaseListeners() is executed.
+  if (progress <= mProgressReported ||
+      mCanceled ||
+      !mProgressSink ||
+      (mLoadFlags & HttpBaseChannel::LOAD_BACKGROUND)) {
+    return;
+  }
+
+  // Capture the host name on the first set of calls to avoid doing this
+  // string processing repeatedly.
+  if (mProgressReported == 0) {
+    nsAutoCString host;
+    MOZ_ALWAYS_SUCCEEDS(mURI->GetHost(host));
+    CopyUTF8toUTF16(host, mStatusHost);
+  }
+
+  mProgressSink->OnStatus(this, mListenerContext, NS_NET_STATUS_READING,
+                          mStatusHost.get());
+
+  mProgressSink->OnProgress(this, mListenerContext, progress,
+                            mSynthesizedStreamLength);
+
+  mProgressReported = progress;
+}
+
+// static
+already_AddRefed<InterceptedHttpChannel>
+InterceptedHttpChannel::CreateForInterception(PRTime aCreationTime,
+                                              const TimeStamp& aCreationTimestamp,
+                                              const TimeStamp& aAsyncOpenTimestamp)
+{
+  // Create an InterceptedHttpChannel that will trigger a FetchEvent
+  // in a ServiceWorker when opened.
+  RefPtr<InterceptedHttpChannel> ref =
+    new InterceptedHttpChannel(aCreationTime, aCreationTimestamp,
+                               aAsyncOpenTimestamp);
+
+  return ref.forget();
+}
+
+// static
+already_AddRefed<InterceptedHttpChannel>
+InterceptedHttpChannel::CreateForSynthesis(const nsHttpResponseHead* aHead,
+                                           nsIInputStream* aBody,
+                                           PRTime aCreationTime,
+                                           const TimeStamp& aCreationTimestamp,
+                                           const TimeStamp& aAsyncOpenTimestamp)
+{
+  MOZ_DIAGNOSTIC_ASSERT(aHead);
+  MOZ_DIAGNOSTIC_ASSERT(aBody);
+
+  // Create an InterceptedHttpChannel that already has a synthesized response.
+  // The synthetic response will be processed when opened.  A FetchEvent
+  // will not be triggered.
+  RefPtr<InterceptedHttpChannel> ref =
+    new InterceptedHttpChannel(aCreationTime, aCreationTimestamp,
+                               aAsyncOpenTimestamp);
+
+  ref->mBodyReader = aBody;
+  ref->mResponseHead = new nsHttpResponseHead(*aHead);
+
+  return ref.forget();
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::Cancel(nsresult aStatus)
+{
+  return CancelInterception(aStatus);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::Suspend(void)
+{
+  nsresult rv = SuspendInternal();
+
+  nsresult rvParentChannel = NS_OK;
+  if (mParentChannel) {
+    rvParentChannel = mParentChannel->SuspendMessageDiversion();
+  }
+
+  return NS_FAILED(rv) ? rv : rvParentChannel;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::Resume(void)
+{
+  nsresult rv = ResumeInternal();
+
+  nsresult rvParentChannel = NS_OK;
+  if (mParentChannel) {
+    rvParentChannel = mParentChannel->ResumeMessageDiversion();
+  }
+
+  return NS_FAILED(rv) ? rv : rvParentChannel;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetSecurityInfo(nsISupports** aSecurityInfo)
+{
+  nsCOMPtr<nsISupports> ref(mSecurityInfo);
+  ref.forget(aSecurityInfo);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext)
+{
+  if (mCanceled) {
+    return mStatus;
+  }
+
+  // We should have pre-set the AsyncOpen time based on the original channel if
+  // timings are enabled.
+  if (mTimingEnabled) {
+    MOZ_DIAGNOSTIC_ASSERT(!mAsyncOpenTime.IsNull());
+  }
+
+  mIsPending = true;
+  mListener = aListener;
+
+  mResponseCouldBeSynthesized = true;
+
+  if (mLoadGroup) {
+    mLoadGroup->AddRequest(this, nullptr);
+  }
+
+  // If we already have a synthesized body then we are pre-synthesized.
+  // This can happen for two reasons:
+  //  1. We have a pre-synthesized redirect in e10s mode.  In this case
+  //     we should follow the redirect.
+  //  2. We are handling a "fake" redirect for an opaque response.  Here
+  //     we should just process the synthetic body.
+  if (mBodyReader) {
+    if (ShouldRedirect()) {
+      return FollowSyntheticRedirect();
+    }
+
+    return StartPump();
+  }
+
+  // Otherwise we need to trigger a FetchEvent in a ServiceWorker.
+  nsCOMPtr<nsINetworkInterceptController> controller;
+  GetCallback(controller);
+
+  if (NS_WARN_IF(!controller)) {
+    Cancel(NS_ERROR_FAILURE);
+    DoNotifyListener();
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv = controller->ChannelIntercepted(this);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    Cancel(rv);
+    DoNotifyListener();
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::AsyncOpen2(nsIStreamListener* aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener(aListener);
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mStatus = rv;
+    DoNotifyListener();
+    return rv;
+  }
+  return AsyncOpen(listener, nullptr);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage)
+{
+  // Synthetic responses should not trigger CORS blocking.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetupFallbackChannel(const char*  aFallbackKey)
+{
+  // AppCache should not be used with service worker intercepted channels.
+  // This should never be called.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetResponseSynthesized(bool* aResponseSynthesized)
+{
+  *aResponseSynthesized = mResponseHead || mBodyReader;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetPriority(int32_t aPriority)
+{
+  mPriority = clamped<int32_t>(aPriority, INT16_MIN, INT16_MAX);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetClassFlags(uint32_t aClassFlags)
+{
+  mClassOfService = aClassFlags;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::ClearClassFlags(uint32_t aClassFlags)
+{
+  mClassOfService &= ~aClassFlags;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::AddClassFlags(uint32_t aClassFlags)
+{
+  mClassOfService |= aClassFlags;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::ResumeAt(uint64_t aStartPos,
+                                 const nsACString & aEntityId)
+{
+  // We don't support resuming synthesized responses, but we do track this
+  // information so it can be passed on to the resulting nsHttpChannel if
+  // ResetInterception is called.
+  mResumeStartPos = aStartPos;
+  mResumeEntityId = aEntityId;
+  return NS_OK;
+}
+
+void
+InterceptedHttpChannel::DoNotifyListenerCleanup()
+{
+  // Prefer to cleanup in ReleaseListeners() as it seems to be called
+  // more consistently in necko.
+}
+
+
+NS_IMETHODIMP
+InterceptedHttpChannel::ResetInterception(void)
+{
+  if (mCanceled) {
+    return mStatus;
+  }
+
+  uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
+
+  nsCOMPtr<nsIChannel> newChannel;
+  nsCOMPtr<nsILoadInfo> redirectLoadInfo =
+    CloneLoadInfoForRedirect(mURI, flags);
+  nsresult rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
+                                      mURI,
+                                      redirectLoadInfo,
+                                      nullptr, // aLoadGroup
+                                      nullptr, // aCallbacks
+                                      mLoadFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = SetupReplacementChannel(mURI, newChannel, true, flags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (mRedirectMode != nsIHttpChannelInternal::REDIRECT_MODE_MANUAL) {
+    nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
+    rv = newChannel->GetLoadFlags(&loadFlags);
+    NS_ENSURE_SUCCESS(rv, rv);
+    loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
+    rv = newChannel->SetLoadFlags(loadFlags);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  mRedirectChannel = newChannel.forget();
+
+  rv = gHttpHandler->AsyncOnChannelRedirect(this, mRedirectChannel, flags);
+
+  if (NS_FAILED(rv)) {
+    OnRedirectVerifyCallback(rv);
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SynthesizeStatus(uint16_t aStatus,
+                                         const nsACString& aReason)
+{
+  if (mCanceled) {
+    return mStatus;
+  }
+
+  if (!mSynthesizedResponseHead) {
+    mSynthesizedResponseHead.reset(new nsHttpResponseHead());
+  }
+
+  nsAutoCString statusLine;
+  statusLine.AppendLiteral("HTTP/1.1 ");
+  statusLine.AppendInt(aStatus);
+  statusLine.AppendLiteral(" ");
+  statusLine.Append(aReason);
+
+  mSynthesizedResponseHead->ParseStatusLine(statusLine);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SynthesizeHeader(const nsACString& aName,
+                                         const nsACString& aValue)
+{
+  if (mCanceled) {
+    return mStatus;
+  }
+
+  if (!mSynthesizedResponseHead) {
+    mSynthesizedResponseHead.reset(new nsHttpResponseHead());
+  }
+
+  nsAutoCString header = aName + NS_LITERAL_CSTRING(": ") + aValue;
+  // Overwrite any existing header.
+  nsresult rv = mSynthesizedResponseHead->ParseHeaderLine(header);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
+{
+  if (mCanceled) {
+    return mStatus;
+  }
+
+  if (mBodyWriter) {
+    mBodyWriter->Close();
+  }
+
+  if (!mSynthesizedResponseHead) {
+    mSynthesizedResponseHead.reset(new nsHttpResponseHead());
+  }
+
+  mResponseHead = mSynthesizedResponseHead.release();
+
+  if (ShouldRedirect()) {
+    return FollowSyntheticRedirect();
+  }
+
+  // Intercepted responses should already be decoded.
+  SetApplyConversion(false);
+
+  // Errors and redirects may not have a body.  Synthesize an empty string stream
+  // here so later code can be simpler.
+  if (!mBodyReader) {
+    nsresult rv = NS_NewCStringInputStream(getter_AddRefs(mBodyReader),
+                                           EmptyCString());
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  nsCOMPtr<nsIURI> responseURI;
+  if (!aFinalURLSpec.IsEmpty()) {
+    nsresult rv = NS_NewURI(getter_AddRefs(responseURI), aFinalURLSpec);
+    NS_ENSURE_SUCCESS(rv, rv);
+  } else {
+    responseURI = mURI;
+  }
+
+  bool equal = false;
+  Unused << mURI->Equals(responseURI, &equal);
+  if (!equal) {
+    return RedirectForOpaqueResponse(responseURI);
+  }
+
+  return StartPump();
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::CancelInterception(nsresult aStatus)
+{
+  if (mCanceled) {
+    return NS_OK;
+  }
+  mCanceled = true;
+
+  MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aStatus));
+  if (NS_SUCCEEDED(mStatus)) {
+    mStatus = aStatus;
+  }
+
+  if (mPump) {
+    return mPump->Cancel(mStatus);
+  }
+
+  return AsyncAbort(mStatus);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetResponseBody(nsIOutputStream** aResponseBody)
+{
+  if (!mBodyWriter) {
+    nsresult rv = NS_NewPipe(getter_AddRefs(mBodyReader),
+                             getter_AddRefs(mBodyWriter),
+                             0,          // default segment size
+                             UINT32_MAX, // infinite pipe length
+                             true,       // non-blocking reader
+                             true);      // non-blocking writer
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  nsCOMPtr<nsIOutputStream> ref(mBodyWriter);
+  ref.forget(aResponseBody);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetChannel(nsIChannel** aChannel)
+{
+  nsCOMPtr<nsIChannel> ref(this);
+  ref.forget(aChannel);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetSecureUpgradedChannelURI(nsIURI** aSecureUpgradedChannelURI)
+{
+  nsCOMPtr<nsIURI> ref(mURI);
+  ref.forget(aSecureUpgradedChannelURI);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo)
+{
+  return aChannelInfo->ResurrectInfoOnChannel(this);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetInternalContentPolicyType(nsContentPolicyType* aPolicyType)
+{
+  if (mLoadInfo) {
+    *aPolicyType = mLoadInfo->InternalContentPolicyType();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetConsoleReportCollector(nsIConsoleReportCollector** aConsoleReportCollector)
+{
+  nsCOMPtr<nsIConsoleReportCollector> ref(this);
+  ref.forget(aConsoleReportCollector);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetLaunchServiceWorkerStart(mozilla::TimeStamp* aTimeStamp)
+{
+  return HttpBaseChannel::GetLaunchServiceWorkerStart(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetLaunchServiceWorkerStart(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetLaunchServiceWorkerStart(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::GetLaunchServiceWorkerEnd(mozilla::TimeStamp* aTimeStamp)
+{
+  return HttpBaseChannel::GetLaunchServiceWorkerEnd(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetLaunchServiceWorkerEnd(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetLaunchServiceWorkerEnd(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetDispatchFetchEventStart(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetDispatchFetchEventStart(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetDispatchFetchEventEnd(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetDispatchFetchEventEnd(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetHandleFetchEventStart(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetHandleFetchEventStart(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetHandleFetchEventEnd(mozilla::TimeStamp aTimeStamp)
+{
+  return HttpBaseChannel::SetHandleFetchEventEnd(aTimeStamp);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetFinishResponseStart(mozilla::TimeStamp aTimeStamp)
+{
+  mFinishResponseStart = aTimeStamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetFinishSynthesizedResponseEnd(mozilla::TimeStamp aTimeStamp)
+{
+  MOZ_ASSERT(mSynthesizedOrReset == Invalid);
+  mSynthesizedOrReset = Synthesized;
+  mFinishResponseEnd = aTimeStamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetChannelResetEnd(mozilla::TimeStamp aTimeStamp)
+{
+  MOZ_ASSERT(mSynthesizedOrReset == Invalid);
+  mSynthesizedOrReset = Reset;
+  mFinishResponseEnd = aTimeStamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SaveTimeStamps(void)
+{
+  nsCString navigationOrSubresource = nsContentUtils::IsNonSubresourceRequest(this) ?
+    NS_LITERAL_CSTRING("navigation") : NS_LITERAL_CSTRING("subresource");
+
+  // We may have null timestamps if the fetch dispatch runnable was cancelled
+  // and we defaulted to resuming the request.
+  if (!mFinishResponseStart.IsNull() && !mFinishResponseEnd.IsNull()) {
+    Telemetry::HistogramID id = (mSynthesizedOrReset == Synthesized) ?
+      Telemetry::SERVICE_WORKER_FETCH_EVENT_FINISH_SYNTHESIZED_RESPONSE_MS :
+      Telemetry::SERVICE_WORKER_FETCH_EVENT_CHANNEL_RESET_MS;
+    Telemetry::Accumulate(id, navigationOrSubresource,
+      static_cast<uint32_t>((mFinishResponseEnd - mFinishResponseStart).ToMilliseconds()));
+  }
+
+  Telemetry::Accumulate(Telemetry::SERVICE_WORKER_FETCH_EVENT_DISPATCH_MS,
+    navigationOrSubresource,
+    static_cast<uint32_t>((mHandleFetchEventStart - mDispatchFetchEventStart).ToMilliseconds()));
+
+  if (!mFinishResponseEnd.IsNull()) {
+    Telemetry::Accumulate(Telemetry::SERVICE_WORKER_FETCH_INTERCEPTION_DURATION_MS,
+      navigationOrSubresource,
+      static_cast<uint32_t>((mFinishResponseEnd - mDispatchFetchEventStart).ToMilliseconds()));
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SetReleaseHandle(nsISupports* aHandle)
+{
+  mReleaseHandle = aHandle;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::OnRedirectVerifyCallback(nsresult rv)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_SUCCEEDED(rv)) {
+    rv = OpenRedirectChannel();
+  }
+
+  nsCOMPtr<nsIRedirectResultListener> hook;
+  GetCallback(hook);
+  if (hook) {
+    hook->OnRedirectResult(NS_SUCCEEDED(rv));
+  }
+
+  if (NS_FAILED(rv)) {
+    Cancel(rv);
+  }
+
+  mIsPending = false;
+  ReleaseListeners();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest,
+                                       nsISupports* aContext)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mProgressSink) {
+    GetCallback(mProgressSink);
+  }
+  mTransactionTimings.responseStart = TimeStamp::Now();
+  if (mListener) {
+    mListener->OnStartRequest(this, mListenerContext);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::OnStopRequest(nsIRequest* aRequest,
+                                      nsISupports* aContext,
+                                      nsresult aStatus)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (NS_SUCCEEDED(mStatus)) {
+    mStatus = aStatus;
+  }
+
+  // Its possible that we have any async runnable queued to report some
+  // progress when OnStopRequest() is triggered.  Report any left over
+  // progress immediately.  The extra runnable will then do nothing thanks
+  // to the ReleaseListeners() call below.
+  MaybeCallStatusAndProgress();
+
+  mTransactionTimings.responseEnd = TimeStamp::Now();
+
+  mIsPending = false;
+
+  // Register entry to the Performance resource timing
+  mozilla::dom::Performance* documentPerformance = GetPerformance();
+  if (documentPerformance) {
+    documentPerformance->AddEntry(this, this);
+  }
+
+  if (mListener) {
+    mListener->OnStopRequest(this, mListenerContext, mStatus);
+  }
+
+  gHttpHandler->OnStopRequest(this);
+
+  ReleaseListeners();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::OnDataAvailable(nsIRequest* aRequest,
+                                        nsISupports* aContext,
+                                        nsIInputStream* aInputStream,
+                                        uint64_t aOffset,
+                                        uint32_t aCount)
+{
+  // Any thread if the channel has been retargeted.
+
+  if (mCanceled || !mListener) {
+    // If there is no listener, we still need to drain the stream in order
+    // maintain necko invariants.
+    uint32_t unused = 0;
+    aInputStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &unused);
+    return mStatus;
+  }
+  if (mProgressSink) {
+    if (!(mLoadFlags & HttpBaseChannel::LOAD_BACKGROUND)) {
+      mProgress = aOffset + aCount;
+      MaybeCallStatusAndProgress();
+    }
+  }
+
+  return mListener->OnDataAvailable(this, mListenerContext, aInputStream,
+                                    aOffset, aCount);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::MessageDiversionStarted(ADivertableParentChannel* aParentChannel)
+{
+  MOZ_ASSERT(!mParentChannel);
+  mParentChannel = aParentChannel;
+  uint32_t suspendCount = mSuspendCount;
+  while(suspendCount--) {
+    mParentChannel->SuspendMessageDiversion();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::MessageDiversionStop()
+{
+  MOZ_ASSERT(mParentChannel);
+  mParentChannel = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::SuspendInternal()
+{
+  ++mSuspendCount;
+  if (mPump) {
+    return mPump->Suspend();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::ResumeInternal()
+{
+  --mSuspendCount;
+  if (mPump) {
+    return mPump->Resume();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::RetargetDeliveryTo(nsIEventTarget* aNewTarget)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  NS_ENSURE_ARG(aNewTarget);
+
+  // If retargeting to the main thread, do nothing.
+  if (aNewTarget->IsOnCurrentThread()) {
+    return NS_OK;
+  }
+
+  // Retargeting is only valid during OnStartRequest for nsIChannels.  So
+  // we should only be called if we have a pump.
+  if (!mPump) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  return mPump->RetargetDeliveryTo(aNewTarget);
+}
+
+NS_IMETHODIMP
+InterceptedHttpChannel::CheckListenerChain()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
+  do_QueryInterface(mListener, &rv);
+  if (retargetableListener) {
+    rv = retargetableListener->CheckListenerChain();
+  }
+  return rv;
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/InterceptedHttpChannel.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_InterceptedHttpChannel_h
+#define mozilla_net_InterceptedHttpChannel_h
+
+#include "HttpBaseChannel.h"
+#include "nsINetworkInterceptController.h"
+#include "nsIInputStream.h"
+#include "nsIChannelWithDivertableParentListener.h"
+#include "nsIThreadRetargetableRequest.h"
+
+namespace mozilla {
+namespace net {
+
+// This class represents an http channel that is being intercepted by a
+// ServiceWorker.  This means that when the channel is opened a FetchEvent
+// will be fired on the ServiceWorker thread.  The channel will complete
+// depending on what the worker does.  The options are:
+//
+// 1. If the ServiceWorker does not handle the FetchEvent or does not call
+//    FetchEvent.respondWith(), then the channel needs to fall back to a
+//    normal request.  When this happens ResetInterception() is called and
+//    the channel will perform an internal redirect back to an nsHttpChannel.
+//
+// 2. If the ServiceWorker provides a Response to FetchEvent.respondWith()
+//    then the status, headers, and body must be synthesized.  When
+//    FinishSynthesizedResponse() is called the synthesized data must be
+//    reported back to the channel listener.  This is handled in a few
+//    different ways:
+//      a. If a redirect was synthesized, then we perform the redirect to
+//         a new nsHttpChannel.  This new channel might trigger yet another
+//         interception.
+//      b. If a same-origin or CORS Response was synthesized, then we simply
+//         crate an nsInputStreamPump to process it and call back to the
+//         listener.
+//      c. If an opaque Response was synthesized, then we perform an internal
+//         redirect to a new InterceptedHttpChannel using the cross-origin URL.
+//         When this new channel is opened, it then creates a pump as in case
+//         (b).  The extra redirect here is to make sure the various listeners
+//         treat the result as unsafe cross-origin data.
+//
+// 3. If an error occurs, such as the ServiceWorker passing garbage to
+//    FetchEvent.respondWith(), then CancelInterception() is called.  This is
+//    handled the same as a normal nsIChannel::Cancel() call.  We abort the
+//    channel and end up calling OnStopRequest() with an error code.
+class InterceptedHttpChannel final : public HttpBaseChannel
+                                   , public HttpAsyncAborter<InterceptedHttpChannel>
+                                   , public nsIInterceptedChannel
+                                   , public nsIAsyncVerifyRedirectCallback
+                                   , public nsIStreamListener
+                                   , public nsIChannelWithDivertableParentListener
+                                   , public nsIThreadRetargetableRequest
+                                   , public nsIThreadRetargetableStreamListener
+{
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIINTERCEPTEDCHANNEL
+  NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_NSICHANNELWITHDIVERTABLEPARENTLISTENER
+  NS_DECL_NSITHREADRETARGETABLEREQUEST
+  NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
+
+private:
+  friend class HttpAsyncAborter<InterceptedHttpChannel>;
+
+  UniquePtr<nsHttpResponseHead> mSynthesizedResponseHead;
+  nsCOMPtr<nsIChannel> mRedirectChannel;
+  nsCOMPtr<nsIInputStream> mBodyReader;
+  nsCOMPtr<nsIOutputStream> mBodyWriter;
+  nsCOMPtr<nsISupports> mReleaseHandle;
+  nsCOMPtr<nsIProgressEventSink> mProgressSink;
+  RefPtr<nsInputStreamPump> mPump;
+  RefPtr<ADivertableParentChannel> mParentChannel;
+  TimeStamp mFinishResponseStart;
+  TimeStamp mFinishResponseEnd;
+  Atomic<int64_t> mProgress;
+  int64_t mProgressReported;
+  int64_t mSynthesizedStreamLength;
+  uint64_t mResumeStartPos;
+  nsCString mResumeEntityId;
+  nsString mStatusHost;
+  enum {
+    Invalid = 0,
+    Synthesized,
+    Reset
+  } mSynthesizedOrReset;
+  Atomic<bool> mCallingStatusAndProgress;
+
+  InterceptedHttpChannel(PRTime aCreationTime,
+                         const TimeStamp& aCreationTimestamp,
+                         const TimeStamp& aAsyncOpenTimestamp);
+  ~InterceptedHttpChannel() = default;
+
+  virtual void
+  ReleaseListeners() override;
+
+  virtual MOZ_MUST_USE nsresult
+  SetupReplacementChannel(nsIURI *aURI, nsIChannel *aChannel,
+                          bool aPreserveMethod,
+                          uint32_t aRedirectFlags) override;
+
+  bool
+  ShouldRedirect() const;
+
+  nsresult
+  FollowSyntheticRedirect();
+
+  nsresult
+  RedirectForOpaqueResponse(nsIURI* aResponseURI);
+
+  nsresult
+  StartPump();
+
+  nsresult
+  OpenRedirectChannel();
+
+  void
+  MaybeCallStatusAndProgress();
+
+public:
+  static already_AddRefed<InterceptedHttpChannel>
+  CreateForInterception(PRTime aCreationTime, const TimeStamp& aCreationTimestamp,
+                        const TimeStamp& aAsyncOpenTimestamp);
+
+  static already_AddRefed<InterceptedHttpChannel>
+  CreateForSynthesis(const nsHttpResponseHead* aHead, nsIInputStream* aBody,
+                     PRTime aCreationTime,
+                     const TimeStamp& aCreationTimestamp,
+                     const TimeStamp& aAsyncOpenTimestamp);
+
+  NS_IMETHOD
+  Cancel(nsresult aStatus) override;
+
+  NS_IMETHOD
+  Suspend(void) override;
+
+  NS_IMETHOD
+  Resume(void) override;
+
+  NS_IMETHOD
+  GetSecurityInfo(nsISupports * *aSecurityInfo) override;
+
+  NS_IMETHOD
+  AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) override;
+
+  NS_IMETHOD
+  AsyncOpen2(nsIStreamListener *aListener) override;
+
+  NS_IMETHOD
+  LogBlockedCORSRequest(const nsAString & aMessage) override;
+
+  NS_IMETHOD
+  SetupFallbackChannel(const char * aFallbackKey) override;
+
+  NS_IMETHOD
+  GetResponseSynthesized(bool *aResponseSynthesized) override;
+
+  NS_IMETHOD
+  SetPriority(int32_t aPriority) override;
+
+  NS_IMETHOD
+  SetClassFlags(uint32_t aClassFlags) override;
+
+  NS_IMETHOD
+  ClearClassFlags(uint32_t flags) override;
+
+  NS_IMETHOD
+  AddClassFlags(uint32_t flags) override;
+
+  NS_IMETHOD
+  ResumeAt(uint64_t startPos, const nsACString & entityID) override;
+
+  void
+  DoNotifyListenerCleanup() override;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_InterceptedHttpChannel_h
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -72,16 +72,17 @@ UNIFIED_SOURCES += [
     'HttpBackgroundChannelChild.cpp',
     'HttpBackgroundChannelParent.cpp',
     'HttpBaseChannel.cpp',
     'HttpChannelChild.cpp',
     'HttpChannelParent.cpp',
     'HttpChannelParentListener.cpp',
     'HttpInfo.cpp',
     'InterceptedChannel.cpp',
+    'InterceptedHttpChannel.cpp',
     'nsCORSListenerProxy.cpp',
     'nsHttp.cpp',
     'nsHttpActivityDistributor.cpp',
     'nsHttpAuthCache.cpp',
     'nsHttpAuthManager.cpp',
     'nsHttpBasicAuth.cpp',
     'nsHttpChannel.cpp',
     'nsHttpChunkedDecoder.cpp',
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -102,33 +102,31 @@
 #include "mozilla/extensions/StreamFilterParent.h"
 #include "mozilla/net/Predictor.h"
 #include "mozilla/MathAlgorithms.h"
 #include "CacheControlParser.h"
 #include "nsMixedContentBlocker.h"
 #include "HSTSPrimerListener.h"
 #include "CacheStorageService.h"
 #include "HttpChannelParent.h"
+#include "InterceptedHttpChannel.h"
 #include "nsIBufferedStreams.h"
 #include "nsIFileStreams.h"
 #include "nsIMIMEInputStream.h"
 #include "nsIMultiplexInputStream.h"
 #include "../../cache2/CacheFileUtils.h"
 
 #ifdef MOZ_TASK_TRACER
 #include "GeckoTaskTracer.h"
 #endif
 
 namespace mozilla { namespace net {
 
 namespace {
 
-// Monotonically increasing ID for generating unique cache entries per
-// intercepted channel.
-static uint64_t gNumIntercepted = 0;
 static bool sRCWNEnabled = false;
 static uint32_t sRCWNQueueSizeNormal = 50;
 static uint32_t sRCWNQueueSizePriority = 10;
 static uint32_t sRCWNSmallResourceSizeKB = 256;
 static uint32_t sRCWNMinWaitMs = 0;
 static uint32_t sRCWNMaxWaitMs = 500;
 
 // True if the local cache should be bypassed when processing a request.
@@ -303,18 +301,16 @@ AutoRedirectVetoNotifier::ReportRedirect
 
 nsHttpChannel::nsHttpChannel()
     : HttpAsyncAborter<nsHttpChannel>(this)
     , mLogicalOffset(0)
     , mPostID(0)
     , mRequestTime(0)
     , mOfflineCacheLastModifiedTime(0)
     , mSuspendTotalTime(0)
-    , mInterceptCache(DO_NOT_INTERCEPT)
-    , mInterceptionID(gNumIntercepted++)
     , mCacheOpenWithPriority(false)
     , mCacheQueueSizeWhenOpen(0)
     , mCachedContentIsValid(false)
     , mCachedContentIsPartial(false)
     , mCacheOnlyMetadata(false)
     , mTransactionReplaced(false)
     , mAuthRetryPending(false)
     , mProxyAuthPending(false)
@@ -540,16 +536,20 @@ nsHttpChannel::Connect()
     LOG(("nsHttpChannel::Connect [this=%p]\n", this));
 
     // Don't allow resuming when cache must be used
     if (mResuming && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
         LOG(("Resuming from cache is not supported yet"));
         return NS_ERROR_DOCUMENT_NOT_CACHED;
     }
 
+    if (ShouldIntercept()) {
+        return RedirectToInterceptedChannel();
+    }
+
     bool isTrackingResource = mIsTrackingResource; // is atomic
     LOG(("nsHttpChannel %p tracking resource=%d, local blocklist=%d, cos=%u",
           this, isTrackingResource, mLocalBlocklist, mClassOfService));
 
     if (isTrackingResource || mLocalBlocklist) {
         AddClassFlags(nsIClassOfService::Tail);
     }
 
@@ -643,18 +643,17 @@ nsHttpChannel::TryHSTSPriming()
             return ContinueConnect();
         }
 
         // HSTS priming requires the LoadInfo provided with AsyncOpen2
         bool requireHSTSPriming =
             mLoadInfo->GetForceHSTSPriming();
 
         if (requireHSTSPriming &&
-                nsMixedContentBlocker::sSendHSTSPriming &&
-                mInterceptCache == DO_NOT_INTERCEPT) {
+                nsMixedContentBlocker::sSendHSTSPriming) {
             if (!isHttpsScheme) {
                 rv = HSTSPrimingListener::StartHSTSPriming(this, this);
 
                 if (NS_FAILED(rv)) {
                     CloseCacheEntry(false);
                     Telemetry::Accumulate(Telemetry::MIXED_CONTENT_HSTS_PRIMING_REQUESTS,
                                       HSTSPrimingRequest::eHSTS_PRIMING_REQUEST_ERROR);
                     return rv;
@@ -803,29 +802,26 @@ nsHttpChannel::ContinueConnect()
     if (!mReqContentLengthDetermined) {
         return NS_OK;
     }
 
     // If we have had HSTS priming, we need to reevaluate whether we need
     // a CORS preflight. Bug: 1272440
     // If we need to start a CORS preflight, do it now!
     // Note that it is important to do this before the early returns below.
-    if (!mIsCorsPreflightDone && mRequireCORSPreflight &&
-        mInterceptCache != INTERCEPTED) {
+    if (!mIsCorsPreflightDone && mRequireCORSPreflight) {
         MOZ_ASSERT(!mPreflightChannel);
         nsresult rv =
             nsCORSListenerProxy::StartCORSPreflight(this, this,
                                                     mUnsafeHeaders,
                                                     getter_AddRefs(mPreflightChannel));
         return rv;
     }
 
-    MOZ_RELEASE_ASSERT(!(mRequireCORSPreflight &&
-                         mInterceptCache != INTERCEPTED) ||
-                       mIsCorsPreflightDone,
+    MOZ_RELEASE_ASSERT(!mRequireCORSPreflight || mIsCorsPreflightDone,
                        "CORS preflight must have been finished by the time we "
                        "do the rest of ContinueConnect");
 
     // we may or may not have a cache entry at this point
     if (mCacheEntry) {
         // read straight from the cache if possible...
         if (mCachedContentIsValid) {
             nsRunnableMethod<nsHttpChannel> *event = nullptr;
@@ -838,20 +834,17 @@ nsHttpChannel::ContinueConnect()
                          static_cast<uint32_t>(rv)));
                 }
             }
             rv = ReadFromCache(true);
             if (NS_FAILED(rv) && event) {
                 event->Revoke();
             }
 
-            // Don't accumulate the cache hit telemetry for intercepted channels.
-            if (mInterceptCache != INTERCEPTED) {
-                AccumulateCacheHitTelemetry(kCacheHit);
-            }
+            AccumulateCacheHitTelemetry(kCacheHit);
 
             return rv;
         }
         else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
             // the cache contains the requested resource, but it must be
             // validated before we can reuse it.  since we are not allowed
             // to hit the net, there's nothing more to do.  the document
             // is effectively not in the cache.
@@ -1568,19 +1561,17 @@ EnsureMIMEOfScript(nsIURI* aURI, nsHttpR
 }
 
 
 nsresult
 nsHttpChannel::CallOnStartRequest()
 {
     LOG(("nsHttpChannel::CallOnStartRequest [this=%p]", this));
 
-    MOZ_RELEASE_ASSERT(!(mRequireCORSPreflight &&
-                         mInterceptCache != INTERCEPTED) ||
-                       mIsCorsPreflightDone,
+    MOZ_RELEASE_ASSERT(!mRequireCORSPreflight || mIsCorsPreflightDone,
                        "CORS preflight must have been finished by the time we "
                        "call OnStartRequest");
 
     if (mOnStartRequestCalled) {
         // This can only happen when a range request loading rest of the data
         // after interrupted concurrent cache read asynchronously failed, e.g.
         // the response range bytes are not as expected or this channel has
         // been externally canceled.
@@ -2986,26 +2977,16 @@ nsHttpChannel::StartRedirectChannelToURI
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Inform consumers about this fake redirect
     mRedirectChannel = newChannel;
 
-    if (!(flags & nsIChannelEventSink::REDIRECT_STS_UPGRADE) &&
-        mInterceptCache == INTERCEPTED) {
-        // Mark the channel as intercepted in order to propagate the response URL.
-        nsCOMPtr<nsIHttpChannelInternal> httpRedirect = do_QueryInterface(mRedirectChannel);
-        if (httpRedirect) {
-            rv = httpRedirect->ForceIntercepted(mInterceptionID);
-            MOZ_ASSERT(NS_SUCCEEDED(rv));
-        }
-    }
-
     PushRedirectAsyncFunc(
         &nsHttpChannel::ContinueAsyncRedirectChannelToURI);
     rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
 
     if (NS_SUCCEEDED(rv))
         rv = WaitForRedirectCallback();
 
     if (NS_FAILED(rv)) {
@@ -3791,17 +3772,17 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
 
     if (mRequestHead.IsPost()) {
         // If the post id is already set then this is an attempt to replay
         // a post transaction via the cache.  Otherwise, we need a unique
         // post id for this transaction.
         if (mPostID == 0)
             mPostID = gHttpHandler->GenerateUniqueID();
     }
-    else if (!PossiblyIntercepted() && !mRequestHead.IsGet() && !mRequestHead.IsHead()) {
+    else if (!mRequestHead.IsGet() && !mRequestHead.IsHead()) {
         // don't use the cache for other types of requests
         return NS_OK;
     }
 
     if (mResuming) {
         // We don't support caching for requests initiated
         // via nsIResumableChannel.
         return NS_OK;
@@ -3809,17 +3790,17 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
 
     // Don't cache byte range requests which are subranges, only cache 0-
     // byte range requests.
     if (IsSubRangeRequest(mRequestHead))
         return NS_OK;
 
     // Pick up an application cache from the notification
     // callbacks if available and if we are not an intercepted channel.
-    if (!PossiblyIntercepted() && !mApplicationCache &&
+    if (!mApplicationCache &&
         mInheritApplicationCache) {
         nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
         GetCallback(appCacheContainer);
 
         if (appCacheContainer) {
             appCacheContainer->GetApplicationCache(getter_AddRefs(mApplicationCache));
         }
     }
@@ -3832,46 +3813,38 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
     nsCOMPtr<nsICacheStorage> cacheStorage;
     nsCOMPtr<nsIURI> openURI;
     if (!mFallbackKey.IsEmpty() && mFallbackChannel) {
         // This is a fallback channel, open fallback URI instead
         rv = NS_NewURI(getter_AddRefs(openURI), mFallbackKey);
         NS_ENSURE_SUCCESS(rv, rv);
     }
     else {
-        // In the case of intercepted channels, we need to construct the cache
-        // entry key based on the original URI, so that in case the intercepted
-        // channel is redirected, the cache entry key before and after the
-        // redirect is the same.
-        if (PossiblyIntercepted()) {
-            openURI = mOriginalURI;
-        } else {
-            openURI = mURI;
-        }
+        openURI = mURI;
     }
 
     RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
     if (!info) {
         return NS_ERROR_FAILURE;
     }
 
     uint32_t cacheEntryOpenFlags;
     bool offline = gIOService->IsOffline();
 
     bool maybeRCWN = false;
 
     nsAutoCString cacheControlRequestHeader;
     Unused << mRequestHead.GetHeader(nsHttp::Cache_Control, cacheControlRequestHeader);
     CacheControlParser cacheControlRequest(cacheControlRequestHeader);
-    if (cacheControlRequest.NoStore() && !PossiblyIntercepted()) {
+    if (cacheControlRequest.NoStore()) {
         goto bypassCacheEntryOpen;
     }
 
     if (offline || (mLoadFlags & INHIBIT_CACHING)) {
-        if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline && !PossiblyIntercepted()) {
+        if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) {
             goto bypassCacheEntryOpen;
         }
         cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
         mCacheEntryIsReadOnly = true;
     }
     else if (BYPASS_LOCAL_CACHE(mLoadFlags) && !mApplicationCache) {
         cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
     }
@@ -3888,20 +3861,16 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
         mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
         mRequestHead.HasHeader(nsHttp::If_Match) ||
         mRequestHead.HasHeader(nsHttp::If_Range);
 
     if (!mPostID && mApplicationCache) {
         rv = cacheStorageService->AppCacheStorage(info,
             mApplicationCache,
             getter_AddRefs(cacheStorage));
-    } else if (PossiblyIntercepted()) {
-        // The synthesized cache has less restrictions on file size and so on.
-        rv = cacheStorageService->SynthesizedCacheStorage(info,
-            getter_AddRefs(cacheStorage));
     } else if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
         rv = cacheStorageService->MemoryCacheStorage(info, // ? choose app cache as well...
             getter_AddRefs(cacheStorage));
     }
     else if (mPinCacheContent) {
         rv = cacheStorageService->PinningCacheStorage(info,
             getter_AddRefs(cacheStorage));
     }
@@ -3920,94 +3889,61 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
         (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI))
         cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
 
     // Only for backward compatibility with the old cache back end.
     // When removed, remove the flags and related code snippets.
     if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY)
         cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
 
-    if (PossiblyIntercepted()) {
-        extension.Append(nsPrintfCString("u%" PRIu64, mInterceptionID));
-    } else if (mPostID) {
+    if (mPostID) {
         extension.Append(nsPrintfCString("%d", mPostID));
     }
 
-    // If this channel should be intercepted, we do not open a cache entry for this channel
-    // until the interception process is complete and the consumer decides what to do with it.
-    if (mInterceptCache == MAYBE_INTERCEPT) {
-        DebugOnly<bool> exists;
-        MOZ_ASSERT(NS_FAILED(cacheStorage->Exists(openURI, extension, &exists)) || !exists,
-                   "The entry must not exist in the cache before we create it here");
-
-        nsCOMPtr<nsICacheEntry> entry;
-        rv = cacheStorage->OpenTruncate(openURI, extension, getter_AddRefs(entry));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        nsCOMPtr<nsINetworkInterceptController> controller;
-        GetCallback(controller);
-
-        RefPtr<InterceptedChannelChrome> intercepted =
-                new InterceptedChannelChrome(this, controller, entry);
-        intercepted->NotifyController();
+    mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
+    mCacheQueueSizeWhenOpen = CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
+
+    if (sRCWNEnabled && maybeRCWN && !mApplicationCacheForWrite) {
+        bool hasAltData = false;
+        uint32_t sizeInKb = 0;
+        rv = cacheStorage->GetCacheIndexEntryAttrs(openURI, extension,
+                                                   &hasAltData, &sizeInKb);
+
+        // We will attempt to race the network vs the cache if we've found
+        // this entry in the cache index, and it has appropriate attributes
+        // (doesn't have alt-data, and has a small size)
+        if (NS_SUCCEEDED(rv) && !hasAltData &&
+            sizeInKb < sRCWNSmallResourceSizeKB) {
+            MaybeRaceCacheWithNetwork();
+        }
+    }
+
+    if (!mCacheOpenDelay) {
+        MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread");
+        if (mNetworkTriggered) {
+            mRaceCacheWithNetwork = sRCWNEnabled;
+        }
+        rv = cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, this);
     } else {
-        if (mInterceptCache == INTERCEPTED) {
-            cacheEntryOpenFlags |= nsICacheStorage::OPEN_INTERCEPTED;
-            // Clear OPEN_TRUNCATE for the fake cache entry, since otherwise
-            // cache storage will close the current entry which breaks the
-            // response synthesis.
-            cacheEntryOpenFlags &= ~nsICacheStorage::OPEN_TRUNCATE;
-            DebugOnly<bool> exists;
-            MOZ_ASSERT(NS_SUCCEEDED(cacheStorage->Exists(openURI, extension, &exists)) && exists,
-                       "The entry must exist in the cache after we create it here");
-        }
-
-        mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
-        mCacheQueueSizeWhenOpen = CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
-
-        if (sRCWNEnabled && maybeRCWN && !mApplicationCacheForWrite &&
-            mInterceptCache != INTERCEPTED) {
-            bool hasAltData = false;
-            uint32_t sizeInKb = 0;
-            rv = cacheStorage->GetCacheIndexEntryAttrs(openURI, extension,
-                                                       &hasAltData, &sizeInKb);
-
-            // We will attempt to race the network vs the cache if we've found
-            // this entry in the cache index, and it has appropriate attributes
-            // (doesn't have alt-data, and has a small size)
-            if (NS_SUCCEEDED(rv) && !hasAltData &&
-                sizeInKb < sRCWNSmallResourceSizeKB) {
-                MaybeRaceCacheWithNetwork();
+        // We pass `this` explicitly as a parameter due to the raw pointer
+        // to refcounted object in lambda analysis.
+        mCacheOpenFunc = [openURI, extension, cacheEntryOpenFlags, cacheStorage] (nsHttpChannel* self) -> void {
+            MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread");
+            if (self->mNetworkTriggered) {
+                self->mRaceCacheWithNetwork = true;
             }
-        }
-
-        if (!mCacheOpenDelay) {
-            MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread");
-            if (mNetworkTriggered) {
-                mRaceCacheWithNetwork = sRCWNEnabled;
-            }
-            rv = cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, this);
-        } else {
-            // We pass `this` explicitly as a parameter due to the raw pointer
-            // to refcounted object in lambda analysis.
-            mCacheOpenFunc = [openURI, extension, cacheEntryOpenFlags, cacheStorage] (nsHttpChannel* self) -> void {
-                MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread");
-                if (self->mNetworkTriggered) {
-                    self->mRaceCacheWithNetwork = true;
-                }
-                cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, self);
-            };
-
-            mCacheOpenTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-            // calls nsHttpChannel::Notify after `mCacheOpenDelay` milliseconds
-            mCacheOpenTimer->InitWithCallback(this, mCacheOpenDelay, nsITimer::TYPE_ONE_SHOT);
-
-        }
-        NS_ENSURE_SUCCESS(rv, rv);
-    }
+            cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, self);
+        };
+
+        mCacheOpenTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+        // calls nsHttpChannel::Notify after `mCacheOpenDelay` milliseconds
+        mCacheOpenTimer->InitWithCallback(this, mCacheOpenDelay, nsITimer::TYPE_ONE_SHOT);
+
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
 
 bypassCacheEntryOpen:
     if (!mApplicationCacheForWrite)
         return NS_OK;
 
     // If there is an app cache to write to, open the entry right now in parallel.
@@ -4219,17 +4155,17 @@ nsHttpChannel::OnCacheEntryCheck(nsICach
             }
 
             if (size == 0 && mCacheOnlyMetadata) {
                 // Don't break cache entry load when the entry's data size
                 // is 0 and mCacheOnlyMetadata flag is set. In that case we
                 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
                 // also set.
                 MOZ_ASSERT(mLoadFlags & LOAD_ONLY_IF_MODIFIED);
-            } else if (mInterceptCache != INTERCEPTED) {
+            } else {
                 return rv;
             }
         }
     }
 
     bool isHttps = false;
     rv = mURI->SchemeIs("https", &isHttps);
     NS_ENSURE_SUCCESS(rv,rv);
@@ -4320,20 +4256,16 @@ nsHttpChannel::OnCacheEntryCheck(nsICach
         LOG(("Redirection-chain %s key %s\n",
              doValidation ? "contains" : "does not contain", cacheKey.get()));
 
         // Append cacheKey if not in the chain already
         if (!doValidation)
             mRedirectedCachekeys->AppendElement(cacheKey);
     }
 
-    if (doValidation && mInterceptCache == INTERCEPTED) {
-        doValidation = false;
-    }
-
     mCachedContentIsValid = !doValidation;
 
     if (doValidation) {
         //
         // now, we are definitely going to issue a HTTP request to the server.
         // make it conditional if possible.
         //
         // do not attempt to validate no-store content, since servers will not
@@ -5647,27 +5579,16 @@ nsHttpChannel::SetupReplacementChannel(n
         nsCOMPtr<nsIResumableChannel> resumableChannel(do_QueryInterface(newChannel));
         if (!resumableChannel) {
             NS_WARNING("Got asked to resume, but redirected to non-resumable channel!");
             return NS_ERROR_NOT_RESUMABLE;
         }
         resumableChannel->ResumeAt(mStartPos, mEntityID);
     }
 
-    if (!(redirectFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE) &&
-        mInterceptCache != INTERCEPTED &&
-        mRedirectMode != nsIHttpChannelInternal::REDIRECT_MODE_MANUAL) {
-      nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
-      rv = newChannel->GetLoadFlags(&loadFlags);
-      NS_ENSURE_SUCCESS(rv, rv);
-      loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
-      rv = newChannel->SetLoadFlags(loadFlags);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
     return NS_OK;
 }
 
 nsresult
 nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType)
 {
     LOG(("nsHttpChannel::AsyncProcessRedirection [this=%p type=%u]\n",
         this, redirectType));
@@ -6159,21 +6080,16 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
         mListenerContext = context;
         MOZ_DIAGNOSTIC_ASSERT(!mOnTailUnblock);
         mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
 
         LOG(("  put on hold until tail is unblocked"));
         return NS_OK;
     }
 
-    if (mInterceptCache != INTERCEPTED && ShouldIntercept()) {
-        mInterceptCache = MAYBE_INTERCEPT;
-        SetCouldBeSynthesized();
-    }
-
     // Remember the cookie header that was set, if any
     nsAutoCString cookieHeader;
     if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))) {
         mUserSetCookieHeader = cookieHeader;
     }
 
     AddCookiesToRequest();
 
@@ -6688,31 +6604,16 @@ nsHttpChannel::SetupFallbackChannel(cons
          this, aFallbackKey));
     mFallbackChannel = true;
     mFallbackKey = aFallbackKey;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHttpChannel::ForceIntercepted(uint64_t aInterceptionID)
-{
-    ENSURE_CALLED_BEFORE_ASYNC_OPEN();
-
-    if (NS_WARN_IF(mLoadFlags & LOAD_BYPASS_SERVICE_WORKER)) {
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    MarkIntercepted();
-    mResponseCouldBeSynthesized = true;
-    mInterceptionID = aInterceptionID;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload)
 {
   if (aChannelIsForDownload) {
     AddClassFlags(nsIClassOfService::Throttleable);
   } else {
     ClearClassFlags(nsIClassOfService::Throttleable);
   }
 
@@ -8675,27 +8576,21 @@ nsHttpChannel::SetNotificationCallbacks(
 
     nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
     if (NS_SUCCEEDED(rv)) {
         UpdateAggregateCallbacks();
     }
     return rv;
 }
 
-void
-nsHttpChannel::MarkIntercepted()
-{
-    mInterceptCache = INTERCEPTED;
-}
-
 NS_IMETHODIMP
 nsHttpChannel::GetResponseSynthesized(bool* aSynthesized)
 {
     NS_ENSURE_ARG_POINTER(aSynthesized);
-    *aSynthesized = (mInterceptCache == INTERCEPTED);
+    *aSynthesized = false;
     return NS_OK;
 }
 
 bool
 nsHttpChannel::AwaitingCacheCallbacks()
 {
     return mCacheEntriesToWaitFor != 0;
 }
@@ -9572,10 +9467,55 @@ nsHttpChannel::SetWarningReporter(HttpCh
 
 HttpChannelSecurityWarningReporter*
 nsHttpChannel::GetWarningReporter()
 {
     LOG(("nsHttpChannel [this=%p] GetWarningReporter [%p]", this, mWarningReporter.get()));
     return mWarningReporter.get();
 }
 
+nsresult
+nsHttpChannel::RedirectToInterceptedChannel()
+{
+    nsCOMPtr<nsINetworkInterceptController> controller;
+    GetCallback(controller);
+
+    RefPtr<InterceptedHttpChannel> intercepted =
+      InterceptedHttpChannel::CreateForInterception(mChannelCreationTime,
+                                                    mChannelCreationTimestamp,
+                                                    mAsyncOpenTime);
+
+    nsresult rv =
+      intercepted->Init(mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
+                        mProxyResolveFlags, mProxyURI, mChannelId);
+
+    nsCOMPtr<nsILoadInfo> redirectLoadInfo =
+      CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
+    intercepted->SetLoadInfo(redirectLoadInfo);
+
+    rv = SetupReplacementChannel(mURI, intercepted, true,
+                                 nsIChannelEventSink::REDIRECT_INTERNAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mRedirectChannel = intercepted;
+
+    PushRedirectAsyncFunc(
+        &nsHttpChannel::ContinueAsyncRedirectChannelToURI);
+
+    rv = gHttpHandler->AsyncOnChannelRedirect(this, intercepted,
+                                              nsIChannelEventSink::REDIRECT_INTERNAL);
+
+    if (NS_SUCCEEDED(rv)) {
+        rv = WaitForRedirectCallback();
+    }
+
+    if (NS_FAILED(rv)) {
+        AutoRedirectVetoNotifier notifier(this);
+
+        PopRedirectAsyncFunc(
+            &nsHttpChannel::ContinueAsyncRedirectChannelToURI);
+    }
+
+    return rv;
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -160,17 +160,16 @@ public:
     // nsIChannel
     NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override;
     NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) override;
     NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener) override;
     // nsIHttpChannel
     NS_IMETHOD GetEncodedBodySize(uint64_t *aEncodedBodySize) override;
     // nsIHttpChannelInternal
     NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
-    NS_IMETHOD ForceIntercepted(uint64_t aInterceptionID) override;
     NS_IMETHOD SetChannelIsForDownload(bool aChannelIsForDownload) override;
     // nsISupportsPriority
     NS_IMETHOD SetPriority(int32_t value) override;
     // nsIClassOfService
     NS_IMETHOD SetClassFlags(uint32_t inFlags) override;
     NS_IMETHOD AddClassFlags(uint32_t inFlags) override;
     NS_IMETHOD ClearClassFlags(uint32_t inFlags) override;
 
@@ -198,37 +197,16 @@ public:
     NS_IMETHOD LogBlockedCORSRequest(const nsAString& aMessage) override;
 
     void SetWarningReporter(HttpChannelSecurityWarningReporter *aReporter);
     HttpChannelSecurityWarningReporter* GetWarningReporter();
 public: /* internal necko use only */
 
     using InitLocalBlockListCallback = std::function<void(bool)>;
 
-    void InternalSetUploadStream(nsIInputStream *uploadStream)
-      { mUploadStream = uploadStream; }
-    void SetUploadStreamHasHeaders(bool hasHeaders)
-      { mUploadStreamHasHeaders = hasHeaders; }
-
-    MOZ_MUST_USE nsresult
-    SetReferrerWithPolicyInternal(nsIURI *referrer, uint32_t referrerPolicy) {
-        nsAutoCString spec;
-        nsresult rv = referrer->GetAsciiSpec(spec);
-        if (NS_FAILED(rv)) return rv;
-        mReferrer = referrer;
-        mReferrerPolicy = referrerPolicy;
-        rv = mRequestHead.SetHeader(nsHttp::Referer, spec);
-        return rv;
-    }
-
-    MOZ_MUST_USE nsresult SetTopWindowURI(nsIURI* aTopWindowURI) {
-        mTopWindowURI = aTopWindowURI;
-        return NS_OK;
-    }
-
     uint32_t GetRequestTime() const
     {
         return mRequestTime;
     }
 
     MOZ_MUST_USE nsresult OpenCacheEntry(bool usingSSL);
     MOZ_MUST_USE nsresult ContinueConnect();
 
@@ -280,17 +258,16 @@ public: /* internal necko use only */
         mChannel->mCacheEntriesToWaitFor &= mKeep;
       }
 
     private:
       nsHttpChannel* mChannel;
       uint32_t mKeep : 2;
     };
 
-    void MarkIntercepted();
     NS_IMETHOD GetResponseSynthesized(bool* aSynthesized) override;
     bool AwaitingCacheCallbacks();
     void SetCouldBeSynthesized();
 
     // Return true if the latest ODA is invoked by mCachePump.
     // Should only be called on the same thread as ODA.
     bool IsReadingFromCache() const { return mIsReadingFromCache; }
 
@@ -515,16 +492,20 @@ private:
     void MaybeWarnAboutAppCache();
 
     void SetLoadGroupUserAgentOverride();
 
     void SetDoNotTrack();
 
     already_AddRefed<nsChannelClassifier> GetOrCreateChannelClassifier();
 
+    // Start an internal redirect to a new InterceptedHttpChannel which will
+    // resolve in firing a ServiceWorker FetchEvent.
+    MOZ_MUST_USE nsresult RedirectToInterceptedChannel();
+
 private:
     // this section is for main-thread-only object
     // all the references need to be proxy released on main thread.
     nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite;
     // auth specific data
     nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
     nsCOMPtr<nsIURI> mRedirectURI;
     nsCOMPtr<nsIChannel> mRedirectChannel;
@@ -570,30 +551,16 @@ private:
     mozilla::TimeStamp                mOnStartRequestTimestamp;
     // Timestamp of the time the cnannel was suspended.
     mozilla::TimeStamp                mSuspendTimestamp;
     mozilla::TimeStamp                mOnCacheEntryCheckTimestamp;
     // Total time the channel spent suspended. This value is reported to
     // telemetry in nsHttpChannel::OnStartRequest().
     uint32_t                          mSuspendTotalTime;
 
-    // States of channel interception
-    enum {
-        DO_NOT_INTERCEPT,  // no interception will occur
-        MAYBE_INTERCEPT,   // interception in progress, but can be cancelled
-        INTERCEPTED,       // a synthesized response has been provided
-    } mInterceptCache;
-    // ID of this channel for the interception purposes. Unique unless this
-    // channel is replacing an intercepted one via an redirection.
-    uint64_t mInterceptionID;
-
-    bool PossiblyIntercepted() {
-        return mInterceptCache != DO_NOT_INTERCEPT;
-    }
-
     // If the channel is associated with a cache, and the URI matched
     // a fallback namespace, this will hold the key for the fallback
     // cache entry.
     nsCString                         mFallbackKey;
 
     friend class AutoRedirectVetoNotifier;
     friend class HttpAsyncAborter<nsHttpChannel>;
 
--- a/netwerk/protocol/http/nsIHttpChannelInternal.idl
+++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl
@@ -220,23 +220,16 @@ interface nsIHttpChannelInternal : nsISu
      * An opaque flags for non-standard behavior of the TLS system.
      * It is unlikely this will need to be set outside of telemetry studies
      * relating to the TLS implementation.
      */
     [must_use] attribute unsigned long tlsFlags;
 
     [must_use] readonly attribute PRTime lastModifiedTime;
 
-    /**
-     * Force a channel that has not been AsyncOpen'ed to skip any check for possible
-     * interception and proceed immediately to open a previously-synthesized cache
-     * entry using the provided ID.
-     */
-    [must_use] void forceIntercepted(in uint64_t aInterceptionID);
-
     [must_use] readonly attribute boolean responseSynthesized;
 
     /**
      * Set by nsCORSListenerProxy if credentials should be included in
      * cross-origin requests. false indicates "same-origin", users should still
      * check flag LOAD_ANONYMOUS!
      */
     [must_use] attribute boolean corsIncludeCredentials;
--- a/netwerk/streamconv/converters/ParseFTPList.cpp
+++ b/netwerk/streamconv/converters/ParseFTPList.cpp
@@ -5,21 +5,24 @@
 
 #include "ParseFTPList.h"
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include "plstr.h"
 #include "nsDebug.h"
 #include "prprf.h"
+#include "mozilla/CheckedInt.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Sprintf.h"
 
 /* ==================================================================== */
 
+using mozilla::CheckedInt;
+
 static inline int ParsingFailed(struct list_state *state)
 {
   if (state->parsed_one || state->lstyle) /* junk if we fail to parse */
     return '?';      /* this time but had previously parsed successfully */
   return '"';        /* its part of a comment or error message */
 }
 
 int ParseFTPList(const char *line, struct list_state *state,
@@ -1187,24 +1190,27 @@ int ParseFTPList(const char *line, struc
 
         result->fe_fnlen = (&(line[linelen]))
                            - (result->fe_fname);
 
         if (result->fe_type == 'l' && result->fe_fnlen > 4)
         {
           /* First try to use result->fe_size to find " -> " sequence.
              This can give proper result for cases like "aaa -> bbb -> ccc". */
-          uint32_t fe_size = atoi(result->fe_size);
+          uintptr_t fe_size = atoi(result->fe_size);
+          CheckedInt<uintptr_t> arrow_start(result->fe_fnlen);
+          arrow_start -= fe_size;
+          arrow_start -= 4;
 
-          if (result->fe_fnlen > (fe_size + 4) &&
-              PL_strncmp(result->fe_fname + result->fe_fnlen - fe_size - 4 , " -> ", 4) == 0)
+          if (arrow_start.isValid() &&
+              PL_strncmp(result->fe_fname + arrow_start.value(), " -> ", 4) == 0)
           {
             result->fe_lname = result->fe_fname + (result->fe_fnlen - fe_size);
             result->fe_lnlen = (&(line[linelen])) - (result->fe_lname);
-            result->fe_fnlen -= fe_size + 4;
+            result->fe_fnlen = arrow_start.value();
           }
           else
           {
             /* Search for sequence " -> " from the end for case when there are
                more occurrences. F.e. if ftpd returns "a -> b -> c" assume
                "a -> b" as a name. Powerusers can remove unnecessary parts
                manually but there is no way to follow the link when some
                essential part is missing. */
--- a/netwerk/test/unit/test_idn_urls.js
+++ b/netwerk/test/unit/test_idn_urls.js
@@ -295,16 +295,19 @@ const testcases = [
     ["䕮䕵䕶䕱.中国123", "xn--google.xn--123-u68dy61b",           false, true,  true],
     ["xn--accountlogin.䕮䕵䕶䕱", "xn--accountlogin.xn--google", false, true,  true],
     ["䕮䕵䕶䕱.xn--accountlogin", "xn--google.xn--accountlogin", false, true,  true],
 
     // Arabic diacritic not allowed in Latin text (bug 1370497)
     ["goo\u0650gle", "xn--google-yri", false, false, false],
     // ...but Arabic diacritics are allowed on Arabic text
     ["العَرَبِي", "xn--mgbc0a5a6cxbzabt", false, true, true],
+
+    // Hebrew diacritic also not allowed in Latin text (bug 1404349)
+    ["goo\u05b4gle", "xn--google-rvh", false, false, false],
 ];
 
 const profiles = ["ASCII", "high", "moderate"];
 
 function run_test() {
     var pbi = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
     var oldProfile = pbi.getCharPref("network.IDN.restriction_profile", "moderate");
     var oldWhitelistCom = pbi.getBoolPref("network.IDN.whitelist.com", false);
--- a/netwerk/test/unit/test_synthesized_response.js
+++ b/netwerk/test/unit/test_synthesized_response.js
@@ -178,29 +178,29 @@ add_test(function() {
   });
   chan.asyncOpen2(new ChannelListener(handle_synthesized_response, null,
 				     CL_ALLOW_UNKNOWN_CL | CL_SUSPEND | CL_EXPECT_3S_DELAY));
 });
 
 // ensure that the intercepted channel can be cancelled
 add_test(function() {
   var chan = make_channel(URL + '/body', null, function(intercepted) {
-    intercepted.cancel(Cr.NS_BINDING_ABORTED);
+    intercepted.cancelInterception(Cr.NS_BINDING_ABORTED);
   });
   chan.asyncOpen2(new ChannelListener(run_next_test, null, CL_EXPECT_FAILURE));
 });
 
 // ensure that the channel can't be cancelled via nsIInterceptedChannel after making a decision
 add_test(function() {
   var chan = make_channel(URL + '/body', null, function(chan) {
     chan.resetInterception();
     do_timeout(0, function() {
       var gotexception = false;
       try {
-        chan.cancel();
+        chan.cancelInterception();
       } catch (x) {
         gotexception = true;
       }
       do_check_true(gotexception);
     });
   });
   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 });
--- a/python/mozbuild/mozbuild/action/test_archive.py
+++ b/python/mozbuild/mozbuild/action/test_archive.py
@@ -365,16 +365,22 @@ ARCHIVE_FILES = {
         }
     ],
     'talos': [
         {
             'source': buildconfig.topsrcdir,
             'base': 'testing',
             'pattern': 'talos/**',
         },
+        {
+            'source': buildconfig.topsrcdir,
+            'base': 'third_party/speedometer',
+            'pattern': '**',
+            'dest': 'talos/talos/tests/speedometer/',
+        },
     ],
     'awsy': [
         {
             'source': buildconfig.topsrcdir,
             'base': 'testing',
             'pattern': 'awsy/**',
         },
     ],
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1135,9 +1135,9 @@ static const TransportSecurityPreload kP
   { "za.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
   { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
 };
 
 // Pinning Preload List Length = 479;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1515995399924000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1516038167454000);
--- a/security/manager/ssl/nsCertOverrideService.h
+++ b/security/manager/ssl/nsCertOverrideService.h
@@ -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/. */
 
 #ifndef nsCertOverrideService_h
 #define nsCertOverrideService_h
 
+#include "mozilla/Move.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TypedEnumBits.h"
 #include "nsICertOverrideService.h"
 #include "nsIFile.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 #include "nsWeakReference.h"
@@ -74,20 +75,20 @@ class nsCertOverrideEntry final : public
     typedef const char* KeyType;
     typedef const char* KeyTypePointer;
 
     // do nothing with aHost - we require mHead to be set before we're live!
     explicit nsCertOverrideEntry(KeyTypePointer aHostWithPortUTF8)
     {
     }
 
-    nsCertOverrideEntry(const nsCertOverrideEntry& toCopy)
+    nsCertOverrideEntry(nsCertOverrideEntry&& toMove)
+      : mSettings(mozilla::Move(toMove.mSettings))
+      , mHostWithPort(mozilla::Move(toMove.mHostWithPort))
     {
-      mSettings = toCopy.mSettings;
-      mHostWithPort = toCopy.mHostWithPort;
     }
 
     ~nsCertOverrideEntry()
     {
     }
 
     KeyType GetKey() const
     {
--- a/security/manager/ssl/nsClientAuthRemember.h
+++ b/security/manager/ssl/nsClientAuthRemember.h
@@ -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/. */
 
 #ifndef __NSCLIENTAUTHREMEMBER_H__
 #define __NSCLIENTAUTHREMEMBER_H__
 
+#include "mozilla/Move.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsTHashtable.h"
 #include "nsIObserver.h"
 #include "nsIX509Cert.h"
 #include "nsNSSCertificate.h"
 #include "nsString.h"
 #include "nsWeakReference.h"
 #include "mozilla/Attributes.h"
@@ -57,19 +58,20 @@ class nsClientAuthRememberEntry final : 
     typedef const char* KeyType;
     typedef const char* KeyTypePointer;
 
     // do nothing with aHost - we require mHead to be set before we're live!
     explicit nsClientAuthRememberEntry(KeyTypePointer aHostWithCertUTF8)
     {
     }
 
-    nsClientAuthRememberEntry(const nsClientAuthRememberEntry& aToCopy)
+    nsClientAuthRememberEntry(nsClientAuthRememberEntry&& aToMove)
+      : mSettings(mozilla::Move(aToMove.mSettings))
+      , mEntryKey(mozilla::Move(aToMove.mEntryKey))
     {
-      mSettings = aToCopy.mSettings;
     }
 
     ~nsClientAuthRememberEntry()
     {
     }
 
     KeyType GetKey() const
     {
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -4,238 +4,219 @@ 360live.fr: could not connect to host
 47tech.com: could not connect to host
 4loc.us: could not connect to host
 4x4.lk: could not connect to host
 724go.com: could not connect to host
 8560.be: could not connect to host
 8887999.com: could not connect to host
 91-freedom.com: could not connect to host
 aamwa.com: could not connect to host
-abcdef.be: could not connect to host
 abolition.co: could not connect to host
 acrossgw.com: could not connect to host
 aevpn.org: could not connect to host
 aivd.lol: could not connect to host
 akul.co.in: could not connect to host
+alexandros.io: could not connect to host
+alltubedownload.net: could not connect to host
 altestore.com: could not connect to host
 amua.fr: could not connect to host
 annetaan.fi: could not connect to host
 arent.kz: could not connect to host
 arox.eu: could not connect to host
 assdecoeur.org: could not connect to host
 astral.gq: could not connect to host
-avi9526.pp.ua: could not connect to host
 aviv.nyc: could not connect to host
 azabani.com: could not connect to host
 backschues.com: could not connect to host
 backschues.net: could not connect to host
 balonmano.co: could not connect to host
 bbdos.ru: could not connect to host
 beamitapp.com: could not connect to host
 berna.fr: could not connect to host
 bianinapiccanovias.com: could not connect to host
 bilder-designs.de: could not connect to host
-binsp.net: could not connect to host
 bip.gov.sa: could not connect to host
 black-khat.com: could not connect to host
 blumen-garage.de: could not connect to host
 brettabel.com: could not connect to host
-brooke-fan.com: could not connect to host
 buyshoe.org: could not connect to host
 by1898.com: could not connect to host
 cais.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 cake-time.co.uk: could not connect to host
 capekeen.com: could not connect to host
-capellidipremoli.com: could not connect to host
 casperpanel.com: could not connect to host
-cbdev.de: could not connect to host
 chattergalerie.eu: could not connect to host
 chattergallery.com: could not connect to host
-chez-janine.de: could not connect to host
 chloehorler.com: could not connect to host
 chonghe.org: could not connect to host
 christina-quast.de: could not connect to host
 cielly.com: could not connect to host
-cigoteket.se: could not connect to host
 cirfi.com: could not connect to host
 clearviewwealthprojector.com.au: could not connect to host
 cloudbased.info: could not connect to host
 cloudbleed.info: could not connect to host
 cmpr.es: could not connect to host
 cnlic.com: could not connect to host
 colleencornez.com: could not connect to host
 cosirex.com: could not connect to host
 cpaneltips.com: could not connect to host
 csgo77.com: could not connect to host
-customerbox.ir: could not connect to host
 cyberxpert.nl: could not connect to host
 cypherpunk.ws: could not connect to host
 czlx.co: could not connect to host
-d-bood.site: could not connect to host
 dahlberg.cologne: could not connect to host
+danielalvarez.net: could not connect to host
+danonsecurity.com: could not connect to host
 datorb.com: could not connect to host
+dawnson.is: could not connect to host
 dcc.moe: could not connect to host
 de-servers.de: could not connect to host
 decoyrouting.com: could not connect to host
 derivativeshub.pro: could not connect to host
 deutschland-dsl.de: could not connect to host
 dev-talk.eu: could not connect to host
 digioccumss.ddns.net: could not connect to host
 dijks.com: could not connect to host
 dingcc.xyz: could not connect to host
 disco-crazy-world.de: could not connect to host
 dkravchenko.su: could not connect to host
 donotspellitgav.in: could not connect to host
-dopply.com: could not connect to host
 dreizwosechs.de: could not connect to host
 drkmtrx.xyz: could not connect to host
-drlazarina.net: could not connect to host
 duch.cloud: could not connect to host
+duelsow.eu: could not connect to host
 duo.money: could not connect to host
+dutchweballiance.nl: could not connect to host
 dyeager.org: could not connect to host
+economy.st: could not connect to host
 ectora.com: could not connect to host
 edit.yahoo.com: could not connect to host
 educatoys.com.br: could not connect to host
 ehuber.info: could not connect to host
 endlessdiy.ca: could not connect to host
 estan.cn: could not connect to host
 eurostrategy.vn.ua: could not connect to host
 evony.eu: could not connect to host
-faxite.com: could not connect to host
-fernangp.com: could not connect to host
 ficklenote.net: could not connect to host
 filhomes.ph: could not connect to host
 firebaseio.com: could not connect to host
 firexarxa.de: could not connect to host
 fixate.ru: could not connect to host
 fixmyglitch.com: could not connect to host
 fossewayflowers.co.uk: could not connect to host
 fossewayflowers.com: could not connect to host
 foxmay.co.uk: could not connect to host
-fuckav.ru: could not connect to host
 fukuko.biz: could not connect to host
-fukuoka-cityliner.jp: could not connect to host
+fukuko.xyz: could not connect to host
 fuliydys.com: could not connect to host
 funfunmstdn.tokyo: could not connect to host
 funideas.org: could not connect to host
 funksteckdosen24.de: could not connect to host
 fyol.pw: could not connect to host
 g4w.co: could not connect to host
 gam3rs.de: could not connect to host
 gdevpenze.ru: could not connect to host
-getcolq.com: could not connect to host
 getwarden.net: could not connect to host
 gevaulug.fr: could not connect to host
 gfoss.gr: could not connect to host
 globalgivingtime.com: could not connect to host
 gmantra.org: could not connect to host
-gongjuhao.com: could not connect to host
 google: could not connect to host
 gottfridsberg.org: could not connect to host
+gra2.com: could not connect to host
+gradsm-ci.net: could not connect to host
 gritte.net: could not connect to host
+gtdgo.com: could not connect to host
 gvt2.com: could not connect to host
 gvt3.com: could not connect to host
 happygadget.me: could not connect to host
 heijblok.com: could not connect to host
 here.ml: could not connect to host
 hg881.com: could not connect to host
 hoodoo.io: could not connect to host
 hoodoo.tech: could not connect to host
 hopesb.org: could not connect to host
 hostam.link: could not connect to host
 hukkatavara.com: could not connect to host
 ifxnet.com: could not connect to host
-im-design.com.ua: could not connect to host
+ikwilthepiratebay.org: could not connect to host
+imouyang.com: could not connect to host
 industreiler.com: could not connect to host
 industreiler.com.br: could not connect to host
 inexpensivecomputers.net: could not connect to host
-injust.me: could not connect to host
 ipv6.watch: could not connect to host
 iskai.net: could not connect to host
 islief.com: could not connect to host
 isoroc-nidzica.pl: could not connect to host
 jaredfraser.com: could not connect to host
 javascriptlab.fr: could not connect to host
 jeffreymagee.com: could not connect to host
 jhburton.co.uk: could not connect to host
 jie.dance: could not connect to host
-jimmynelson.com: could not connect to host
 johnblackbourn.com: could not connect to host
 just-pools.co.za: could not connect to host
 justmy.website: could not connect to host
+kabus.org: could not connect to host
 kamikaichimaru.com: could not connect to host
 kapo.info: could not connect to host
-kappit.dk: could not connect to host
 kenrogers.co: could not connect to host
-kevinmeijer.nl: could not connect to host
 kieranweightman.me: could not connect to host
 knapp.noip.me: could not connect to host
-knep.me: could not connect to host
 kostya.net: could not connect to host
 kousaku.jp: could not connect to host
 kozmik.co: could not connect to host
 kteen.info: could not connect to host
+kuoruan.com: could not connect to host
 lacasa.fr: could not connect to host
 lathamlabs.com: could not connect to host
 lathamlabs.net: could not connect to host
 lathamlabs.org: could not connect to host
 lcht.ch: could not connect to host
 legitaxi.com: could not connect to host
 leninalbertop.com.ve: could not connect to host
 lezdomsm.com: could not connect to host
 lheinrich.org: could not connect to host
 libscode.com: could not connect to host
 linksanitizer.com: could not connect to host
+lipex.com: could not connect to host
 littleservice.cn: could not connect to host
 livnev.me: could not connect to host
 logcat.info: could not connect to host
 logimagine.com: could not connect to host
 luav.org: could not connect to host
-lukas-oppermann.de: could not connect to host
-lukasoppermann.com: could not connect to host
-lukasoppermann.de: could not connect to host
 lunix.io: could not connect to host
-maartenterpstra.xyz: could not connect to host
 macedopesca.com.br: could not connect to host
-markprof.ru: could not connect to host
 martin-mattel.com: could not connect to host
 martinrogalla.com: could not connect to host
-mastodon.top: could not connect to host
 mattferderer.com: could not connect to host
 mc-team.org: could not connect to host
 mcdanieldevelopmentservices.com: could not connect to host
 mcea-hld.jp: could not connect to host
 mchopkins.net: could not connect to host
-mesvt.com: could not connect to host
 metachris.com: could not connect to host
 mingy.ddns.net: could not connect to host
 mmstick.tk: could not connect to host
 modded-minecraft-server-list.com: could not connect to host
-moderntld.net: could not connect to host
 montage-kaika.de: could not connect to host
 mosaique-lachenaie.fr: could not connect to host
-muahahahaha.co.uk: could not connect to host
-muga.space: could not connect to host
 muh.io: could not connect to host
 muj-svet.cz: could not connect to host
 multimedia-pool.com: could not connect to host
 munduch.cz: could not connect to host
-myday.eu.com: could not connect to host
 navdeep.ca: could not connect to host
-nba2k.cn: could not connect to host
-nba2k.com.cn: could not connect to host
-nbalive.cn: could not connect to host
 ncdesigns-studio.com: could not connect to host
 necesitodinero.org: could not connect to host
+nedcf.org.uk: could not connect to host
 negai.moe: could not connect to host
 nevolution.me: could not connect to host
 nginxyii.tk: could not connect to host
-nicic.gov: could not connect to host
 nikolasbradshaw.com: could not connect to host
+nnote.net: could not connect to host
 nostraspace.com: could not connect to host
+noxlogic.nl: could not connect to host
 nqesh.com: could not connect to host
 nsbfalconacademy.org: could not connect to host
 nup.pw: could not connect to host
 oliverspringer.eu: could not connect to host
 onewebdev.info: could not connect to host
 onstud.com: could not connect to host
 opengg.me: could not connect to host
 optimist.bg: could not connect to host
@@ -254,104 +235,100 @@ persjrp.ca: could not connect to host
 persoform.ch: could not connect to host
 picallo.es: could not connect to host
 pkov.cz: could not connect to host
 plaasprodukte.com: could not connect to host
 polit.im: could not connect to host
 poolinstallers.co.za: could not connect to host
 pouets.ovh: could not connect to host
 projectasterk.com: could not connect to host
-projectunity.io: could not connect to host
 proxydesk.eu: could not connect to host
+psylab.cc: could not connect to host
+psylab.vip: could not connect to host
+pythia.nz: could not connect to host
 qionouu.cn: could not connect to host
 qto.net: could not connect to host
 quantumfurball.net: could not connect to host
 rainbin.com: could not connect to host
 real-compare.com: could not connect to host
+refactor.zone: could not connect to host
 reignsphere.net: could not connect to host
 reinaertvandecruys.me: could not connect to host
-rezexpert.com: could not connect to host
-rfeif.org: could not connect to host
 rolodato.com: could not connect to host
 sallysubs.com: could not connect to host
 sanatrans.com: could not connect to host
-santojuken.co.jp: could not connect to host
 sarndipity.com: could not connect to host
 schlachter.ca: could not connect to host
 security201.co.uk: could not connect to host
 securitymap.wiki: could not connect to host
 semantheme.fr: could not connect to host
 shadowplus.net: could not connect to host
 shadowrocket.net: could not connect to host
+sharekey.com: could not connect to host
 sharevari.com: could not connect to host
 shavingks.com: could not connect to host
 shirakaba-cc.com: could not connect to host
 simbolo.co.uk: could not connect to host
 simonkjellberg.com: could not connect to host
-simphony.cz: could not connect to host
 simplerses.com: could not connect to host
 slaughterhouse.fr: could not connect to host
 socialworkout.com: could not connect to host
 socialworkout.net: could not connect to host
 socialworkout.org: could not connect to host
 socialworkout.tv: could not connect to host
-sotiran.com: could not connect to host
+sonic.sk: could not connect to host
 soubriquet.org: could not connect to host
 soulema.com: could not connect to host
 spicywombat.com: could not connect to host
 sputnik1net.org: could not connect to host
 sss3s.com: could not connect to host
+stadionmanager.com: could not connect to host
 stitthappens.com: could not connect to host
 stytt.com: could not connect to host
 surdam.casa: could not connect to host
 sviz.pro: could not connect to host
 taberu-fujitsubo.com: could not connect to host
 taidu.news: could not connect to host
 taskotron.stg.fedoraproject.org: could not connect to host
-tcpweb.net: could not connect to host
 tech-blog.fr: could not connect to host
+techademy.nl: could not connect to host
 tenispopular.com: could not connect to host
 terminalvelocity.co.nz: could not connect to host
 thesehighsandlows.com: could not connect to host
 thinkcash.nl: could not connect to host
 tiliaze.info: could not connect to host
 tiliaze.net: could not connect to host
 totch.de: could not connect to host
 totot.net: could not connect to host
 transcendmotor.sg: could not connect to host
-trekfriend.com: could not connect to host
 turn-sticks.com: could not connect to host
-underskatten.tk: could not connect to host
-unicorncloud.org: could not connect to host
-vea.re: could not connect to host
+uptimed.com: could not connect to host
 venmos.com: could not connect to host
 viditut.com: could not connect to host
 vilog.me: could not connect to host
 visionless.me: could not connect to host
 vitapingu.de: could not connect to host
 vmgirls.com: could not connect to host
-vocalviews.com: could not connect to host
 waffle.at: could not connect to host
-warlions.info: could not connect to host
+watchinventory.com: could not connect to host
 watchweasel.com: could not connect to host
 weareincognito.org: could not connect to host
-web-wave.jp: could not connect to host
 webart-factory.de: could not connect to host
 webduck.nl: could not connect to host
 weicn.org: could not connect to host
 welby.cat: could not connect to host
 werhatunsverraten.eu: could not connect to host
 whilsttraveling.com: could not connect to host
 wm-talk.net: could not connect to host
 wnnc.co.uk: could not connect to host
 wordpresspro.cl: could not connect to host
 www-8887999.com: could not connect to host
 www.simbolo.co.uk: could not connect to host
 xa1.uk: could not connect to host
-xs2a.no: could not connect to host
+xing.ml: could not connect to host
 xtremenutrition.com.br: could not connect to host
 xyfun.net: could not connect to host
 yoonas.com: could not connect to host
 zenfusion.fr: could not connect to host
 zenghx.tk: could not connect to host
 zmk.fr: could not connect to host
 zulu7.com: could not connect to host
 zuviel.space: could not connect to host
@@ -390,16 +367,17 @@ 123.gg: could not connect to host
 123share.org: could not connect to host
 123test.de: did not receive HSTS header
 123test.es: did not receive HSTS header
 123test.fr: did not receive HSTS header
 126ium.moe: could not connect to host
 127011-networks.ch: could not connect to host
 12vpn.org: could not connect to host
 12vpnchina.com: could not connect to host
+1359826938.rsc.cdn77.org: did not receive HSTS header
 13826145000.com: could not connect to host
 1391kj.com: did not receive HSTS header
 1396.net: could not connect to host
 1536.cf: could not connect to host
 163pwd.com: could not connect to host
 166166.com: could not connect to host
 16deza.com: did not receive HSTS header
 16packets.com: could not connect to host
@@ -475,17 +453,17 @@ 4cclothing.com: could not connect to hos
 4elements.com: did not receive HSTS header
 4eyes.ch: did not receive HSTS header
 4miners.net: could not connect to host
 4ourty2.org: did not receive HSTS header
 4sqsu.eu: could not connect to host
 4w-performers.link: could not connect to host
 50millionablaze.org: could not connect to host
 513vpn.net: did not receive HSTS header
-517vpn.cn: could not connect to host
+517vpn.cn: did not receive HSTS header
 540.co: did not receive HSTS header
 54bf.com: could not connect to host
 55558522.com: could not connect to host
 56ct.com: could not connect to host
 5piecesofadvice.com: could not connect to host
 5w5.la: could not connect to host
 60ych.net: did not receive HSTS header
 6120.eu: did not receive HSTS header
@@ -526,17 +504,16 @@ 8522v.com: could not connect to host
 8522w.com: could not connect to host
 8522x.com: could not connect to host
 8522y.com: could not connect to host
 8522z.com: could not connect to host
 88.to: could not connect to host
 8888av.co: did not receive HSTS header
 888lu.co: could not connect to host
 89955.com: could not connect to host
-8azino777.ru: did not receive HSTS header
 90smthng.com: could not connect to host
 9118b.com: could not connect to host
 911911.pw: could not connect to host
 922.be: could not connect to host
 960news.ca: could not connect to host
 9651678.ru: could not connect to host
 98laba.com: could not connect to host
 98laba.net: could not connect to host
@@ -675,16 +652,17 @@ agevio.com: could not connect to host
 agonswim.com: could not connect to host
 agrimap.com: did not receive HSTS header
 agrios.de: could not connect to host
 agro-id.gov.ua: did not receive HSTS header
 agtv.com.br: did not receive HSTS header
 ahabingo.com: did not receive HSTS header
 ahoynetwork.com: did not receive HSTS header
 ahri.ovh: could not connect to host
+ahwatukeefoothillsmontessori.com: did not receive HSTS header
 aicial.co.uk: could not connect to host
 aicial.com.au: could not connect to host
 aidanwoods.com: did not receive HSTS header
 aids.gov: did not receive HSTS header
 aifreeze.ru: could not connect to host
 aify.eu: could not connect to host
 ainrb.com: did not receive HSTS header
 aip-marine.com: could not connect to host
@@ -731,17 +709,16 @@ alessandro.pw: did not receive HSTS head
 alessandroz.pro: could not connect to host
 alethearose.com: did not receive HSTS header
 alexandre.sh: did not receive HSTS header
 alexbaker.org: did not receive HSTS header
 alexdodge.ca: could not connect to host
 alexvetter.de: could not connect to host
 alfa24.pro: could not connect to host
 alfredxing.com: did not receive HSTS header
-alilialili.ga: could not connect to host
 alittlebitcheeky.com: did not receive HSTS header
 aljmz.com: could not connect to host
 alkami.com: could not connect to host
 all-subtitles.com: could not connect to host
 all.tf: could not connect to host
 alldaymonitoring.com: could not connect to host
 allemobieleproviders.nl: did not receive HSTS header
 allinnote.com: could not connect to host
@@ -1107,17 +1084,16 @@ bangzafran.com: max-age too low: 36000
 banqingdiao.com: could not connect to host
 barely.sexy: did not receive HSTS header
 bariller.fr: could not connect to host
 barrelhead.org: could not connect to host
 barrut.me: did not receive HSTS header
 barshout.co.uk: could not connect to host
 barss.io: could not connect to host
 barunisystems.com: could not connect to host
-bashc.at: could not connect to host
 bashcode.ninja: could not connect to host
 basicsolutionsus.com: did not receive HSTS header
 basilisk.io: could not connect to host
 bassh.net: did not receive HSTS header
 baud.ninja: could not connect to host
 baum.ga: could not connect to host
 baumstark.ca: could not connect to host
 baysse.eu: could not connect to host
@@ -1395,17 +1371,16 @@ bratteng.xyz: could not connect to host
 bravz.de: could not connect to host
 bremensaki.com: max-age too low: 2592000
 brenden.net.au: did not receive HSTS header
 brfvh24.se: could not connect to host
 brickoo.com: could not connect to host
 brickyardbuffalo.com: did not receive HSTS header
 bridholm.se: could not connect to host
 brightstarkids.com.au: did not receive HSTS header
-brigidaarie.com: did not receive HSTS header
 brilliantbuilders.co.uk: did not receive HSTS header
 britzer-toner.de: did not receive HSTS header
 brix.ninja: did not receive HSTS header
 brks.xyz: could not connect to host
 broken-oak.com: could not connect to host
 brookechase.com: did not receive HSTS header
 browserid.org: could not connect to host
 brrd.io: could not connect to host
@@ -1457,17 +1432,16 @@ burian-server.cz: could not connect to h
 burningcrash.de: max-age too low: 600000
 burpsuite.site: could not connect to host
 burrow.ovh: could not connect to host
 burrowingsec.com: could not connect to host
 burtrum.me: could not connect to host
 burtrum.top: could not connect to host
 buryat-mongol.cf: could not connect to host
 business.lookout.com: could not connect to host
-businessadviceperth.com.au: did not receive HSTS header
 businesshosting.nl: did not receive HSTS header
 businessloanconnection.org: did not receive HSTS header
 busold.ws: could not connect to host
 bustimes.org: could not connect to host
 butchersworkshop.com: did not receive HSTS header
 butian518.com: did not receive HSTS header
 buttercoin.com: could not connect to host
 butterfieldstraining.com: did not receive HSTS header
@@ -1699,16 +1673,17 @@ chriskyrouac.com: could not connect to h
 chrisopperwall.com: did not receive HSTS header
 christiaandruif.nl: could not connect to host
 christianbro.gq: could not connect to host
 christophercolumbusfoundation.gov: could not connect to host
 christophersole.com: could not connect to host
 christophheich.me: could not connect to host
 chrisupjohn.com: could not connect to host
 chrisvicmall.com: did not receive HSTS header
+chromaryu.net: did not receive HSTS header
 chrome-devtools-frontend.appspot.com: did not receive HSTS header (error ignored - included regardless)
 chrome.google.com: did not receive HSTS header (error ignored - included regardless)
 chrst.ph: could not connect to host
 chua.cf: could not connect to host
 chulado.com: did not receive HSTS header
 churchux.co: did not receive HSTS header
 churrasqueirafacil.com.br: could not connect to host
 cidr.ml: could not connect to host
@@ -1733,17 +1708,16 @@ claimit.ml: could not connect to host
 clan-ww.com: did not receive HSTS header
 clara-baumert.de: could not connect to host
 claralabs.com: did not receive HSTS header
 classicday.nl: could not connect to host
 classicsandexotics.com: did not receive HSTS header
 classicshop.ua: did not receive HSTS header
 classicspublishing.com: could not connect to host
 classifiedssa.co.za: could not connect to host
-claudio4.com: did not receive HSTS header
 clcleaningco.com: could not connect to host
 cleanexperts.co.uk: could not connect to host
 cleaningsquad.ca: did not receive HSTS header
 cleanmta.com: could not connect to host
 clearc.tk: could not connect to host
 clearsky.me: did not receive HSTS header
 clerkendweller.uk: did not receive HSTS header
 clickandgo.com: did not receive HSTS header
@@ -1765,17 +1739,16 @@ cloudcert.org: did not receive HSTS head
 cloudcy.net: could not connect to host
 clouddesktop.co.nz: could not connect to host
 cloudey.net: did not receive HSTS header
 cloudflare.com: did not receive HSTS header
 cloudfren.com: did not receive HSTS header
 cloudimag.es: could not connect to host
 cloudlink.club: could not connect to host
 cloudns.com.au: could not connect to host
-cloudopt.net: max-age too low: 2592000
 clouds.webcam: could not connect to host
 cloudspotterapp.com: did not receive HSTS header
 cloudstoragemaus.com: could not connect to host
 cloudstorm.me: could not connect to host
 cloudstrike.co: could not connect to host
 cloudwalk.io: did not receive HSTS header
 clounix.online: could not connect to host
 clovissantos.com: could not connect to host
@@ -2072,16 +2045,18 @@ dancerdates.net: could not connect to ho
 dane-bre.net: did not receive HSTS header
 daniel-du.com: could not connect to host
 daniel-mosquera.com: could not connect to host
 daniel-steuer.de: could not connect to host
 danielcowie.me: could not connect to host
 danieldk.eu: did not receive HSTS header
 danielheal.net: could not connect to host
 danieliancu.com: could not connect to host
+danielmostertman.com: did not receive HSTS header
+danielmostertman.nl: did not receive HSTS header
 danielverlaan.nl: did not receive HSTS header
 danielworthy.com: did not receive HSTS header
 danijobs.com: could not connect to host
 danishenanigans.com: could not connect to host
 dankeblog.com: could not connect to host
 danmark.guide: did not receive HSTS header
 dannycrichton.com: did not receive HSTS header
 danrl.de: could not connect to host
@@ -2193,17 +2168,17 @@ derpumpkinfuhrer.com: could not connect 
 derwaldschrat.net: did not receive HSTS header
 derwolfe.net: did not receive HSTS header
 desiccantpackets.com: did not receive HSTS header
 designandmore.it: did not receive HSTS header
 designgears.com: did not receive HSTS header
 designthinking.or.jp: did not receive HSTS header
 desserteagleselvenar.tk: could not connect to host
 destinationbijoux.fr: could not connect to host
-destom.be: could not connect to host
+destom.be: did not receive HSTS header
 detalhecomercio.com.br: did not receive HSTS header
 detector.exposed: could not connect to host
 detest.org: could not connect to host
 detutorial.com: max-age too low: 0
 deuxvia.com: could not connect to host
 dev: could not connect to host
 dev-aegon.azurewebsites.net: did not receive HSTS header
 dev-bluep.pantheonsite.io: did not receive HSTS header
@@ -2211,18 +2186,16 @@ devafterdark.com: could not connect to h
 devct.cz: did not receive HSTS header
 devcu.com: could not connect to host
 devcu.net: could not connect to host
 develop.fitness: could not connect to host
 devh.net: could not connect to host
 deviltraxxx.de: could not connect to host
 devincrow.me: could not connect to host
 devisonline.ch: could not connect to host
-devkit.cc: could not connect to host
-devklog.net: could not connect to host
 devmsg.com: did not receive HSTS header
 devnsec.com: could not connect to host
 devnull.team: could not connect to host
 devopps.me: did not receive HSTS header
 devopsconnected.com: could not connect to host
 devpsy.info: could not connect to host
 devtub.com: did not receive HSTS header
 devuan.org: did not receive HSTS header
@@ -2405,17 +2378,17 @@ drycreekapiary.com: could not connect to
 ds-christiansen.de: could not connect to host
 dshiv.io: could not connect to host
 dtub.co: could not connect to host
 dualias.xyz: could not connect to host
 dubik.su: did not receive HSTS header
 duelysthub.com: could not connect to host
 duerls.de: did not receive HSTS header
 dukec.me: could not connect to host
-dullsir.com: could not connect to host
+dullsir.com: did not receive HSTS header
 dungi.org: could not connect to host
 duongpho.com: did not receive HSTS header
 duskopy.top: could not connect to host
 dutchessuganda.com: did not receive HSTS header
 dutchrank.com: did not receive HSTS header
 duuu.ch: could not connect to host
 dycontrol.de: could not connect to host
 dylanscott.com.au: did not receive HSTS header
@@ -2517,17 +2490,16 @@ ego-world.org: could not connect to host
 ehealthcounselor.com: could not connect to host
 ehipaadev.com: could not connect to host
 ehito.ovh: could not connect to host
 ehrenamt-skpfcw.de: could not connect to host
 eicfood.com: could not connect to host
 eidolonhost.com: did not receive HSTS header
 eigo.work: could not connect to host
 einhorn.space: could not connect to host
-einsteinathome.org: did not receive HSTS header
 ekbanden.nl: could not connect to host
 eksik.com: could not connect to host
 elaintehtaat.fi: did not receive HSTS header
 elan-organics.com: did not receive HSTS header
 elanguest.pl: could not connect to host
 elanguest.ro: could not connect to host
 elanguest.ru: could not connect to host
 elaon.de: did not receive HSTS header
@@ -2584,17 +2556,16 @@ encryptio.com: could not connect to host
 end.pp.ua: could not connect to host
 endlessdark.net: max-age too low: 600
 endlesshorizon.net: could not connect to host
 endlesstone.com: could not connect to host
 endohaus.ca: could not connect to host
 endohaus.com: could not connect to host
 endohaus.eu: could not connect to host
 enefan.jp: could not connect to host
-enfield-kitchens.co.uk: did not receive HSTS header
 engelwerbung.com: did not receive HSTS header
 enginsight.com: did not receive HSTS header
 englishyamal.ru: did not receive HSTS header
 enigmacpt.com: did not receive HSTS header
 enigmail.net: did not receive HSTS header
 enjen.net: did not receive HSTS header
 enjoymayfield.com: max-age too low: 0
 enskat.de: could not connect to host
@@ -2715,16 +2686,17 @@ evin.ml: could not connect to host
 evites.me: could not connect to host
 evomon.com: could not connect to host
 evossd.tk: could not connect to host
 evowl.com: could not connect to host
 ewallet-optimizer.com: did not receive HSTS header
 ewex.org: could not connect to host
 excelgum.ca: did not receive HSTS header
 exceptionalservers.com: could not connect to host
+exchangecoordinator.com: did not receive HSTS header
 exfiles.cz: did not receive HSTS header
 exgravitus.com: could not connect to host
 exno.co: could not connect to host
 exousiakaidunamis.xyz: could not connect to host
 expertmile.com: did not receive HSTS header
 expo-designers.com: did not receive HSTS header
 expoundite.net: could not connect to host
 express-vpn.com: did not receive HSTS header
@@ -2773,16 +2745,17 @@ fallenangelspirits.uk: could not connect
 fam-weyer.de: did not receive HSTS header
 fame-agency.net: could not connect to host
 familie-sprink.de: could not connect to host
 familie-zimmermann.at: could not connect to host
 famio.cn: could not connect to host
 fantasyfootballpundit.com: did not receive HSTS header
 fanyl.cn: could not connect to host
 farces.com: did not receive HSTS header
+farhadexchange.com: did not receive HSTS header
 fashion.net: did not receive HSTS header
 fashioncare.cz: did not receive HSTS header
 fashionholic.my: did not receive HSTS header
 fasset.jp: could not connect to host
 fastcomcorp.com: did not receive HSTS header
 fastcomcorp.net: did not receive HSTS header
 fastograph.com: could not connect to host
 fastopen.ml: could not connect to host
@@ -2880,17 +2853,17 @@ flags.ninja: could not connect to host
 flairbros.at: could not connect to host
 flamewall.net: could not connect to host
 flamingkeys.com.au: could not connect to host
 flareon.net: could not connect to host
 flatbellyreview.com: max-age too low: 2592000
 flawcheck.com: could not connect to host
 fliexer.com: could not connect to host
 flipkey.com: did not receive HSTS header
-flirchi.com: did not receive HSTS header
+flirchi.com: could not connect to host
 flixtor.net: could not connect to host
 floless.co.uk: did not receive HSTS header
 florafiora.com.br: did not receive HSTS header
 florian-lillpopp.de: max-age too low: 10
 florianlillpopp.de: max-age too low: 10
 floridaescapes.co.uk: did not receive HSTS header
 florispoort.nl: did not receive HSTS header
 flouartistique.ch: could not connect to host
@@ -3670,24 +3643,25 @@ icntorrent.download: could not connect t
 icq-project.net: could not connect to host
 icreative.nl: did not receive HSTS header
 id-co.in: could not connect to host
 id-conf.com: did not receive HSTS header
 idcrane.com: could not connect to host
 ideal-envelopes.co.uk: did not receive HSTS header
 idealmoto.com: did not receive HSTS header
 idealmykonos.com: did not receive HSTS header
-ideaman924.com: did not receive HSTS header
+ideaman924.com: could not connect to host
 ideaplus.me: could not connect to host
 ideasmeetingpoint.com: could not connect to host
 ideation-inc.co.jp: could not connect to host
 idecode.net: could not connect to host
 idedr.com: could not connect to host
 identitylabs.uk: could not connect to host
 idgsupply.com: did not receive HSTS header
+idinby.dk: did not receive HSTS header
 idisplay.es: did not receive HSTS header
 idlekernel.com: could not connect to host
 idontexist.me: did not receive HSTS header
 ie.search.yahoo.com: did not receive HSTS header
 ierna.com: did not receive HSTS header
 ies-italia.it: did not receive HSTS header
 ies.id.lv: could not connect to host
 ievgenialehner.com: did not receive HSTS header
@@ -3842,17 +3816,16 @@ iolife.dk: could not connect to host
 ionas-law.ro: did not receive HSTS header
 ionx.co.uk: did not receive HSTS header
 iop.intuit.com: max-age too low: 86400
 iora.fr: could not connect to host
 iosmods.com: did not receive HSTS header
 iostips.ru: could not connect to host
 ip6.im: did not receive HSTS header
 ipbill.org.uk: could not connect to host
-iplantom.com: did not receive HSTS header
 iplife.cn: could not connect to host
 ipmimagazine.com: did not receive HSTS header
 iprice.co.id: did not receive HSTS header
 iprice.hk: did not receive HSTS header
 iprice.my: did not receive HSTS header
 iprice.ph: did not receive HSTS header
 iprice.sg: did not receive HSTS header
 iprice.vn: did not receive HSTS header
@@ -4154,16 +4127,17 @@ kamikatse.net: could not connect to host
 kanada.guide: did not receive HSTS header
 kaneo-gmbh.de: could not connect to host
 kaniklani.co.za: could not connect to host
 kanscooking.org: did not receive HSTS header
 kany.me: did not receive HSTS header
 kanzlei-wirtschaftsrecht.berlin: did not receive HSTS header
 kaohub.com: could not connect to host
 kaplatz.is: could not connect to host
+kappit.dk: did not receive HSTS header
 kapucini.si: max-age too low: 0
 kaputt.com: could not connect to host
 kapverde.guide: did not receive HSTS header
 karaoketonight.com: could not connect to host
 karloskontana.tk: could not connect to host
 karpanhellas.com: did not receive HSTS header
 karting34.com: did not receive HSTS header
 kashdash.ca: could not connect to host
@@ -4329,17 +4303,16 @@ kroetenfuchs.de: could not connect to ho
 kroodle.nl: did not receive HSTS header
 kruegerrand-wert.de: did not receive HSTS header
 krunut.com: did not receive HSTS header
 krypteia.org: could not connect to host
 kryptomech.com: could not connect to host
 ksfh-mail.de: could not connect to host
 kstan.me: could not connect to host
 kswriter.com: could not connect to host
-kts-thueringen.de: did not receive HSTS header
 kuba.guide: did not receive HSTS header
 kucom.it: did not receive HSTS header
 kuechenplan.online: did not receive HSTS header
 kueulangtahunanak.net: could not connect to host
 kum.com: could not connect to host
 kummerlaender.eu: did not receive HSTS header
 kupelne-ptacek.sk: did not receive HSTS header
 kuppingercole.com: did not receive HSTS header
@@ -4579,16 +4552,17 @@ loafbox.com: could not connect to host
 loansonline.today: could not connect to host
 localchum.com: could not connect to host
 localdrive.me: could not connect to host
 localnetwork.nz: could not connect to host
 locktheirphone.com: could not connect to host
 locomotive.ca: did not receive HSTS header
 locvis.ru: could not connect to host
 loftboard.eu: could not connect to host
+log2n.uk: did not receive HSTS header
 logario.com.br: could not connect to host
 logicaladvertising.com: could not connect to host
 login.corp.google.com: max-age too low: 7776000 (error ignored - included regardless)
 login.persona.org: could not connect to host
 loginseite.com: could not connect to host
 logistify.com.mx: did not receive HSTS header
 lognot.net: could not connect to host
 logymedia.com: could not connect to host
@@ -4748,17 +4722,17 @@ mammut.space: could not connect to host
 manaboutahor.se: did not receive HSTS header
 manage.zenpayroll.com: did not receive HSTS header
 manage4all.com: could not connect to host
 manageall.de: could not connect to host
 manageforall.com: could not connect to host
 manageforall.de: could not connect to host
 managemynetsuite.com: did not receive HSTS header
 manageprojects.com: did not receive HSTS header
-manantial.mx: did not receive HSTS header
+manantial.mx: could not connect to host
 mandpress.com: did not receive HSTS header
 maniadeprazer.com.br: could not connect to host
 manifestbin.com: did not receive HSTS header
 manitasicily.com: did not receive HSTS header
 manningbrothers.com: did not receive HSTS header
 manshop24.com: could not connect to host
 mansion-note.com: did not receive HSTS header
 manududu.com.br: did not receive HSTS header
@@ -4855,24 +4829,23 @@ maxserver.com: did not receive HSTS head
 maya.mg: could not connect to host
 mazz-tech.com: could not connect to host
 mbconsultancy.nu: did not receive HSTS header
 mc81.com: could not connect to host
 mca2017.org: did not receive HSTS header
 mcard.vn: did not receive HSTS header
 mcc.re: could not connect to host
 mccarty.io: could not connect to host
-mcdonalds.ru: did not receive HSTS header
+mcdonalds.ru: could not connect to host
 mcga.media: could not connect to host
 mclab.su: could not connect to host
 mclist.it: could not connect to host
 mclyr.com: max-age too low: 7776000
 mcooperlaw.com: did not receive HSTS header
 mdfnet.se: did not receive HSTS header
-mdkr.nl: did not receive HSTS header
 mdscomp.net: did not receive HSTS header
 meadowfen.farm: could not connect to host
 meadowfenfarm.com: could not connect to host
 meamod.com: max-age too low: 0
 meat-education.com: could not connect to host
 mebio.us: did not receive HSTS header
 mecenat-cassous.com: did not receive HSTS header
 mechmk1.me: did not receive HSTS header
@@ -4953,17 +4926,17 @@ mhict.nl: could not connect to host
 mht-travel.com: could not connect to host
 mhx.pw: could not connect to host
 mi80.com: could not connect to host
 mia.to: could not connect to host
 mianfei-vpn.com: did not receive HSTS header
 michaeldemuth.com: could not connect to host
 michaelfitzpatrickruth.com: could not connect to host
 michaelmorpurgo.com: did not receive HSTS header
-michaeln.net: did not receive HSTS header
+michaeln.net: could not connect to host
 michaelscrivo.com: did not receive HSTS header
 michaelwaite.org: could not connect to host
 michal-kral.cz: could not connect to host
 michalborka.cz: could not connect to host
 miconware.de: could not connect to host
 micro-dv.ru: could not connect to host
 micro-rain-systems.com: did not receive HSTS header
 microme.ga: could not connect to host
@@ -5193,16 +5166,17 @@ musewearflipflops.com: could not connect
 mushroomandfern.com: could not connect to host
 musi.cx: could not connect to host
 musicalbim.com.br: could not connect to host
 musicchris.de: did not receive HSTS header
 musikkfondene.no: did not receive HSTS header
 mustardking.me: did not receive HSTS header
 mustika.cf: could not connect to host
 mutamatic.com: could not connect to host
+mutuals.cool: did not receive HSTS header
 mutuelle-obligatoire-pme.fr: did not receive HSTS header
 muzgra.in: did not receive HSTS header
 muzykaprzeszladoplay.pl: could not connect to host
 mvanmarketing.nl: did not receive HSTS header
 mvsecurity.nl: could not connect to host
 mw.search.yahoo.com: did not receive HSTS header
 mwohlfarth.de: did not receive HSTS header
 my-owncloud.com: could not connect to host
@@ -5288,17 +5262,17 @@ nandex.org: could not connect to host
 naniki.co.uk: did not receive HSTS header
 nanogeneinc.com: could not connect to host
 nanokamo.com: did not receive HSTS header
 nanrenba.net: could not connect to host
 nansay.cn: could not connect to host
 nanto.eu: could not connect to host
 narodniki.com: did not receive HSTS header
 nashira.cz: did not receive HSTS header
-nasralmabrooka.com: could not connect to host
+nasralmabrooka.com: did not receive HSTS header
 natalia-fadeeva.ru: could not connect to host
 natalia.io: could not connect to host
 natalieandjoshua.com: could not connect to host
 natalt.org: did not receive HSTS header
 nathanmfarrugia.com: did not receive HSTS header
 nationwidevehiclecontracts.co.uk: did not receive HSTS header
 natural-progesterone.net: could not connect to host
 naturecoaster.com: did not receive HSTS header
@@ -5400,16 +5374,17 @@ niconode.com: could not connect to host
 nidux.com: did not receive HSTS header
 niduxcomercial.com: could not connect to host
 nien.chat: could not connect to host
 nightsnack.cf: could not connect to host
 nightwinds.tk: could not connect to host
 niho.jp: did not receive HSTS header
 nikcub.com: could not connect to host
 niklaslindblad.se: did not receive HSTS header
+nikobradshaw.com: did not receive HSTS header
 niloxy.com: did not receive HSTS header
 ninchisho-online.com: did not receive HSTS header
 ninhs.org: could not connect to host
 ninjaspiders.com: did not receive HSTS header
 nippler.org: did not receive HSTS header
 nippombashi.net: did not receive HSTS header
 nipponcareers.com: did not receive HSTS header
 nitropanel.com: did not receive HSTS header
@@ -5434,16 +5409,17 @@ nodi.at: did not receive HSTS header
 noexpect.org: could not connect to host
 noima.com: did not receive HSTS header
 noisebridge.social: could not connect to host
 nolberg.net: did not receive HSTS header
 nolimitsbook.de: did not receive HSTS header
 nolte.work: could not connect to host
 nomorebytes.de: could not connect to host
 noodlesandwich.com: did not receive HSTS header
+nootropicsource.com: did not receive HSTS header
 nope.website: could not connect to host
 nopex.no: could not connect to host
 nopol.de: could not connect to host
 norandom.com: could not connect to host
 norb.at: could not connect to host
 nordlicht.photography: did not receive HSTS header
 norge.guide: did not receive HSTS header
 northcutt.com: did not receive HSTS header
@@ -5797,17 +5773,16 @@ payments-reference.org: could not connec
 payments.google.com: did not receive HSTS header (error ignored - included regardless)
 payroll.ch: could not connect to host
 paytwopay.com: could not connect to host
 pbapp.net: did not receive HSTS header
 pbbr.com: did not receive HSTS header
 pbprint.ru: did not receive HSTS header
 pc-nf.de: did not receive HSTS header
 pcat.io: could not connect to host
-pccentral.nl: did not receive HSTS header
 pcfun.net: could not connect to host
 pchax.net: could not connect to host
 pchospital.cc: did not receive HSTS header
 pdamsidoarjo.co.id: could not connect to host
 pdevio.com: could not connect to host
 pdf.yt: could not connect to host
 peaceandwool.com: did not receive HSTS header
 peakapp.nl: could not connect to host
@@ -6104,17 +6079,16 @@ providerlijst.nl: did not receive HSTS h
 prowhisky.de: did not receive HSTS header
 proximato.com: could not connect to host
 proxybay.al: could not connect to host
 proxybay.club: could not connect to host
 proxybay.info: did not receive HSTS header
 proxybay.top: did not receive HSTS header
 proxydesk.net: could not connect to host
 proxyowl.pw: could not connect to host
-proxyportal.org: did not receive HSTS header
 proxyrox.com: could not connect to host
 prxio.date: could not connect to host
 prxio.site: could not connect to host
 prytkov.com: did not receive HSTS header
 ps-provider.co.jp: could not connect to host
 ps4all.nl: could not connect to host
 pscleaningsolutions.co.uk: could not connect to host
 pseudo.coffee: could not connect to host
@@ -6280,17 +6254,16 @@ readr.pw: could not connect to host
 reagir43.fr: did not receive HSTS header
 realmic.net: could not connect to host
 realmofespionage.com: could not connect to host
 realraghavgupta.com: could not connect to host
 reaper.rip: could not connect to host
 reardenporn.com: could not connect to host
 rebekaesgabor.online: could not connect to host
 recommended.reviews: could not connect to host
-recyclingpromotions.us: did not receive HSTS header
 redar.xyz: could not connect to host
 reddit.com: did not receive HSTS header
 rede.ca: did not receive HSTS header
 redhorsemountainranch.com: did not receive HSTS header
 redicabo.de: could not connect to host
 redirectman.com: did not receive HSTS header
 redlatam.org: did not receive HSTS header
 redmbk.com: did not receive HSTS header
@@ -6463,17 +6436,16 @@ rozeapp.nl: could not connect to host
 rr.in.th: could not connect to host
 rrke.cc: did not receive HSTS header
 rsajeey.info: could not connect to host
 rsampaio.info: could not connect to host
 rsauget.fr: could not connect to host
 rsblake.net: could not connect to host
 rsf.io: could not connect to host
 rsmaps.org: could not connect to host
-rsttraining.co.uk: could not connect to host
 rubbereggs.ca: could not connect to host
 rubecodeberg.com: could not connect to host
 rubenschulz.nl: could not connect to host
 rubi-ka.net: max-age too low: 0
 ruborr.se: did not receive HSTS header
 rubysecurity.org: did not receive HSTS header
 rubyshop.nl: max-age too low: 604800
 rudeotter.com: did not receive HSTS header
@@ -6509,17 +6481,17 @@ saabwa.org: could not connect to host
 safelist.eu: did not receive HSTS header
 safematix.com: could not connect to host
 safemovescheme.co.uk: did not receive HSTS header
 safersurfing.eu: did not receive HSTS header
 safewings-nh.nl: could not connect to host
 sagarhandicraft.com: could not connect to host
 sageth.com: max-age too low: 0
 sah3.net: could not connect to host
-saharalondon.com: did not receive HSTS header
+saharalondon.com: max-age too low: 0
 saharmassachi.com: could not connect to host
 sail-nyc.com: did not receive HSTS header
 sairai.bid: did not receive HSTS header
 sakaki.anime.my: max-age too low: 5184000
 sakaserver.com: did not receive HSTS header
 sakib.ninja: did not receive HSTS header
 sakurabuff.com: could not connect to host
 salserocafe.com: did not receive HSTS header
@@ -6613,17 +6585,17 @@ scrambler.in: could not connect to host
 scrapings.net: could not connect to host
 screencaster.io: did not receive HSTS header
 screenresolution.space: could not connect to host
 screensaversplanet.com: did not receive HSTS header
 scribbleserver.com: could not connect to host
 scribe.systems: could not connect to host
 scrion.com: could not connect to host
 script.google.com: did not receive HSTS header (error ignored - included regardless)
-scriptenforcer.net: could not connect to host
+scriptenforcer.net: did not receive HSTS header
 scriptict.nl: could not connect to host
 scrollstory.com: did not receive HSTS header
 sdhmanagementgroup.com: could not connect to host
 sdia.ru: could not connect to host
 sdmoscow.ru: could not connect to host
 sdrobs.com: did not receive HSTS header
 sdsl-speedtest.de: could not connect to host
 seans.cc: did not receive HSTS header
@@ -6747,30 +6719,30 @@ shadowsocks.vc: did not receive HSTS hea
 shadowsocks.wiki: did not receive HSTS header
 shadowsoks.com: could not connect to host
 shakebox.de: could not connect to host
 shanekoster.net: could not connect to host
 shanesage.com: could not connect to host
 shaobin.wang: could not connect to host
 shapesedinburgh.co.uk: did not receive HSTS header
 shardsoft.com: could not connect to host
-shareeri.com: did not receive HSTS header
 shareimg.xyz: could not connect to host
 sharejoy.cn: did not receive HSTS header
 sharepass.pw: could not connect to host
 sharepic.xyz: could not connect to host
 sharezen.de: could not connect to host
 shauncrowley.co.uk: could not connect to host
 shaunwheelhou.se: could not connect to host
 shawnh.net: could not connect to host
 shellsec.pw: did not receive HSTS header
 shep.co.il: did not receive HSTS header
 shereallyheals.com: did not receive HSTS header
 shervik.ga: could not connect to host
 shg-pornographieabhaengigkeit.de: did not receive HSTS header
+shiatsu-institut.ch: did not receive HSTS header
 shibe.club: could not connect to host
 shiftins.com: could not connect to host
 shiftplanning.com: did not receive HSTS header
 shiinko.com: could not connect to host
 shindorei.fr: did not receive HSTS header
 shinebijoux.com.br: could not connect to host
 shinju.moe: could not connect to host
 shiona.xyz: could not connect to host
@@ -6830,17 +6802,17 @@ simon-pokorny.com: did not receive HSTS 
 simon.butcher.name: max-age too low: 2629743
 simongong.net: did not receive HSTS header
 simonsaxon.com: did not receive HSTS header
 simpan.id: did not receive HSTS header
 simpleai.net: max-age too low: 600
 simplelearner.com: could not connect to host
 simplepractice.com: did not receive HSTS header
 simplixos.org: could not connect to host
-simply-premium.com: did not receive HSTS header
+simply-premium.com: max-age too low: 0
 simplyenak.com: did not receive HSTS header
 sin30.net: could not connect to host
 sincai666.com: could not connect to host
 sincron.org: could not connect to host
 sinful.pw: could not connect to host
 singul4rity.com: could not connect to host
 sinneserweiterung.de: could not connect to host
 sinosky.org: did not receive HSTS header
@@ -6900,16 +6872,17 @@ smarterskies.gov: did not receive HSTS h
 smartfon4you.ru: did not receive HSTS header
 smarthomedna.com: did not receive HSTS header
 smartofficesandsmarthomes.com: did not receive HSTS header
 smartphone.continental.com: could not connect to host
 smartrak.co.nz: did not receive HSTS header
 smdev.fr: could not connect to host
 smet.us: could not connect to host
 smexpt.com: did not receive HSTS header
+smiledirectsales.com: did not receive HSTS header
 smimea.com: could not connect to host
 smirkingwhorefromhighgarden.pro: could not connect to host
 smittix.co.uk: did not receive HSTS header
 smkn1lengkong.sch.id: did not receive HSTS header
 smksi2.com: could not connect to host
 smksultanismail2.com: did not receive HSTS header
 smove.sg: did not receive HSTS header
 smplix.com: could not connect to host
@@ -7135,17 +7108,16 @@ streamingmagazin.de: could not connect t
 strictlysudo.com: could not connect to host
 strife.tk: could not connect to host
 strila.me: could not connect to host
 strivephysmed.com: did not receive HSTS header
 stroeercrm.de: could not connect to host
 strongest-privacy.com: could not connect to host
 stuartbaxter.co: could not connect to host
 student-scientist.org: did not receive HSTS header
-student.andover.edu: did not receive HSTS header
 studentrdh.com: did not receive HSTS header
 studentresearcher.org: did not receive HSTS header
 studentskydenik.cz: could not connect to host
 studenttravel.cz: did not receive HSTS header
 studinf.xyz: could not connect to host
 studio-panic.com: did not receive HSTS header
 studiozelden.com: did not receive HSTS header
 studybay.com: did not receive HSTS header
@@ -7255,24 +7227,22 @@ sytpartners.com: max-age too low: 0
 szaszm.tk: max-age too low: 0
 t-complex.space: could not connect to host
 t-ken.xyz: could not connect to host
 t-tz.com: could not connect to host
 t0dd.eu: could not connect to host
 t4c-rebirth.com: could not connect to host
 t4x.org: could not connect to host
 taabe.xyz: could not connect to host
-taartenfeesies.nl: did not receive HSTS header
 tabino.top: could not connect to host
 tacomafia.net: did not receive HSTS header
 tadigitalstore.com: could not connect to host
 tafoma.com: did not receive HSTS header
 tageau.com: could not connect to host
 taglondon.org: did not receive HSTS header
-tahakomat.cz: did not receive HSTS header
 tailify.com: did not receive HSTS header
 tails.com.ar: did not receive HSTS header
 talado.gr: could not connect to host
 tales-of-interia.de: could not connect to host
 talheim-records.ca: could not connect to host
 talk.google.com: did not receive HSTS header (error ignored - included regardless)
 talkitup.mx: could not connect to host
 talkitup.online: did not receive HSTS header
@@ -7303,16 +7273,17 @@ tasmansecurity.com: could not connect to
 tassup.com: could not connect to host
 tastyyy.co: could not connect to host
 tatilbus.com: did not receive HSTS header
 tatt.io: could not connect to host
 tauchkater.de: could not connect to host
 tavoittaja.fi: did not receive HSTS header
 tavopica.lt: did not receive HSTS header
 taxbench.com: could not connect to host
+taxi-24std.de: did not receive HSTS header
 taxiindenbosch.nl: did not receive HSTS header
 taxsnaps.co.nz: did not receive HSTS header
 tazz.in: could not connect to host
 tbspace.de: did not receive HSTS header
 tc-bonito.de: did not receive HSTS header
 tcao.info: could not connect to host
 tcby45.xyz: could not connect to host
 tcdw.net: could not connect to host
@@ -7525,17 +7496,17 @@ tierrarp.com: could not connect to host
 tightlineproductions.com: did not receive HSTS header
 tikutiku.pl: could not connect to host
 tildebot.com: could not connect to host
 tiliaze.be: could not connect to host
 tiliaze.biz: could not connect to host
 tiliaze.eu: did not receive HSTS header
 tilient.eu: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 119"  data: no]
 tilikum.io: did not receive HSTS header
-tilkah.com.au: did not receive HSTS header
+tilkah.com.au: could not connect to host
 tillcraft.com: could not connect to host
 timbeilby.com: could not connect to host
 timbuktutimber.com: did not receive HSTS header
 timcamara.com: could not connect to host
 time-river.xyz: could not connect to host
 timesavingplugins.com: could not connect to host
 timesavingplugins.net: could not connect to host
 timeserver0.de: could not connect to host
@@ -7563,16 +7534,17 @@ titouan.co: did not receive HSTS header
 tittarpuls.se: could not connect to host
 titties.ml: could not connect to host
 tjc.host: did not receive HSTS header
 tjc.wiki: could not connect to host
 tjeckien.guide: did not receive HSTS header
 tjullrich.de: could not connect to host
 tkappertjedemetamorfose.nl: could not connect to host
 tkonstantopoulos.tk: could not connect to host
+tlach.cz: did not receive HSTS header
 tlcdn.net: could not connect to host
 tlo.hosting: could not connect to host
 tlo.link: could not connect to host
 tlo.network: could not connect to host
 tls.li: could not connect to host
 tlsbv.nl: did not receive HSTS header
 tlshost.net: could not connect to host
 tm-solutions.eu: did not receive HSTS header
@@ -7670,16 +7642,17 @@ trance-heal.me: did not receive HSTS hea
 tranceheal.com: did not receive HSTS header
 tranceheal.de: did not receive HSTS header
 tranceheal.me: did not receive HSTS header
 transdirect.com.au: did not receive HSTS header
 transformify.org: did not receive HSTS header
 transl8.eu: did not receive HSTS header
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 transportal.sk: did not receive HSTS header
+trashnothing.com: did not receive HSTS header
 travality.ru: could not connect to host
 travel-kuban.ru: did not receive HSTS header
 travelinsightswriter.com: could not connect to host
 travelinsurance.co.nz: did not receive HSTS header
 trazosdearte.com: did not receive HSTS header
 treatprostatewithhifu.com: could not connect to host
 treeby.net: could not connect to host
 treeremovaljohannesburg.co.za: could not connect to host
@@ -7869,17 +7842,16 @@ upboard.jp: could not connect to host
 upldr.pw: could not connect to host
 uporoops.com: could not connect to host
 uprotect.it: could not connect to host
 upstats.eu: could not connect to host
 ur-lauber.de: did not receive HSTS header
 urandom.eu.org: did not receive HSTS header
 urban-garden.lt: could not connect to host
 urban-garden.lv: could not connect to host
-urbanstylestaging.com: did not receive HSTS header
 urbpic.com: could not connect to host
 urlchomp.com: did not receive HSTS header
 urphp.com: could not connect to host
 us-immigration.com: did not receive HSTS header
 usaab.org: did not receive HSTS header
 usafuelservice.com: did not receive HSTS header
 usbirthcertificate.com: did not receive HSTS header
 usbtypeccompliant.com: could not connect to host
@@ -7891,34 +7863,35 @@ usercare.com: did not receive HSTS heade
 userify.com: max-age too low: 0
 uslab.io: could not connect to host
 usr.nz: did not receive HSTS header
 ustr.gov: max-age too low: 86400
 utilitronium-shockwave.com: could not connect to host
 utleieplassen.no: could not connect to host
 utopiagalaxy.space: could not connect to host
 utopian-surgery.com: could not connect to host
+utopianconcept.com: did not receive HSTS header
 utopianhomespa.com: did not receive HSTS header
 utopianrealms.org: did not receive HSTS header
-uttnetgroup.fr: could not connect to host
 utumno.ch: did not receive HSTS header
 utvbloggen.se: max-age too low: 604800
 uvarov.pw: could not connect to host
 uwstartups.com: could not connect to host
 uxux.pl: could not connect to host
 uy.search.yahoo.com: did not receive HSTS header
 uyym.com: could not connect to host
 uz.search.yahoo.com: did not receive HSTS header
 uzmandroid.com: did not receive HSTS header
 uzmandroid.net: could not connect to host
 uzmandroid.top: could not connect to host
 v0rtex.xyz: could not connect to host
 v0tti.com: could not connect to host
 v2.pw: did not receive HSTS header
 v2ex.us: did not receive HSTS header
+v4s.ro: did not receive HSTS header
 v4veedu.com: could not connect to host
 v7.cl: could not connect to host
 v789xl.com: did not receive HSTS header
 vaalmarketplace.co.za: did not receive HSTS header
 vacationality.com: could not connect to host
 vackerbetong.se: could not connect to host
 vaddder.com: could not connect to host
 vadodesign.nl: did not receive HSTS header
@@ -7934,17 +7907,16 @@ valleyridgepta.org: could not connect to
 vallis.net: could not connect to host
 valmagus.com: could not connect to host
 vamoaeturismo.com.br: could not connect to host
 vampirism.eu: could not connect to host
 vanacht.co.za: did not receive HSTS header
 vande-walle.eu: did not receive HSTS header
 vanderkley.it: could not connect to host
 vanderstraeten.dynv6.net: could not connect to host
-vanessabalibridal.com: did not receive HSTS header
 vanestack.com: could not connect to host
 vanetv.com: could not connect to host
 vanitas.xyz: could not connect to host
 vanitynailworkz.com: could not connect to host
 vansieleghem.com: could not connect to host
 vapordepot.jp: did not receive HSTS header
 vasanth.org: could not connect to host
 vbest.net: could not connect to host
@@ -8017,17 +7989,16 @@ vio.no: did not receive HSTS header
 violenceinterrupted.org: did not receive HSTS header
 viperdns.com: could not connect to host
 viphospitality.se: could not connect to host
 vipmusic.ga: could not connect to host
 vipnettikasinoklubi.com: could not connect to host
 viral8.jp: could not connect to host
 virginiacrimeanalysisnetwork.org: did not receive HSTS header
 virtualstrongbox.ca: did not receive HSTS header
-visalogy.com: could not connect to host
 visanhigia.com: did not receive HSTS header
 viserproject.com: could not connect to host
 vision-painting.com: did not receive HSTS header
 visitbroadstairs.com: could not connect to host
 vissanum.com: did not receive HSTS header
 vistarait.com: did not receive HSTS header
 visualvotes.co.uk: could not connect to host
 vitagenda.nl: could not connect to host
@@ -8089,16 +8060,17 @@ vyncke.org: max-age too low: 2678400
 vyvybean.cf: could not connect to host
 vyvygen.com: did not receive HSTS header
 vzk.io: could not connect to host
 w4a.fr: did not receive HSTS header
 w4xzr.top: could not connect to host
 w4xzr.xyz: could not connect to host
 waaw.tv: did not receive HSTS header
 wachtwoordencheck.nl: could not connect to host
+wafairhaven.com.au: did not receive HSTS header
 wahhoi.net: did not receive HSTS header
 wait.moe: could not connect to host
 waixingrenfuli7.vip: could not connect to host
 wakapp.de: could not connect to host
 wakened.net: did not receive HSTS header
 walkeryoung.ca: could not connect to host
 wallabag.it: did not receive HSTS header
 wallabag.org: did not receive HSTS header
@@ -8180,28 +8152,28 @@ webwork.pw: could not connect to host
 webypass.xyz: could not connect to host
 wecanfindit.co.za: could not connect to host
 weddingenvelopes.co.uk: did not receive HSTS header
 weddingibiza.nl: could not connect to host
 weekly.fyi: could not connect to host
 wegenaer.nl: could not connect to host
 weiji.ga: did not receive HSTS header
 welkers.org: could not connect to host
-wellastore.ru: could not connect to host
+wellastore.ru: did not receive HSTS header
 wellcomp.com.br: did not receive HSTS header
 wellies.com.au: max-age too low: 7776000
 wellness.so: could not connect to host
 welpy.com: could not connect to host
 weltentreff.com: could not connect to host
 weltmeisterschaft.net: could not connect to host
 wemakeonlinereviews.com: did not receive HSTS header
 weme.eu: could not connect to host
 wendalyncheng.com: did not receive HSTS header
 werdeeintimo.de: did not receive HSTS header
-werkenbijkfc.nl: did not receive HSTS header
+werkenbijkfc.nl: could not connect to host
 werkplaatsoost.nl: did not receive HSTS header
 werkruimtebottendaal.nl: did not receive HSTS header
 wesleyharris.ca: did not receive HSTS header
 westendzone.com: max-age too low: 0
 westerhoud.nl: did not receive HSTS header
 westlinwinds.com: did not receive HSTS header
 westsussexconnecttosupport.org: could not connect to host
 wetoxic.com: did not receive HSTS header
@@ -8253,17 +8225,16 @@ winecodeavocado.com: could not connect t
 winfield.me.uk: did not receive HSTS header
 winged.io: could not connect to host
 wingos.net: could not connect to host
 wingumd.net: could not connect to host
 winpack.cf: could not connect to host
 winpack.eu.org: could not connect to host
 winsec.nl: could not connect to host
 winshiplending.com: did not receive HSTS header
-wipc.net: could not connect to host
 wirc.gr: could not connect to host
 wiretrip.io: could not connect to host
 wiseloan.com: did not receive HSTS header
 wishcert.com: could not connect to host
 wispapp.com: did not receive HSTS header
 withgoogle.com: did not receive HSTS header (error ignored - included regardless)
 withmy.beer: could not connect to host
 withustrading.com: could not connect to host
@@ -8378,17 +8349,17 @@ x509.pub: could not connect to host
 x509.pw: could not connect to host
 xa.search.yahoo.com: did not receive HSTS header
 xandocs.com: could not connect to host
 xat.re: could not connect to host
 xavierbarroso.com: could not connect to host
 xbind.io: could not connect to host
 xcoop.me: could not connect to host
 xdd.io: could not connect to host
-xecure.zone: could not connect to host
+xecure.zone: did not receive HSTS header
 xehoivn.vn: did not receive HSTS header
 xellos.ga: could not connect to host
 xellos.ml: could not connect to host
 xenesisziarovky.sk: could not connect to host
 xett.com: did not receive HSTS header
 xf-liam.com: did not receive HSTS header
 xfd3.de: did not receive HSTS header
 xfive.de: could not connect to host
@@ -8559,17 +8530,18 @@ zahyantechnologies.com: could not connec
 zakoncontrol.com: did not receive HSTS header
 zamorano.edu: could not connect to host
 zamos.ru: max-age too low: 0
 zaneweb.org: could not connect to host
 zao.fi: did not receive HSTS header
 zaoshanghao-dajia.rhcloud.com: did not receive HSTS header
 zap.yt: did not receive HSTS header
 zarooba.com: could not connect to host
-zavca.com: did not receive HSTS header
+zary.me: did not receive HSTS header
+zavca.com: could not connect to host
 zbigniewgalucki.eu: did not receive HSTS header
 zcon.nl: could not connect to host
 zdravotnickasluzba.eu: could not connect to host
 zebrababy.cn: could not connect to host
 zebry.nl: could not connect to host
 zecrypto.com: could not connect to host
 zeedroom.be: did not receive HSTS header
 zefiris.org: did not receive HSTS header
@@ -8591,16 +8563,17 @@ zeroday.sk: did not receive HSTS header
 zerofox.gq: could not connect to host
 zeroml.ml: could not connect to host
 zerudi.com: did not receive HSTS header
 zett4.me: could not connect to host
 zeytin.pro: could not connect to host
 zh.search.yahoo.com: did not receive HSTS header
 zh1.li: could not connect to host
 zhang.wtf: could not connect to host
+zhangge.net: did not receive HSTS header
 zhangruilin.com: did not receive HSTS header
 zhaojin97.cn: could not connect to host
 zhendingresources.com: did not receive HSTS header
 zhh.in: could not connect to host
 zhihua-lai.com: did not receive HSTS header
 zhiin.net: could not connect to host
 zhiku8.com: could not connect to host
 zhuji.com.cn: could not connect to host
@@ -8624,17 +8597,16 @@ zk.gd: did not receive HSTS header
 zkillboard.com: did not receive HSTS header
 zking.ga: could not connect to host
 zmsastro.co.za: could not connect to host
 zmy.im: did not receive HSTS header
 zocken.com: did not receive HSTS header
 zockenbiszumumfallen.de: did not receive HSTS header
 zoe.vc: could not connect to host
 zohar.link: could not connect to host
-zolotoy-standart.com.ua: did not receive HSTS header
 zomiac.pp.ua: could not connect to host
 zoneminder.com: did not receive HSTS header
 zoners.si: did not receive HSTS header
 zonky.io: could not connect to host
 zoo24.de: did not receive HSTS header
 zoofaeth.de: did not receive HSTS header
 zoomingin.net: max-age too low: 5184000
 zoommailing.com: did not receive HSTS header
--- a/security/manager/ssl/nsSTSPreloadList.inc
+++ b/security/manager/ssl/nsSTSPreloadList.inc
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsSiteSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include <stdint.h>
-const PRTime gPreloadListExpirationTime = INT64_C(1518414589664000);
+const PRTime gPreloadListExpirationTime = INT64_C(1518457357921000);
 %%
 0.me.uk, 1
 00001.am, 1
 00002.am, 1
 0005pay.com, 1
 0010100.net, 1
 00220022.net, 1
 007-preisvergleich.de, 1
@@ -108,17 +108,16 @@ 123midterm.com, 1
 123plons.nl, 1
 123test.com, 1
 123test.nl, 1
 125m125.de, 1
 12vpn.net, 1
 130.ua, 1
 132kv.ch, 1
 13318522.com, 1
-1359826938.rsc.cdn77.org, 1
 1395kj.com, 1
 1396.cc, 1
 1453914078.rsc.cdn77.org, 1
 1464424382.rsc.cdn77.org, 1
 14it.de, 1
 14x3.de, 1
 15-10.com, 1
 1511774230.rsc.cdn77.org, 1
@@ -391,16 +390,17 @@ 888azino.com, 1
 888msc.vip, 1
 888sport.dk, 1
 888sport.it, 1
 88laohu.cc, 1
 88laohu.com, 1
 899699.com, 1
 8ack.de, 1
 8ackprotect.com, 1
+8azino777.ru, 1
 8mpay.com, 1
 8ox.ru, 0
 8pecxstudios.com, 1
 8svn.com, 1
 8t8.eu, 1
 8t88.biz, 1
 8thportsmouth.org.uk, 1
 8tuffbeers.com, 1
@@ -565,17 +565,17 @@ aceinstituteonline.com, 1
 acelpb.com, 1
 acemobileforce.com, 1
 acendealuz.com.br, 1
 acerislaw.com, 1
 acessoeducacao.com, 1
 acevik.de, 1
 acg.mn, 1
 acg.sb, 1
-acg18.us, 1
+acg18.us, 0
 acgaudio.com, 1
 achalay.org, 1
 acheconcursos.com.br, 1
 achenar.net, 1
 achow101.com, 1
 achromatisch.de, 1
 achterhoekseveiligheidsbeurs.nl, 1
 achterstieg.dedyn.io, 1
@@ -867,17 +867,16 @@ ahmedabadflowermall.com, 1
 ahmedcharles.com, 1
 ahmerjamilkhan.org, 1
 aholic.co, 1
 ahoy.travel, 1
 ahoyconference.com, 1
 ahrq.gov, 0
 ahughes03.com, 1
 ahwah.net, 1
-ahwatukeefoothillsmontessori.com, 1
 ahxxm.com, 1
 ai-english.jp, 1
 aia.de, 1
 aibenzi.com, 1
 aicial.com, 1
 aidanmontare.net, 1
 aide-valais.ch, 1
 aiden.link, 1
@@ -1062,16 +1061,17 @@ aliantsoft.pl, 1
 alibangash.com, 1
 alibip.de, 1
 alicestudio.it, 1
 alicetone.net, 1
 alicialab.org, 1
 alienation.biz, 1
 alienstat.com, 1
 alignrs.com, 1
+alilialili.ga, 1
 alinasmusicstudio.com, 1
 alinode.com, 1
 alisonisrealestate.com, 1
 alisonlitchfield.com, 1
 alistairpialek.com, 1
 alistairstowing.com, 1
 alisync.com, 1
 aliwebstore.com, 1
@@ -2387,16 +2387,17 @@ bascht.com, 1
 basculasconfiables.com, 1
 base-autonome-durable.com, 1
 baseballrampage.com, 1
 baseballsavings.com, 1
 baseballwarehouse.com, 1
 baselang.com, 1
 basementdoctor.com, 1
 basementdoctornorthwest.com, 1
+bashc.at, 1
 bashstreetband.co.uk, 1
 basilicaknights.org, 1
 basilm.co, 1
 baskettemple.com, 1
 basnieuwenhuizen.nl, 1
 basnoslovno.com.ua, 1
 basnoslovno.ru, 1
 bass-pro.ru, 1
@@ -3509,16 +3510,17 @@ bridgeout.com, 1
 brie.tech, 1
 briefhansa.de, 1
 brightfuturemadebyme.com, 1
 brightonbank.com, 1
 brightonchilli.org.uk, 1
 brightstarkids.co.uk, 0
 brightstarkids.net, 0
 brightstarkids.sg, 0
+brigidaarie.com, 1
 brilliantdecisionmaking.com, 1
 brinkhu.is, 1
 brinquedoseducativos.art.br, 1
 brio-shop.ch, 1
 brisbanelogistics.com.au, 1
 bristebein.com, 1
 britelocate.com, 1
 britishbeef.com, 1
@@ -3699,16 +3701,17 @@ burtrum.name, 1
 burtrum.org, 1
 burzmali.com, 1
 bush41.org, 1
 bushbaby.com, 1
 busindre.com, 1
 business-garden.com, 1
 business.facebook.com, 0
 business.medbank.com.mt, 1
+businessadviceperth.com.au, 0
 businessamongus.com, 1
 businesscentermarin.ch, 1
 businessesdirectory.eu, 1
 businessfurs.info, 1
 businesshub.cz, 1
 businessimmigration-eu.com, 1
 businessimmigration-eu.ru, 1
 businessmodeler.se, 1
@@ -4551,17 +4554,16 @@ christopherpritchard.co.uk, 1
 christophertruncer.com, 1
 christophkreileder.com, 1
 christophsackl.de, 1
 chrisu3050.at, 1
 chrisupjohn.xyz, 1
 chriswarrick.com, 1
 chriswbarry.com, 1
 chriswells.io, 1
-chromaryu.net, 0
 chromaxa.com, 1
 chrome-devtools-frontend.appspot.com, 1
 chrome.com, 0
 chrome.google.com, 1
 chromebookchart.com, 1
 chromebooksforwork.com, 1
 chromiumbugs.appspot.com, 1
 chromiumcodereview.appspot.com, 0
@@ -4694,16 +4696,17 @@ clapping-rhymes.com, 1
 clarkeaward.com, 1
 clashersrepublic.com, 1
 classdojo.com, 1
 classicalpilates.ca, 1
 classics.io, 1
 classpoint.cz, 1
 classteaching.com.au, 1
 claudia-urio.com, 1
+claudio4.com, 1
 clauseriksen.net, 1
 clawe.de, 1
 clayandcottonkirkwood.com, 1
 claytoncondon.com, 1
 cldly.com, 1
 clearblueday.co.uk, 1
 clearchatsandbox.com, 1
 clearkonjac.com, 1
@@ -4772,16 +4775,17 @@ cloudbasedsite.com, 1
 cloudbleed.info, 1
 cloudbolin.es, 1
 cloudcaprice.net, 1
 cloudflareonazure.com, 1
 cloudia.org, 1
 cloudily.com, 1
 cloudlight.biz, 1
 cloudmigrator365.com, 1
+cloudopt.net, 1
 cloudoptimizedsmb.com, 1
 cloudoptimus.com, 1
 cloudpagesforwork.com, 1
 cloudpebble.net, 1
 cloudpengu.in, 1
 cloudpipes.com, 1
 cloudsecurityalliance.org, 1
 cloudservice.io, 1
@@ -5814,18 +5818,16 @@ danielehniss.de, 1
 danielepestilli.com, 1
 danielhochleitner.de, 1
 danieljamesscott.org, 1
 danieljireh.com, 1
 danielkoster.nl, 1
 danielkratz.com, 1
 danielmarquard.com, 1
 danielmoch.com, 1
-danielmostertman.com, 1
-danielmostertman.nl, 1
 danielrozenberg.com, 1
 danielsblog.org, 1
 danielschreurs.com, 1
 danielstach.cz, 1
 danielthompson.info, 1
 danieltollot.de, 1
 danielvoogsgerd.nl, 1
 danielzuzevich.com, 1
@@ -6343,16 +6345,18 @@ deviant.email, 1
 devillers-occasions.be, 1
 devilshakerz.com, 1
 deviltracks.net, 1
 devinfo.net, 0
 devisnow.fr, 1
 devistravaux.org, 1
 devjack.de, 1
 devkid.net, 1
+devkit.cc, 1
+devklog.net, 1
 devlamvzw.org, 1
 devlatron.net, 1
 devlogr.com, 1
 devlux.ch, 1
 devolution.ws, 1
 devonsawatzky.ca, 1
 devops-survey.com, 1
 devops.moe, 1
@@ -7431,16 +7435,17 @@ einar.io, 1
 einaros.is, 1
 einfachbahn.de, 1
 einfachmaldiefressehalten.de, 1
 einheft.info, 1
 einheizpreis.de, 1
 einmonolog.de, 1
 einsatzstellenverwaltung.de, 1
 einsatzstiefel.info, 1
+einsteinathome.org, 1
 eintageinzug.de, 1
 eintragsservice24.de, 1
 eipione.com, 1
 eirastudios.co.uk, 0
 eisaev.ru, 1
 eisp.it, 0
 eit-web.de, 0
 eitler.cx, 1
@@ -7688,16 +7693,17 @@ energy.eu, 1
 energyatlas.com, 1
 energyaupair.se, 1
 energydrinkblog.de, 1
 energyelephant.com, 1
 energyled.com.br, 1
 enersec.co.uk, 1
 enet-navigator.de, 1
 enfantsdelarue.ch, 1
+enfield-kitchens.co.uk, 1
 enfoqueseguro.com, 1
 enfu.se, 1
 engarde.net, 1
 engaugetools.com, 1
 engelundlicht.ch, 1
 engg.ca, 1
 engineowning.com, 1
 enginepit.com, 1
@@ -8141,17 +8147,16 @@ exactphilosophy.net, 1
 examenpilotos.com, 0
 example.sc, 1
 example.wf, 1
 exampleessays.com, 1
 exaplac.com, 1
 exceed.global, 1
 exceltobarcode.com, 1
 excessamerica.com, 1
-exchangecoordinator.com, 1
 exchangeworks.co, 1
 exe-boss.tech, 1
 exehack.net, 1
 exeintel.com, 1
 exekutori.com, 1
 exembit.com, 1
 exemples-de-stands.com, 1
 exeria.de, 1
@@ -8371,17 +8376,16 @@ faq.ie, 1
 faq.lookout.com, 0
 fara.gov, 1
 faraslot8.com, 1
 faraslot8.net, 1
 faretravel.co.uk, 1
 farfallapets.com.br, 1
 farfetchos.com, 1
 fargtorget.se, 1
-farhadexchange.com, 1
 farhood.org, 1
 farkas.bz, 1
 farm24.co.uk, 1
 farmacia.pt, 1
 farmaciaformula.com.br, 1
 farmacialaboratorio.it, 1
 farmer.dating, 1
 farmkazuto.com, 1
@@ -11439,17 +11443,16 @@ idemo.in, 1
 idensys.nl, 1
 identifyme.net, 1
 identity-hash.online, 1
 identitytheft.gov, 1
 idexxpublicationportal.com, 1
 idgard.de, 1
 idhosts.co.id, 1
 idid.tk, 1
-idinby.dk, 1
 idiopolis.org, 1
 idiotentruppe.de, 1
 idmanagement.gov, 1
 idmobile.co.uk, 1
 idndx.com, 1
 idoc24.com, 1
 idol-bikes.ru, 1
 idolf.dk, 1
@@ -11996,16 +11999,17 @@ ipcareers.net, 1
 ipcfg.me, 1
 ipconsulting.se, 1
 ipfirebox.de, 1
 ipfp.pl, 1
 ipfs.ink, 1
 iphoneunlock.nu, 1
 ipintel.io, 1
 iplabs.de, 1
+iplantom.com, 1
 ipleak.net, 1
 ipledgeonline.org, 0
 iplog.info, 1
 ipmotion.ca, 1
 ipo-times.com, 1
 ipokabu.net, 1
 ipomue.com, 0
 ipop.gr, 1
@@ -13017,17 +13021,16 @@ kantankye.nl, 1
 kantanmt.com, 1
 kantorad.io, 1
 kantorosobisty.pl, 1
 kanuvu.de, 1
 kanzashi.com, 1
 kanzlei-sixt.de, 1
 kap-genial.de, 1
 kapo.info, 1
-kappit.dk, 1
 kapseli.net, 1
 kaptadata.com, 1
 kaptamedia.com, 1
 karabas.com, 1
 karabijnhaken.nl, 0
 karachi.dating, 1
 karamna.com, 1
 karamomo.net, 1
@@ -13686,16 +13689,17 @@ ks-watch.de, 1
 kschv-rdeck.de, 1
 ksero.center, 1
 kshlm.in, 1
 ksukelife.com, 1
 kswcosmetics.com, 1
 ktbnetbank.com, 1
 kteen.info, 1
 kthnxbai.xyz, 1
+kts-thueringen.de, 1
 ktsee.eu.org, 1
 ktube.yt, 1
 ku.io, 1
 kualo.co.uk, 1
 kualo.com, 1
 kualo.in, 1
 kuaza.com, 1
 kub.hr, 1
@@ -14598,17 +14602,16 @@ locksport.org.nz, 1
 lockyourcomputer.pw, 1
 locomore.com, 1
 lodash.com, 0
 lodgesdureynou.fr, 1
 loenshotel.de, 1
 loforo.com, 1
 lofttravel.com, 1
 log.my, 0
-log2n.uk, 1
 logaldeveloper.com, 1
 loganmarchione.com, 1
 loganparkneighborhood.org, 1
 logbook.ch, 1
 logcat.info, 1
 logement-saisonnier.com, 1
 logentries.com, 0
 logfile.at, 1
@@ -15551,16 +15554,17 @@ mcynews.com, 1
 mcyukon.com, 1
 md5file.com, 1
 md5hashing.net, 1
 mdcloudpracticesolutions.com, 1
 mdcloudps.com, 1
 mdek.at, 1
 mdewendt.de, 1
 mdf-bis.com, 1
+mdkr.nl, 1
 mdma.net, 1
 mdmed.clinic, 1
 mdosch.de, 1
 mdpraha.cz, 1
 mdsave.com, 1
 mdwftw.com, 1
 mdx.no, 1
 mdxn.org, 1
@@ -16592,17 +16596,16 @@ musmann.io, 1
 muspla.com, 1
 muspla.com.br, 1
 musselsblog.com, 1
 mustard.co.uk, 1
 musthavesforreal.com, 1
 mutantmonkey.in, 1
 mutantmonkey.info, 1
 mutantmonkey.sexy, 1
-mutuals.cool, 1
 mutuelle.fr, 1
 muusikoiden.net, 1
 muwatenraqamy.org, 1
 muzeumkomiksu.eu, 1
 muzi.cz, 1
 mv-wohnen.de, 1
 mvbits.com, 1
 mvnet.com.br, 1
@@ -17410,17 +17413,16 @@ nikandcara.com, 1
 nikao-tech.com, 1
 nikavandenbos.nl, 1
 nikimix.com, 1
 nikkila.me, 1
 nikklassen.ca, 1
 nikksno.io, 1
 niklas.pw, 1
 niklasbabel.com, 1
-nikobradshaw.com, 1
 nikolaichik.photo, 1
 nikolasbradshaw.com, 1
 nikolasgrottendieck.com, 1
 nikomo.fi, 0
 nikz.in, 1
 nil.gs, 1
 nilrem.org, 1
 nimeshjm.com, 1
@@ -17537,17 +17539,16 @@ noob-box.net, 1
 noobunbox.net, 1
 noodles.net.nz, 1
 noodplan.co.za, 1
 noodweer.be, 1
 noop.ch, 1
 noordsee.de, 1
 noorsolidarity.com, 1
 nootropic.com, 1
-nootropicsource.com, 1
 nopaste.xyz, 1
 nord-sud.be, 1
 nordakademie.de, 1
 nordic-survival.de, 1
 nordiccasinocommunity.com, 1
 nordinfo.fi, 1
 nordnetz-hamburg.de, 1
 nordor.homeip.net, 1
@@ -18639,16 +18640,17 @@ pbcknd.ml, 1
 pbosquet.com, 1
 pbraunschdash.com, 1
 pbreen.co.uk, 1
 pbrumby.com, 1
 pbscreens.com, 1
 pbytes.com, 1
 pc-rescue.me, 1
 pc-tweak.de, 1
+pccentral.nl, 1
 pcel.com, 1
 pcf92.fr, 1
 pcfeuerwehr.de, 1
 pcforum.sk, 1
 pcgamingfreaks.at, 1
 pchelpforum.net, 1
 pciconcursos.com.br, 1
 pcipac.com, 1
@@ -19688,16 +19690,17 @@ proweser.de, 1
 prowise.com, 1
 proxybay.co, 1
 proxybay.eu.org, 1
 proxybay.la, 1
 proxybay.one, 1
 proxybay.tv, 1
 proxydesk.eu, 1
 proxyportal.me, 1
+proxyportal.org, 1
 proxyweb.us, 1
 proymaganadera.com, 1
 prstatic.com, 1
 prt.in.th, 1
 prtimes.com, 1
 prtpe.com, 1
 pruikshop.nl, 1
 prvikvadrat.hr, 1
@@ -20250,16 +20253,17 @@ recordeuropa.com, 0
 recoveringspirit.com, 1
 recreation.gov, 1
 recreoviral.com, 1
 recruitsecuritytraining.co.uk, 1
 recruitsecuritytraining.com, 1
 rectoraudiparts.com, 1
 recuerdafilms.com, 1
 recurly.com, 1
+recyclingpromotions.us, 1
 red-t-shirt.ru, 1
 redable.hosting, 1
 redable.nl, 1
 redair.es, 1
 redb.cz, 1
 redballoonsecurity.com, 1
 redburn.com, 1
 redcomet.org, 1
@@ -20896,16 +20900,17 @@ rs-devdemo.host, 1
 rsgcard.com, 1
 rsi.im, 0
 rsingermd.com, 1
 rsm-liga.de, 1
 rss.sh, 0
 rssr.se, 1
 rstraining.co.uk, 1
 rstsecuritygroup.co.uk, 1
+rsttraining.co.uk, 1
 rsvaachen.de, 1
 rsync.eu, 0
 rtate.ca, 1
 rtate.se, 1
 rtc.fun, 1
 rtcx.net, 1
 rtd.uk.com, 1
 rte.eu, 1
@@ -21924,16 +21929,17 @@ shanewadleigh.com, 1
 shang-yu.cn, 1
 shannoneichorn.com, 1
 shansing.cn, 1
 shansing.com, 1
 shansing.net, 1
 shansing.space, 1
 sharanyamunsi.net, 1
 sharedhost.de, 1
+shareeri.com, 1
 sharekey.com, 1
 shareoffice.ch, 1
 shareoine.com, 1
 sharepointdrive.com, 1
 sharescope.co.uk, 0
 shareselecttools.com, 1
 sharesplitter.com, 1
 sharevari.com, 1
@@ -21972,17 +21978,16 @@ sheratan.web.id, 1
 sherbers.de, 1
 shethbox.com, 1
 shevronpatriot.ru, 1
 sheying.tm, 1
 shft.cl, 1
 shgt.jp, 1
 shh-listen.com, 1
 shh.sh, 1
-shiatsu-institut.ch, 1
 shiawasedo.co.jp, 1
 shibainu.com.br, 1
 shichibukai.net, 1
 shieldofachilles.in, 1
 shift-to.co.jp, 1
 shiftdevices.com, 1
 shiftj.is, 1
 shiftleft.org, 1
@@ -22527,17 +22532,16 @@ smatch.com, 1
 smb445.com, 1
 smdavis.us, 1
 smdcn.net, 1
 sme-gmbh.net, 1
 smeetsengraas.com, 1
 smiatek.name, 1
 smileandpay.com, 1
 smileawei.com, 1
-smiledirectsales.com, 1
 smime.io, 1
 smipty.cn, 1
 smipty.com, 1
 smit.com.ua, 1
 smith.is, 1
 smithandcanova.co.uk, 1
 smkw.com, 0
 sml.lc, 1
@@ -23352,16 +23356,17 @@ strutta.me, 1
 struxureon.com, 1
 strydom.me.uk, 1
 stt.wiki, 1
 stuartbell.co.uk, 1
 stuco.co, 1
 studenckiemetody.pl, 1
 student-eshop.cz, 1
 student-eshop.sk, 1
+student.andover.edu, 1
 studentforums.biz, 1
 studentite.bg, 0
 studentloans.gov, 1
 studentrightsadvocate.org, 1
 studentshare.net, 1
 studenttenant.com, 1
 studer.su, 1
 studienportal.eu, 1
@@ -23700,16 +23705,17 @@ t2000headphones.com, 1
 t2000laserpointers.com, 1
 t23m-navi.jp, 0
 t2i.nl, 1
 t3rror.net, 1
 t7e.de, 0
 ta-65.com, 1
 ta-sports.net, 1
 ta65.com, 1
+taartenfeesies.nl, 1
 tab.watch, 1
 tabelfirme.ro, 1
 tabernadovinho.com.br, 1
 taberu-fujitsubo.com, 1
 tabithawebb.co.uk, 1
 tabla-periodica.com, 1
 tablescraps.com, 1
 tablet.facebook.com, 0
@@ -23725,16 +23731,17 @@ tadcastercircuit.org.uk, 1
 tadtadya.com, 1
 tadu.de, 1
 tagdocumentary.com, 1
 tagesmutter-in-bilm.de, 1
 taggedpdf.com, 1
 taglioepiega.com, 1
 taglioepiega.eu, 1
 taglioepiega.it, 1
+tahakomat.cz, 1
 tahf.net, 1
 tahosa.co, 1
 tahosalodge.org, 1
 taidu.news, 1
 tailpuff.net, 1
 tails.boum.org, 1
 taim.io, 1
 taishon.nagoya, 1
@@ -23828,17 +23835,16 @@ tateesq.com, 1
 tatiloley.com, 1
 tatort-fanpage.de, 1
 tatsidou.gr, 1
 tattoo.dating, 1
 tattvaayoga.com, 1
 tavolaquadrada.com.br, 1
 tavsys.net, 1
 taxaroo.com, 1
-taxi-24std.de, 1
 taxi-chamonix.fr, 1
 taxi-collectif.ch, 1
 taxicollectif.ch, 1
 taxis-collectifs.ch, 1
 taxisafmatosinhos.pt, 1
 taxiscollectifs.ch, 1
 taxlab.co.nz, 1
 taxmadras.com, 1
@@ -24161,17 +24167,17 @@ thai.dating, 1
 thai.land, 0
 thaianthro.com, 1
 thaicyberpoint.com, 1
 thaiforest.ch, 1
 thaigirls.xyz, 1
 thaihomecooking.com, 1
 thailandpharmacy.net, 1
 thailandpropertylisting.com, 1
-thaimooc.org, 1
+thaimooc.org, 0
 thairehabassociation.com, 1
 thajskyraj.com, 1
 thalan.fr, 1
 thalgott.net, 1
 thalhammer.it, 1
 thalskarth.com, 1
 thamesfamilydentistry.com, 1
 thanatoid.net, 1
@@ -24627,17 +24633,16 @@ tjs.me, 1
 tkacz.pro, 1
 tkarstens.de, 0
 tkat.ch, 1
 tkgpm.com, 1
 tkjg.fi, 1
 tkn.tokyo, 1
 tkts.cl, 1
 tkusano.jp, 1
-tlach.cz, 1
 tlehseasyads.com, 1
 tlo.xyz, 1
 tloxygen.com, 1
 tls.builders, 1
 tls.care, 1
 tls1914.org, 1
 tlsrobot.se, 1
 tlthings.net, 1
@@ -25036,17 +25041,16 @@ translate.stg.fedoraproject.org, 1
 translateblender.ru, 1
 translatoruk.co.uk, 1
 transmisjeonline.pl, 1
 transmithe.net, 1
 transparentcorp.com, 1
 transport.eu, 1
 transsexualpantyhose.com, 1
 transverify.com, 1
-trashnothing.com, 1
 trask.no, 1
 trauertexte.info, 1
 traumhuetten.de, 1
 traut.cloud, 1
 travador.com, 1
 travaux-toiture-idf.fr, 1
 travel-dealz.de, 1
 travel-to-nature.ch, 1
@@ -25620,16 +25624,17 @@ urban-culture.fr, 1
 urban.melbourne, 1
 urbanesecurity.com, 1
 urbanfi.sh, 1
 urbanguerillas.de, 1
 urbanietz-immobilien.de, 1
 urbanmelbourne.info, 1
 urbannewsservice.com, 1
 urbansparrow.in, 1
+urbanstylestaging.com, 1
 urbanwildlifealliance.org, 1
 urbexdk.nl, 1
 urcentral.com, 1
 urcentral.org, 1
 ureka.org, 1
 urgences-valais.ch, 1
 uripura.de, 1
 urist1011.ru, 1
@@ -25688,33 +25693,32 @@ utilitarian.org, 1
 utilitarianism.com, 1
 utilitarianism.org, 1
 utilitarismo.com, 1
 utilitronium.com, 1
 utilityapi.com, 1
 utitreatment.com, 1
 utonia.ch, 1
 utopialgb.org.uk, 1
-utopianconcept.com, 1
 utopians.dk, 1
 utopicestudios.com, 1
 utox.io, 1
+uttnetgroup.fr, 0
 utugnn.ru, 1
 utw.me, 1
 uvocorp.com, 1
 uwesander.de, 1
 uwfreelanceopticien.nl, 1
 uwimonacs.org.jm, 1
 uygindir.ml, 1
 v-u-z.ru, 1
 v12.co.uk, 1
 v1sit0r.ru, 1
 v2bv.win, 1
 v2ex.com, 1
-v4s.ro, 1
 va-reitartikel.com, 1
 vaaddress.co, 1
 vacationscostarica.com, 1
 vaccines.gov, 1
 vaclavambroz.cz, 1
 vacuumpump.co.id, 1
 vacuumreviewcenter.com, 1
 vadennissanofhiltonheadparts.com, 1
@@ -25772,16 +25776,17 @@ vancouvercosmeticsurgery.ca, 1
 vandalfsen.me, 1
 vandam.io, 1
 vandenbroeck-usedcars.be, 1
 vandeput.be, 1
 vanderkrieken.org, 1
 vandermeer.frl, 1
 vanderrijt.nl, 1
 vanderziel.org, 1
+vanessabalibridal.com, 1
 vangeluwedeberlaere.be, 1
 vanhoudt-usedcars.be, 1
 vanhoutte.be, 0
 vanhove.biz, 1
 vanlaanen.com, 1
 vanmalland.com, 1
 vannaos.com, 1
 vannaos.net, 1
@@ -26061,16 +26066,17 @@ viridis-milites.cz, 1
 virtualdesignmedia.com, 0
 virtuallifestyle.nl, 1
 virtualsanity.com, 1
 virtualvaults.com, 1
 virtubox.net, 1
 virtusaero.com, 1
 visa-shinsei.com, 1
 visaexpert.co.za, 1
+visalogy.com, 1
 visaop.com, 1
 visapourailleurs.fr, 1
 visaya.com.co, 1
 viscoelastico.com.br, 1
 viscopic.com, 1
 vishwashantiyoga.com, 1
 visibox.nl, 1
 visikom.de, 1
@@ -26192,17 +26198,17 @@ vop.li, 1
 vorderklier.de, 1
 vorkbaard.nl, 1
 vorlicek.de, 1
 vorlif.org, 1
 vorm2.com, 1
 vorodevops.com, 1
 vos-fleurs.ch, 1
 vos-fleurs.com, 1
-voshod.org, 0
+voshod.org, 1
 vosky.fr, 1
 vostronet.com, 1
 voter-info.uk, 1
 voterstartingpoint.uk, 1
 votocek.cz, 1
 votockova.cz, 1
 votoot.com, 1
 votre-site-internet.ch, 1
@@ -26287,17 +26293,16 @@ wabatam.com, 1
 wabifoggynuts.com, 1
 wachter.biz, 1
 wadidi.com, 1
 wadsworth.gallery, 1
 wadvisor.com, 1
 waelisch.de, 1
 waelti.xxx, 1
 wafa4hw.com, 1
-wafairhaven.com.au, 1
 waffle.at, 1
 wafni.com, 1
 wahidhasan.com, 1
 wahlman.org, 1
 wahrnehmungswelt.de, 1
 wahrnehmungswelten.de, 1
 wai-in.com, 1
 waigel.org, 1
@@ -26861,16 +26866,17 @@ winter.engineering, 0
 winterbergwebcams.com, 1
 wintercircle.co, 1
 winterfeldt.de, 1
 winterhillbank.com, 1
 wintermeyer-consulting.de, 1
 wintermeyer.de, 1
 winterschoen.nl, 1
 wintodoor.com, 1
+wipc.net, 1
 wipply.com, 0
 wir-bewegen.sh, 1
 wirbatz.org, 1
 wircon-int.net, 1
 wiredcut.com, 1
 wireframesoftware.com, 1
 wireheading.com, 1
 wireless-emergency-stop.com, 1
@@ -27794,17 +27800,16 @@ zamis.net, 1
 zamocosmeticos.com.br, 1
 zamow.co, 1
 zandcell.com, 1
 zanthra.com, 1
 zapier.com, 1
 zappbuildapps.com, 1
 zaratan.fr, 1
 zarmarket.org, 1
-zary.me, 1
 zaufanatrzeciastrona.pl, 1
 zavetaji.lv, 1
 zawo-electric.de, 1
 zbasenem.pl, 1
 zbchen.com, 1
 zberger.com, 1
 zbetcheck.in, 1
 zbp.at, 0
@@ -27877,17 +27882,16 @@ zevelev.net, 1
 zewtie.com, 1
 zfast.com.br, 1
 zfly.me, 1
 zfo.gg, 1
 zfree.co.nz, 1
 zgrep.org, 1
 zhang-hao.com, 1
 zhangfangzhou.com, 1
-zhangge.net, 1
 zhanghao.me, 1
 zhangsidan.com, 1
 zhangsir.net, 1
 zhangyuhao.com, 1
 zhangzifan.com, 1
 zhaochen.xyz, 1
 zhaofeng.li, 1
 zhaoxixiangban.cc, 1
@@ -27942,16 +27946,17 @@ zobraz.cz, 1
 zoeller.me, 1
 zohar.shop, 1
 zohar.wang, 0
 zoigl.club, 1
 zojadravai.com, 1
 zoki.art, 1
 zokster.net, 1
 zolokar.xyz, 1
+zolotoy-standart.com.ua, 1
 zombiesecured.com, 1
 zomerschoen.nl, 1
 zone-produkte.de, 1
 zone39.com, 1
 zonecb.com, 1
 zonemaster.fr, 1
 zonemaster.net, 1
 zonesec.org, 1
--- a/security/sandbox/linux/SandboxUtil.cpp
+++ b/security/sandbox/linux/SandboxUtil.cpp
@@ -57,17 +57,16 @@ WriteStringToFile(const char* aPath, con
 bool
 UnshareUserNamespace()
 {
   // The uid and gid need to be retrieved before the unshare; see
   // below.
   uid_t uid = getuid();
   gid_t gid = getgid();
   char buf[80];
-  size_t len;
 
   if (syscall(__NR_unshare, CLONE_NEWUSER) != 0) {
     return false;
   }
 
   // As mentioned in the header, this function sets up uid/gid
   // mappings that preserve the process's previous ids.  Mapping the
   // uid/gid to something is necessary in order to nest user
@@ -79,25 +78,29 @@ UnshareUserNamespace()
   // establishing gid mappings will fail unless the process first
   // revokes its ability to call setgroups() by using a /proc node
   // added in the same set of patches.
   //
   // Note that /proc/self points to the thread group leader, not the
   // current thread.  However, CLONE_NEWUSER can be unshared only in a
   // single-threaded process, so those are equivalent if we reach this
   // point.
-  len = size_t(SprintfLiteral(buf, "%u %u 1\n", uid, uid));
-  MOZ_ASSERT(len < sizeof(buf));
-  if (!WriteStringToFile("/proc/self/uid_map", buf, len)) {
+  int len = SprintfLiteral(buf, "%u %u 1\n", uid, uid);
+  if (len >= int(sizeof(buf)) || len < 0) {
+    return false;
+  }
+  if (!WriteStringToFile("/proc/self/uid_map", buf, size_t(len))) {
     MOZ_CRASH("Failed to write /proc/self/uid_map");
   }
 
   Unused << WriteStringToFile("/proc/self/setgroups", "deny", 4);
 
-  len = size_t(SprintfLiteral(buf, "%u %u 1\n", gid, gid));
-  MOZ_ASSERT(len < sizeof(buf));
-  if (!WriteStringToFile("/proc/self/gid_map", buf, len)) {
+  len = SprintfLiteral(buf, "%u %u 1\n", gid, gid);
+  if (len >= int(sizeof(buf)) || len < 0) {
+    return false;
+  }
+  if (!WriteStringToFile("/proc/self/gid_map", buf, size_t(len))) {
     MOZ_CRASH("Failed to write /proc/self/gid_map");
   }
   return true;
 }
 
 } // namespace mozilla
--- a/testing/talos/talos/ffsetup.py
+++ b/testing/talos/talos/ffsetup.py
@@ -88,20 +88,16 @@ class FFSetup(object):
             if type(value) is str:
                 value = utils.interpolate(value, webserver=webserver)
                 preferences[name] = value
 
         extensions = self.browser_config['extensions'][:]
         if self.test_config.get('extensions'):
             extensions.append(self.test_config['extensions'])
 
-        if self.browser_config['develop'] or \
-           'try' in str.lower(self.browser_config['branch_name']):
-            extensions = [os.path.dirname(i) for i in extensions]
-
         # downloading a profile instead of using the empty one
         if self.test_config['profile'] is not None:
             path = heavy.download_profile(self.test_config['profile'])
             self.test_config['profile_path'] = path
 
         profile = Profile.clone(
             os.path.normpath(self.test_config['profile_path']),
             self.profile_dir,
--- a/testing/talos/talos/run_tests.py
+++ b/testing/talos/talos/run_tests.py
@@ -113,22 +113,16 @@ def run_tests(config, browser_config):
         test['profile'] = config.get('profile')
 
     # pass --no-remote to firefox launch, if --develop is specified
     # we do that to allow locally the user to have another running firefox
     # instance
     if browser_config['develop']:
         browser_config['extra_args'] = '--no-remote'
 
-    # with addon signing for production talos, we want to develop without it
-    if browser_config['develop'] or 'try' in str.lower(browser_config['branch_name']):
-        browser_config['preferences']['xpinstall.signatures.required'] = False
-
-    browser_config['preferences']['extensions.allow-non-mpc-extensions'] = True
-
     # if using firstNonBlankPaint, must turn on pref for it
     if test.get('fnbpaint', False):
         LOG.info("Using firstNonBlankPaint, so turning on pref for it")
         browser_config['preferences']['dom.performance.time_to_non_blank_paint.enabled'] = True
 
     # set defaults
     testdate = config.get('testdate', '')
 
deleted file mode 100644
--- a/testing/web-platform/meta/domxpath/interfaces.html.ini
+++ /dev/null
@@ -1,38 +0,0 @@
-[interfaces.html]
-  type: testharness
-  [XPathEvaluator interface: operation createExpression(DOMString,XPathNSResolver)]
-    expected: FAIL
-
-  [XPathEvaluator interface: operation evaluate(DOMString,Node,XPathNSResolver,unsigned short,object)]
-    expected: FAIL
-
-  [XPathExpression interface: operation evaluate(Node,unsigned short,object)]
-    expected: FAIL
-
-  [Document interface: operation createExpression(DOMString,XPathNSResolver)]
-    expected: FAIL
-
-  [Document interface: operation evaluate(DOMString,Node,XPathNSResolver,unsigned short,object)]
-    expected: FAIL
-
-  [Document must be primary interface of document]
-    expected: FAIL
-
-  [Stringification of document]
-    expected: FAIL
-
-  [XPathEvaluator interface: operation createExpression(DOMString, XPathNSResolver)]
-    expected: FAIL
-
-  [XPathEvaluator interface: operation evaluate(DOMString, Node, XPathNSResolver, unsigned short, object)]
-    expected: FAIL
-
-  [XPathExpression interface: operation evaluate(Node, unsigned short, object)]
-    expected: FAIL
-
-  [Document interface: operation createExpression(DOMString, XPathNSResolver)]
-    expected: FAIL
-
-  [Document interface: operation evaluate(DOMString, Node, XPathNSResolver, unsigned short, object)]
-    expected: FAIL
-
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -313,17 +313,18 @@ var dataProviders = {
   experiments: function experiments(done) {
     if (Experiments === undefined) {
       done([]);
       return;
     }
 
     // getExperiments promises experiment history
     Experiments.instance().getExperiments().then(
-      experiments => done(experiments)
+      experiments => done(experiments),
+      () => done([])
     );
   },
 
   modifiedPreferences: function modifiedPreferences(done) {
     done(getPrefList(name => Services.prefs.prefHasUserValue(name)));
   },
 
   lockedPreferences: function lockedPreferences(done) {
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -1445,18 +1445,22 @@ NS_IMETHODIMP nsDocLoader::AsyncOnChanne
     aOldChannel->GetLoadFlags(&loadFlags);
     // If the document channel is being redirected, then indicate that the
     // document is being redirected in the notification...
     if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI)
     {
       stateFlags |= nsIWebProgressListener::STATE_IS_DOCUMENT;
 
 #if defined(DEBUG)
-      nsCOMPtr<nsIRequest> request(do_QueryInterface(aOldChannel));
-      NS_ASSERTION(request == mDocumentRequest, "Wrong Document Channel");
+      // We only set mDocumentRequest in OnStartRequest(), but its possible
+      // to get a redirect before that for service worker interception.
+      if (mDocumentRequest) {
+        nsCOMPtr<nsIRequest> request(do_QueryInterface(aOldChannel));
+        NS_ASSERTION(request == mDocumentRequest, "Wrong Document Channel");
+      }
 #endif /* DEBUG */
     }
 
     OnRedirectStateChange(aOldChannel, aNewChannel, aFlags, stateFlags);
     FireOnStateChange(this, aOldChannel, stateFlags, NS_OK);
   }
 
   cb->OnRedirectVerifyCallback(NS_OK);
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -701,17 +701,17 @@ nsSystemInfo::Init()
 #endif
 
   if (gtkver_len <= 0) {
     gtkver_len = SprintfLiteral(gtkver, "GTK %u.%u.%u", gtk_major_version,
                                 gtk_minor_version, gtk_micro_version);
   }
 
   nsAutoCString secondaryLibrary;
-  if (gtkver_len > 0) {
+  if (gtkver_len > 0 && gtkver_len < int(sizeof(gtkver))) {
     secondaryLibrary.Append(nsDependentCSubstring(gtkver, gtkver_len));
   }
 
   void* libpulse = dlopen("libpulse.so.0", RTLD_LAZY);
   const char* libpulseVersion = "not-available";
   if (libpulse) {
     auto pa_get_library_version = reinterpret_cast<const char* (*)()>
       (dlsym(libpulse, "pa_get_library_version"));
--- a/xpcom/ds/nsTArray.h
+++ b/xpcom/ds/nsTArray.h
@@ -32,16 +32,17 @@
 #include "nsRegionFwd.h"
 #include <functional>
 #include <initializer_list>
 #include <new>
 
 namespace JS {
 template<class T>
 class Heap;
+class ObjectPtr;
 } /* namespace JS */
 
 class nsRegion;
 namespace mozilla {
 namespace layers {
 struct TileClient;
 } // namespace layers
 } // namespace mozilla
@@ -703,55 +704,53 @@ struct nsTArray_CopyWithConstructors
 };
 
 //
 // The default behaviour is to use memcpy/memmove for everything.
 //
 template<class E>
 struct MOZ_NEEDS_MEMMOVABLE_TYPE nsTArray_CopyChooser
 {
-  typedef nsTArray_CopyWithMemutils Type;
+  using Type = nsTArray_CopyWithMemutils;
 };
 
 //
 // Some classes require constructors/destructors to be called, so they are
 // specialized here.
 //
 #define DECLARE_USE_COPY_CONSTRUCTORS(T)                \
   template<>                                            \
   struct nsTArray_CopyChooser<T>                        \
   {                                                     \
-    typedef nsTArray_CopyWithConstructors<T> Type;      \
+    using Type = nsTArray_CopyWithConstructors<T>;      \
   };
 
-template<class E>
-struct nsTArray_CopyChooser<JS::Heap<E>>
-{
-  typedef nsTArray_CopyWithConstructors<JS::Heap<E>> Type;
-};
+#define DECLARE_USE_COPY_CONSTRUCTORS_FOR_TEMPLATE(T)   \
+  template<typename S>                                  \
+  struct nsTArray_CopyChooser<T<S>>                     \
+  {                                                     \
+    using Type = nsTArray_CopyWithConstructors<T<S>>;   \
+  };
+
+DECLARE_USE_COPY_CONSTRUCTORS_FOR_TEMPLATE(JS::Heap)
+DECLARE_USE_COPY_CONSTRUCTORS_FOR_TEMPLATE(std::function)
 
 DECLARE_USE_COPY_CONSTRUCTORS(nsRegion)
 DECLARE_USE_COPY_CONSTRUCTORS(nsIntRegion)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::layers::TileClient)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::SerializedStructuredCloneBuffer)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::ipc::StructuredCloneData)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::ClonedMessageData)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::indexedDB::StructuredCloneReadInfo);
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::indexedDB::ObjectStoreCursorResponse)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::indexedDB::SerializedStructuredCloneReadInfo);
 DECLARE_USE_COPY_CONSTRUCTORS(JSStructuredCloneData)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::MessagePortMessage)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::SourceBufferTask)
-
-template<typename T>
-struct nsTArray_CopyChooser<std::function<T>>
-{
-  typedef nsTArray_CopyWithConstructors<std::function<T>> Type;
-};
-
+DECLARE_USE_COPY_CONSTRUCTORS(JS::ObjectPtr)
 
 //
 // Base class for nsTArray_Impl that is templated on element type and derived
 // nsTArray_Impl class, to allow extra conversions to be added for specific
 // types.
 //
 template<class E, class Derived>
 struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper<E, Derived>
--- a/xpcom/threads/SystemGroup.cpp
+++ b/xpcom/threads/SystemGroup.cpp
@@ -12,50 +12,42 @@
 #include "nsINamed.h"
 
 using namespace mozilla;
 
 class SystemGroupImpl final : public SchedulerGroup
 {
 public:
   SystemGroupImpl();
-  ~SystemGroupImpl() {}
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SystemGroupImpl)
 
   static void InitStatic();
   static void ShutdownStatic();