merge mozilla-central to autoland. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Mon, 09 Oct 2017 23:56:28 +0200
changeset 435969 12293a4b3e23904229f8afd3e56805ffe072fde4
parent 435968 7e960acfd90c6a709e1cb157a5f9bf63b1a1349f (current diff)
parent 435955 2ed5e7fbf39e949693d8a7455d6313b14a7aeaf6 (diff)
child 435970 035d3125ca2f0e5eeb25a04be9faeaffd156546b
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-central to autoland. r=merge a=merge
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_CopyWithConstructor