Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 05 Jan 2017 17:30:35 -0800
changeset 328150 a14094edbad78fc1d16e8d4c57902537cf286fd1
parent 328082 53193729a50b40c00889b1fa07df8dffab7781f9 (current diff)
parent 328149 c216c29d0c1871c0ce71fe7100ab13924e0591ba (diff)
child 328151 7c082f3bbf0d75cdae5c13f758b1d40e3fb405c0
child 328179 5ae3e55675da612e605b8b982a42111e49d0e283
child 328229 6f7b660eb31b27b4411c856fd2bf68aff99033fa
push id31163
push userkwierso@gmail.com
push dateFri, 06 Jan 2017 01:30:45 +0000
treeherdermozilla-central@a14094edbad7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone53.0a1
first release with
nightly linux32
a14094edbad7 / 53.0a1 / 20170106030204 / files
nightly linux64
a14094edbad7 / 53.0a1 / 20170106030204 / files
nightly mac
a14094edbad7 / 53.0a1 / 20170106030204 / files
nightly win32
a14094edbad7 / 53.0a1 / 20170106030204 / files
nightly win64
a14094edbad7 / 53.0a1 / 20170106030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to central, a=merge MozReview-Commit-ID: 1ij6nLf8f8s
browser/base/content/browser.js
js/src/jit-test/tests/basic/bug1220766.js
layout/style/StyleAnimationValue.cpp
taskcluster/ci/test/test-platforms.yml
taskcluster/ci/test/tests.yml
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/IGeckoCustom.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import "objidl.idl";
+import "oaidl.idl";
+
+[object, uuid(7510360f-cdae-4de9-88c8-d167eda62afc)]
+interface IGeckoCustom : IUnknown
+{
+  [propget] HRESULT ID([out, retval] unsigned __int64* aID);
+  [propget] HRESULT anchorCount([out, retval] long* aCount);
+}
+
+
+[
+    uuid(55769d85-f830-4d76-9e39-3670914a28f7),
+    helpstring("private custom gecko interfaces")
+]
+library IGeckoCustom
+{
+  interface IGeckoCustom;
+};
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/Makefile.in
@@ -0,0 +1,31 @@
+# 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/.
+
+GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c
+
+MIDL_GENERATED_FILES = \
+	IGeckoCustom.h \
+	IGeckoCustom_p.c \
+	IGeckoCustom_i.c \
+	$(NULL)
+
+$(MIDL_GENERATED_FILES): done_gen
+
+done_gen: IGeckoCustom.idl
+	$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/IGeckoCustom.idl
+	touch $@
+
+export:: done_gen
+
+midl_exports := \
+    IGeckoCustom.h \
+    IGeckoCustom_i.c \
+    $(NULL)
+
+INSTALL_TARGETS += midl_exports
+midl_exports_FILES := $(midl_exports)
+midl_exports_DEST = $(DIST)/include
+midl_exports_TARGET := midl
+
+export:: midl
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/gecko/moz.build
@@ -0,0 +1,25 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+    '!dlldata.c',
+    '!IGeckoCustom_i.c',
+    '!IGeckoCustom_p.c',
+]
+
+GENERATED_FILES += [
+    'IGeckoCustom.tlb',
+]
+
+FINAL_LIBRARY = 'xul'
+
+# The Windows MIDL code generator creates things like:
+#
+#   #endif !_MIDL_USE_GUIDDEF_
+#
+# which clang-cl complains about.  MSVC doesn't, so turn this warning off.
+if CONFIG['CLANG_CL']:
+    CFLAGS += ['-Wno-extra-tokens']
--- a/accessible/interfaces/moz.build
+++ b/accessible/interfaces/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows' and CONFIG['COMPILE_ENVIRONMENT']:
-    DIRS += ['msaa', 'ia2']
+    DIRS += ['gecko', 'msaa', 'ia2']
 
 XPIDL_SOURCES += [
     'nsIAccessibilityService.idl',
     'nsIAccessible.idl',
     'nsIAccessibleApplication.idl',
     'nsIAccessibleCaretMoveEvent.idl',
     'nsIAccessibleDocument.idl',
     'nsIAccessibleEditableText.idl',
--- a/accessible/ipc/win/ProxyAccessible.cpp
+++ b/accessible/ipc/win/ProxyAccessible.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Accessible2.h"
 #include "ProxyAccessible.h"
 #include "ia2AccessibleValue.h"
+#include "IGeckoCustom.h"
 #include "mozilla/a11y/DocAccessibleParent.h"
 #include "DocAccessible.h"
 #include "mozilla/a11y/DocManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/Unused.h"
 #include "mozilla/a11y/Platform.h"
 #include "RelationType.h"
@@ -62,16 +63,28 @@ struct InterfaceIID<IAccessibleValue>
 };
 
 template<>
 struct InterfaceIID<IAccessibleText>
 {
   static REFIID Value() { return IID_IAccessibleText; }
 };
 
+template<>
+struct InterfaceIID<IAccessibleHyperlink>
+{
+  static REFIID Value() { return IID_IAccessibleHyperlink; }
+};
+
+template<>
+struct InterfaceIID<IGeckoCustom>
+{
+  static REFIID Value() { return IID_IGeckoCustom; }
+};
+
 /**
  * Get the COM proxy for this proxy accessible and QueryInterface it with the
  * correct IID
  */
 template<typename Interface>
 static already_AddRefed<Interface>
 QueryInterface(const ProxyAccessible* aProxy)
 {
@@ -84,16 +97,33 @@ QueryInterface(const ProxyAccessible* aP
   if (FAILED(acc->QueryInterface(InterfaceIID<Interface>::Value(),
                                  (void**)getter_AddRefs(acc2)))) {
     return nullptr;
   }
 
   return acc2.forget();
 }
 
+static ProxyAccessible*
+GetProxyFor(DocAccessibleParent* aDoc, IUnknown* aCOMProxy)
+{
+  RefPtr<IGeckoCustom> custom;
+  if (FAILED(aCOMProxy->QueryInterface(IID_IGeckoCustom,
+                                       (void**) getter_AddRefs(custom)))) {
+    return nullptr;
+  }
+
+  uint64_t id;
+  if (FAILED(custom->get_ID(&id))) {
+    return nullptr;
+  }
+
+  return aDoc->GetAccessible(id);
+}
+
 void
 ProxyAccessible::Name(nsString& aName) const
 {
   aName.Truncate();
   RefPtr<IAccessible> acc;
   if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
     return;
   }
@@ -590,10 +620,91 @@ ProxyAccessible::ScrollSubstringToPoint(
 
   acc->scrollSubstringToPoint(static_cast<long>(aStartOffset),
                               static_cast<long>(aEndOffset),
                               coordType,
                               static_cast<long>(aX),
                               static_cast<long>(aY));
 }
 
+uint32_t
+ProxyAccessible::StartOffset(bool* aOk)
+{
+  RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+  if (!acc) {
+    *aOk = false;
+    return 0;
+  }
+
+  long startOffset;
+  *aOk = SUCCEEDED(acc->get_startIndex(&startOffset));
+  return static_cast<uint32_t>(startOffset);
+}
+
+uint32_t
+ProxyAccessible::EndOffset(bool* aOk)
+{
+  RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+  if (!acc) {
+    *aOk = false;
+    return 0;
+  }
+
+  long endOffset;
+  *aOk = SUCCEEDED(acc->get_endIndex(&endOffset));
+  return static_cast<uint32_t>(endOffset);
+}
+
+bool
+ProxyAccessible::IsLinkValid()
+{
+  RefPtr<IAccessibleHyperlink> acc = QueryInterface<IAccessibleHyperlink>(this);
+  if (!acc) {
+    return false;
+  }
+
+  boolean valid;
+  if (FAILED(acc->get_valid(&valid))) {
+    return false;
+  }
+
+  return valid;
+}
+
+uint32_t
+ProxyAccessible::AnchorCount(bool* aOk)
+{
+  *aOk = false;
+  RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
+  if (!custom) {
+    return 0;
+  }
+
+  long count;
+  if (FAILED(custom->get_anchorCount(&count))) {
+    return 0;
+  }
+
+  *aOk = true;
+  return count;
+}
+
+ProxyAccessible*
+ProxyAccessible::AnchorAt(uint32_t aIdx)
+{
+  RefPtr<IAccessibleHyperlink> link = QueryInterface<IAccessibleHyperlink>(this);
+  if (!link) {
+    return nullptr;
+  }
+
+  VARIANT anchor;
+  if (FAILED(link->get_anchor(aIdx, &anchor))) {
+    return nullptr;
+  }
+
+  MOZ_ASSERT(anchor.vt == VT_UNKNOWN);
+  ProxyAccessible* proxyAnchor = GetProxyFor(Document(), anchor.punkVal);
+  anchor.punkVal->Release();
+  return proxyAnchor;
+}
+
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -6,16 +6,17 @@
 
 #include "AccessibleWrap.h"
 #include "Accessible-inl.h"
 
 #include "Compatibility.h"
 #include "DocAccessible-inl.h"
 #include "mozilla/a11y/DocAccessibleParent.h"
 #include "EnumVariant.h"
+#include "GeckoCustom.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibleEvent.h"
 #include "nsWinUtils.h"
 #include "mozilla/a11y/ProxyAccessible.h"
 #include "ProxyWrappers.h"
 #include "ServiceProvider.h"
 #include "Relation.h"
@@ -152,16 +153,22 @@ AccessibleWrap::QueryInterface(REFIID ii
   }
 
   if (nullptr == *ppv && !IsProxy()) {
     HRESULT hr = ia2AccessibleValue::QueryInterface(iid, ppv);
     if (SUCCEEDED(hr))
       return hr;
   }
 
+  if (!*ppv && iid == IID_IGeckoCustom) {
+    RefPtr<GeckoCustom> gkCrap = new GeckoCustom(this);
+    gkCrap.forget(ppv);
+    return S_OK;
+  }
+
   if (nullptr == *ppv)
     return E_NOINTERFACE;
 
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/GeckoCustom.cpp
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GeckoCustom.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+IMPL_IUNKNOWN_QUERY_HEAD(GeckoCustom)
+IMPL_IUNKNOWN_QUERY_IFACE(IGeckoCustom)
+IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mAcc)
+
+HRESULT
+GeckoCustom::get_anchorCount(long* aCount)
+{
+  *aCount = mAcc->AnchorCount();
+  return S_OK;
+}
+
+STDMETHODIMP
+GeckoCustom::get_ID(uint64_t* aID)
+{
+  *aID = mAcc->IsDoc() ? 0 : reinterpret_cast<uintptr_t>(mAcc.get());
+  return S_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/GeckoCustom.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_GeckoCustom_h_
+#define mozilla_a11y_GeckoCustom_h_
+
+#include "AccessibleWrap.h"
+#include "IUnknownImpl.h"
+#include "IGeckoCustom.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * a dumpster to put things exposed by the xpcom API but not a windows platform
+ * API for the purposes of testing.
+ */
+class GeckoCustom final : public IGeckoCustom
+{
+public:
+  explicit GeckoCustom(AccessibleWrap* aAcc) : mAcc(aAcc) {}
+
+  // IUnknown
+  DECL_IUNKNOWN
+
+  virtual STDMETHODIMP get_anchorCount(long* aCount);
+  virtual STDMETHODIMP get_ID(uint64_t* aID);
+
+private:
+  GeckoCustom() = delete;
+  GeckoCustom& operator =(const GeckoCustom&) = delete;
+  GeckoCustom(const GeckoCustom&) = delete;
+  GeckoCustom(GeckoCustom&&) = delete;
+  GeckoCustom& operator=(GeckoCustom&&) = delete;
+
+  ~GeckoCustom() { }
+
+protected:
+  RefPtr<AccessibleWrap> mAcc;
+};
+
+} // a11y namespace
+} // mozilla namespace
+
+#endif
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -18,16 +18,17 @@ EXPORTS.mozilla.a11y += [
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
     'EnumVariant.cpp',
+    'GeckoCustom.cpp',
     'HTMLTableAccessibleWrap.cpp',
     'HTMLWin32ObjectAccessible.cpp',
     'HyperTextAccessibleWrap.cpp',
     'ImageAccessibleWrap.cpp',
     'IUnknownImpl.cpp',
     'MsaaIdGenerator.cpp',
     'nsWinUtils.cpp',
     'Platform.cpp',
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -850,17 +850,17 @@ function gKeywordURIFixup({ target: brow
 // load a URI or redirect it to the correct process.
 function _loadURIWithFlags(browser, uri, params) {
   if (!uri) {
     uri = "about:blank";
   }
   let flags = params.flags || 0;
   let referrer = params.referrerURI;
   let referrerPolicy = ('referrerPolicy' in params ? params.referrerPolicy :
-                        Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
+                        Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
   let postData = params.postData;
 
   let currentRemoteType = browser.remoteType;
   let requiredRemoteType =
     E10SUtils.getRemoteTypeForURI(uri, gMultiProcessBrowser, currentRemoteType);
   let mustChangeProcess = requiredRemoteType != currentRemoteType;
 
   // !requiredRemoteType means we're loading in the parent/this process.
@@ -1191,17 +1191,17 @@ var gBrowserInit = {
         if (typeof(referrerURI) == "string") {
           try {
             referrerURI = makeURI(referrerURI);
           } catch (e) {
             referrerURI = null;
           }
         }
         let referrerPolicy = (window.arguments[5] != undefined ?
-            window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
+            window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
         let userContextId = (window.arguments[6] != undefined ?
             window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
         loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
                 window.arguments[4] || false, referrerPolicy, userContextId,
                 // pass the origin principal (if any) and force its use to create
                 // an initial about:blank viewer if present:
                 window.arguments[7], !!window.arguments[7]);
         window.focus();
@@ -5009,17 +5009,17 @@ nsBrowserAccess.prototype = {
       if (isExternal &&
           gPrefService.prefHasUserValue("browser.link.open_newwindow.override.external"))
         aWhere = gPrefService.getIntPref("browser.link.open_newwindow.override.external");
       else
         aWhere = gPrefService.getIntPref("browser.link.open_newwindow");
     }
 
     let referrer = aOpener ? makeURI(aOpener.location.href) : null;
-    let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT;
+    let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
     if (aOpener && aOpener.document) {
       referrerPolicy = aOpener.document.referrerPolicy;
     }
     let isPrivate = aOpener
                   ? PrivateBrowsingUtils.isContentWindowPrivate(aOpener)
                   : PrivateBrowsingUtils.isWindowPrivate(window);
 
     switch (aWhere) {
@@ -8101,16 +8101,39 @@ var PanicButtonNotifier = {
     if (!this._initialized) {
       window.PanicButtonNotifierShouldNotify = true;
       return;
     }
     // Display notification panel here...
     try {
       let popup = document.getElementById("panic-button-success-notification");
       popup.hidden = false;
+      // To close the popup in 3 seconds after the popup is shown but left uninteracted.
+      let onTimeout = () => {
+        PanicButtonNotifier.close();
+        removeListeners();
+      };
+      popup.addEventListener("popupshown", function() {
+        PanicButtonNotifier.timer = setTimeout(onTimeout, 3000);
+      });
+      // To prevent the popup from closing when user tries to interact with the
+      // popup using mouse or keyboard.
+      let onUserInteractsWithPopup = () => {
+        clearTimeout(PanicButtonNotifier.timer);
+        removeListeners();
+       };
+      popup.addEventListener("mouseover", onUserInteractsWithPopup);
+      window.addEventListener("keydown", onUserInteractsWithPopup);
+      let removeListeners = () => {
+        popup.removeEventListener("mouseover", onUserInteractsWithPopup);
+        window.removeEventListener("keydown", onUserInteractsWithPopup);
+        popup.removeEventListener("popuphidden", removeListeners);
+      };
+      popup.addEventListener("popuphidden", removeListeners);
+
       let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
       let anchor = widget.anchor;
       anchor = document.getAnonymousElementByAttribute(anchor, "class", "toolbarbutton-icon");
       popup.openPopup(anchor, popup.getAttribute("position"));
     } catch (ex) {
       Cu.reportError(ex);
     }
   },
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4841,17 +4841,17 @@
                 sendCancelPrerendering();
                 break;
               }
 
               let groupedSHistory = browser.frameLoader.ensureGroupedSHistory();
 
               let newTab = this.loadOneTab(data.href, {
                 referrerURI: (data.referrer ? makeURI(data.referrer) : null),
-                referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+                referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                 postData: null,
                 allowThirdPartyFixup: true,
                 relatedToCurrent: true,
                 isPrerendered: true,
               });
               let partialSHistory = newTab.linkedBrowser.frameLoader.partialSHistory;
               groupedSHistory.addPrerenderingPartialSHistory(partialSHistory, data.id);
               break;
--- a/browser/base/content/test/general/browser_close_dependent_tabs.js
+++ b/browser/base/content/test/general/browser_close_dependent_tabs.js
@@ -57,17 +57,17 @@ add_task(function* () {
   // At this point prerendered tab should be closed
   is(gBrowser.tabs.length, 1, "The new tab and the prerendered 'tab' should be closed");
 
   // Test 2: Create prerendered browser, switch to it, then close the tab
   let closed2 = awaitTabClose(2);
   yield BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, function* (browser1) {
     // Set up the grouped SHEntry setup
     let tab2 = gBrowser.loadOneTab("data:text/html,b", {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
   });
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -85,17 +85,17 @@ function openUILink(url, event, aIgnoreB
     aIgnoreAlt = params.ignoreAlt;
     delete params.ignoreButton;
     delete params.ignoreAlt;
   } else {
     params = {
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
       referrerURI: aReferrerURI,
-      referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_UNSET,
       initiatingDoc: event ? event.target.ownerDocument : null,
     };
   }
 
   let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
   openUILinkIn(url, where, params);
 }
 
@@ -180,17 +180,17 @@ function openUILinkIn(url, where, aAllow
 
   if (arguments.length == 3 && typeof arguments[2] == "object") {
     params = aAllowThirdPartyFixup;
   } else {
     params = {
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
       referrerURI: aReferrerURI,
-      referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Components.interfaces.nsIHttpChannel.REFERRER_POLICY_UNSET,
     };
   }
 
   params.fromChrome = true;
 
   openLinkIn(url, where, params);
 }
 
@@ -201,17 +201,17 @@ function openLinkIn(url, where, params) 
   const Ci = Components.interfaces;
 
   var aFromChrome           = params.fromChrome;
   var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
   var aPostData             = params.postData;
   var aCharset              = params.charset;
   var aReferrerURI          = params.referrerURI;
   var aReferrerPolicy       = ('referrerPolicy' in params ?
-      params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
+      params.referrerPolicy : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
   var aRelatedToCurrent     = params.relatedToCurrent;
   var aAllowMixedContent    = params.allowMixedContent;
   var aInBackground         = params.inBackground;
   var aDisallowInheritPrincipal = params.disallowInheritPrincipal;
   var aInitiatingDoc        = params.initiatingDoc;
   var aIsPrivate            = params.private;
   var aSkipTabAnimation     = params.skipTabAnimation;
   var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange;
--- a/browser/components/sessionstore/ContentRestore.jsm
+++ b/browser/components/sessionstore/ContentRestore.jsm
@@ -196,17 +196,17 @@ ContentRestoreInternal.prototype = {
     try {
       if (loadArguments) {
         // A load has been redirected to a new process so get history into the
         // same state it was before the load started then trigger the load.
         let referrer = loadArguments.referrer ?
                        Utils.makeURI(loadArguments.referrer) : null;
         let referrerPolicy = ('referrerPolicy' in loadArguments
             ? loadArguments.referrerPolicy
-            : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
+            : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
         let postData = loadArguments.postData ?
                        Utils.makeInputStream(loadArguments.postData) : null;
 
         if (loadArguments.userContextId) {
           webNavigation.setOriginAttributesBeforeLoading({ userContextId: loadArguments.userContextId });
         }
 
         webNavigation.loadURIWithOptions(loadArguments.uri, loadArguments.flags,
--- a/browser/components/sessionstore/test/browser_grouped_session_store.js
+++ b/browser/components/sessionstore/test/browser_grouped_session_store.js
@@ -59,17 +59,17 @@ add_task(function* () {
     yield* validate(browser1, 1, 1);
 
     browser1.loadURI(URIs[1], null, null);
     yield BrowserTestUtils.browserLoaded(browser1);
     yield* validate(browser1, 2, 2);
 
     // Create a new hidden prerendered tab to swap to.
     let tab2 = gBrowser.loadOneTab(URIs[2], {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
     yield* validate(browser1, 3, 3);
@@ -101,17 +101,17 @@ add_task(function* () {
 
     // Navigate across process to a page which was not recently loaded in the other direction.
     browser1.gotoIndex(3);
     yield awaitProcessChange(browser1);
     yield* validate(browser1, 4, 4);
 
     // Create a new hidden prerendered tab to swap to
     let tab3 = gBrowser.loadOneTab(URIs[4], {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab3.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab3.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
     yield* validate(browser1, 5, 5);
new file mode 100644
--- /dev/null
+++ b/browser/config/tooltool-manifests/macosx64/cross-clang.manifest
@@ -0,0 +1,43 @@
+[
+{
+"version": "clang 3.8.0, libgcc 4.9.4 + PR64905",
+"size": 155933720,
+"digest": "7a3a9a5ff455554d120596fe4bc06c19e41ecbd1e67b1e95e778c0b8ce6d9472f30fd4a27c66d48d9c047aac7a077f23f87397711dd6f33175f95cf4a2ada862",
+"algorithm": "sha512",
+"filename": "clang.tar.xz",
+"unpack": true
+},
+{
+"version": "gcc 4.9.4 + PR64905",
+"size": 101297752,
+"digest": "42aa2e3fdd232b5e390472a788e7f7db71a1fee4221e260b6cb58c9a1d73e6cdd10afcbac137f7844290169cd6b561b424ecc92b159e9726b0ad5de3f478a8be",
+"algorithm": "sha512",
+"filename": "gcc.tar.xz",
+"unpack": true
+},
+{
+"size": 3008804,
+"visibility": "public",
+"digest": "ba6937f14f3d8b26dcb2d39490dee6b0a8afb60f672f5debb71d7b62c1ec52103201b4b1a3d258f945567de531384b36ddb2ce4aa73dc63d72305b11c146847c",
+"algorithm": "sha512",
+"unpack": true,
+"filename": "cctools.tar.gz"
+},
+{
+"size": 30823112,
+"visibility": "internal",
+"digest": "0c58e06a3ea8f4641c991a7406fc8733c574f0b4aa773bce0feaa5468d2b8440fa33cea056e16fad2b8a7ef4409ca7228113eb12adc87c3e115129d8a3b3b565",
+"algorithm": "sha512",
+"unpack": true,
+"filename": "MacOSX10.10.sdk.tar.xz"
+},
+{
+"version": "sccache rev b21198a7183a2fe226ff49348b1c0b51bae9f4f8",
+"algorithm": "sha512",
+"visibility": "public",
+"filename": "sccache2.tar.xz",
+"unpack": true,
+"digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
+"size": 1020700
+}
+]
--- a/build/build-clang/README
+++ b/build/build-clang/README
@@ -34,13 +34,26 @@ build-clang.py accepts a JSON config for
 * clang_repo: SVN path to the Clang repo.
 * compiler_repo: SVN path to the compiler-rt repo.
 * libcxx_repo: SVN path to the libcxx repo.
 * libcxxabi_repo: SVN path to the libcxxabi repo.
 * python_path: Path to the Python 2.7 installation on the machine building clang.
 * gcc_dir: Path to the gcc toolchain installation, only required on Linux.
 * cc: Path to the bootsraping C Compiler.
 * cxx: Path to the bootsraping C++ Compiler.
+* ar: Path to the library archiver tool.
+* ranlib: Path to the ranlib tool.
+* ld: Path to the linker.
 * patches: Optional list of patches to apply per platform.  Supported platforms: macosx64, linux32, linux64.  The default is Release.
 * build_type: The type of build to make.  Supported types: Release, Debug, RelWithDebInfo or MinSizeRel.
 * build_libcxx: Whether to build with libcxx.  The default is false.
 * import_clang_tidy: Whether to import Mozilla checks into clang-tidy before building.  The default is false.
+* osx_cross_compile: Whether to invoke CMake for OS X cross compile builds.
 * assertions: Whether to enable LLVM assertions.  The default is false.
+
+Environment Variables
+---------------------
+
+The following environment variables are used for cross-compile builds targeting OS X on Linux.
+
+* CROSS_CCTOOLS_PATH: Path to the cctools directory where the cross compiler toolchain is located.
+* CROSS_SYSROOT: Path to the OS X SDK directory for cross compile builds.
+* LIBCXX_INCLUDE_PATH: Path to the cross compiler libc++ headers.
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -185,73 +185,102 @@ def is_darwin():
 def is_linux():
     return platform.system() == "Linux"
 
 
 def is_windows():
     return platform.system() == "Windows"
 
 
-def build_one_stage(cc, cxx, src_dir, stage_dir, build_libcxx,
-                    build_type, assertions, python_path, gcc_dir):
+def build_one_stage(cc, cxx, ld, ar, ranlib,
+                    src_dir, stage_dir, build_libcxx,
+                    osx_cross_compile, build_type, assertions,
+                    python_path, gcc_dir):
     if not os.path.exists(stage_dir):
         os.mkdir(stage_dir)
 
     build_dir = stage_dir + "/build"
     inst_dir = stage_dir + "/clang"
 
     # If CMake has already been run, it may have been run with different
     # arguments, so we need to re-run it.  Make sure the cached copy of the
     # previous CMake run is cleared before running it again.
     if os.path.exists(build_dir + "/CMakeCache.txt"):
-        os.path.remove(build_dir + "/CMakeCache.txt")
+        os.remove(build_dir + "/CMakeCache.txt")
 
     # cmake doesn't deal well with backslashes in paths.
     def slashify_path(path):
         return path.replace('\\', '/')
 
     cmake_args = ["-GNinja",
                   "-DCMAKE_C_COMPILER=%s" % slashify_path(cc[0]),
                   "-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx[0]),
                   "-DCMAKE_ASM_COMPILER=%s" % slashify_path(cc[0]),
+                  "-DCMAKE_LINKER=%s" % slashify_path(ld[0]),
+                  "-DCMAKE_AR=%s" % slashify_path(ar),
                   "-DCMAKE_C_FLAGS=%s" % ' '.join(cc[1:]),
                   "-DCMAKE_CXX_FLAGS=%s" % ' '.join(cxx[1:]),
+                  "-DCMAKE_EXE_LINKER_FLAGS=%s" % ' '.join(ld[1:]),
+                  "-DCMAKE_SHARED_LINKER_FLAGS=%s" % ' '.join(ld[1:]),
                   "-DCMAKE_BUILD_TYPE=%s" % build_type,
                   "-DLLVM_TARGETS_TO_BUILD=X86;ARM",
                   "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions else "OFF"),
                   "-DPYTHON_EXECUTABLE=%s" % slashify_path(python_path),
                   "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir,
                   "-DLLVM_TOOL_LIBCXX_BUILD=%s" % ("ON" if build_libcxx else "OFF"),
                   "-DLIBCXX_LIBCPPABI_VERSION=\"\"",
                   src_dir];
     if is_windows():
         cmake_args.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON")
         cmake_args.insert(-1, "-DLLVM_USE_CRT_RELEASE=MT")
+    if ranlib is not None:
+        cmake_args += ["-DCMAKE_RANLIB=%s" % slashify_path(ranlib)]
+    if osx_cross_compile:
+        cmake_args += ["-DCMAKE_SYSTEM_NAME=Darwin",
+                       "-DCMAKE_SYSTEM_VERSION=10.10",
+                       "-DLLVM_ENABLE_THREADS=OFF",
+                       "-DLIBCXXABI_LIBCXX_INCLUDES=%s" % slashify_path(os.getenv("LIBCXX_INCLUDE_PATH")),
+                       "-DCMAKE_OSX_SYSROOT=%s" % slashify_path(os.getenv("CROSS_SYSROOT")),
+                       "-DCMAKE_FIND_ROOT_PATH=%s" % slashify_path(os.getenv("CROSS_CCTOOLS_PATH")),
+                       "-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER",
+                       "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY",
+                       "-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY",
+                       "-DCMAKE_MACOSX_RPATH=@executable_path",
+                       "-DCMAKE_OSX_ARCHITECTURES=x86_64",
+                       "-DDARWIN_osx_ARCHS=x86_64",
+                       "-DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-apple-darwin10"]
     build_package(build_dir, cmake_args)
 
     if is_linux():
         install_libgcc(gcc_dir, inst_dir)
     # For some reasons the import library clang.lib of clang.exe is not
     # installed, so we copy it by ourselves.
     if is_windows():
         install_import_library(build_dir, inst_dir)
 
-def get_compiler(config, key):
-    if key not in config:
-        raise ValueError("Config file needs to set %s" % key)
-
-    f = config[key]
-    if os.path.isabs(f):
-        if not os.path.exists(f):
-            raise ValueError("%s must point to an existing path" % key)
-        return f
+# Return the absolute path of a build tool.  We first look to see if the
+# variable is defined in the config file, and if so we make sure it's an
+# absolute path to an existing tool, otherwise we look for a program in
+# $PATH named "key".
+#
+# This expects the name of the key in the config file to match the name of
+# the tool in the default toolchain on the system (for example, "ld" on Unix
+# and "link" on Windows).
+def get_tool(config, key):
+    f = None
+    if key in config:
+        f = config[key]
+        if os.path.isabs(f):
+            if not os.path.exists(f):
+                raise ValueError("%s must point to an existing path" % key)
+            return f
 
     # Assume that we have the name of some program that should be on PATH.
     try:
-        return which.which(f)
+        return which.which(f) if f else which.which(key)
     except which.WhichError:
         raise ValueError("%s not found on PATH" % f)
 
 if __name__ == "__main__":
     # The directories end up in the debug info, so the easy way of getting
     # a reproducible build is to run it in a know absolute directory.
     # We use a directory in /builds/slave because the mozilla infrastructure
     # cleans it up automatically.
@@ -327,34 +356,44 @@ if __name__ == "__main__":
         build_libcxx = config["build_libcxx"]
         if build_libcxx not in (True, False):
             raise ValueError("Only boolean values are accepted for build_libcxx.")
     import_clang_tidy = False
     if "import_clang_tidy" in config:
         import_clang_tidy = config["import_clang_tidy"]
         if import_clang_tidy not in (True, False):
             raise ValueError("Only boolean values are accepted for import_clang_tidy.")
+    osx_cross_compile = False
+    if "osx_cross_compile" in config:
+        osx_cross_compile = config["osx_cross_compile"]
+        if osx_cross_compile not in (True, False):
+            raise ValueError("Only boolean values are accepted for osx_cross_compile.")
+        if osx_cross_compile and not is_linux():
+            raise ValueError("osx_cross_compile can only be used on Linux.")
     assertions = False
     if "assertions" in config:
         assertions = config["assertions"]
         if assertions not in (True, False):
             raise ValueError("Only boolean values are accepted for assertions.")
     python_path = None
     if "python_path" not in config:
         raise ValueError("Config file needs to set python_path")
     python_path = config["python_path"]
     gcc_dir = None
     if "gcc_dir" in config:
         gcc_dir = config["gcc_dir"]
         if not os.path.exists(gcc_dir):
             raise ValueError("gcc_dir must point to an existing path")
     if is_linux() and gcc_dir is None:
         raise ValueError("Config file needs to set gcc_dir")
-    cc = get_compiler(config, "cc")
-    cxx = get_compiler(config, "cxx")
+    cc = get_tool(config, "cc")
+    cxx = get_tool(config, "cxx")
+    ld = get_tool(config, "link" if is_windows() else "ld")
+    ar = get_tool(config, "lib" if is_windows() else "ar")
+    ranlib = None if is_windows() else get_tool(config, "ranlib")
 
     if not os.path.exists(source_dir):
         os.makedirs(source_dir)
     if os.path.exists(llvm_source_dir):
         svn_update(llvm_source_dir, llvm_revision)
     else:
         svn_co(source_dir, llvm_repo, llvm_source_dir, llvm_revision)
     if os.path.exists(clang_source_dir):
@@ -414,60 +453,90 @@ if __name__ == "__main__":
 
     final_stage_dir = stage1_dir
 
     if is_darwin():
         extra_cflags = []
         extra_cxxflags = ["-stdlib=libc++"]
         extra_cflags2 = []
         extra_cxxflags2 = ["-stdlib=libc++"]
+        extra_ldflags = []
     elif is_linux():
         extra_cflags = ["-static-libgcc"]
         extra_cxxflags = ["-static-libgcc", "-static-libstdc++"]
         extra_cflags2 = ["-fPIC"]
         extra_cxxflags2 = ["-fPIC", "-static-libstdc++"]
+        extra_ldflags = []
 
         if os.environ.has_key('LD_LIBRARY_PATH'):
             os.environ['LD_LIBRARY_PATH'] = '%s/lib64/:%s' % (gcc_dir, os.environ['LD_LIBRARY_PATH']);
         else:
             os.environ['LD_LIBRARY_PATH'] = '%s/lib64/' % gcc_dir
     elif is_windows():
         extra_cflags = []
         extra_cxxflags = []
         # clang-cl would like to figure out what it's supposed to be emulating
         # by looking at an MSVC install, but we don't really have that here.
         # Force things on.
         extra_cflags2 = []
         extra_cxxflags2 = ['-fms-compatibility-version=19.00.24213', '-Xclang', '-std=c++14']
+        extra_ldflags = []
+
+    if osx_cross_compile:
+        # undo the damage done in the is_linux() block above, and also simulate
+        # the is_darwin() block above.
+        extra_cflags = []
+        extra_cxxflags = ["-stdlib=libc++"]
+        extra_cxxflags2 = ["-stdlib=libc++"]
+
+        extra_flags = ["-target", "x86_64-apple-darwin10", "-mlinker-version=136",
+                       "-B", "%s/bin" %  os.getenv("CROSS_CCTOOLS_PATH"),
+                       "-isysroot", os.getenv("CROSS_SYSROOT"),
+                       # technically the sysroot flag there should be enough to deduce this,
+                       # but clang needs some help to figure this out.
+                       "-I%s/usr/include" % os.getenv("CROSS_SYSROOT"),
+                       "-iframework", "%s/System/Library/Frameworks" % os.getenv("CROSS_SYSROOT")]
+        extra_cflags += extra_flags
+        extra_cxxflags += extra_flags
+        extra_cflags2 += extra_flags
+        extra_cxxflags2 += extra_flags
+        extra_ldflags = ["-Wl,-syslibroot,%s" % os.getenv("CROSS_SYSROOT"),
+                         "-Wl,-dead_strip"]
 
     build_one_stage(
         [cc] + extra_cflags,
         [cxx] + extra_cxxflags,
-        llvm_source_dir, stage1_dir, build_libcxx,
+        [ld] + extra_ldflags,
+        ar, ranlib,
+        llvm_source_dir, stage1_dir, build_libcxx, osx_cross_compile,
         build_type, assertions, python_path, gcc_dir)
 
     if stages > 1:
         stage2_dir = build_dir + '/stage2'
         stage2_inst_dir = stage2_dir + '/clang'
         final_stage_dir = stage2_dir
         build_one_stage(
             [stage1_inst_dir + "/bin/%s%s" %
                 (cc_name, exe_ext)] + extra_cflags2,
             [stage1_inst_dir + "/bin/%s%s" %
                 (cxx_name, exe_ext)] + extra_cxxflags2,
-            llvm_source_dir, stage2_dir, build_libcxx,
+            [ld] + extra_ldflags,
+            ar, ranlib,
+            llvm_source_dir, stage2_dir, build_libcxx, osx_cross_compile,
             build_type, assertions, python_path, gcc_dir)
 
     if stages > 2:
         stage3_dir = build_dir + '/stage3'
         final_stage_dir = stage3_dir
         build_one_stage(
             [stage2_inst_dir + "/bin/%s%s" %
                 (cc_name, exe_ext)] + extra_cflags2,
             [stage2_inst_dir + "/bin/%s%s" %
                 (cxx_name, exe_ext)] + extra_cxxflags2,
-            llvm_source_dir, stage3_dir, build_libcxx,
+            [ld] + extra_ldflags,
+            ar, ranlib,
+            llvm_source_dir, stage3_dir, build_libcxx, osx_cross_compile,
             build_type, assertions, python_path, gcc_dir)
 
     if is_darwin() or is_windows():
         build_tar_package("tar", "clang.tar.bz2", final_stage_dir, "clang")
     else:
         build_tar_package("tar", "clang.tar.xz", final_stage_dir, "clang")
new file mode 100644
--- /dev/null
+++ b/build/build-clang/clang-tidy-linux64.json
@@ -0,0 +1,18 @@
+{
+    "llvm_revision": "290055",
+    "stages": "1",
+    "build_libcxx": true,
+    "build_type": "Release",
+    "assertions": false,
+    "import_clang_tidy": true,
+    "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
+    "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
+    "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/trunk",
+    "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
+    "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
+    "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk",
+    "python_path": "/usr/bin/python2.7",
+    "gcc_dir": "/home/worker/workspace/build/src/gcc",
+    "cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
+    "cxx": "/home/worker/workspace/build/src/gcc/bin/g++"
+}
new file mode 100644
--- /dev/null
+++ b/build/build-clang/clang-tidy-macosx64.json
@@ -0,0 +1,22 @@
+{
+    "llvm_revision": "290055",
+    "stages": "1",
+    "build_libcxx": true,
+    "build_type": "Release",
+    "assertions": false,
+    "import_clang_tidy": true,
+    "osx_cross_compile": true,
+    "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
+    "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
+    "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/trunk",
+    "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
+    "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
+    "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk",
+    "python_path": "/usr/bin/python2.7",
+    "gcc_dir": "/home/worker/workspace/build/src/gcc",
+    "cc": "/home/worker/workspace/build/src/clang/bin/clang",
+    "cxx": "/home/worker/workspace/build/src/clang/bin/clang++",
+    "ar": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin10-ar",
+    "ranlib": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin10-ranlib",
+    "ld": "/home/worker/workspace/build/src/clang/bin/clang"
+}
--- a/devtools/client/responsive.html/browser/web-navigation.js
+++ b/devtools/client/responsive.html/browser/web-navigation.js
@@ -55,17 +55,17 @@ BrowserElementWebNavigation.prototype = 
   gotoIndex(index) {
     // No equivalent in the current BrowserElement API
     this._sendMessage("WebNavigation:GotoIndex", { index });
   },
 
   loadURI(uri, flags, referrer, postData, headers) {
     // No equivalent in the current BrowserElement API
     this.loadURIWithOptions(uri, flags, referrer,
-                            Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+                            Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                             postData, headers, null);
   },
 
   loadURIWithOptions(uri, flags, referrer, referrerPolicy, postData, headers,
                      baseURI) {
     // No equivalent in the current BrowserElement API
     this._sendMessage("WebNavigation:LoadURI", {
       uri,
--- a/devtools/shared/gcli/commands/screenshot.js
+++ b/devtools/shared/gcli/commands/screenshot.js
@@ -554,18 +554,17 @@ var saveToFile = Task.async(function* (c
           null,
           persist,
           isPrivate);
   let listener = new DownloadListener(window, tr);
   persist.progressListener = listener;
   persist.savePrivacyAwareURI(sourceURI,
                               null,
                               document.documentURIObject,
-                              Ci.nsIHttpChannel
-                                .REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE,
+                              Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                               null,
                               null,
                               targetFileURI,
                               isPrivate);
 
   try {
     // Await successful completion of the save via the listener
     yield listener.completed;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1257,17 +1257,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
   nsCOMPtr<nsIURI> originalURI;
   bool loadReplace = false;
   nsCOMPtr<nsIInputStream> postStream;
   nsCOMPtr<nsIInputStream> headersStream;
   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   bool inheritPrincipal = false;
   bool principalIsExplicit = false;
   bool sendReferrer = true;
-  uint32_t referrerPolicy = mozilla::net::RP_Default;
+  uint32_t referrerPolicy = mozilla::net::RP_Unset;
   bool isSrcdoc = false;
   nsCOMPtr<nsISHEntry> shEntry;
   nsXPIDLString target;
   nsAutoString srcdoc;
   nsCOMPtr<nsIDocShell> sourceDocShell;
   nsCOMPtr<nsIURI> baseURI;
 
   uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
@@ -4692,17 +4692,17 @@ nsDocShell::GotoIndex(int32_t aIndex)
 NS_IMETHODIMP
 nsDocShell::LoadURI(const char16_t* aURI,
                     uint32_t aLoadFlags,
                     nsIURI* aReferringURI,
                     nsIInputStream* aPostStream,
                     nsIInputStream* aHeaderStream)
 {
   return LoadURIWithOptions(aURI, aLoadFlags, aReferringURI,
-                            mozilla::net::RP_Default, aPostStream,
+                            mozilla::net::RP_Unset, aPostStream,
                             aHeaderStream, nullptr);
 }
 
 NS_IMETHODIMP
 nsDocShell::LoadURIWithOptions(const char16_t* aURI,
                                uint32_t aLoadFlags,
                                nsIURI* aReferringURI,
                                uint32_t aReferrerPolicy,
@@ -5358,17 +5358,17 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   errorPageUrl.AppendLiteral("&d=");
   errorPageUrl.AppendASCII(escapedDescription.get());
 
   nsCOMPtr<nsIURI> errorPageURI;
   nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return InternalLoad(errorPageURI, nullptr, false, nullptr,
-                      mozilla::net::RP_Default,
+                      mozilla::net::RP_Unset,
                       nsContentUtils::GetSystemPrincipal(), nullptr,
                       INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
                       nullptr, true, NullString(), this, nullptr, false,
                       nullptr, nullptr);
 }
 
 NS_IMETHODIMP
@@ -12225,17 +12225,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
     }
   }
 
   // Get the post data & referrer
   nsCOMPtr<nsIInputStream> inputStream;
   nsCOMPtr<nsIURI> originalURI;
   bool loadReplace = false;
   nsCOMPtr<nsIURI> referrerURI;
-  uint32_t referrerPolicy = mozilla::net::RP_Default;
+  uint32_t referrerPolicy = mozilla::net::RP_Unset;
   nsCOMPtr<nsISupports> cacheKey;
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
   bool expired = false;
   bool discardLayoutState = false;
   nsCOMPtr<nsICacheInfoChannel> cacheChannel;
   if (aChannel) {
     cacheChannel = do_QueryInterface(aChannel);
--- a/docshell/base/nsDocShellLoadInfo.cpp
+++ b/docshell/base/nsDocShellLoadInfo.cpp
@@ -11,17 +11,17 @@
 #include "nsIDocShell.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 nsDocShellLoadInfo::nsDocShellLoadInfo()
   : mLoadReplace(false)
   , mInheritPrincipal(false)
   , mPrincipalIsExplicit(false)
   , mSendReferrer(true)
-  , mReferrerPolicy(mozilla::net::RP_Default)
+  , mReferrerPolicy(mozilla::net::RP_Unset)
   , mLoadType(nsIDocShellLoadInfo::loadNormal)
   , mIsSrcdocLoad(false)
 {
 }
 
 nsDocShellLoadInfo::~nsDocShellLoadInfo()
 {
 }
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -259,17 +259,17 @@ interface nsIWebNavigation : nsISupports
    *        combination of the load flags defined above.  (Undefined bits are
    *        reserved for future use.)  Generally you will pass LOAD_FLAGS_NONE
    *        for this parameter.
    * @param aReferrer
    *        The referring URI.  If this argument is null, then the referring
    *        URI will be inferred internally.
    * @param aReferrerPolicy
    *        One of the REFERRER_POLICY_* constants from nsIHttpChannel.
-   *        Normal case is REFERRER_POLICY_DEFAULT.
+   *        Normal case is REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE.
    * @param aPostData
    *        If the URI corresponds to a HTTP request, then this stream is
    *        appended directly to the HTTP request headers.  It may be prefixed
    *        with additional HTTP headers.  This stream must contain a "\r\n"
    *        sequence separating any HTTP headers from the HTTP request body.
    *        This parameter is optional and may be null.
    * @param aHeaders
    *        If the URI corresponds to a HTTP request, then any HTTP headers
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -19,17 +19,17 @@
 
 namespace dom = mozilla::dom;
 
 static uint32_t gEntryID = 0;
 
 nsSHEntry::nsSHEntry()
   : mShared(new nsSHEntryShared())
   , mLoadReplace(false)
-  , mReferrerPolicy(mozilla::net::RP_Default)
+  , mReferrerPolicy(mozilla::net::RP_Unset)
   , mLoadType(0)
   , mID(gEntryID++)
   , mScrollPositionX(0)
   , mScrollPositionY(0)
   , mParent(nullptr)
   , mURIWasModified(false)
   , mIsSrcdocEntry(false)
   , mScrollRestorationIsManual(false)
--- a/docshell/test/browser/browser_grouped_shistory_bfcache_cleaning.js
+++ b/docshell/test/browser/browser_grouped_shistory_bfcache_cleaning.js
@@ -18,17 +18,17 @@ add_task(function* () {
     return tab.linkedBrowser &&
       tab.linkedBrowser.frameLoader &&
       !tab.linkedBrowser.frameLoader.isDead;
   }
 
   yield BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, function* (browser1) {
     // Set up the grouped SHEntry setup
     let tab2 = gBrowser.loadOneTab("data:text/html,b", {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
     ok(isAlive(tab2));
--- a/docshell/test/browser/browser_grouped_shistory_crossproc.js
+++ b/docshell/test/browser/browser_grouped_shistory_crossproc.js
@@ -23,17 +23,17 @@ add_task(function* () {
         resolve();
       });
     });
   }
 
   yield BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, function* (browser1) {
     // Set up the grouped SHEntry setup
     let tab2 = gBrowser.loadOneTab("data:text/html,b", {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
 
--- a/docshell/test/browser/browser_grouped_shistory_dead_navigate.js
+++ b/docshell/test/browser/browser_grouped_shistory_dead_navigate.js
@@ -12,17 +12,17 @@ add_task(function* () {
         resolve();
       });
     });
   }
 
   yield BrowserTestUtils.withNewTab({ gBrowser, url: "data:text/html,a" }, function* (browser1) {
     // Set up the grouped SHEntry setup
     let tab2 = gBrowser.loadOneTab("data:text/html,b", {
-      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+      referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
       allowThirdPartyFixup: true,
       relatedToCurrent: true,
       isPrerendered: true,
     });
     yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
     browser1.frameLoader.appendPartialSHistoryAndSwap(tab2.linkedBrowser.frameLoader);
     yield awaitProcessChange(browser1);
 
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -104,17 +104,17 @@ Location::CheckURL(nsIURI* aURI, nsIDocS
 {
   *aLoadInfo = nullptr;
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
 
   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   nsCOMPtr<nsIURI> sourceURI;
-  net::ReferrerPolicy referrerPolicy = net::RP_Default;
+  net::ReferrerPolicy referrerPolicy = net::RP_Unset;
 
   if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
     // No cx means that there's no JS running, or at least no JS that
     // was run through code that properly pushed a context onto the
     // context stack (as all code that runs JS off of web pages
     // does). We won't bother with security checks in this case, but
     // we need to create the loadinfo etc.
 
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -332,17 +332,17 @@ WebSocketImpl::PrintErrorOnConsole(const
 
   if (!NS_IsMainThread()) {
     MOZ_ASSERT(mWorkerPrivate);
 
     RefPtr<PrintErrorOnConsoleRunnable> runnable =
       new PrintErrorOnConsoleRunnable(this, aBundleURI, aError, aFormatStrings,
                                       aFormatStringsLen);
     ErrorResult rv;
-    runnable->Dispatch(rv);
+    runnable->Dispatch(Killing, rv);
     // XXXbz this seems totally broken.  We should be propagating this out, but
     // none of our callers really propagate anything usefully.  Come to think of
     // it, why is this a syncrunnable anyway?  Can't this be a fire-and-forget
     // runnable??
     rv.SuppressException();
     return;
   }
 
@@ -617,17 +617,17 @@ WebSocketImpl::Disconnect()
   // the main thread.
 
   if (NS_IsMainThread()) {
     DisconnectInternal();
   } else {
     RefPtr<DisconnectInternalRunnable> runnable =
       new DisconnectInternalRunnable(this);
     ErrorResult rv;
-    runnable->Dispatch(rv);
+    runnable->Dispatch(Killing, rv);
     // XXXbz this seems totally broken.  We should be propagating this out, but
     // where to, exactly?
     rv.SuppressException();
   }
 
   // DontKeepAliveAnyMore() can release the object. So hold a reference to this
   // until the end of the method.
   RefPtr<WebSocketImpl> kungfuDeathGrip = this;
@@ -1299,17 +1299,17 @@ WebSocket::ConstructorCommon(const Globa
                                     &column)) {
       NS_WARNING("Failed to get line number and filename in workers.");
     }
 
     RefPtr<InitRunnable> runnable =
       new InitRunnable(webSocketImpl, !!aTransportProvider, aUrl,
                        protocolArray, nsDependentCString(file.get()), lineno,
                        column, &connectionFailed);
-    runnable->Dispatch(aRv);
+    runnable->Dispatch(Terminating, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     aRv = runnable->ErrorCode();
   }
 
   if (NS_WARN_IF(aRv.Failed())) {
@@ -1388,17 +1388,17 @@ WebSocket::ConstructorCommon(const Globa
 
     aRv = webSocket->mImpl->AsyncOpen(principal, windowID, aTransportProvider,
                                       aNegotiatedExtensions);
   } else {
     MOZ_ASSERT(!aTransportProvider && aNegotiatedExtensions.IsEmpty(),
                "not yet implemented");
     RefPtr<AsyncOpenRunnable> runnable =
       new AsyncOpenRunnable(webSocket->mImpl);
-    runnable->Dispatch(aRv);
+    runnable->Dispatch(Terminating, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     aRv = runnable->ErrorCode();
   }
 
   if (NS_WARN_IF(aRv.Failed())) {
@@ -2017,20 +2017,21 @@ WebSocket::CreateAndDispatchMessageEvent
                           nullptr);
 }
 
 nsresult
 WebSocket::CreateAndDispatchCloseEvent(bool aWasClean,
                                        uint16_t aCode,
                                        const nsAString& aReason)
 {
-  MOZ_ASSERT(mImpl);
   AssertIsOnTargetThread();
 
-  if (mImpl->mChannel) {
+  // This method is called by a runnable and it can happen that, in the
+  // meantime, GC unlinked this object, so mImpl could be null.
+  if (mImpl && mImpl->mChannel) {
     mImpl->mService->WebSocketClosed(mImpl->mChannel->Serial(),
                                      mImpl->mInnerWindowID,
                                      aWasClean, aCode, aReason);
   }
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -160,17 +160,17 @@ nsContentAreaDragDropDataProvider::SaveU
     do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                       &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   persist->SetPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION);
 
   // referrer policy can be anything since the referrer is nullptr
   return persist->SavePrivacyAwareURI(sourceURI, nullptr, nullptr,
-                                      mozilla::net::RP_Default,
+                                      mozilla::net::RP_Unset,
                                       nullptr, nullptr,
                                       inDestFile, isPrivate);
 }
 
 // This is our nsIFlavorDataProvider callback. There are several
 // assumptions here that make this work:
 //
 // 1. Someone put a kFilePromiseURLMime flavor into the transferable
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8509,32 +8509,33 @@ nsContentUtils::SetFetchReferrerURIWithP
       referrerURI = docCurURI;
     }
   }
 
   if (!referrerURI) {
     referrerURI = principalURI;
   }
 
-  net::ReferrerPolicy referrerPolicy = (aReferrerPolicy != net::RP_Unset) ?
-                                       aReferrerPolicy : net::RP_Default;
-  return aChannel->SetReferrerWithPolicy(referrerURI, referrerPolicy);
+  return aChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
 }
 
 // static
 net::ReferrerPolicy
 nsContentUtils::GetReferrerPolicyFromHeader(const nsAString& aHeader)
 {
   // Multiple headers could be concatenated into one comma-separated
   // list of policies. Need to tokenize the multiple headers.
   nsCharSeparatedTokenizer tokenizer(aHeader, ',');
   nsAutoString token;
   net::ReferrerPolicy referrerPolicy = mozilla::net::RP_Unset;
   while (tokenizer.hasMoreTokens()) {
     token = tokenizer.nextToken();
+    if (token.IsEmpty()) {
+      continue;
+    }
     net::ReferrerPolicy policy = net::ReferrerPolicyFromString(token);
     if (policy != net::RP_Unset) {
       referrerPolicy = policy;
     }
   }
   return referrerPolicy;
 }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -108,16 +108,17 @@
 #include "nsDocument.h"
 #include "HTMLImageElement.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
 #include "mozilla/dom/Promise.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/dom/TimeoutManager.h"
+#include "mozilla/PreloadedStyleSheet.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -3445,32 +3446,37 @@ nsDOMWindowUtils::LoadSheetUsingURIStrin
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aSheetURI);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return LoadSheet(uri, aSheetType);
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::AddSheet(nsIDOMStyleSheet *aSheet, uint32_t aSheetType)
+nsDOMWindowUtils::AddSheet(nsIPreloadedStyleSheet* aSheet, uint32_t aSheetType)
 {
   NS_ENSURE_ARG_POINTER(aSheet);
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
                 aSheetType == AUTHOR_SHEET);
 
   nsCOMPtr<nsIDocument> doc = GetDocument();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
-  nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
-  RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
+  StyleSheet* sheet = nullptr;
+  auto preloadedSheet = static_cast<PreloadedStyleSheet*>(aSheet);
+  nsresult rv = preloadedSheet->GetSheet(doc->GetStyleBackendType(), &sheet);
+  NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
+
   if (sheet->GetOwningDocument()) {
     return NS_ERROR_INVALID_ARG;
   }
+
+  nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
   return doc->AddAdditionalStyleSheet(type, sheet);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RemoveSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG_POINTER(aSheetURI);
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1274,17 +1274,17 @@ struct nsIDocument::FrameRequest
 static already_AddRefed<mozilla::dom::NodeInfo> nullNodeInfo;
 
 // ==================================================================
 // =
 // ==================================================================
 nsIDocument::nsIDocument()
   : nsINode(nullNodeInfo),
     mReferrerPolicySet(false),
-    mReferrerPolicy(mozilla::net::RP_Default),
+    mReferrerPolicy(mozilla::net::RP_Unset),
     mBlockAllMixedContent(false),
     mBlockAllMixedContentPreloads(false),
     mUpgradeInsecureRequests(false),
     mUpgradeInsecurePreloads(false),
     mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
     mNodeInfoManager(nullptr),
     mCompatMode(eCompatibility_FullStandards),
     mVisibilityState(dom::VisibilityState::Hidden),
@@ -2463,17 +2463,17 @@ nsDocument::ApplySettingsFromCSP(bool aS
   if (!aSpeculative) {
     // 1) apply settings from regular CSP
     nsCOMPtr<nsIContentSecurityPolicy> csp;
     rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
     NS_ENSURE_SUCCESS_VOID(rv);
     if (csp) {
       // Set up any Referrer Policy specified by CSP
       bool hasReferrerPolicy = false;
-      uint32_t referrerPolicy = mozilla::net::RP_Default;
+      uint32_t referrerPolicy = mozilla::net::RP_Unset;
       rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
       NS_ENSURE_SUCCESS_VOID(rv);
       if (hasReferrerPolicy) {
         mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
         mReferrerPolicySet = true;
       }
 
       // Set up 'block-all-mixed-content' if not already inherited
--- a/dom/base/nsScriptLoader.h
+++ b/dom/base/nsScriptLoader.h
@@ -86,17 +86,17 @@ public:
       mIsTracking(false),
       mOffThreadToken(nullptr),
       mScriptTextBuf(nullptr),
       mScriptTextLength(0),
       mJSVersion(aVersion),
       mLineNo(1),
       mCORSMode(aCORSMode),
       mIntegrity(aIntegrity),
-      mReferrerPolicy(mozilla::net::RP_Default)
+      mReferrerPolicy(mozilla::net::RP_Unset)
   {
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptLoadRequest)
 
   bool IsModuleRequest() const
   {
--- a/dom/base/test/referrer_helper.js
+++ b/dom/base/test/referrer_helper.js
@@ -71,16 +71,20 @@ var tests = (function*() {
   // enable referrer attribute
   yield SpecialPowers.pushPrefEnv({"set": [['network.http.enablePerElementReferrer', true]]}, advance);
   yield SpecialPowers.pushPrefEnv({"set": [['security.mixed_content.block_active_content', false]]}, advance);
   yield SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], advance);
 
   var iframe = document.getElementById("testframe");
 
   for (var j = 0; j < testCases.length; j++) {
+    if (testCases[j].PREFS) {
+      yield SpecialPowers.pushPrefEnv({"set": testCases[j].PREFS}, advance);
+    }
+
     var actions = testCases[j].ACTION;
     var tests = testCases[j].TESTS;
     for (var k = 0; k < actions.length; k++) {
       var actionString = actions[k];
       for (var i = 0; i < tests.length; i++) {
         yield resetState();
         var searchParams = new URLSearchParams();
         searchParams.append("ACTION", actionString);
--- a/dom/base/test/referrer_testserver.sjs
+++ b/dom/base/test/referrer_testserver.sjs
@@ -186,16 +186,35 @@ function createLinkPageUsingRefferer(aMe
              <body>
                 <script>
                   ${changeString}
                 </script>
              </body>
            </html>`;
 }
 
+function createFetchUserControlRPTestCase(aName, aSchemeFrom, aSchemeTo) {
+  var srcUrl = createTestUrl("", "test", aName, "iframe", aSchemeFrom, aSchemeTo);
+
+  return `<!DOCTYPE HTML>
+          <html>
+          <head>
+          <meta charset="utf-8">
+          <title>Test user control referrer policies</title>
+          </head>
+          <body>
+          <script>
+            fetch("${srcUrl}", {referrerPolicy: ""}).then(function (response) {
+              window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");
+            });
+          </script>
+          </body>
+          </html>`;
+}
+
 function buildLinkString(aPolicy, aName, aRelString, aSchemeFrom, aSchemeTo, aTestType) {
   var result;
   var href = '';
   var onChildComplete = `window.parent.postMessage("childLoadComplete", "http://mochi.test:8888");`
   if (!aTestType) {
     href = `href=${createTestUrl(aPolicy, "test", aName, "link_element", aSchemeFrom, aSchemeTo)}`;
   }
   if (!aPolicy) {
@@ -208,16 +227,18 @@ function buildLinkString(aPolicy, aName,
 }
 
 function handleRequest(request, response) {
   var params = new URLSearchParams(request.queryString);
   var action = params.get("ACTION");
   var schemeFrom = params.get("SCHEME_FROM") || "http";
   var schemeTo = params.get("SCHEME_TO") || "http";
 
+  response.setHeader("Access-Control-Allow-Origin", "*", false);
+
   if (action === "resetState") {
     setSharedState(SHARED_KEY, "{}");
     response.write("");
     return;
   }
   if (action === "get-test-results") {
     // ?action=get-result
     response.setHeader("Cache-Control", "no-cache", false);
@@ -381,11 +402,16 @@ function handleRequest(request, response
     response.write(_getLinkPage("setAttribute"));
     return;
   }
   if (action === "generate-link-policy-test-property") {
     response.write(_getLinkPage("property"));
     return;
   }
 
+  if (action === "generate-fetch-user-control-policy-test") {
+    response.write(createFetchUserControlRPTestCase(name, schemeFrom, schemeTo));
+    return;
+  }
+
   response.write("I don't know action " + action);
   return;
 }
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -329,17 +329,17 @@ BroadcastChannel::Constructor(const Glob
     }
   } else {
     JSContext* cx = aGlobal.Context();
     workerPrivate = GetWorkerPrivateFromContext(cx);
     MOZ_ASSERT(workerPrivate);
 
     RefPtr<InitializeRunnable> runnable =
       new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
-    runnable->Dispatch(aRv);
+    runnable->Dispatch(Closing, aRv);
   }
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
   RefPtr<BroadcastChannel> bc =
     new BroadcastChannel(window, principalInfo, origin, aChannel);
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -994,17 +994,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj
     RefPtr<CreateImageFromRawDataInMainThreadSyncTask> task
       = new CreateImageFromRawDataInMainThreadSyncTask(array.Data(),
                                                        dataLength,
                                                        imageStride,
                                                        FORMAT,
                                                        imageSize,
                                                        aCropRect,
                                                        getter_AddRefs(data));
-    task->Dispatch(aRv);
+    task->Dispatch(Terminating, aRv);
   }
 
   if (NS_WARN_IF(!data)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return nullptr;
   }
 
   // Create an ImageBimtap.
@@ -1430,20 +1430,20 @@ private:
     Maybe<IntRect> originalCropRect = mCropRect;
 
     RefPtr<layers::Image> data;
 
     ErrorResult rv;
     RefPtr<DecodeBlobInMainThreadSyncTask> task =
       new DecodeBlobInMainThreadSyncTask(mWorkerPrivate, *mBlob, mCropRect,
                                          getter_AddRefs(data), sourceSize);
-    task->Dispatch(rv); // This is a synchronous call.
+    task->Dispatch(Terminating, rv); // This is a synchronous call.
 
+    // In case the worker is terminating, this rejection can be handled.
     if (NS_WARN_IF(rv.Failed())) {
-      // XXXbz does this really make sense if we're shutting down?  Ah, well.
       mPromise->MaybeReject(rv);
       return nullptr;
     }
 
     if (NS_WARN_IF(!data)) {
       mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
       return nullptr;
     }
@@ -2160,17 +2160,20 @@ ImageBitmap::Create(nsIGlobalObject* aGl
                                               aFormat, aLayout);
   } else {
     RefPtr<CreateImageFromBufferSourceRawDataInMainThreadSyncTask> task =
       new CreateImageFromBufferSourceRawDataInMainThreadSyncTask(bufferData + aOffset,
                                                                  bufferLength,
                                                                  aFormat,
                                                                  aLayout,
                                                                  getter_AddRefs(data));
-    task->Dispatch(aRv);
+    task->Dispatch(Terminating, aRv);
+    if (aRv.Failed()) {
+      return promise.forget();
+    }
   }
 
   if (NS_WARN_IF(!data)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return promise.forget();
   }
 
   // Create an ImageBimtap.
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -1024,35 +1024,36 @@ WebGLContext::ValidateBufferFetching(con
 WebGLVertexAttrib0Status
 WebGLContext::WhatDoesVertexAttrib0Need() const
 {
     MOZ_ASSERT(mCurrentProgram);
     MOZ_ASSERT(mActiveProgramLinkInfo);
 
     const auto& isAttribArray0Enabled = mBoundVertexArray->mAttribs[0].mEnabled;
 
-    // work around Mac OSX crash, see bug 631420
+    bool legacyAttrib0 = gl->IsCompatibilityProfile();
 #ifdef XP_MACOSX
-    if (gl->WorkAroundDriverBugs() &&
-        isAttribArray0Enabled &&
-        !mBufferFetch_IsAttrib0Active)
-    {
-        return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
+    if (gl->WorkAroundDriverBugs()) {
+        // Failures in conformance/attribs/gl-disabled-vertex-attrib.
+        // Even in Core profiles on NV. Sigh.
+        legacyAttrib0 |= (gl->Vendor() == gl::GLVendor::NVIDIA);
     }
 #endif
 
-    if (MOZ_LIKELY(!gl->IsCompatibilityProfile() ||
-                   isAttribArray0Enabled))
-    {
+    if (!legacyAttrib0)
+        return WebGLVertexAttrib0Status::Default;
+
+    if (isAttribArray0Enabled && mBufferFetch_IsAttrib0Active)
         return WebGLVertexAttrib0Status::Default;
-    }
 
-    return mBufferFetch_IsAttrib0Active
-           ? WebGLVertexAttrib0Status::EmulatedInitializedArray
-           : WebGLVertexAttrib0Status::EmulatedUninitializedArray;
+    if (mBufferFetch_IsAttrib0Active)
+        return WebGLVertexAttrib0Status::EmulatedInitializedArray;
+
+    // Ensure that the legacy code has enough buffer.
+    return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
 }
 
 bool
 WebGLContext::DoFakeVertexAttrib0(const char* funcName, GLuint vertexCount)
 {
     if (!vertexCount) {
         vertexCount = 1;
     }
@@ -1065,16 +1066,18 @@ WebGLContext::DoFakeVertexAttrib0(const 
         GenerateWarning("Drawing without vertex attrib 0 array enabled forces the browser "
                         "to do expensive emulation work when running on desktop OpenGL "
                         "platforms, for example on Mac. It is preferable to always draw "
                         "with vertex attrib 0 array enabled, by using bindAttribLocation "
                         "to bind some always-used attribute to location 0.");
         mAlreadyWarnedAboutFakeVertexAttrib0 = true;
     }
 
+    gl->fEnableVertexAttribArray(0);
+
     if (!mFakeVertexAttrib0BufferObject) {
         gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
         mFakeVertexAttrib0BufferObjectSize = 0;
     }
     gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
 
     ////
 
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -531,20 +531,16 @@ WebGLContext::InitAndValidateGL(FailureR
     mCurrentProgram = nullptr;
 
     mBoundDrawFramebuffer = nullptr;
     mBoundReadFramebuffer = nullptr;
     mBoundRenderbuffer = nullptr;
 
     MakeContextCurrent();
 
-    // For OpenGL compat. profiles, we always keep vertex attrib 0 array enabled.
-    if (gl->IsCompatibilityProfile())
-        gl->fEnableVertexAttribArray(0);
-
     if (MinCapabilityMode())
         mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
     else
         gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
 
     if (mGLMaxVertexAttribs < 8) {
         const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
                                      mGLMaxVertexAttribs);
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -167,17 +167,17 @@ webgl::UniformInfo::UniformInfo(WebGLAct
 {
     if (mSamplerTexList) {
         mSamplerValues.assign(mActiveInfo->mElemCount, 0);
     }
 }
 
 //////////
 
-#define DUMP_SHADERVAR_MAPPINGS
+//#define DUMP_SHADERVAR_MAPPINGS
 
 static already_AddRefed<const webgl::LinkedProgramInfo>
 QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
 {
     WebGLContext* const webgl = prog->mContext;
 
     RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
 
@@ -235,22 +235,29 @@ QueryProgramInfo(WebGLProgram* prog, gl:
 
         nsCString userName;
         if (!prog->FindAttribUserNameByMappedName(mappedName, &userName)) {
             userName = mappedName;
         }
 
         ///////
 
-        const GLint loc = gl->fGetAttribLocation(prog->mGLName,
-                                                 mappedName.BeginReading());
+        GLint loc = gl->fGetAttribLocation(prog->mGLName,
+                                           mappedName.BeginReading());
+        if (gl->WorkAroundDriverBugs() &&
+            mappedName.EqualsIgnoreCase("gl_", 3))
+        {
+            // Bug 1328559: Appears problematic on ANGLE and OSX, but not Linux or Win+GL.
+            loc = -1;
+        }
 #ifdef DUMP_SHADERVAR_MAPPINGS
         printf_stderr("[attrib %u/%u] @%i %s->%s\n", i, numActiveAttribs, loc,
                       userName.BeginReading(), mappedName.BeginReading());
 #endif
+        MOZ_ASSERT_IF(mappedName.EqualsIgnoreCase("gl_", 3), loc == -1);
 
         ///////
 
         const bool isArray = false;
         const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
                                                                        elemType, isArray,
                                                                        userName,
                                                                        mappedName);
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -2011,16 +2011,19 @@ DoCopyTexOrSubImage(WebGLContext* webgl,
     ////
 
     uint32_t readX, readY;
     uint32_t writeX, writeY;
     uint32_t rwWidth, rwHeight;
     Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
     Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
 
+    writeX += xOffset;
+    writeY += yOffset;
+
     ////
 
     GLenum error = 0;
     do {
         const auto& idealUnpack = dstUsage->idealUnpack;
         if (!isSubImage) {
             UniqueBuffer buffer;
 
@@ -2053,17 +2056,16 @@ DoCopyTexOrSubImage(WebGLContext* webgl,
             // There aren't any pixels to copy, so we're 'done'.
             return true;
         }
 
         const auto& srcFormat = srcUsage->format;
         ScopedCopyTexImageSource maybeSwizzle(webgl, funcName, srcTotalWidth,
                                               srcTotalHeight, srcFormat, dstUsage);
 
-        const uint8_t zOffset = 0;
         error = DoCopyTexSubImage(gl, target, level, writeX, writeY, zOffset, readX,
                                   readY, rwWidth, rwHeight);
         if (error)
             break;
 
         return true;
     } while (false);
 
--- a/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/00_test_list.txt
@@ -1,11 +1,12 @@
 --max-version 1.9.9 compressed-tex-image.html
 copy-tex-image-and-sub-image-2d.html
 --min-version 1.0.2 copy-tex-image-2d-formats.html
+--min-version 1.0.4 copy-tex-sub-image-2d-partial-texture.html
 --min-version 1.0.4 cube-incomplete-fbo.html
 --min-version 1.0.3 default-texture.html
 --min-version 1.0.2 --max-version 1.9.9 gl-get-tex-parameter.html
 gl-pixelstorei.html
 gl-teximage.html
 origin-clean-conformance.html
 tex-image-and-sub-image-2d-with-array-buffer-view.html
 tex-image-and-uniform-binding-bugs.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/textures/misc/copy-tex-sub-image-2d-partial-texture.html
@@ -0,0 +1,191 @@
+<!--
+
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CopyTexSubImage2D partial destination texture test</title>
+<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
+<script src="../../../js/js-test-pre.js"></script>
+<script src="../../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas"></canvas>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Verifies that copyTexSubImage2D redefining part of the destination texture works as expected.");
+
+////
+
+var kWidth = 16;
+var kHeight = 16;
+
+////
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+canvas.width = kWidth;
+canvas.height = kHeight;
+var gl = wtu.create3DContext(canvas);
+
+////
+
+function clearTo(color) {
+    gl.clearColor(color[0], color[1], color[2], color[3]);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+}
+
+function readInto(view) {
+    gl.readPixels(0, 0, kWidth, kHeight, gl.RGBA, gl.UNSIGNED_BYTE,
+                  new Uint8Array(view.buffer));
+}
+
+////
+
+function runTest() {
+    gl.enable(gl.SCISSOR_TEST);
+
+    gl.scissor(0, 0, kWidth/2, kHeight/2);
+    clearTo([1,0,0,1]);
+    gl.scissor(kWidth/2, 0, kWidth/2, kHeight/2);
+    clearTo([0,1,0,1]);
+    gl.scissor(0, kHeight/2, kWidth/2, kHeight/2);
+    clearTo([0,0,1,1]);
+    gl.scissor(kWidth/2, kHeight/2, kWidth/2, kHeight/2);
+    clearTo([0,1,1,1]);
+
+    var srcData = new Uint32Array(kWidth * kHeight);
+    readInto(srcData);
+    console.log('0x' + srcData[0].toString(16));
+
+    ////
+
+    var dstTex = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, dstTex);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, kWidth, kHeight,
+                  0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Uploads zeros.
+    var dstRefData = new Uint32Array(kWidth * kHeight); // Also cleared to zeros!
+    var dstTestData = new Uint32Array(kWidth * kHeight);
+
+    var dstFB = gl.createFramebuffer();
+    gl.bindFramebuffer(gl.FRAMEBUFFER, dstFB);
+    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+                            gl.TEXTURE_2D, dstTex, 0);
+
+    ////
+
+    function pixelPos(x, y) {
+        return y * kWidth + x;
+    }
+
+    function testCmd(tuple) {
+        var dstX0, dstY0, srcX0, srcY0, width, height;
+        [dstX0, dstY0, srcX0, srcY0, width, height] = tuple
+        debug("copyTexSubImage2D(" +
+              [dstX0+','+dstY0, srcX0+','+srcY0, width+','+height].join(', ') +
+              ")");
+
+        // Test
+        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+        gl.copyTexSubImage2D(gl.TEXTURE_2D, 0,
+                             dstX0, dstY0, srcX0, srcY0, width, height);
+
+        // Emulate for reference
+        for (var x = 0; x < width; x++) {
+            var srcX = srcX0 + x;
+            var dstX = dstX0 + x;
+            if (srcX < 0 || srcX >= kWidth ||
+                dstX < 0 || dstX >= kWidth)
+            {
+                continue;
+            }
+
+            for (var y = 0; y < height; y++) {
+                var srcY = srcY0 + y;
+                var dstY = dstY0 + y;
+                if (srcY < 0 || srcY >= kHeight ||
+                    dstY < 0 || dstY >= kHeight)
+                {
+                    continue;
+                }
+
+
+                var srcPos = pixelPos(srcX, srcY);
+                var dstPos = pixelPos(dstX, dstY);
+                dstRefData[dstPos] = srcData[srcPos];
+            }
+        }
+
+        // Compare
+        gl.bindFramebuffer(gl.FRAMEBUFFER, dstFB);
+        readInto(dstTestData);
+
+        for (var x = 0; x < kWidth; x++) {
+            for (var y = 0; y < kHeight; y++) {
+                var pos = pixelPos(x, y);
+                var refPixel = dstRefData[pos];
+                var testPixel = dstTestData[pos];
+
+                //console.log([x, y].join(",") + ":",
+                //            testPixel.toString(16), refPixel.toString(16))
+                if (testPixel == refPixel)
+                    continue;
+
+                testFailed("Mismatch at (" + [x, y].join(", ") + "): " +
+                           " Should be 0x" + refPixel.toString(16) +
+                           ", was 0x" + testPixel.toString(16));
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    var tests = [
+        [0,0, 0,0, 2,3],
+        [0,0, 5,8, 2,3],
+        [1,0, 0,0, 2,3],
+        [1,7, 0,0, 2,3],
+    ];
+
+    tests.every(x => testCmd(x));
+}
+
+runTest();
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/00_test_list.txt
@@ -1,14 +1,15 @@
 attribs/00_test_list.txt
 buffers/00_test_list.txt
 context/00_test_list.txt
 extensions/00_test_list.txt
 glsl3/00_test_list.txt
 misc/00_test_list.txt
+programs/00_test_list.txt
 query/00_test_list.txt
 reading/00_test_list.txt
 renderbuffers/00_test_list.txt
 rendering/00_test_list.txt
 samplers/00_test_list.txt
 state/00_test_list.txt
 textures/00_test_list.txt
 transform_feedback/00_test_list.txt
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/00_test_list.txt
@@ -0,0 +1,2 @@
+active-built-in-attribs.html
+gl-get-frag-data-location.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/active-built-in-attribs.html
@@ -0,0 +1,107 @@
+<!--
+
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Verify validation for active built-in attribs</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 64px; height: 64px;"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+void main() {
+  gl_Position = vec4(gl_VertexID % 2, (gl_VertexID/2) % 2, 0, 1);
+}
+</script>
+
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 fragColor;
+void main() {
+  fragColor = vec4(0, 1, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies validation for active built-in attribs.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+  testFailed("WebGL context does not exist");
+} else {
+  testPassed("WebGL context exists");
+  runTests();
+}
+
+var activeInfo, attribLoc;
+
+function runTests() {
+  var prog = wtu.setupProgram(gl, ["vs", "fs"]);
+  if (!prog) {
+    testFailed("Set up program failed");
+    return;
+  }
+  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+  var numActive = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
+  if (numActive != 1) {
+    testFailed('ACTIVE_ATTRIBUTES should be 1.');
+    return;
+  }
+  testPassed('ACTIVE_ATTRIBUTES should be 1.');
+
+  activeInfo = gl.getActiveAttrib(prog, 0);
+  if (!activeInfo) {
+    testFailed('getActiveAttrib should return an info object.');
+    return;
+  }
+
+  shouldBe('activeInfo.name', '"gl_VertexID"');
+  attribLoc = gl.getAttribLocation(prog, 'gl_VertexID');
+  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be able to request the location of a built-in.");
+  shouldBe('attribLoc', '-1');
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/programs/gl-get-frag-data-location.html
@@ -0,0 +1,121 @@
+<!--
+
+/*
+** Copyright (c) 2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Conformance Tests: Verify getFragDataLocation</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 4px; height: 4px;"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">#version 300 es
+void main() {
+  gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="fs" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout(location = 2) out vec4 fragColor0;
+layout(location = 0) out vec4 fragColor1;
+void main() {
+  fragColor0 = vec4(0, 1, 0, 1);
+  fragColor1 = vec4(1, 0, 0, 1);
+}
+</script>
+
+<script id="fs-array" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+out vec4 fragColor[2];
+void main() {
+  fragColor[0] = vec4(0, 1, 0, 1);
+  fragColor[1] = vec4(1, 0, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+description("This test verifies getFragDataLocation behaviors.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+if (!gl) {
+  testFailed("WebGL context does not exist");
+} else {
+  testPassed("WebGL context exists");
+  runTests();
+}
+
+function runTests() {
+  var program = wtu.setupProgram(gl, ["vs", "fs"]);
+  var programArray = wtu.setupProgram(gl, ["vs", "fs-array"]);
+  if (!program || !programArray) {
+    testFailed("Set up program failed");
+    return;
+  }
+  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+  var loc0 = gl.getFragDataLocation(program, "fragColor0");
+  var loc1 = gl.getFragDataLocation(program, "fragColor1");
+  if (loc0 != 2 || loc1 != 0) {
+    testFailed("Fail to query scalar output variable locations, " +
+               "expected: fragColor0->2, fragColor1->0, " +
+               "got: fragColor0->" + loc0 + ", fragColor1->" + loc1);
+  } else {
+    testPassed("getFragDataLocation on scalar variables works fine");
+  }
+
+  var loc = gl.getFragDataLocation(programArray, "fragColor");
+  loc0 = gl.getFragDataLocation(programArray, "fragColor[0]");
+  loc1 = gl.getFragDataLocation(programArray, "fragColor[1]");
+  if (loc < 0 || loc0 < 0 || loc1 < 0 || loc != loc0 || loc0 + 1 != loc1) {
+    testFailed("Fail to query scalar output variable locations, " +
+               "expected: fragColor->0, fragColor[0]->0, fragColor[1]->1, " +
+               "got: fragColor->" + loc + ", fragColor[0]->" + loc0 + ", fragColor[1]->" + loc1);
+  } else {
+    testPassed("getFragDataLocation on variable arrays works fine");
+  }
+  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from testing");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -2320,16 +2320,17 @@ support-files = always-fail.html
                 checkout/conformance/textures/image_data/tex-2d-rgb-rgb-unsigned_short_5_6_5.html
                 checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_byte.html
                 checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html
                 checkout/conformance/textures/image_data/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html
                 checkout/conformance/textures/misc/00_test_list.txt
                 checkout/conformance/textures/misc/compressed-tex-image.html
                 checkout/conformance/textures/misc/copy-tex-image-2d-formats.html
                 checkout/conformance/textures/misc/copy-tex-image-and-sub-image-2d.html
+                checkout/conformance/textures/misc/copy-tex-sub-image-2d-partial-texture.html
                 checkout/conformance/textures/misc/cube-incomplete-fbo.html
                 checkout/conformance/textures/misc/default-texture.html
                 checkout/conformance/textures/misc/gl-get-tex-parameter.html
                 checkout/conformance/textures/misc/gl-pixelstorei.html
                 checkout/conformance/textures/misc/gl-teximage.html
                 checkout/conformance/textures/misc/mipmap-fbo.html
                 checkout/conformance/textures/misc/origin-clean-conformance.html
                 checkout/conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html
@@ -2451,16 +2452,19 @@ support-files = always-fail.html
                 checkout/conformance2/glsl3/short-circuiting-in-loop-condition.html
                 checkout/conformance2/glsl3/texture-offset-out-of-range.html
                 checkout/conformance2/glsl3/uniform-location-length-limits.html
                 checkout/conformance2/glsl3/vector-dynamic-indexing.html
                 checkout/conformance2/misc/00_test_list.txt
                 checkout/conformance2/misc/expando-loss-2.html
                 checkout/conformance2/misc/instanceof-test.html
                 checkout/conformance2/misc/uninitialized-test-2.html
+                checkout/conformance2/programs/00_test_list.txt
+                checkout/conformance2/programs/active-built-in-attribs.html
+                checkout/conformance2/programs/gl-get-frag-data-location.html
                 checkout/conformance2/query/00_test_list.txt
                 checkout/conformance2/query/occlusion-query.html
                 checkout/conformance2/query/query.html
                 checkout/conformance2/reading/00_test_list.txt
                 checkout/conformance2/reading/read-pixels-from-fbo-test.html
                 checkout/conformance2/reading/read-pixels-into-pixel-pack-buffer.html
                 checkout/conformance2/reading/read-pixels-pack-parameters.html
                 checkout/conformance2/renderbuffers/00_test_list.txt
@@ -4542,16 +4546,20 @@ skip-if = (os == 'win' && debug) || (os 
 [generated/test_2_conformance2__glsl3__vector-dynamic-indexing.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__misc__expando-loss-2.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__misc__instanceof-test.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__misc__uninitialized-test-2.html]
 skip-if = (os == 'mac') || (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
+[generated/test_2_conformance2__programs__active-built-in-attribs.html]
+skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
+[generated/test_2_conformance2__programs__gl-get-frag-data-location.html]
+skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__query__occlusion-query.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__query__query.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__reading__read-pixels-from-fbo-test.html]
 skip-if = (os == 'mac') || (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance2__reading__read-pixels-into-pixel-pack-buffer.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
@@ -5800,16 +5808,18 @@ skip-if = (os == 'android' || os == 'lin
 [generated/test_2_conformance__state__gl-initial-state.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__state__state-uneffected-after-compositing.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__textures__misc__copy-tex-image-2d-formats.html]
 skip-if = (os == 'mac') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__textures__misc__copy-tex-image-and-sub-image-2d.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
+[generated/test_2_conformance__textures__misc__copy-tex-sub-image-2d-partial-texture.html]
+skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__textures__misc__cube-incomplete-fbo.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 fail-if = (os == 'mac')
 [generated/test_2_conformance__textures__misc__default-texture.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__textures__misc__gl-pixelstorei.html]
 skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
 [generated/test_2_conformance__textures__misc__gl-teximage.html]
@@ -6686,16 +6696,17 @@ skip-if = (os == 'mac') || (os == 'andro
 [generated/test_conformance__state__gl-getstring.html]
 [generated/test_conformance__state__gl-initial-state.html]
 [generated/test_conformance__state__gl-object-get-calls.html]
 [generated/test_conformance__state__state-uneffected-after-compositing.html]
 [generated/test_conformance__textures__misc__compressed-tex-image.html]
 [generated/test_conformance__textures__misc__copy-tex-image-2d-formats.html]
 skip-if = (os == 'win' && os_version == '5.1')
 [generated/test_conformance__textures__misc__copy-tex-image-and-sub-image-2d.html]
+[generated/test_conformance__textures__misc__copy-tex-sub-image-2d-partial-texture.html]
 [generated/test_conformance__textures__misc__cube-incomplete-fbo.html]
 skip-if = (os == 'android')
 fail-if = (os == 'mac') || (os == 'linux')
 [generated/test_conformance__textures__misc__default-texture.html]
 [generated/test_conformance__textures__misc__gl-get-tex-parameter.html]
 [generated/test_conformance__textures__misc__gl-pixelstorei.html]
 [generated/test_conformance__textures__misc__gl-teximage.html]
 skip-if = (os == 'android')
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__programs__active-built-in-attribs.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance2/programs/active-built-in-attribs.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__programs__gl-get-frag-data-location.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance2/programs/gl-get-frag-data-location.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance__textures__misc__copy-tex-sub-image-2d-partial-texture.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance/textures/misc/copy-tex-sub-image-2d-partial-texture.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_conformance__textures__misc__copy-tex-sub-image-2d-partial-texture.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance/textures/misc/copy-tex-sub-image-2d-partial-texture.html'></iframe>
+  </body>
+</html>
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -1220,17 +1220,17 @@ FetchBody<Derived>::ContinueConsumeBody(
         MOZ_ASSERT(mWorkerPrivate);
         // In case of worker thread, we block the worker while the request is
         // canceled on the main thread. This ensures that OnStreamComplete has
         // a valid FetchBody around to call CancelPump and we don't release the
         // FetchBody on the main thread.
         RefPtr<CancelPumpRunnable<Derived>> r =
           new CancelPumpRunnable<Derived>(this);
         ErrorResult rv;
-        r->Dispatch(rv);
+        r->Dispatch(Terminating, rv);
         if (rv.Failed()) {
           NS_WARNING("Could not dispatch CancelPumpRunnable. Nothing we can do here");
           // None of our callers are callled directly from JS, so there is no
           // point in trying to propagate this failure out of here.  And
           // localPromise is already rejected.  Just suppress the failure.
           rv.SuppressException();
         }
       }
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -103,16 +103,18 @@ FetchDriver::Fetch(FetchDriverObserver* 
 }
 
 // This function implements the "HTTP Fetch" algorithm from the Fetch spec.
 // Functionality is often split between here, the CORS listener proxy and the
 // Necko HTTP implementation.
 nsresult
 FetchDriver::HttpFetch()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   // Step 1. "Let response be null."
   mResponse = nullptr;
   nsresult rv;
 
   nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString url;
@@ -272,17 +274,19 @@ FetchDriver::HttpFetch()
     if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) {
       mRequest->SetReferrerPolicy(net_referrerPolicy);
     }
     // Step 7 of
     // https://fetch.spec.whatwg.org/#main-fetch
     // If request’s referrer policy is the empty string,
     // then set request’s referrer policy to "no-referrer-when-downgrade".
     if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) {
-      mRequest->SetReferrerPolicy(net::RP_No_Referrer_When_Downgrade);
+      net::ReferrerPolicy referrerPolicy =
+        static_cast<net::ReferrerPolicy>(NS_GetDefaultReferrerPolicy());
+      mRequest->SetReferrerPolicy(referrerPolicy);
     }
 
     rv = FetchUtil::SetRequestReferrer(mPrincipal,
                                        mDocument,
                                        httpChan,
                                        mRequest);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -77,17 +77,17 @@ InternalRequest::Clone()
 }
 InternalRequest::InternalRequest(const nsACString& aURL,
                                  const nsACString& aFragment)
   : mMethod("GET")
   , mHeaders(new InternalHeaders(HeadersGuardEnum::None))
   , mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
   , mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
   , mReferrerPolicy(ReferrerPolicy::_empty)
-  , mEnvironmentReferrerPolicy(net::RP_Default)
+  , mEnvironmentReferrerPolicy(net::RP_Unset)
   , mMode(RequestMode::No_cors)
   , mCredentialsMode(RequestCredentials::Omit)
   , mResponseTainting(LoadTainting::Basic)
   , mCacheMode(RequestCache::Default)
   , mRedirectMode(RequestRedirect::Follow)
   , mAuthenticationFlag(false)
   , mForceOriginHeader(false)
   , mPreserveContentCodings(false)
@@ -116,17 +116,17 @@ InternalRequest::InternalRequest(const n
                                  ReferrerPolicy aReferrerPolicy,
                                  nsContentPolicyType aContentPolicyType,
                                  const nsAString& aIntegrity)
   : mMethod(aMethod)
   , mHeaders(aHeaders)
   , mContentPolicyType(aContentPolicyType)
   , mReferrer(aReferrer)
   , mReferrerPolicy(aReferrerPolicy)
-  , mEnvironmentReferrerPolicy(net::RP_Default)
+  , mEnvironmentReferrerPolicy(net::RP_Unset)
   , mMode(aMode)
   , mCredentialsMode(aRequestCredentials)
   , mResponseTainting(LoadTainting::Basic)
   , mCacheMode(aCacheMode)
   , mRedirectMode(aRequestRedirect)
   , mIntegrity(aIntegrity)
   , mAuthenticationFlag(false)
   , mForceOriginHeader(false)
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -398,17 +398,17 @@ Request::Constructor(const GlobalObject&
           nsresult rv = NS_OK;
           // ReferrerSameOriginChecker uses a sync loop to get the main thread
           // to perform the same-origin check.  Overall, on Workers this method
           // can create 3 sync loops (two for constructing URLs and one here) so
           // in the future we may want to optimize it all by off-loading all of
           // this work in a single sync loop.
           RefPtr<ReferrerSameOriginChecker> checker =
             new ReferrerSameOriginChecker(worker, referrerURL, rv);
-          checker->Dispatch(aRv);
+          checker->Dispatch(Terminating, aRv);
           if (aRv.Failed() || NS_FAILED(rv)) {
             aRv.ThrowTypeError<MSG_CROSS_ORIGIN_REFERRER_URL>(referrer,
                                                               worker->GetLocationInfo().mOrigin);
             return nullptr;
           }
         }
       }
       request->SetReferrer(referrerURL);
--- a/dom/file/File.cpp
+++ b/dom/file/File.cpp
@@ -916,17 +916,17 @@ BlobImplFile::GetType(nsAString& aType)
         // return any valid value.
         return;
       }
 
       RefPtr<GetTypeRunnable> runnable =
         new GetTypeRunnable(workerPrivate, this);
 
       ErrorResult rv;
-      runnable->Dispatch(rv);
+      runnable->Dispatch(Terminating, rv);
       if (NS_WARN_IF(rv.Failed())) {
         rv.SuppressException();
       }
       return;
     }
 
     nsresult rv;
     nsCOMPtr<nsIMIMEService> mimeService =
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -407,32 +407,33 @@ FileReader::ReadFileContent(Blob& aBlob,
   mAsyncStream = do_QueryInterface(wrapper);
   MOZ_ASSERT(mAsyncStream);
 
   mTotal = mBlob->GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  aRv = DoAsyncWait();
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  //FileReader should be in loading state here
-  mReadyState = LOADING;
-  DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
-
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     mFileData = js_pod_malloc<char>(mTotal);
     if (!mFileData) {
       NS_WARNING("Preallocation failed for ReadFileData");
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     }
   }
+
+  aRv = DoAsyncWait();
+  if (NS_WARN_IF(aRv.Failed())) {
+    FreeFileData();
+    return;
+  }
+
+  //FileReader should be in loading state here
+  mReadyState = LOADING;
+  DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
 }
 
 nsresult
 FileReader::GetAsText(Blob *aBlob,
                       const nsACString &aCharset,
                       const char *aFileData,
                       uint32_t aDataLen,
                       nsAString& aResult)
--- a/dom/html/crashtests/crashtests.list
+++ b/dom/html/crashtests/crashtests.list
@@ -26,17 +26,17 @@ load 494225.html
 load 495543.svg
 load 495546-1.html
 load 504183-1.html
 load 515829-1.html
 load 515829-2.html
 load 564461.xhtml
 load 570566-1.html
 load 571428-1.html
-skip-if(stylo) load 580507-1.xhtml # bug 1323655
+load 580507-1.xhtml
 load 590387.html
 load 596785-1.html
 load 596785-2.html
 load 601422.html
 load 602117.html
 load 604807.html
 load 605264.html
 load 606430-1.html
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -30,17 +30,17 @@ native nscolor(nscolor);
 typedef unsigned long long nsViewID;
 
 interface nsICycleCollectorListener;
 interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
-interface nsIDOMStyleSheet;
+interface nsIPreloadedStyleSheet;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIFile;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
@@ -1739,17 +1739,17 @@ interface nsIDOMWindowUtils : nsISupport
 
   /**
    * Adds a style sheet to the list of additional style sheets of the document.
    *
    * Style sheets can be preloaded with nsIStyleSheetService.preloadSheet.
    *
    * Sheets added via this API take effect immediately on the document.
    */
-  void addSheet(in nsIDOMStyleSheet sheet, in unsigned long type);
+  void addSheet(in nsIPreloadedStyleSheet sheet, in unsigned long type);
 
   /**
    * Remove the document style sheet at |sheetURI| from the list of additional 
    * style sheets of the document.  The removal takes effect immediately.
    */
   void removeSheet(in nsIURI sheetURI, in unsigned long type);
 
   /**
--- a/dom/media/test/crashtests/crashtests.list
+++ b/dom/media/test/crashtests/crashtests.list
@@ -3,17 +3,17 @@ skip-if(Android) load 459439-1.html # bu
 load 466607-1.html
 load 466945-1.html
 load 468763-1.html
 load 474744-1.html
 asserts-if(stylo,8) HTTP load 481136-1.html # bug 1324671 # needs to be HTTP to recognize the ogg as an audio file?
 load 492286-1.xhtml
 load 493915-1.html
 load 495794-1.html
- load 576612-1.html # bug 1323890
+load 576612-1.html
 load 752784-1.html
 load 789075-1.html
 HTTP load 795892-1.html
 load 844563.html
 load 846612.html
 load 852838.html
 load 865537-1.html
 load 868504.html
--- a/dom/network/ConnectionWorker.cpp
+++ b/dom/network/ConnectionWorker.cpp
@@ -173,17 +173,17 @@ ConnectionWorker::Create(WorkerPrivate* 
     aRv.ThrowTypeError<MSG_WORKER_THREAD_SHUTTING_DOWN>();
     return nullptr;
   }
 
   hal::NetworkInformation networkInfo;
   RefPtr<InitializeRunnable> runnable =
     new InitializeRunnable(aWorkerPrivate, c->mProxy, networkInfo);
 
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   c->Update(static_cast<ConnectionType>(networkInfo.type()),
             networkInfo.isWifi(), networkInfo.dhcpGateway(), false);
   return c.forget();
 }
@@ -231,17 +231,18 @@ ConnectionProxy::Shutdown()
   }
 
   mConnection = nullptr;
 
   RefPtr<ShutdownRunnable> runnable =
     new ShutdownRunnable(mWorkerPrivate, this);
 
   ErrorResult rv;
-  runnable->Dispatch(rv);
+  // This runnable _must_ be executed.
+  runnable->Dispatch(Killing, rv);
   if (NS_WARN_IF(rv.Failed())) {
     rv.SuppressException();
   }
 
   ReleaseWorker();
 }
 
 } // namespace network
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -1876,17 +1876,17 @@ Notification::GetPermission(nsIGlobalObj
 {
   if (NS_IsMainThread()) {
     return GetPermissionInternal(aGlobal, aRv);
   } else {
     WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(worker);
     RefPtr<GetPermissionRunnable> r =
       new GetPermissionRunnable(worker);
-    r->Dispatch(aRv);
+    r->Dispatch(Terminating, aRv);
     if (aRv.Failed()) {
       return NotificationPermission::Denied;
     }
 
     return r->GetPermission();
   }
 }
 
@@ -2479,17 +2479,17 @@ NotificationWorkerHolder::Notify(Status 
     // on the main thread, but the main thread dispatches the control runnable,
     // invalidating mNotification.
     RefPtr<Notification> kungFuDeathGrip = mNotification;
 
     // Dispatched to main thread, blocks on closing the Notification.
     RefPtr<CloseNotificationRunnable> r =
       new CloseNotificationRunnable(kungFuDeathGrip);
     ErrorResult rv;
-    r->Dispatch(rv);
+    r->Dispatch(Killing, rv);
     // XXXbz I'm told throwing and returning false from here is pointless (and
     // also that doing sync stuff from here is really weird), so I guess we just
     // suppress the exception on rv, if any.
     rv.SuppressException();
 
     // Only call ReleaseObject() to match the observer's NotificationRef
     // ownership (since CloseNotificationRunnable asked the observer to drop the
     // reference to the notification).
@@ -2616,17 +2616,17 @@ Notification::ShowPersistentNotification
       return nullptr;
     }
   } else {
     WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(worker);
     worker->AssertIsOnWorkerThread();
     RefPtr<CheckLoadRunnable> loadChecker =
       new CheckLoadRunnable(worker, NS_ConvertUTF16toUTF8(aScope));
-    loadChecker->Dispatch(aRv);
+    loadChecker->Dispatch(Terminating, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
     if (NS_WARN_IF(NS_FAILED(loadChecker->Result()))) {
       if (loadChecker->Result() == NS_ERROR_NOT_AVAILABLE) {
         aRv.ThrowTypeError<MSG_NO_ACTIVE_WORKER>(aScope);
       } else {
@@ -2755,9 +2755,8 @@ Notification::Observe(nsISupports* aSubj
     }
   }
 
   return NS_OK;
 }
 
 } // namespace dom
 } // namespace mozilla
-
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -3299,17 +3299,17 @@ nsresult nsPluginHost::NewPluginURLStrea
   // deal with headers and post data
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     if (!aPostStream) {
       // Only set the Referer header for GET requests because IIS throws
       // errors about malformed requests if we include it in POSTs. See
       // bug 724465.
       nsCOMPtr<nsIURI> referer;
-      net::ReferrerPolicy referrerPolicy = net::RP_Default;
+      net::ReferrerPolicy referrerPolicy = net::RP_Unset;
 
       nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(element);
       if (olc)
         olc->GetSrcURI(getter_AddRefs(referer));
 
 
       if (!referer) {
         if (!doc) {
--- a/dom/quota/StorageManager.cpp
+++ b/dom/quota/StorageManager.cpp
@@ -319,17 +319,17 @@ StorageManager::Estimate(ErrorResult& aR
   if (NS_WARN_IF(!promiseProxy)) {
     return nullptr;
   }
 
   RefPtr<EstimateWorkerMainThreadRunnable> runnnable =
     new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(),
                                          promiseProxy);
 
-  runnnable->Dispatch(aRv);
+  runnnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   return promise.forget();
 }
 
 // static
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -341,19 +341,19 @@ nsCSPContext::GetBlockAllMixedContent(bo
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
 {
   *outIsSet = false;
-  *outPolicy = mozilla::net::RP_Default;
+  *outPolicy = mozilla::net::RP_Unset;
   nsAutoString refpol;
-  mozilla::net::ReferrerPolicy previousPolicy = mozilla::net::RP_Default;
+  mozilla::net::ReferrerPolicy previousPolicy = mozilla::net::RP_Unset;
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     mPolicies[i]->getReferrerPolicy(refpol);
     // only set the referrer policy if not delievered through a CSPRO and
     // note that and an empty string in refpol means it wasn't set
     // (that's the default in nsCSPPolicy).
     if (!mPolicies[i]->getReportOnlyFlag() && !refpol.IsEmpty()) {
       // Referrer Directive in CSP is no more used and going to be replaced by
       // Referrer-Policy HTTP header. But we still keep using referrer directive,
--- a/dom/tests/mochitest/fetch/mochitest.ini
+++ b/dom/tests/mochitest/fetch/mochitest.ini
@@ -26,32 +26,35 @@ support-files =
   !/dom/xhr/tests/file_XHR_pass1.xml
   !/dom/xhr/tests/file_XHR_pass2.txt
   !/dom/xhr/tests/file_XHR_pass3.txt
   !/dom/xhr/tests/file_XHR_pass3.txt^headers^
   !/dom/xhr/tests/responseIdentical.sjs
   !/dom/xhr/tests/temporaryFileBlob.sjs
   !/dom/html/test/form_submit_server.sjs
   !/dom/security/test/cors/file_CrossSiteXHR_server.sjs
+  !/dom/base/test/referrer_helper.js
+  !/dom/base/test/referrer_testserver.sjs
 
 [test_headers.html]
 [test_headers_sw_reroute.html]
 [test_headers_mainthread.html]
 [test_fetch_basic.html]
 [test_fetch_basic_sw_reroute.html]
 [test_fetch_basic_sw_empty_reroute.html]
 [test_fetch_basic_http.html]
 [test_fetch_basic_http_sw_reroute.html]
 [test_fetch_basic_http_sw_empty_reroute.html]
 [test_fetch_cors.html]
 skip-if = toolkit == 'android' && debug # Bug 1210282
 [test_fetch_cors_sw_reroute.html]
 skip-if = toolkit == 'android' && debug # Bug 1210282
 [test_fetch_cors_sw_empty_reroute.html]
 skip-if = toolkit == 'android' && debug # Bug 1210282
+[test_fetch_user_control_rp.html]
 [test_formdataparsing.html]
 [test_formdataparsing_sw_reroute.html]
 [test_request.html]
 [test_request_context.html]
 [test_request_sw_reroute.html]
 [test_response.html]
 [test_response_sw_reroute.html]
 [test_temporaryFileBlob.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/fetch/test_fetch_user_control_rp.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test fetch user control referrer policy Bug 1304623</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="application/javascript;version=1.7">
+  const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
+  const PARAMS = ["SCHEME_FROM", "SCHEME_TO"];
+
+  const testCases = [
+    {ACTION: ["generate-fetch-user-control-policy-test"],
+      PREFS: [['network.http.referer.userControlPolicy', 0]],
+      TESTS: [
+         // 0. No referrer.
+        {NAME: 'default-policy-value-no-referrer-https-http',
+         DESC: 'default-policy-value-no-referrer-https-http',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {NAME: 'default-policy-value-no-referrer-https-https',
+         DESC: 'default-policy-value-no-referrer-https-https',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'none'}],
+    },
+    {ACTION: ["generate-fetch-user-control-policy-test"],
+      PREFS: [['network.http.referer.userControlPolicy', 1]],
+      TESTS: [
+         // 1. Same origin.
+        {NAME: 'default-policy-value-same-origin-https-http',
+         DESC: 'default-policy-value-same-origin-https-http',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {NAME: 'default-policy-value-same-origin-http-https',
+         DESC: 'default-policy-value-same-origin-http-https',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         RESULT: 'none'},
+        {NAME: 'default-policy-value-same-origin-https-https',
+         DESC: 'default-policy-value-same-origin-https-https',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'}],
+    },
+    {ACTION: ["generate-fetch-user-control-policy-test"],
+      PREFS: [['network.http.referer.userControlPolicy', 2]],
+      TESTS: [
+         // 2. strict-origin-when-cross-origin.
+        {NAME: 'default-policy-value-strict-origin-when-cross-origin-https-http',
+         DESC: 'default-policy-value-strict-origin-when-cross-origin-https-http',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {NAME: 'default-policy-value-strict-origin-when-cross-origin-http-https',
+         DESC: 'default-policy-value-strict-origin-when-cross-origin-http-https',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         RESULT: 'origin'},
+        {NAME: 'default-policy-value-strict-origin-when-cross-origin-https-https',
+         DESC: 'default-policy-value-strict-origin-when-cross-origin-https-https',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'}],
+    },
+    {ACTION: ["generate-fetch-user-control-policy-test"],
+      PREFS: [['network.http.referer.userControlPolicy', 3]],
+      TESTS: [
+         // 3. Default no-referrer-when-downgrade.
+        {NAME: 'default-policy-value-no-referrer-when-downgrade-https-http',
+         DESC: 'default-policy-value-no-referrer-when-downgrade-https-http',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {NAME: 'default-policy-value-no-referrer-when-downgrade-http-https',
+         DESC: 'default-policy-value-no-referrer-when-downgrade-http-https',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         RESULT: 'full'},
+        {NAME: 'default-policy-value-no-referrer-when-downgrade-https-https',
+         DESC: 'default-policy-value-no-referrer-when-downgrade-https-https',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'}],
+    },
+  ];
+
+  </script>
+  <script type="application/javascript;version=1.7" src="/tests/dom/base/test/referrer_helper.js"></script>
+
+</head>
+<body onload="tests.next();">
+  <iframe id="testframe"></iframe>
+</body>
+</html>
--- a/dom/url/URL.cpp
+++ b/dom/url/URL.cpp
@@ -1108,16 +1108,22 @@ public:
         mURLProxy->URL()->GetHash(mValue, rv);
         break;
     }
 
     MOZ_ASSERT(!rv.Failed(), "Main-thread getters do not fail.");
     return true;
   }
 
+  void
+  Dispatch(ErrorResult& aRv)
+  {
+    WorkerMainThreadRunnable::Dispatch(Terminating, aRv);
+  }
+
 private:
   nsAString& mValue;
   GetterType mType;
   RefPtr<URLProxy> mURLProxy;
 };
 
 // This class is the generic setter for any URL property.
 class SetterRunnable : public WorkerMainThreadRunnable
@@ -1208,28 +1214,34 @@ public:
     return true;
   }
 
   bool Failed() const
   {
     return mFailed;
   }
 
+  void
+  Dispatch(ErrorResult& aRv)
+  {
+    WorkerMainThreadRunnable::Dispatch(Terminating, aRv);
+  }
+
 private:
   const nsString mValue;
   SetterType mType;
   RefPtr<URLProxy> mURLProxy;
   bool mFailed;
 };
 
 already_AddRefed<URLWorker>
 FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate,
                   ConstructorRunnable* aRunnable, ErrorResult& aRv)
 {
-  aRunnable->Dispatch(aRv);
+  aRunnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   RefPtr<URLProxy> proxy = aRunnable->GetURLProxy(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
@@ -1297,17 +1309,17 @@ URLWorker::CreateObjectURL(const GlobalO
   aRv = blobImpl->SetMutable(false);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   RefPtr<CreateURLRunnable> runnable =
     new CreateURLRunnable(workerPrivate, blobImpl, aOptions, aResult);
 
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (workerPrivate->IsSharedWorker() || workerPrivate->IsServiceWorker()) {
     WorkerGlobalScope* scope = workerPrivate->GlobalScope();
     MOZ_ASSERT(scope);
 
@@ -1320,17 +1332,17 @@ URLWorker::RevokeObjectURL(const GlobalO
                            ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
 
   RefPtr<RevokeURLRunnable> runnable =
     new RevokeURLRunnable(workerPrivate, aUrl);
 
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (workerPrivate->IsSharedWorker() || workerPrivate->IsServiceWorker()) {
     WorkerGlobalScope* scope = workerPrivate->GlobalScope();
     MOZ_ASSERT(scope);
 
@@ -1343,17 +1355,17 @@ URLWorker::IsValidURL(const GlobalObject
                       ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
 
   RefPtr<IsValidURLRunnable> runnable =
     new IsValidURLRunnable(workerPrivate, aUrl);
 
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return false;
   }
 
   return runnable->IsValidURL();
 }
 
 URLWorker::URLWorker(WorkerPrivate* aWorkerPrivate, URLProxy* aURLProxy)
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -618,17 +618,17 @@ ContentSecurityPolicyAllows(JSContext* a
     } else {
       MOZ_ASSERT(!JS_IsExceptionPending(aCx));
     }
 
     RefPtr<LogViolationDetailsRunnable> runnable =
         new LogViolationDetailsRunnable(worker, fileName, lineNum);
 
     ErrorResult rv;
-    runnable->Dispatch(rv);
+    runnable->Dispatch(Killing, rv);
     if (NS_WARN_IF(rv.Failed())) {
       rv.SuppressException();
     }
   }
 
   return worker->IsEvalAllowed();
 }
 
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -201,17 +201,17 @@ ChannelFromScriptURL(nsIPrincipal* princ
                        aLoadFlags,
                        ios);
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel)) {
     mozilla::net::ReferrerPolicy referrerPolicy = parentDoc ?
-      parentDoc->GetReferrerPolicy() : mozilla::net::RP_Default;
+      parentDoc->GetReferrerPolicy() : mozilla::net::RP_Unset;
     rv = nsContentUtils::SetFetchReferrerURIWithPolicy(principal, parentDoc,
                                                        httpChannel, referrerPolicy);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   channel.forget(aChannel);
@@ -1228,17 +1228,17 @@ private:
           NS_ENSURE_SUCCESS(rv, rv);
 
           mWorkerPrivate->SetCSP(csp);
           mWorkerPrivate->SetEvalAllowed(evalAllowed);
           mWorkerPrivate->SetReportCSPViolations(reportEvalViolations);
 
           // Set ReferrerPolicy, default value is set in GetReferrerPolicy
           bool hasReferrerPolicy = false;
-          uint32_t rp = mozilla::net::RP_Default;
+          uint32_t rp = mozilla::net::RP_Unset;
           rv = csp->GetReferrerPolicy(&rp, &hasReferrerPolicy);
           NS_ENSURE_SUCCESS(rv, rv);
 
 
           if (hasReferrerPolicy) { //FIXME bug 1307366: move RP out of CSP code
             mWorkerPrivate->SetReferrerPolicy(static_cast<net::ReferrerPolicy>(rp));
           }
         }
@@ -2106,22 +2106,26 @@ ScriptExecutorRunnable::LogExceptionToCo
 void
 LoadAllScripts(WorkerPrivate* aWorkerPrivate,
                nsTArray<ScriptLoadInfo>& aLoadInfos, bool aIsMainScript,
                WorkerScriptType aWorkerScriptType, ErrorResult& aRv)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(!aLoadInfos.IsEmpty(), "Bad arguments!");
 
-  AutoSyncLoopHolder syncLoop(aWorkerPrivate);
+  AutoSyncLoopHolder syncLoop(aWorkerPrivate, Terminating);
+  nsCOMPtr<nsIEventTarget> syncLoopTarget = syncLoop.GetEventTarget();
+  if (!syncLoopTarget) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
 
   RefPtr<ScriptLoaderRunnable> loader =
-    new ScriptLoaderRunnable(aWorkerPrivate, syncLoop.EventTarget(),
-                             aLoadInfos, aIsMainScript, aWorkerScriptType,
-                             aRv);
+    new ScriptLoaderRunnable(aWorkerPrivate, syncLoopTarget, aLoadInfos,
+                             aIsMainScript, aWorkerScriptType, aRv);
 
   NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
 
   ScriptLoaderHolder workerHolder(loader);
 
   if (NS_WARN_IF(!workerHolder.HoldWorker(aWorkerPrivate, Terminating))) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
@@ -2172,17 +2176,17 @@ ChannelFromScriptURLWorkerThread(JSConte
                                  nsIChannel** aChannel)
 {
   aParent->AssertIsOnWorkerThread();
 
   RefPtr<ChannelGetterRunnable> getter =
     new ChannelGetterRunnable(aParent, aScriptURL, aChannel);
 
   ErrorResult rv;
-  getter->Dispatch(rv);
+  getter->Dispatch(Terminating, rv);
   if (rv.Failed()) {
     NS_ERROR("Failed to dispatch!");
     return rv.StealNSResult();
   }
 
   return getter->GetResult();
 }
 
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -1266,17 +1266,17 @@ ServiceWorkerRegistrationWorkerThread::R
   if (aReason == RegistrationIsGoingAway) {
     RefPtr<AsyncStopListeningRunnable> r =
       new AsyncStopListeningRunnable(mListener);
     MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(r.forget()));
   } else if (aReason == WorkerIsGoingAway) {
     RefPtr<SyncStopListeningRunnable> r =
       new SyncStopListeningRunnable(mWorkerPrivate, mListener);
     ErrorResult rv;
-    r->Dispatch(rv);
+    r->Dispatch(Killing, rv);
     if (rv.Failed()) {
       NS_ERROR("Failed to dispatch stop listening runnable!");
       // And now what?
       rv.SuppressException();
     }
   } else {
     MOZ_CRASH("Bad reason");
   }
--- a/dom/workers/WorkerNavigator.cpp
+++ b/dom/workers/WorkerNavigator.cpp
@@ -164,17 +164,17 @@ WorkerNavigator::GetUserAgent(nsString& 
                               ErrorResult& aRv) const
 {
   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(workerPrivate);
 
   RefPtr<GetUserAgentRunnable> runnable =
     new GetUserAgentRunnable(workerPrivate, aUserAgent);
 
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 uint64_t
 WorkerNavigator::HardwareConcurrency() const
 {
   RuntimeService* rts = RuntimeService::GetService();
   MOZ_ASSERT(rts);
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1606,17 +1606,17 @@ TimerThreadEventTarget::IsOnCurrentThrea
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(TimerThreadEventTarget, nsIEventTarget)
 
 WorkerLoadInfo::WorkerLoadInfo()
   : mWindowID(UINT64_MAX)
   , mServiceWorkerID(0)
-  , mReferrerPolicy(net::RP_Default)
+  , mReferrerPolicy(net::RP_Unset)
   , mFromWindow(false)
   , mEvalAllowed(false)
   , mReportCSPViolations(false)
   , mXHRParamsAllowed(false)
   , mPrincipalIsSystem(false)
   , mStorageAllowed(false)
   , mServiceWorkersTestingInWindow(false)
 {
@@ -3496,17 +3496,17 @@ WorkerPrivateParent<Derived>::SetPrincip
 
   aPrincipal->GetCsp(getter_AddRefs(mLoadInfo.mCSP));
 
   if (mLoadInfo.mCSP) {
     mLoadInfo.mCSP->GetAllowsEval(&mLoadInfo.mReportCSPViolations,
                                   &mLoadInfo.mEvalAllowed);
     // Set ReferrerPolicy
     bool hasReferrerPolicy = false;
-    uint32_t rp = mozilla::net::RP_Default;
+    uint32_t rp = mozilla::net::RP_Unset;
 
     nsresult rv = mLoadInfo.mCSP->GetReferrerPolicy(&rp, &hasReferrerPolicy);
     NS_ENSURE_SUCCESS_VOID(rv);
 
     if (hasReferrerPolicy) {
       mLoadInfo.mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
     }
   } else {
@@ -5303,20 +5303,28 @@ WorkerPrivate::CancelAllTimeouts()
   }
 #endif
 
   mTimer = nullptr;
   mTimerRunnable = nullptr;
 }
 
 already_AddRefed<nsIEventTarget>
-WorkerPrivate::CreateNewSyncLoop()
+WorkerPrivate::CreateNewSyncLoop(Status aFailStatus)
 {
   AssertIsOnWorkerThread();
 
+  {
+    MutexAutoLock lock(mMutex);
+
+    if (mStatus >= aFailStatus) {
+      return nullptr;
+    }
+  }
+
   nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(NS_GetCurrentThread());
   MOZ_ASSERT(thread);
 
   nsCOMPtr<nsIEventTarget> realEventTarget;
   MOZ_ALWAYS_SUCCEEDS(thread->PushEventQueue(getter_AddRefs(realEventTarget)));
 
   RefPtr<EventTarget> workerEventTarget =
     new EventTarget(this, realEventTarget);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1449,18 +1449,21 @@ private:
 
   void
   GetAllPreferences(bool aPreferences[WORKERPREF_COUNT]) const
   {
     AssertIsOnWorkerThread();
     memcpy(aPreferences, mPreferences, WORKERPREF_COUNT * sizeof(bool));
   }
 
+  // If the worker shutdown status is equal or greater then aFailStatus, this
+  // operation will fail and nullptr will be returned. See WorkerHolder.h for
+  // more information about the correct value to use.
   already_AddRefed<nsIEventTarget>
-  CreateNewSyncLoop();
+  CreateNewSyncLoop(Status aFailStatus);
 
   bool
   RunCurrentSyncLoop();
 
   bool
   DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread = nullptr);
 
   void
@@ -1525,27 +1528,29 @@ GetCurrentThreadWorkerGlobal();
 
 class AutoSyncLoopHolder
 {
   WorkerPrivate* mWorkerPrivate;
   nsCOMPtr<nsIEventTarget> mTarget;
   uint32_t mIndex;
 
 public:
-  explicit AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate)
+  // See CreateNewSyncLoop() for more information about the correct value to use
+  // for aFailStatus.
+  AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, Status aFailStatus)
   : mWorkerPrivate(aWorkerPrivate)
-  , mTarget(aWorkerPrivate->CreateNewSyncLoop())
+  , mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus))
   , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
   {
     aWorkerPrivate->AssertIsOnWorkerThread();
   }
 
   ~AutoSyncLoopHolder()
   {
-    if (mWorkerPrivate) {
+    if (mWorkerPrivate && mTarget) {
       mWorkerPrivate->AssertIsOnWorkerThread();
       mWorkerPrivate->StopSyncLoop(mTarget, false);
       mWorkerPrivate->DestroySyncLoop(mIndex);
     }
   }
 
   bool
   Run()
@@ -1554,18 +1559,19 @@ public:
     mWorkerPrivate = nullptr;
 
     workerPrivate->AssertIsOnWorkerThread();
 
     return workerPrivate->RunCurrentSyncLoop();
   }
 
   nsIEventTarget*
-  EventTarget() const
+  GetEventTarget() const
   {
+    // This can be null if CreateNewSyncLoop() fails.
     return mTarget;
   }
 };
 
 class TimerThreadEventTarget final : public nsIEventTarget
 {
   ~TimerThreadEventTarget();
 
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -563,25 +563,30 @@ WorkerMainThreadRunnable::WorkerMainThre
                                                    const nsACString& aTelemetryKey)
 : mWorkerPrivate(aWorkerPrivate)
 , mTelemetryKey(aTelemetryKey)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 }
 
 void
-WorkerMainThreadRunnable::Dispatch(ErrorResult& aRv)
+WorkerMainThreadRunnable::Dispatch(Status aFailStatus, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   TimeStamp startTime = TimeStamp::NowLoRes();
 
-  AutoSyncLoopHolder syncLoop(mWorkerPrivate);
+  AutoSyncLoopHolder syncLoop(mWorkerPrivate, aFailStatus);
 
-  mSyncLoopTarget = syncLoop.EventTarget();
+  mSyncLoopTarget = syncLoop.GetEventTarget();
+  if (!mSyncLoopTarget) {
+    // SyncLoop creation can fail if the worker is shutting down.
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
 
   DebugOnly<nsresult> rv = mWorkerPrivate->DispatchToMainThread(this);
   MOZ_ASSERT(NS_SUCCEEDED(rv),
              "Should only fail after xpcom-shutdown-threads and we're gone by then");
 
   if (!syncLoop.Run()) {
     aRv.ThrowUncatchableException();
   }
@@ -616,17 +621,17 @@ WorkerCheckAPIExposureOnMainThreadRunnab
 
 WorkerCheckAPIExposureOnMainThreadRunnable::~WorkerCheckAPIExposureOnMainThreadRunnable()
 {}
 
 bool
 WorkerCheckAPIExposureOnMainThreadRunnable::Dispatch()
 {
   ErrorResult rv;
-  WorkerMainThreadRunnable::Dispatch(rv);
+  WorkerMainThreadRunnable::Dispatch(Terminating, rv);
   bool ok = !rv.Failed();
   rv.SuppressException();
   return ok;
 }
 
 bool
 WorkerSameThreadRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate)
 {
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -396,19 +396,22 @@ protected:
   explicit WorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate,
                                     const nsACString& aTelemetryKey);
   ~WorkerMainThreadRunnable() {}
 
   virtual bool MainThreadRun() = 0;
 
 public:
   // Dispatch the runnable to the main thread.  If dispatch to main thread
-  // fails, or if the worker is shut down while dispatching, an error will be
-  // reported on aRv.  In that case the error MUST be propagated out to script.
-  void Dispatch(ErrorResult& aRv);
+  // fails, or if the worker is in a state equal or greater of aFailStatus, an
+  // error will be reported on aRv. Normally you want to use 'Terminating' for
+  // aFailStatus, except if you want an infallible runnable. In this case, use
+  // 'Killing'.
+  // In that case the error MUST be propagated out to script.
+  void Dispatch(Status aFailStatus, ErrorResult& aRv);
 
 private:
   NS_IMETHOD Run() override;
 };
 
 // This runnable is an helper class for dispatching something from a worker
 // thread to the main-thread and back to the worker-thread. During this
 // operation, this class will keep the worker alive.
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -413,17 +413,27 @@ class MOZ_STACK_CLASS AutoStyleNewChildr
 {
 public:
   explicit AutoStyleNewChildren(Element* aElement) : mElement(aElement) { MOZ_ASSERT(mElement); }
   ~AutoStyleNewChildren()
   {
     nsIPresShell* presShell = mElement->OwnerDoc()->GetShell();
     ServoStyleSet* servoSet = presShell ? presShell->StyleSet()->GetAsServo() : nullptr;
     if (servoSet) {
-      servoSet->StyleNewChildren(mElement);
+      // In general the element is always styled by the time we're applying XBL
+      // bindings, because we need to style the element to know what the binding
+      // URI is. However, programmatic consumers of the XBL service (like the
+      // XML pretty printer) _can_ apply bindings without having styled the bound
+      // element. We could assert against this and require the callers manually
+      // resolve the style first, but it's easy enough to just handle here.
+      if (MOZ_UNLIKELY(!mElement->HasServoData())) {
+        servoSet->StyleNewSubtree(mElement);
+      } else {
+        servoSet->StyleNewChildren(mElement);
+      }
     }
   }
 
 private:
   Element* mElement;
 };
 
 // This function loads a particular XBL file and installs all of the bindings
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2598,17 +2598,17 @@ XMLHttpRequestMainThread::InitiateFetch(
     }
 
     mAuthorRequestHeaders.ApplyToChannel(httpChannel);
 
     if (!IsSystemXHR()) {
       nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
       nsCOMPtr<nsIDocument> doc = owner ? owner->GetExtantDoc() : nullptr;
       mozilla::net::ReferrerPolicy referrerPolicy = doc ?
-        doc->GetReferrerPolicy() : mozilla::net::RP_Default;
+        doc->GetReferrerPolicy() : mozilla::net::RP_Unset;
       nsContentUtils::SetFetchReferrerURIWithPolicy(mPrincipal, doc,
                                                     httpChannel, referrerPolicy);
     }
 
     // Some extensions override the http protocol handler and provide their own
     // implementation. The channels returned from that implementation don't
     // always seem to implement the nsIUploadChannel2 interface, presumably
     // because it's a new interface. Eventually we should remove this and simply
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -203,19 +203,19 @@ public:
   , mErrorCode(NS_OK)
   {
     MOZ_ASSERT(aWorkerPrivate);
     MOZ_ASSERT(aProxy);
     aWorkerPrivate->AssertIsOnWorkerThread();
   }
 
   void
-  Dispatch(ErrorResult& aRv)
+  Dispatch(Status aFailStatus, ErrorResult& aRv)
   {
-    WorkerMainThreadRunnable::Dispatch(aRv);
+    WorkerMainThreadRunnable::Dispatch(aFailStatus, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
 
     if (NS_FAILED(mErrorCode)) {
       aRv.Throw(mErrorCode);
     }
   }
@@ -1629,17 +1629,18 @@ XMLHttpRequestWorker::ReleaseProxy(Relea
       }
 
       // We need to make a sync call here.
       RefPtr<SyncTeardownRunnable> runnable =
         new SyncTeardownRunnable(mWorkerPrivate, mProxy);
       mProxy = nullptr;
 
       ErrorResult forAssertionsOnly;
-      runnable->Dispatch(forAssertionsOnly);
+      // This runnable _must_ be executed.
+      runnable->Dispatch(Killing, forAssertionsOnly);
       if (forAssertionsOnly.Failed()) {
         NS_ERROR("Failed to dispatch teardown runnable!");
       }
     }
   }
 }
 
 void
@@ -1799,28 +1800,32 @@ XMLHttpRequestWorker::SendInternal(SendR
   }
 
   AutoUnpinXHR autoUnpin(this);
   Maybe<AutoSyncLoopHolder> autoSyncLoop;
 
   nsCOMPtr<nsIEventTarget> syncLoopTarget;
   bool isSyncXHR = mProxy->mIsSyncXHR;
   if (isSyncXHR) {
-    autoSyncLoop.emplace(mWorkerPrivate);
-    syncLoopTarget = autoSyncLoop->EventTarget();
+    autoSyncLoop.emplace(mWorkerPrivate, Terminating);
+    syncLoopTarget = autoSyncLoop->GetEventTarget();
+    if (!syncLoopTarget) {
+      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+      return;
+    }
   }
 
   mProxy->mOuterChannelId++;
 
   aRunnable->SetSyncLoopTarget(syncLoopTarget);
   aRunnable->SetHaveUploadListeners(hasUploadListeners);
 
   mStateData.mFlagSend = true;
 
-  aRunnable->Dispatch(aRv);
+  aRunnable->Dispatch(Terminating, aRv);
   if (aRv.Failed()) {
     // Dispatch() may have spun the event loop and we may have already unrooted.
     // If so we don't want autoUnpin to try again.
     if (!mRooted) {
       autoUnpin.Clear();
     }
     return;
   }
@@ -1884,17 +1889,17 @@ XMLHttpRequestWorker::Open(const nsACStr
   mProxy->mOuterEventStreamId++;
 
   RefPtr<OpenRunnable> runnable =
     new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
                      mBackgroundRequest, mWithCredentials,
                      mTimeout, mResponseType);
 
   ++mProxy->mOpenCount;
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (aRv.Failed()) {
     if (!--mProxy->mOpenCount) {
       ReleaseProxy();
     }
 
     return;
   }
 
@@ -1921,17 +1926,17 @@ XMLHttpRequestWorker::SetRequestHeader(c
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   RefPtr<SetRequestHeaderRunnable> runnable =
     new SetRequestHeaderRunnable(mWorkerPrivate, mProxy, aHeader, aValue);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 void
 XMLHttpRequestWorker::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
@@ -1944,17 +1949,17 @@ XMLHttpRequestWorker::SetTimeout(uint32_
   if (!mProxy) {
     // Open may not have been called yet, in which case we'll handle the
     // timeout in OpenRunnable.
     return;
   }
 
   RefPtr<SetTimeoutRunnable> runnable =
     new SetTimeoutRunnable(mWorkerPrivate, mProxy, aTimeout);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 void
 XMLHttpRequestWorker::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
@@ -1967,17 +1972,17 @@ XMLHttpRequestWorker::SetWithCredentials
   if (!mProxy) {
     // Open may not have been called yet, in which case we'll handle the
     // credentials in OpenRunnable.
     return;
   }
 
   RefPtr<SetWithCredentialsRunnable> runnable =
     new SetWithCredentialsRunnable(mWorkerPrivate, mProxy, aWithCredentials);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 void
 XMLHttpRequestWorker::SetMozBackgroundRequest(bool aBackgroundRequest,
                                               ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
@@ -1992,17 +1997,17 @@ XMLHttpRequestWorker::SetMozBackgroundRe
     // Open may not have been called yet, in which case we'll handle the
     // background request in OpenRunnable.
     return;
   }
 
   RefPtr<SetBackgroundRequestRunnable> runnable =
     new SetBackgroundRequestRunnable(mWorkerPrivate, mProxy,
                                      aBackgroundRequest);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 XMLHttpRequestUpload*
 XMLHttpRequestWorker::GetUpload(ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
@@ -2260,17 +2265,17 @@ XMLHttpRequestWorker::Abort(ErrorResult&
     // No one did anything to us while we fired abort events, so reset our state
     // to "unsent"
     mStateData.mReadyState = 0;
   }
 
   mProxy->mOuterEventStreamId++;
 
   RefPtr<AbortRunnable> runnable = new AbortRunnable(mWorkerPrivate, mProxy);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 void
 XMLHttpRequestWorker::GetResponseHeader(const nsACString& aHeader,
                                         nsACString& aResponseHeader, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
@@ -2283,17 +2288,17 @@ XMLHttpRequestWorker::GetResponseHeader(
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsCString responseHeader;
   RefPtr<GetResponseHeaderRunnable> runnable =
     new GetResponseHeaderRunnable(mWorkerPrivate, mProxy, aHeader,
                                   responseHeader);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (aRv.Failed()) {
     return;
   }
   aResponseHeader = responseHeader;
 }
 
 void
 XMLHttpRequestWorker::GetAllResponseHeaders(nsACString& aResponseHeaders,
@@ -2309,17 +2314,17 @@ XMLHttpRequestWorker::GetAllResponseHead
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsCString responseHeaders;
   RefPtr<GetAllResponseHeadersRunnable> runnable =
     new GetAllResponseHeadersRunnable(mWorkerPrivate, mProxy, responseHeaders);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   aResponseHeaders = responseHeaders;
 }
 
 void
@@ -2341,17 +2346,17 @@ XMLHttpRequestWorker::OverrideMimeType(c
                   (mProxy->mSeenLoadStart ||
                    mStateData.mReadyState > nsIXMLHttpRequest::OPENED))) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   RefPtr<OverrideMimeTypeRunnable> runnable =
     new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, aMimeType);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
 }
 
 void
 XMLHttpRequestWorker::SetResponseType(XMLHttpRequestResponseType aResponseType,
                                       ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
@@ -2377,17 +2382,17 @@ XMLHttpRequestWorker::SetResponseType(XM
       (mProxy->mSeenLoadStart ||
        mStateData.mReadyState > nsIXMLHttpRequest::OPENED)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   RefPtr<SetResponseTypeRunnable> runnable =
     new SetResponseTypeRunnable(mWorkerPrivate, mProxy, aResponseType);
-  runnable->Dispatch(aRv);
+  runnable->Dispatch(Terminating, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   mResponseType = runnable->ResponseType();
 }
 
 void
--- a/dom/xml/nsXMLPrettyPrinter.cpp
+++ b/dom/xml/nsXMLPrettyPrinter.cpp
@@ -100,17 +100,17 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocum
     rv = NS_NewURI(getter_AddRefs(xslUri),
                    NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDOMDocument> xslDocument;
     rv = nsSyncLoadService::LoadDocument(xslUri, nsIContentPolicy::TYPE_XSLT,
                                          nsContentUtils::GetSystemPrincipal(),
                                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                                         nullptr, true, mozilla::net::RP_Default,
+                                         nullptr, true, mozilla::net::RP_Unset,
                                          getter_AddRefs(xslDocument));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Transform the document
     nsCOMPtr<nsIXSLTProcessor> transformer =
         do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -1032,17 +1032,17 @@ txMozillaXSLTProcessor::GetFlags(uint32_
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 txMozillaXSLTProcessor::LoadStyleSheet(nsIURI* aUri,
                                        nsIDocument* aLoaderDocument)
 {
-    mozilla::net::ReferrerPolicy refpol = mozilla::net::RP_Default;
+    mozilla::net::ReferrerPolicy refpol = mozilla::net::RP_Unset;
     if (mStylesheetDocument) {
         refpol = mStylesheetDocument->GetReferrerPolicy();
     }
 
     nsresult rv = TX_LoadSheet(aUri, this, aLoaderDocument, refpol);
     if (NS_FAILED(rv) && mObserver) {
         // This is most likely a network or security error, just
         // use the uri as context.
--- a/dom/xslt/xslt/txStylesheetCompiler.cpp
+++ b/dom/xslt/xslt/txStylesheetCompiler.cpp
@@ -1064,17 +1064,17 @@ findFunction(nsIAtom* aName, int32_t aNa
                                        nullptr, aResult);
 }
 
 extern bool
 TX_XSLTFunctionAvailable(nsIAtom* aName, int32_t aNameSpaceID)
 {
     RefPtr<txStylesheetCompiler> compiler =
         new txStylesheetCompiler(EmptyString(),
-                                 mozilla::net::RP_Default, nullptr);
+                                 mozilla::net::RP_Unset, nullptr);
     NS_ENSURE_TRUE(compiler, false);
 
     nsAutoPtr<FunctionCall> fnCall;
 
     return NS_SUCCEEDED(findFunction(aName, aNameSpaceID, compiler,
                                      getter_Transfers(fnCall)));
 }
 
--- a/editor/libeditor/crashtests/crashtests.list
+++ b/editor/libeditor/crashtests/crashtests.list
@@ -23,17 +23,17 @@ load 456727-2.html
 load 459613.html
 skip-if(stylo) needs-focus load 467647-1.html # bug 1323649
 load 475132-1.xhtml
 load 499844-1.html
 load 503709-1.xhtml
 skip-if(stylo) load 513375-1.xhtml # bug 1323654
 load 535632-1.xhtml
 load 574558-1.xhtml
-skip-if(stylo) load 580151-1.xhtml # bug 1323655
+load 580151-1.xhtml
 load 582138-1.xhtml
 load 612565-1.html
 load 615015-1.html
 load 615450-1.html
 load 633709.xhtml
 asserts-if(stylo,1) load 636074-1.html # bug 1324663
 load 639736-1.xhtml
 load 643786-1.html
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -625,17 +625,17 @@ nsWebBrowserPersist::SerializeNextFile()
             rv = AppendPathToURI(fileAsURI, data->mFilename);
             if (NS_WARN_IF(NS_FAILED(rv))) {
                 break;
             }
 
             // The Referrer Policy doesn't matter here since the referrer is
             // nullptr.
             rv = SaveURIInternal(uri, nullptr, nullptr,
-                                 mozilla::net::RP_Default, nullptr, nullptr,
+                                 mozilla::net::RP_Unset, nullptr, nullptr,
                                  fileAsURI, true, mIsPrivate);
             // If SaveURIInternal fails, then it will have called EndDownload,
             // which means that |data| is no longer valid memory. We MUST bail.
             if (NS_WARN_IF(NS_FAILED(rv))) {
                 break;
             }
 
             if (rv == NS_OK) {
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1472,17 +1472,17 @@ gfxUtils::ThreadSafeGetFeatureStatus(con
     dom::workers::WorkerPrivate* workerPrivate =
       dom::workers::GetCurrentThreadWorkerPrivate();
 
     RefPtr<GetFeatureStatusRunnable> runnable =
       new GetFeatureStatusRunnable(workerPrivate, gfxInfo, feature, failureId,
                                    status);
 
     ErrorResult rv;
-    runnable->Dispatch(rv);
+    runnable->Dispatch(dom::workers::Terminating, rv);
     if (rv.Failed()) {
         // XXXbz This is totally broken, since we're supposed to just abort
         // everything up the callstack but the callers basically eat the
         // exception.  Ah, well.
         return rv.StealNSResult();
     }
 
     return runnable->GetNSResult();
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -2004,18 +2004,17 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
     }
     imgRequestProxy* proxy;
     ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy);
     nsCOMPtr<nsINode> node = do_QueryInterface(aCX);
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
     nsresult rv = LoadImage(aURI,
                             aInitialDocumentURI,
                             aReferrerURI,
-                            refpol == mozilla::net::RP_Unset ?
-                              mozilla::net::RP_Default : refpol,
+                            refpol,
                             aLoadingPrincipal,
                             aLoadGroup,
                             aObserver,
                             node,
                             doc,
                             aLoadFlags,
                             aCacheKey,
                             aContentPolicyType,
@@ -2360,17 +2359,17 @@ imgLoader::LoadImageWithChannel(nsIChann
 
       nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
       // if there is a loadInfo, use the right contentType, otherwise
       // default to the internal image type
       nsContentPolicyType policyType = loadInfo
         ? loadInfo->InternalContentPolicyType()
         : nsIContentPolicy::TYPE_INTERNAL_IMAGE;
 
-      if (ValidateEntry(entry, uri, nullptr, nullptr, RP_Default,
+      if (ValidateEntry(entry, uri, nullptr, nullptr, RP_Unset,
                         nullptr, aObserver, aCX, requestFlags,
                         policyType, false, nullptr,
                         nullptr, imgIRequest::CORS_NONE)) {
         request = entry->GetRequest();
       } else {
         nsCOMPtr<nsICacheInfoChannel> cacheChan(do_QueryInterface(channel));
         bool bUseCacheCopy;
 
@@ -2449,17 +2448,17 @@ imgLoader::LoadImageWithChannel(nsIChann
     // assoicated with this load would have gone through necko.
     // We only have the final URI in ImageLib and hence don't know
     // if the request went through insecure redirects.  But if it did,
     // the necko cache should have handled that (since all necko cache hits
     // including the redirects will go through content policy).  Hence, we
     // can set aHadInsecureRedirect to false here.
     rv = request->Init(originalURI, uri, /* aHadInsecureRedirect = */ false,
                        channel, channel, entry, aCX, nullptr,
-                       imgIRequest::CORS_NONE, RP_Default);
+                       imgIRequest::CORS_NONE, RP_Unset);
     NS_ENSURE_SUCCESS(rv, rv);
 
     RefPtr<ProxyListener> pl =
       new ProxyListener(static_cast<nsIStreamListener*>(request.get()));
     pl.forget(listener);
 
     // Try to add the new request into the cache.
     PutIntoCache(originalURIKey, entry);
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -52,17 +52,17 @@ NS_IMPL_ISUPPORTS(imgRequest,
 imgRequest::imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey)
  : mLoader(aLoader)
  , mCacheKey(aCacheKey)
  , mLoadId(nullptr)
  , mFirstProxy(nullptr)
  , mValidator(nullptr)
  , mInnerWindowId(0)
  , mCORSMode(imgIRequest::CORS_NONE)
- , mReferrerPolicy(mozilla::net::RP_Default)
+ , mReferrerPolicy(mozilla::net::RP_Unset)
  , mImageErrorCode(NS_OK)
  , mMutex("imgRequest")
  , mProgressTracker(new ProgressTracker())
  , mIsMultiPartChannel(false)
  , mGotData(false)
  , mIsInCache(false)
  , mDecodeRequested(false)
  , mNewPartPending(false)
--- a/js/public/TrackedOptimizationInfo.h
+++ b/js/public/TrackedOptimizationInfo.h
@@ -102,16 +102,17 @@ namespace JS {
     _(AccessNotSimdObject)                                              \
     _(AccessNotTypedObject)                                             \
     _(AccessNotTypedArray)                                              \
     _(AccessNotString)                                                  \
     _(OperandNotString)                                                 \
     _(OperandNotNumber)                                                 \
     _(OperandNotStringOrNumber)                                         \
     _(OperandNotSimpleArith)                                            \
+    _(OperandNotEasilyCoercibleToString)                                \
     _(StaticTypedArrayUint32)                                           \
     _(StaticTypedArrayCantComputeMask)                                  \
     _(OutOfBounds)                                                      \
     _(GetElemStringNotCached)                                           \
     _(NonNativeReceiver)                                                \
     _(IndexType)                                                        \
     _(SetElemNonDenseNonTANotCached)                                    \
     _(NoSimdJitSupport)                                                 \
--- a/js/src/builtin/Iterator.js
+++ b/js/src/builtin/Iterator.js
@@ -79,49 +79,8 @@ function NewLegacyIterator(iter, wrapper
 
 function LegacyIteratorShim() {
     return NewLegacyIterator(ToObject(this), LegacyIterator);
 }
 
 function LegacyGeneratorIteratorShim() {
     return NewLegacyIterator(ToObject(this), LegacyGeneratorIterator);
 }
-
-// 7.4.8 CreateListIterator()
-function CreateListIterator(array) {
-    let iterator = NewListIterator();
-    UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, array);
-    UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0);
-
-    // 7.4.8.1 ListIterator next()
-    // The spec requires that we use a new next function per iterator object.
-    let next = function() {
-        if (!IsObject(this) || !IsListIterator(this))
-            return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorNext");
-
-        if (ActiveFunction() !== UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_METHOD))
-            ThrowTypeError(JSMSG_INCOMPATIBLE_METHOD, "next", "method", ToString(this));
-
-        let array = UnsafeGetObjectFromReservedSlot(this, ITERATOR_SLOT_TARGET);
-        let index = UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
-
-        if (index >= ToLength(array.length)) {
-            UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, 1/0);
-            return { value: undefined, done: true };
-        }
-
-        UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + 1);
-        return { value: array[index], done: false };
-    };
-
-    UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_METHOD, next);
-    iterator.next = next;
-
-    iterator[std_iterator] = ListIteratorIdentity;
-    return iterator;
-}
-
-function ListIteratorIdentity() {
-    if (!IsObject(this) || !IsListIterator(this))
-        return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorIdentity");
-
-    return this;
-}
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -313,16 +313,8 @@ function ModuleEvaluation()
         let required = requestedModules[i];
         let requiredModule = CallModuleResolveHook(module, required, MODULE_STATE_INSTANTIATED);
         callFunction(requiredModule.evaluation, requiredModule);
     }
 
     return EvaluateModule(module);
 }
 _SetCanonicalName(ModuleEvaluation, "ModuleEvaluation");
-
-function ModuleNamespaceEnumerate()
-{
-    if (!IsObject(this) || !IsModuleNamespace(this))
-        return callFunction(CallModuleMethodIfWrapped, this, "ModuleNamespaceEnumerate");
-
-    return CreateListIterator(ModuleNamespaceExports(this));
-}
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -284,24 +284,16 @@ ModuleNamespaceObject::create(JSContext*
     RootedValue priv(cx, ObjectValue(*module));
     ProxyOptions options;
     options.setLazyProto(true);
     options.setSingleton(true);
     RootedObject object(cx, NewProxyObject(cx, &proxyHandler, priv, nullptr, options));
     if (!object)
         return nullptr;
 
-    RootedId funName(cx, INTERNED_STRING_TO_JSID(cx, cx->names().Symbol_iterator_fun));
-    RootedFunction enumerateFun(cx);
-    enumerateFun = JS::GetSelfHostedFunction(cx, "ModuleNamespaceEnumerate", funName, 0);
-    if (!enumerateFun)
-        return nullptr;
-
-    SetProxyExtra(object, ProxyHandler::EnumerateFunctionSlot, ObjectValue(*enumerateFun));
-
     return &object->as<ModuleNamespaceObject>();
 }
 
 ModuleObject&
 ModuleNamespaceObject::module()
 {
     return GetProxyPrivate(this).toObject().as<ModuleObject>();
 }
@@ -336,33 +328,30 @@ ModuleNamespaceObject::addBinding(JSCont
 }
 
 const char ModuleNamespaceObject::ProxyHandler::family = 0;
 
 ModuleNamespaceObject::ProxyHandler::ProxyHandler()
   : BaseProxyHandler(&family, true)
 {}
 
-JS::Value ModuleNamespaceObject::ProxyHandler::getEnumerateFunction(HandleObject proxy) const
-{
-    return GetProxyExtra(proxy, EnumerateFunctionSlot);
-}
-
 bool
 ModuleNamespaceObject::ProxyHandler::getPrototype(JSContext* cx, HandleObject proxy,
                                                   MutableHandleObject protop) const
 {
     protop.set(nullptr);
     return true;
 }
 
 bool
 ModuleNamespaceObject::ProxyHandler::setPrototype(JSContext* cx, HandleObject proxy,
                                                   HandleObject proto, ObjectOpResult& result) const
 {
+    if (!proto)
+        return result.succeed();
     return result.failCantSetProto();
 }
 
 bool
 ModuleNamespaceObject::ProxyHandler::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy,
                                                             bool* isOrdinary,
                                                             MutableHandleObject protop) const
 {
@@ -397,31 +386,22 @@ ModuleNamespaceObject::ProxyHandler::pre
 bool
 ModuleNamespaceObject::ProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy,
                                                               HandleId id,
                                                               MutableHandle<PropertyDescriptor> desc) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (JSID_IS_SYMBOL(id)) {
         Rooted<JS::Symbol*> symbol(cx, JSID_TO_SYMBOL(id));
-        if (symbol == cx->wellKnownSymbols().iterator) {
-            RootedValue enumerateFun(cx, getEnumerateFunction(proxy));
-            desc.object().set(proxy);
-            desc.setConfigurable(false);
-            desc.setEnumerable(false);
-            desc.setValue(enumerateFun);
-            return true;
-        }
-
         if (symbol == cx->wellKnownSymbols().toStringTag) {
             RootedValue value(cx, StringValue(cx->names().Module));
             desc.object().set(proxy);
             desc.setWritable(false);
             desc.setEnumerable(false);
-            desc.setConfigurable(true);
+            desc.setConfigurable(false);
             desc.setValue(value);
             return true;
         }
 
         return true;
     }
 
     const IndirectBindingMap& bindings = ns->bindings();
@@ -453,36 +433,30 @@ ModuleNamespaceObject::ProxyHandler::def
 
 bool
 ModuleNamespaceObject::ProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id,
                                          bool* bp) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (JSID_IS_SYMBOL(id)) {
         Rooted<JS::Symbol*> symbol(cx, JSID_TO_SYMBOL(id));
-        return symbol == cx->wellKnownSymbols().iterator ||
-               symbol == cx->wellKnownSymbols().toStringTag;
+        return symbol == cx->wellKnownSymbols().toStringTag;
     }
 
     *bp = ns->bindings().has(id);
     return true;
 }
 
 bool
 ModuleNamespaceObject::ProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
                                          HandleId id, MutableHandleValue vp) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (JSID_IS_SYMBOL(id)) {
         Rooted<JS::Symbol*> symbol(cx, JSID_TO_SYMBOL(id));
-        if (symbol == cx->wellKnownSymbols().iterator) {
-            vp.set(getEnumerateFunction(proxy));
-            return true;
-        }
-
         if (symbol == cx->wellKnownSymbols().toStringTag) {
             vp.setString(cx->names().Module);
             return true;
         }
 
         return false;
     }
 
@@ -521,26 +495,28 @@ ModuleNamespaceObject::ProxyHandler::del
 
 bool
 ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
                                                      AutoIdVector& props) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     RootedObject exports(cx, &ns->exports());
     uint32_t count;
-    if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count))
+    if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count + 1))
         return false;
 
     Rooted<ValueVector> names(cx, ValueVector(cx));
     if (!names.resize(count) || !GetElements(cx, exports, count, names.begin()))
         return false;
 
     for (uint32_t i = 0; i < count; i++)
         props.infallibleAppend(AtomToId(&names[i].toString()->asAtom()));
 
+    props.infallibleAppend(SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag));
+
     return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // FunctionDeclaration
 
 FunctionDeclaration::FunctionDeclaration(HandleAtom name, HandleFunction fun)
   : name(name), fun(fun)
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -137,25 +137,18 @@ class ModuleNamespaceObject : public Pro
     IndirectBindingMap& bindings();
 
     bool addBinding(JSContext* cx, HandleAtom exportedName, HandleModuleObject targetModule,
                     HandleAtom localName);
 
   private:
     struct ProxyHandler : public BaseProxyHandler
     {
-        enum
-        {
-            EnumerateFunctionSlot = 0
-        };
-
         ProxyHandler();
 
-        JS::Value getEnumerateFunction(HandleObject proxy) const;
-
         bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
                                       MutableHandle<PropertyDescriptor> desc) const override;
         bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
                             Handle<PropertyDescriptor> desc,
                             ObjectOpResult& result) const override;
         bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
                              AutoIdVector& props) const override;
         bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
--- a/js/src/builtin/SelfHostingDefines.h
+++ b/js/src/builtin/SelfHostingDefines.h
@@ -66,18 +66,16 @@
 #define WEAKSET_MAP_SLOT 0
 
 #define ITERATOR_SLOT_TARGET 0
 // Used for collection iterators.
 #define ITERATOR_SLOT_RANGE 1
 // Used for list, i.e. Array and String, iterators.
 #define ITERATOR_SLOT_NEXT_INDEX 1
 #define ITERATOR_SLOT_ITEM_KIND 2
-// Used for ListIterator.
-#define ITERATOR_SLOT_NEXT_METHOD 2
 
 #define ITEM_KIND_KEY 0
 #define ITEM_KIND_VALUE 1
 #define ITEM_KIND_KEY_AND_VALUE 2
 
 // NB: keep these in sync with the copy in jsfriendapi.h.
 #define JSITER_OWNONLY    0x8   /* iterate over obj's own properties only */
 #define JSITER_HIDDEN     0x10  /* also enumerate non-enumerable properties */
--- a/js/src/doc/JITOptimizations/Outcomes.md
+++ b/js/src/doc/JITOptimizations/Outcomes.md
@@ -183,16 +183,20 @@ Optimization failed because of failing t
 ### OperandNotStringOrNumber
 
 Optimization failed because of failing to speculate the operand is a string or a number.
 
 ### OperandNotSimpleArith
 
 Optimization failed because of failing to speculate the operand is a simple arithmetic type. I.e. definitely not an object, string, symbol or internal magic type.
 
+### OperandNotEasilyCoercibleToString
+
+Optimization failed because of failing to speculate the operand can be easily coerced to a string. I.e. definitely not an object or symbol.
+
 ### StaticTypedArrayUint32
 
 Typed Arrays of uint32 values are not yet fully optimized.
 
 ### StaticTypedArrayCantComputeMask
 ### OutOfBounds
 
 The element access has been observed to be out of the length bounds of
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // JS lexical scanner.
 
 #include "frontend/TokenStream.h"
 
+#include "mozilla/ArrayUtils.h"
 #include "mozilla/IntegerTypeTraits.h"
 #include "mozilla/PodOperations.h"
 
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -28,16 +29,17 @@
 #include "vm/HelperThreads.h"
 #include "vm/Keywords.h"
 #include "vm/StringBuffer.h"
 #include "vm/Unicode.h"
 
 using namespace js;
 using namespace js::frontend;
 
+using mozilla::ArrayLength;
 using mozilla::Maybe;
 using mozilla::PodAssign;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 
 struct KeywordInfo {
     const char* chars;         // C string with keyword text
     TokenKind   tokentype;
@@ -543,18 +545,20 @@ TokenStream::advance(size_t position)
     while (userbuf.addressOfNextRawChar() < end)
         getChar();
 
     Token* cur = &tokens[cursor];
     cur->pos.begin = userbuf.offset();
     MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type));
     lookahead = 0;
 
-    if (flags.hitOOM)
-        return reportError(JSMSG_OUT_OF_MEMORY);
+    if (flags.hitOOM) {
+        error(JSMSG_OUT_OF_MEMORY);
+        return false;
+    }
 
     return true;
 }
 
 void
 TokenStream::tell(Position* pos)
 {
     pos->buf = userbuf.addressOfNextRawChar(/* allowPoisoned = */ true);
@@ -764,17 +768,17 @@ TokenStream::reportErrorNoOffset(unsigne
     va_start(args, errorNumber);
     bool result = reportCompileErrorNumberVA(NoOffset, JSREPORT_ERROR, errorNumber,
                                              args);
     va_end(args);
     return result;
 }
 
 bool
-TokenStream::reportWarning(unsigned errorNumber, ...)
+TokenStream::warning(unsigned errorNumber, ...)
 {
     va_list args;
     va_start(args, errorNumber);
     bool result = reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_WARNING,
                                              errorNumber, args);
     va_end(args);
     return result;
 }
@@ -795,16 +799,42 @@ TokenStream::reportAsmJSError(uint32_t o
     va_start(args, errorNumber);
     unsigned flags = options().throwOnAsmJSValidationFailureOption
                      ? JSREPORT_ERROR
                      : JSREPORT_WARNING;
     reportCompileErrorNumberVA(offset, flags, errorNumber, args);
     va_end(args);
 }
 
+void
+TokenStream::error(unsigned errorNumber, ...)
+{
+    va_list args;
+    va_start(args, errorNumber);
+#ifdef DEBUG
+    bool result =
+#endif
+        reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_ERROR, errorNumber, args);
+    MOZ_ASSERT(!result, "reporting an error returned true?");
+    va_end(args);
+}
+
+void
+TokenStream::errorAt(uint32_t offset, unsigned errorNumber, ...)
+{
+    va_list args;
+    va_start(args, errorNumber);
+#ifdef DEBUG
+    bool result =
+#endif
+        reportCompileErrorNumberVA(offset, JSREPORT_ERROR, errorNumber, args);
+    MOZ_ASSERT(!result, "reporting an error returned true?");
+    va_end(args);
+}
+
 // We have encountered a '\': check for a Unicode escape sequence after it.
 // Return the length of the escape sequence and the character code point (by
 // value) if we found a Unicode escape sequence.  Otherwise, return 0.  In both
 // cases, do not advance along the buffer.
 uint32_t
 TokenStream::peekUnicodeEscape(uint32_t* codePoint)
 {
     int32_t c = getCharIgnoreEOL();
@@ -923,44 +953,59 @@ TokenStream::getDirectives(bool isMultil
     if (!getSourceMappingURL(isMultiline, shouldWarnDeprecated))
         return false;
 
     return true;
 }
 
 bool
 TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
-                          const char* directive, int directiveLength,
+                          const char* directive, uint8_t directiveLength,
                           const char* errorMsgPragma,
                           UniqueTwoByteChars* destination)
 {
     MOZ_ASSERT(directiveLength <= 18);
     char16_t peeked[18];
-    int32_t c;
 
     if (peekChars(directiveLength, peeked) && CharsMatch(peeked, directive)) {
-        if (shouldWarnDeprecated &&
-            !reportWarning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
-            return false;
+        if (shouldWarnDeprecated) {
+            if (!warning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
+                return false;
+        }
 
         skipChars(directiveLength);
         tokenbuf.clear();
 
-        while ((c = peekChar()) && c != EOF && !unicode::IsSpaceOrBOM2(c)) {
-            getChar();
+        do {
+            int32_t c;
+            if (!peekChar(&c))
+                return false;
+
+            if (c == EOF || unicode::IsSpaceOrBOM2(c))
+                break;
+
+            consumeKnownChar(c);
+
             // Debugging directives can occur in both single- and multi-line
             // comments. If we're currently inside a multi-line comment, we also
             // need to recognize multi-line comment terminators.
-            if (isMultiline && c == '*' && peekChar() == '/') {
-                ungetChar('*');
-                break;
+            if (isMultiline && c == '*') {
+                int32_t c2;
+                if (!peekChar(&c2))
+                    return false;
+
+                if (c2 == '/') {
+                    ungetChar('*');
+                    break;
+                }
             }
+
             if (!tokenbuf.append(c))
                 return false;
-        }
+        } while (true);
 
         if (tokenbuf.empty()) {
             // The directive's URL was missing, but this is not quite an
             // exception that we should stop and drop everything for.
             return true;
         }
 
         size_t length = tokenbuf.length();
@@ -982,27 +1027,33 @@ TokenStream::getDisplayURL(bool isMultil
     // Match comments of the form "//# sourceURL=<url>" or
     // "/\* //# sourceURL=<url> *\/"
     //
     // Note that while these are labeled "sourceURL" in the source text,
     // internally we refer to it as a "displayURL" to distinguish what the
     // developer would like to refer to the source as from the source's actual
     // URL.
 
-    return getDirective(isMultiline, shouldWarnDeprecated, " sourceURL=", 11,
+    static const char sourceURLDirective[] = " sourceURL=";
+    constexpr uint8_t sourceURLDirectiveLength = ArrayLength(sourceURLDirective) - 1;
+    return getDirective(isMultiline, shouldWarnDeprecated,
+                        sourceURLDirective, sourceURLDirectiveLength,
                         "sourceURL", &displayURL_);
 }
 
 bool
 TokenStream::getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated)
 {
     // Match comments of the form "//# sourceMappingURL=<url>" or
     // "/\* //# sourceMappingURL=<url> *\/"
 
-    return getDirective(isMultiline, shouldWarnDeprecated, " sourceMappingURL=", 18,
+    static const char sourceMappingURLDirective[] = " sourceMappingURL=";
+    constexpr uint8_t sourceMappingURLDirectiveLength = ArrayLength(sourceMappingURLDirective) - 1;
+    return getDirective(isMultiline, shouldWarnDeprecated,
+                        sourceMappingURLDirective, sourceMappingURLDirectiveLength,
                         "sourceMappingURL", &sourceMapURL_);
 }
 
 MOZ_ALWAYS_INLINE Token*
 TokenStream::newToken(ptrdiff_t adjust)
 {
     cursor = (cursor + 1) & ntokensMask;
     Token* tp = &tokens[cursor];
@@ -1108,18 +1159,20 @@ bool
 TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
 {
     if (!awaitIsKeyword && kw->tokentype == TOK_AWAIT) {
         if (ttp)
             *ttp = TOK_NAME;
         return true;
     }
 
-    if (kw->tokentype == TOK_RESERVED)
-        return reportError(JSMSG_RESERVED_ID, kw->chars);
+    if (kw->tokentype == TOK_RESERVED) {
+        error(JSMSG_RESERVED_ID, kw->chars);
+        return false;
+    }
 
     if (kw->tokentype == TOK_STRICT_RESERVED)
         return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars);
 
     // Working keyword.
     *ttp = kw->tokentype;
     return true;
 }
@@ -1527,20 +1580,21 @@ TokenStream::getTokenInternal(TokenKind*
                 if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
                     goto error;
 
                 // Outside strict mode, we permit 08 and 09 as decimal numbers,
                 // which makes our behaviour a superset of the ECMA numeric
                 // grammar. We might not always be so permissive, so we warn
                 // about it.
                 if (c >= '8') {
-                    if (!reportWarning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09")) {
+                    if (!warning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09"))
                         goto error;
-                    }
-                    goto decimal;   // use the decimal scanner for the rest of the number
+
+                    // Use the decimal scanner for the rest of the number.
+                    goto decimal;
                 }
                 c = getCharIgnoreEOL();
             }
         } else {
             // '0' not followed by 'x', 'X' or a digit;  scan as a decimal number.
             numStart = userbuf.addressOfNextRawChar() - 1;
             goto decimal;
         }
@@ -1679,17 +1733,18 @@ TokenStream::getTokenInternal(TokenKind*
             tp->type = matchChar('=') ? TOK_POWASSIGN : TOK_POW;
         else
             tp->type = matchChar('=') ? TOK_MULASSIGN : TOK_MUL;
         goto out;
 
       case '/':
         // Look for a single-line comment.
         if (matchChar('/')) {
-            c = peekChar();
+            if (!peekChar(&c))
+                goto error;
             if (c == '@' || c == '#') {
                 bool shouldWarn = getChar() == '@';
                 if (!getDirectives(false, shouldWarn))
                     goto error;
             }
 
         skipline:
             while ((c = getChar()) != EOF && c != '\n')
@@ -1746,34 +1801,36 @@ TokenStream::getTokenInternal(TokenKind*
                 }
                 if (!tokenbuf.append(c))
                     goto error;
             }
 
             RegExpFlag reflags = NoFlags;
             unsigned length = tokenbuf.length() + 1;
             while (true) {
-                c = peekChar();
+                if (!peekChar(&c))
+                    goto error;
                 if (c == 'g' && !(reflags & GlobalFlag))
                     reflags = RegExpFlag(reflags | GlobalFlag);
                 else if (c == 'i' && !(reflags & IgnoreCaseFlag))
                     reflags = RegExpFlag(reflags | IgnoreCaseFlag);
                 else if (c == 'm' && !(reflags & MultilineFlag))
                     reflags = RegExpFlag(reflags | MultilineFlag);
                 else if (c == 'y' && !(reflags & StickyFlag))
                     reflags = RegExpFlag(reflags | StickyFlag);
                 else if (c == 'u' && !(reflags & UnicodeFlag))
                     reflags = RegExpFlag(reflags | UnicodeFlag);
                 else
                     break;
                 getChar();
                 length++;
             }
 
-            c = peekChar();
+            if (!peekChar(&c))
+                goto error;
             if (JS7_ISLET(c)) {
                 char buf[2] = { '\0', '\0' };
                 tp->pos.begin += length + 1;
                 buf[0] = char(c);
                 reportError(JSMSG_BAD_REGEXP_FLAG, buf);
                 (void) getChar();
                 goto error;
             }
@@ -1786,18 +1843,23 @@ TokenStream::getTokenInternal(TokenKind*
         goto out;
 
       case '%':
         tp->type = matchChar('=') ? TOK_MODASSIGN : TOK_MOD;
         goto out;
 
       case '-':
         if (matchChar('-')) {
-            if (peekChar() == '>' && !flags.isDirtyLine)
+            int32_t c2;
+            if (!peekChar(&c2))
+                goto error;
+
+            if (c2 == '>' && !flags.isDirtyLine)
                 goto skipline;
+
             tp->type = TOK_DEC;
         } else {
             tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
         }
         goto out;
 
       badchar:
       default:
@@ -1839,42 +1901,61 @@ TokenStream::getTokenInternal(TokenKind*
     // immediately.
     userbuf.poison();
 #endif
     MOZ_MAKE_MEM_UNDEFINED(ttp, sizeof(*ttp));
     return false;
 }
 
 bool
-TokenStream::getBracedUnicode(uint32_t* cp)
+TokenStream::matchBracedUnicode(bool* matched, uint32_t* cp)
 {
+    int32_t c;
+    if (!peekChar(&c))
+        return false;
+    if (c != '{') {
+        *matched = false;
+        return true;
+    }
+
     consumeKnownChar('{');
 
+    uint32_t start = userbuf.offset();
+
     bool first = true;
-    int32_t c;
     uint32_t code = 0;
-    while (true) {
-        c = getCharIgnoreEOL();
-        if (c == EOF)
+    do {
+        int32_t c = getCharIgnoreEOL();
+        if (c == EOF) {
+            error(JSMSG_MALFORMED_ESCAPE, "Unicode");
             return false;
+        }
         if (c == '}') {
-            if (first)
+            if (first) {
+                error(JSMSG_MALFORMED_ESCAPE, "Unicode");
                 return false;
+            }
             break;
         }
 
-        if (!JS7_ISHEX(c))
+        if (!JS7_ISHEX(c)) {
+            error(JSMSG_MALFORMED_ESCAPE, "Unicode");
             return false;
+        }
 
         code = (code << 4) | JS7_UNHEX(c);
-        if (code > unicode::NonBMPMax)
+        if (code > unicode::NonBMPMax) {
+            errorAt(start, JSMSG_UNICODE_OVERFLOW, "escape sequence");
             return false;
+        }
+
         first = false;
-    }
+    } while (true);
 
+    *matched = true;
     *cp = code;
     return true;
 }
 
 bool
 TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
 {
     int c;
@@ -1886,17 +1967,17 @@ TokenStream::getStringOrTemplateToken(in
     tokenbuf.clear();
 
     // We need to detect any of these chars:  " or ', \n (or its
     // equivalents), \\, EOF.  Because we detect EOL sequences here and
     // put them back immediately, we can use getCharIgnoreEOL().
     while ((c = getCharIgnoreEOL()) != untilChar) {
         if (c == EOF) {
             ungetCharIgnoreEOL(c);
-            reportError(JSMSG_UNTERMINATED_STRING);
+            error(JSMSG_UNTERMINATED_STRING);
             return false;
         }
 
         if (c == '\\') {
             switch (c = getChar()) {
               case 'b': c = '\b'; break;
               case 'f': c = '\f'; break;
               case 'n': c = '\n'; break;
@@ -1906,23 +1987,21 @@ TokenStream::getStringOrTemplateToken(in
 
               case '\n':
                 // ES5 7.8.4: an escaped line terminator represents
                 // no character.
                 continue;
 
               // Unicode character specification.
               case 'u': {
-                if (peekChar() == '{') {
-                    uint32_t code;
-                    if (!getBracedUnicode(&code)) {
-                        reportError(JSMSG_MALFORMED_ESCAPE, "Unicode");
-                        return false;
-                    }
-
+                bool matched;
+                uint32_t code;
+                if (!matchBracedUnicode(&matched, &code))
+                    return false;
+                if (matched) {
                     MOZ_ASSERT(code <= unicode::NonBMPMax);
                     if (code < unicode::NonBMPMin) {
                         c = code;
                     } else {
                         if (!tokenbuf.append(unicode::LeadSurrogate(code)))
                             return false;
                         c = unicode::TrailSurrogate(code);
                     }
@@ -1934,57 +2013,59 @@ TokenStream::getStringOrTemplateToken(in
                     JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3]))
                 {
                     c = JS7_UNHEX(cp[0]);
                     c = (c << 4) + JS7_UNHEX(cp[1]);
                     c = (c << 4) + JS7_UNHEX(cp[2]);
                     c = (c << 4) + JS7_UNHEX(cp[3]);
                     skipChars(4);
                 } else {
-                    reportError(JSMSG_MALFORMED_ESCAPE, "Unicode");
+                    error(JSMSG_MALFORMED_ESCAPE, "Unicode");
                     return false;
                 }
                 break;
               }
 
               // Hexadecimal character specification.
               case 'x': {
                 char16_t cp[2];
                 if (peekChars(2, cp) && JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
                     c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
                     skipChars(2);
                 } else {
-                    reportError(JSMSG_MALFORMED_ESCAPE, "hexadecimal");
+                    error(JSMSG_MALFORMED_ESCAPE, "hexadecimal");
                     return false;
                 }
                 break;
               }
 
               default:
                 // Octal character specification.
                 if (JS7_ISOCT(c)) {
                     int32_t val = JS7_UNOCT(c);
 
-                    c = peekChar();
+                    if (!peekChar(&c))
+                        return false;
 
                     // Strict mode code allows only \0, then a non-digit.
                     if (val != 0 || JS7_ISDEC(c)) {
                         if (parsingTemplate) {
-                            reportError(JSMSG_DEPRECATED_OCTAL);
+                            error(JSMSG_DEPRECATED_OCTAL);
                             return false;
                         }
                         if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
                             return false;
                         flags.sawOctalEscape = true;
                     }
 
                     if (JS7_ISOCT(c)) {
                         val = 8 * val + JS7_UNOCT(c);
                         getChar();
-                        c = peekChar();
+                        if (!peekChar(&c))
+                            return false;
                         if (JS7_ISOCT(c)) {
                             int32_t save = val;
                             val = 8 * val + JS7_UNOCT(c);
                             if (val <= 0xFF)
                                 getChar();
                             else
                                 val = save;
                         }
@@ -1992,17 +2073,17 @@ TokenStream::getStringOrTemplateToken(in
 
                     c = char16_t(val);
                 }
                 break;
             }
         } else if (TokenBuf::isRawEOLChar(c)) {
             if (!parsingTemplate) {
                 ungetCharIgnoreEOL(c);
-                reportError(JSMSG_UNTERMINATED_STRING);
+                error(JSMSG_UNTERMINATED_STRING);
                 return false;
             }
             if (c == '\r') {
                 c = '\n';
                 if (userbuf.peekRawChar() == '\n')
                     skipCharsIgnoreEOL(1);
             }
             updateLineInfoForEOL();
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -359,23 +359,31 @@ class MOZ_STACK_CLASS TokenStream
     bool isEOF() const { return flags.isEOF; }
     bool sawOctalEscape() const { return flags.sawOctalEscape; }
     bool hadError() const { return flags.hadError; }
     void clearSawOctalEscape() { flags.sawOctalEscape = false; }
 
     // TokenStream-specific error reporters.
     bool reportError(unsigned errorNumber, ...);
     bool reportErrorNoOffset(unsigned errorNumber, ...);
-    bool reportWarning(unsigned errorNumber, ...);
+
+    // Report the given error at the current offset.
+    void error(unsigned errorNumber, ...);
+
+    // Report the given error at the given offset.
+    void errorAt(uint32_t offset, unsigned errorNumber, ...);
+
+    // Warn at the current offset.
+    MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
 
     static const uint32_t NoOffset = UINT32_MAX;
 
     // General-purpose error reporters.  You should avoid calling these
-    // directly, and instead use the more succinct alternatives (e.g.
-    // reportError()) in TokenStream, Parser, and BytecodeEmitter.
+    // directly, and instead use the more succinct alternatives (error(),
+    // warning(), &c.) in TokenStream, Parser, and BytecodeEmitter.
     bool reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
                                     va_list args);
     bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
                                        va_list args);
     bool reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args);
 
     // asm.js reporter
     void reportAsmJSError(uint32_t offset, unsigned errorNumber, ...);
@@ -942,34 +950,34 @@ class MOZ_STACK_CLASS TokenStream
         const char16_t* base_;          // base of buffer
         uint32_t startOffset_;          // offset of base_[0]
         const char16_t* limit_;         // limit for quick bounds check
         const char16_t* ptr;            // next char to get
     };
 
     MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
 
-    MOZ_MUST_USE bool getBracedUnicode(uint32_t* code);
+    MOZ_MUST_USE bool matchBracedUnicode(bool* matched, uint32_t* code);
     MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp);
 
     int32_t getChar();
     int32_t getCharIgnoreEOL();
     void ungetChar(int32_t c);
     void ungetCharIgnoreEOL(int32_t c);
     Token* newToken(ptrdiff_t adjust);
     uint32_t peekUnicodeEscape(uint32_t* codePoint);
     uint32_t peekExtendedUnicodeEscape(uint32_t* codePoint);
     uint32_t matchUnicodeEscapeIdStart(uint32_t* codePoint);
     bool matchUnicodeEscapeIdent(uint32_t* codePoint);
     bool matchTrailForLeadSurrogate(char16_t lead, char16_t* trail, uint32_t* codePoint);
     bool peekChars(int n, char16_t* cp);
 
     MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
     MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
-                                   const char* directive, int directiveLength,
+                                   const char* directive, uint8_t directiveLength,
                                    const char* errorMsgPragma,
                                    UniquePtr<char16_t[], JS::FreePolicy>* destination);
     MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
     MOZ_MUST_USE bool getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated);
 
     // |expect| cannot be an EOL char.
     bool matchChar(int32_t expect) {
         MOZ_ASSERT(!TokenBuf::isRawEOLChar(expect));
@@ -977,30 +985,35 @@ class MOZ_STACK_CLASS TokenStream
                userbuf.matchRawChar(expect);
     }
 
     void consumeKnownChar(int32_t expect) {
         mozilla::DebugOnly<int32_t> c = getChar();
         MOZ_ASSERT(c == expect);
     }
 
-    int32_t peekChar() {
-        int32_t c = getChar();
-        ungetChar(c);
-        return c;
+    MOZ_MUST_USE bool peekChar(int32_t* c) {
+        *c = getChar();
+        ungetChar(*c);
+        return true;
     }
 
-    void skipChars(int n) {
-        while (--n >= 0)
-            getChar();
+    void skipChars(uint8_t n) {
+        while (n-- > 0) {
+            MOZ_ASSERT(userbuf.hasRawChars());
+            mozilla::DebugOnly<int32_t> c = getCharIgnoreEOL();
+            MOZ_ASSERT(c != '\n');
+        }
     }
 
-    void skipCharsIgnoreEOL(int n) {
-        while (--n >= 0)
+    void skipCharsIgnoreEOL(uint8_t n) {
+        while (n-- > 0) {
+            MOZ_ASSERT(userbuf.hasRawChars());
             getCharIgnoreEOL();
+        }
     }
 
     void updateLineInfoForEOL();
     void updateFlagsForEOL();
 
     const Token& nextToken() const {
         MOZ_ASSERT(hasLookahead());
         return tokens[(cursor + 1) & ntokensMask];
--- a/js/src/irregexp/RegExpParser.cpp
+++ b/js/src/irregexp/RegExpParser.cpp
@@ -238,20 +238,20 @@ RegExpParser<CharT>::RegExpParser(fronte
     contains_anchor_(false),
     is_scanned_for_captures_(false)
 {
     Advance();
 }
 
 template <typename CharT>
 RegExpTree*
-RegExpParser<CharT>::ReportError(unsigned errorNumber)
+RegExpParser<CharT>::ReportError(unsigned errorNumber, const char* param /* = nullptr */)
 {
     gc::AutoSuppressGC suppressGC(ts.context());
-    ts.reportError(errorNumber);
+    ts.reportError(errorNumber, param);
     return nullptr;
 }
 
 template <typename CharT>
 void
 RegExpParser<CharT>::Advance()
 {
     if (next_pos_ < end_) {
@@ -345,17 +345,17 @@ RegExpParser<CharT>::ParseBracedHexEscap
 
         int d = HexValue(c);
         if (d < 0) {
             ReportError(JSMSG_INVALID_UNICODE_ESCAPE);
             return false;
         }
         code = (code << 4) | d;
         if (code > unicode::NonBMPMax) {
-            ReportError(JSMSG_UNICODE_OVERFLOW);
+            ReportError(JSMSG_UNICODE_OVERFLOW, "regular expression");
             return false;
         }
         Advance();
         first = false;
     }
 
     *value = code;
     return true;
--- a/js/src/irregexp/RegExpParser.h
+++ b/js/src/irregexp/RegExpParser.h
@@ -206,17 +206,17 @@ class RegExpParser
 
     // Tries to parse the input as a back reference.  If successful it
     // stores the result in the output parameter and returns true.  If
     // it fails it will push back the characters read so the same characters
     // can be reparsed.
     bool ParseBackReferenceIndex(int* index_out);
 
     bool ParseClassAtom(char16_t* char_class, widechar *value);
-    RegExpTree* ReportError(unsigned errorNumber);
+    RegExpTree* ReportError(unsigned errorNumber, const char* param = nullptr);
     void Advance();
     void Advance(int dist) {
         next_pos_ += dist - 1;
         Advance();
     }
 
     void Reset(const CharT* pos) {
         next_pos_ = pos;
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug1220766.js
+++ /dev/null
@@ -1,3 +0,0 @@
-iter = getSelfHostedValue("CreateListIterator")([]);
-iter.next();
-iter.next();
--- a/js/src/jit-test/tests/modules/import-namespace.js
+++ b/js/src/jit-test/tests/modules/import-namespace.js
@@ -14,19 +14,29 @@ function parseAndEvaluate(source) {
 
 function testHasNames(names, expected) {
     assertEq(names.length, expected.length);
     expected.forEach(function(name) {
         assertEq(names.includes(name), true);
     });
 }
 
+function testEqualArrays(actual, expected) {
+	assertEq(Array.isArray(actual), true);
+	assertEq(Array.isArray(expected), true);
+    assertEq(actual.length, expected.length);
+    for (let i = 0; i < expected.length; i++) {
+    	assertEq(actual[i], expected[i]);
+    }
+}
+
 let a = moduleRepo['a'] = parseModule(
-    `export var a = 1;
-     export var b = 2;`
+    `// Reflection methods should return these exports alphabetically sorted.
+     export var b = 2;
+     export var a = 1;`
 );
 
 let b = moduleRepo['b'] = parseModule(
     `import * as ns from 'a';
      export { ns };
      export var x = ns.a + ns.b;`
 );
 
@@ -34,17 +44,19 @@ b.declarationInstantiation();
 b.evaluation();
 testHasNames(getModuleEnvironmentNames(b), ["ns", "x"]);
 let ns = getModuleEnvironmentValue(b, "ns");
 testHasNames(Object.keys(ns), ["a", "b"]);
 assertEq(getModuleEnvironmentValue(b, "x"), 3);
 
 // Test module namespace internal methods as defined in 9.4.6
 assertEq(Object.getPrototypeOf(ns), null);
-assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, null), TypeError);
+assertEq(Reflect.setPrototypeOf(ns, null), true);
+assertEq(Reflect.setPrototypeOf(ns, Object.prototype), false);
+assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, {}), TypeError);
 assertThrowsInstanceOf(function() { ns.foo = 1; }, TypeError);
 assertEq(Object.isExtensible(ns), false);
 Object.preventExtensions(ns);
 let desc = Object.getOwnPropertyDescriptor(ns, "a");
 assertEq(desc.value, 1);
 assertEq(desc.writable, true);
 assertEq(desc.enumerable, true);
 assertEq(desc.configurable, false);
@@ -54,39 +66,25 @@ assertThrowsInstanceOf(function() { ns.a
 delete ns.foo;
 assertThrowsInstanceOf(function() { delete ns.a; }, TypeError);
 
 // Test @@toStringTag property
 desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag);
 assertEq(desc.value, "Module");
 assertEq(desc.writable, false);
 assertEq(desc.enumerable, false);
-assertEq(desc.configurable, true);
+assertEq(desc.configurable, false);
 assertEq(typeof desc.get, "undefined");
 assertEq(typeof desc.set, "undefined");
 assertEq(Object.prototype.toString.call(ns), "[object Module]");
 
-// Test @@iterator method.
-let iteratorFun = ns[Symbol.iterator];
-assertEq(iteratorFun.name, "[Symbol.iterator]");
-
-let iterator = ns[Symbol.iterator]();
-assertEq(iterator[Symbol.iterator](), iterator);
-assertIteratorNext(iterator, "a");
-assertIteratorNext(iterator, "b");
-assertIteratorDone(iterator);
-
-// The iterator's next method can only be called on the object it was originally
-// associated with.
-iterator = ns[Symbol.iterator]();
-let iterator2 = ns[Symbol.iterator]();
-assertThrowsInstanceOf(() => iterator.next.call({}), TypeError);
-assertThrowsInstanceOf(() => iterator.next.call(iterator2), TypeError);
-assertEq(iterator.next.call(iterator).value, "a");
-assertEq(iterator2.next.call(iterator2).value, "a");
+// Test [[OwnPropertyKeys]] internal method.
+testEqualArrays(Reflect.ownKeys(ns), ["a", "b", Symbol.toStringTag]);
+testEqualArrays(Object.getOwnPropertyNames(ns), ["a", "b"]);
+testEqualArrays(Object.getOwnPropertySymbols(ns), [Symbol.toStringTag]);
 
 // Test cyclic namespace import and access in module evaluation.
 let c = moduleRepo['c'] =
     parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;");
 let d = moduleRepo['d'] =
     parseModule("export let d = 2; import * as ns from 'c'; let c = ns.c;");
 c.declarationInstantiation();
 d.declarationInstantiation();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1319443.js
@@ -0,0 +1,11 @@
+// |jit-test| error: TypeError
+
+var global = newGlobal({ cloneSingletons: true });
+
+var code = cacheEntry(`
+function f() {}
+Object.freeze(this);
+`);
+
+evaluate(code, { global, saveBytecode: true });
+evaluate(code, { global, saveBytecode: true });
--- a/js/src/jit-test/tests/wasm/integer.js
+++ b/js/src/jit-test/tests/wasm/integer.js
@@ -102,20 +102,30 @@ testUnary('i32', 'popcnt', 0xFFFFFFFF, 3
 testUnary('i32', 'eqz', 0, 1);
 testUnary('i32', 'eqz', 1, 0);
 testUnary('i32', 'eqz', 0xFFFFFFFF, 0);
 
 testBinary32('add', 40, 2, 42);
 testBinary32('sub', 40, 2, 38);
 testBinary32('mul', 40, 2, 80);
 testBinary32('div_s', -40, 2, -20);
+testBinary32('div_s', -40, 8, -5);
+testBinary32('div_s', -40, 7, -5);
+testBinary32('div_s', 40, 8, 5);
+testBinary32('div_s', 40, 7, 5);
 testBinary32('div_u', -40, 2, 2147483628);
+testBinary32('div_u', 40, 2, 20);
+testBinary32('div_u', 40, 8, 5);
 testBinary32('rem_s', 40, -3, 1);
 testBinary32('rem_s', 0, -3, 0);
+testBinary32('rem_s', 5, 2, 1);
+testBinary32('rem_s', 65, 64, 1);
+testBinary32('rem_s', -65, 64, -1);
 testBinary32('rem_u', 40, -3, 40);
+testBinary32('rem_u', 41, 8, 1);
 testBinary32('and', 42, 6, 2);
 testBinary32('or', 42, 6, 46);
 testBinary32('xor', 42, 2, 40);
 testBinary32('shl', 40, 2, 160);
 testBinary32('shr_s', -40, 2, -10);
 testBinary32('shr_u', -40, 2, 1073741814);
 
 testTrap32('div_s', 42, 0, /integer divide by zero/);
@@ -162,26 +172,36 @@ assertEq(testTrunc(13.37), 1);
     testBinary64('mul', 2, -1, -2);
     testBinary64('mul', "0x80000000", -1, -2147483648);
     testBinary64('mul', "0x7fffffff", -1, -2147483647);
     testBinary64('mul', "0x7fffffffffffffff", -1, "0x8000000000000001");
     testBinary64('mul', 2, 2, 4);
     testBinary64('mul', "0x80000000", 2, "0x100000000");
     testBinary64('mul', "0x7fffffff", 2, "0xfffffffe");
     testBinary64('div_s', -40, 2, -20);
+    testBinary64('div_s', -40, 8, -5);
+    testBinary64('div_s', -40, 7, -5);
+    testBinary64('div_s', 40, 8, 5);
+    testBinary64('div_s', 40, 7, 5);
     testBinary64('div_s', "0x1234567887654321", 2, "0x91a2b3c43b2a190");
     testBinary64('div_s', "0x1234567887654321", "0x1000000000", "0x1234567");
     testBinary64('div_u', -40, 2, "0x7fffffffffffffec");
     testBinary64('div_u', "0x1234567887654321", 9, "0x205d0b80f0b4059");
+    testBinary64('div_u', 40, 2, 20);
+    testBinary64('div_u', 40, 8, 5);
     testBinary64('rem_s', 40, -3, 1);
+    testBinary64('rem_s', 0, -3, 0);
+    testBinary64('rem_s', 5, 2, 1);
+    testBinary64('rem_s', 65, 64, 1);
     testBinary64('rem_s', "0x1234567887654321", "0x1000000000", "0x887654321");
     testBinary64('rem_s', "0x7fffffffffffffff", -1, 0);
     testBinary64('rem_s', "0x8000000000000001", 1000, -807);
     testBinary64('rem_s', "0x8000000000000000", -1, 0);
     testBinary64('rem_u', 40, -3, 40);
+    testBinary64('rem_u', 41, 8, 1);
     testBinary64('rem_u', "0x1234567887654321", "0x1000000000", "0x887654321");
     testBinary64('rem_u', "0x8000000000000000", -1, "0x8000000000000000");
     testBinary64('rem_u', "0x8ff00ff00ff00ff0", "0x100000001", "0x80000001");
 
     testTrap64('div_s', 10, 0, /integer divide by zero/);
     testTrap64('div_s', "0x8000000000000000", -1, /integer overflow/);
     testTrap64('div_u', 0, 0, /integer divide by zero/);
     testTrap64('rem_s', 10, 0, /integer divide by zero/);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js
@@ -0,0 +1,19 @@
+load(libdir + "wasm.js");
+
+assertEq(wasmEvalText(`
+(module
+  (func $f (param $p i32)
+    block $out
+      i32.const 0
+      if
+        i32.const 1
+        tee_local $p
+        br_table $out $out
+      end
+    end
+    get_local $p
+    br_if 0
+  )
+  (export "f" $f)
+)
+`).exports.f(42), undefined);
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -902,19 +902,17 @@ InitFromBailout(JSContext* cx, HandleScr
                 return false;
             for (uint32_t i = 0; i < inlined_args; i++)
                 savedCallerArgs[i].set(iter.read());
 
             if (IsSetPropPC(pc)) {
                 // We would love to just save all the arguments and leave them
                 // in the stub frame pushed below, but we will lose the inital
                 // argument which the function was called with, which we must
-                // return to the caller, even if the setter internally modifies
-                // its arguments. Stash the initial argument on the stack, to be
-                // later retrieved by the SetProp_Fallback stub.
+                // leave on the stack. It's pushed as the result of the SETPROP.
                 Value initialArg = savedCallerArgs[inlined_args - 1];
                 JitSpew(JitSpew_BaselineBailouts, "     pushing setter's initial argument");
                 if (!builder.writeValue(initialArg, "StackValue"))
                     return false;
             }
             pushedSlots = exprStackSlots;
         }
     }
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2178,26 +2178,29 @@ BaselineCompiler::emit_JSOP_MUTATEPROTO(
 
     frame.pop();
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_INITPROP()
 {
-    // Keep lhs in R0, rhs in R1.
-    frame.popRegsAndSync(2);
-
-    // Push the object to store the result of the IC.
-    frame.push(R0);
+    // Load lhs in R0, rhs in R1.
     frame.syncStack(0);
+    masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
+    masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
 
     // Call IC.
     ICSetProp_Fallback::Compiler compiler(cx);
-    return emitOpIC(compiler.getStub(&stubSpace_));
+    if (!emitOpIC(compiler.getStub(&stubSpace_)))
+        return false;
+
+    // Leave the object on the stack.
+    frame.pop();
+    return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_INITLOCKEDPROP()
 {
     return emit_JSOP_INITPROP();
 }
 
@@ -2413,23 +2416,25 @@ BaselineCompiler::emit_JSOP_BINDVAR()
 }
 
 bool
 BaselineCompiler::emit_JSOP_SETPROP()
 {
     // Keep lhs in R0, rhs in R1.
     frame.popRegsAndSync(2);
 
+    // Keep RHS on the stack.
+    frame.push(R1);
+    frame.syncStack(0);
+
     // Call IC.
     ICSetProp_Fallback::Compiler compiler(cx);
     if (!emitOpIC(compiler.getStub(&stubSpace_)))
         return false;
 
-    // The IC will return the RHS value in R0, mark it as pushed value.
-    frame.push(R0);
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_STRICTSETPROP()
 {
     return emit_JSOP_SETPROP();
 }
@@ -2582,30 +2587,28 @@ bool
 BaselineCompiler::emit_JSOP_SETALIASEDVAR()
 {
     JSScript* outerScript = EnvironmentCoordinateFunctionScript(script, pc);
     if (outerScript && outerScript->treatAsRunOnce()) {
         // Type updates for this operation might need to be tracked, so treat
         // this as a SETPROP.
 
         // Load rhs into R1.
-        frame.syncStack(1);
-        frame.popValue(R1);
+        frame.syncStack(0);
+        masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
 
         // Load and box lhs into R0.
         getEnvironmentCoordinateObject(R2.scratchReg());
         masm.tagValue(JSVAL_TYPE_OBJECT, R2.scratchReg(), R0);
 
         // Call SETPROP IC.
         ICSetProp_Fallback::Compiler compiler(cx);
         if (!emitOpIC(compiler.getStub(&stubSpace_)))
             return false;
 
-        // The IC will return the RHS value in R0, mark it as pushed value.
-        frame.push(R0);
         return true;
     }
 
     // Keep rvalue in R0.
     frame.popRegsAndSync(1);
     Register objReg = R2.scratchReg();
 
     getEnvironmentCoordinateObject(objReg);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2870,18 +2870,18 @@ TryAttachTypedObjectSetPropStub(JSContex
 
     stub->addNewStub(newStub);
 
     *attached = true;
     return true;
 }
 
 static bool
-DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_,
-                  HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_, Value* stack,
+                  HandleValue lhs, HandleValue rhs)
 {
     // This fallback stub may trigger debug mode toggling.
     DebugModeOSRVolatileStub<ICSetProp_Fallback*> stub(frame, stub_);
 
     RootedScript script(cx, frame->script());
     jsbytecode* pc = stub->icEntry()->pc(script);
     JSOp op = JSOp(*pc);
     FallbackICSpew(cx, stub, "SetProp(%s)", CodeName[op]);
@@ -2964,18 +2964,19 @@ DoSetPropFallback(JSContext* cx, Baselin
         ObjectOpResult result;
         if (!SetProperty(cx, obj, id, rhs, lhs, result) ||
             !result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP))
         {
             return false;
         }
     }
 
-    // Leave the RHS on the stack.
-    res.set(rhs);
+    // Overwrite the LHS on the stack (pushed for the decompiler) with the RHS.
+    MOZ_ASSERT(stack[1] == lhs);
+    stack[1] = rhs;
 
     // Check if debug mode toggling made the stub invalid.
     if (stub.invalid())
         return true;
 
     if (stub->numOptimizedStubs() >= ICSetProp_Fallback::MAX_OPTIMIZED_STUBS) {
         // TODO: Discard all stubs in this IC and replace with generic setprop stub.
         return true;
@@ -3011,37 +3012,46 @@ DoSetPropFallback(JSContext* cx, Baselin
 
     MOZ_ASSERT(!attached);
     if (!isTemporarilyUnoptimizable)
         stub->noteUnoptimizableAccess();
 
     return true;
 }
 
-typedef bool (*DoSetPropFallbackFn)(JSContext*, BaselineFrame*, ICSetProp_Fallback*,
-                                    HandleValue, HandleValue, MutableHandleValue);
+typedef bool (*DoSetPropFallbackFn)(JSContext*, BaselineFrame*, ICSetProp_Fallback*, Value*,
+                                    HandleValue, HandleValue);
 static const VMFunction DoSetPropFallbackInfo =
     FunctionInfo<DoSetPropFallbackFn>(DoSetPropFallback, "DoSetPropFallback", TailCall,
-                                      PopValues(2));
+                                      PopValues(1));
 
 bool
 ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
 {
     MOZ_ASSERT(engine_ == Engine::Baseline);
     MOZ_ASSERT(R0 == JSReturnOperand);
 
     EmitRestoreTailCallReg(masm);
 
     // Ensure stack is fully synced for the expression decompiler.
-    masm.pushValue(R0);
+    // Overwrite the RHS value on top of the stack with the object, then push
+    // the RHS in R1 on top of that.
+    masm.storeValue(R0, Address(masm.getStackPointer(), 0));
     masm.pushValue(R1);
 
     // Push arguments.
     masm.pushValue(R1);
     masm.pushValue(R0);
+
+    // Push pointer to stack values, so that the stub can overwrite the object
+    // (pushed for the decompiler) with the RHS.
+    masm.computeEffectiveAddress(Address(masm.getStackPointer(), 2 * sizeof(Value)),
+                                 R0.scratchReg());
+    masm.push(R0.scratchReg());
+
     masm.push(ICStubReg);
     pushStubPayload(masm, R0.scratchReg());
 
     if (!tailCallVM(DoSetPropFallbackInfo, masm))
         return false;
 
     // Even though the fallback frame doesn't enter a stub frame, the CallScripted
     // frame that we are emulating does. Again, we lie.
@@ -3053,19 +3063,16 @@ ICSetProp_Fallback::Compiler::generateSt
     inStubFrame_ = true;
 #endif
 
     // What follows is bailout-only code for inlined script getters.
     // The return address pointed to by the baseline stack points here.
     returnOffset_ = masm.currentOffset();
 
     leaveStubFrame(masm, true);
-
-    // Retrieve the stashed initial argument from the caller's frame before returning
-    EmitUnstowICValues(masm, 1);
     EmitReturnFromIC(masm);
 
     return true;
 }
 
 void
 ICSetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm, Handle<JitCode*> code)
 {
@@ -3158,18 +3165,16 @@ ICSetProp_Native::Compiler::generateStub
     if (cx->runtime()->gc.nursery.exists()) {
         Register scr = regs.takeAny();
         LiveGeneralRegisterSet saveRegs;
         saveRegs.add(R1);
         emitPostWriteBarrierSlot(masm, objReg, R1, scr, saveRegs);
         regs.add(scr);
     }
 
-    // The RHS has to be in R0.
-    masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
@@ -3316,18 +3321,16 @@ ICSetPropNativeAddCompiler::generateStub
 
     if (cx->runtime()->gc.nursery.exists()) {
         Register scr = regs.takeAny();
         LiveGeneralRegisterSet saveRegs;
         saveRegs.add(R1);
         emitPostWriteBarrierSlot(masm, objReg, R1, scr, saveRegs);
     }
 
-    // The RHS has to be in R0.
-    masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failureUnstow);
     EmitUnstowICValues(masm, 2);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
@@ -3383,19 +3386,16 @@ ICSetProp_Unboxed::Compiler::generateStu
     // Compute the address being written to.
     masm.load32(Address(ICStubReg, ICSetProp_Unboxed::offsetOfFieldOffset()), scratch);
     BaseIndex address(object, scratch, TimesOne);
 
     EmitUnboxedPreBarrierForBaseline(masm, address, fieldType_);
     masm.storeUnboxedProperty(address, fieldType_,
                               ConstantOrRegister(TypedOrValueRegister(R1)), &failure);
 
-    // The RHS has to be in R0.
-    masm.moveValue(R1, R0);
-
     EmitReturnFromIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
 bool
@@ -3505,18 +3505,16 @@ ICSetProp_TypedObject::Compiler::generat
             break;
           }
 
           default:
             MOZ_CRASH();
         }
     }
 
-    // The RHS has to be in R0.
-    masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
     masm.bind(&failurePopRHS);
     masm.popValue(R1);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
@@ -3609,17 +3607,16 @@ ICSetProp_CallScripted::Compiler::genera
     masm.callJit(code);
 
     uint32_t framePushedAfterCall = masm.framePushed();
 
     leaveStubFrame(masm, true);
     // Do not care about return value from function. The original RHS should be returned
     // as the result of this operation.
     EmitUnstowICValues(masm, 2);
-    masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
     // Leave stub frame and go to next stub.
     masm.bind(&failureLeaveStubFrame);
     masm.setFramePushed(framePushedAfterCall);
     inStubFrame_ = true;
     leaveStubFrame(masm, false);
 
@@ -3703,17 +3700,16 @@ ICSetProp_CallNative::Compiler::generate
 
     if (!callVM(DoCallNativeSetterInfo, masm))
         return false;
     leaveStubFrame(masm);
 
     // Do not care about return value from function. The original RHS should be returned
     // as the result of this operation.
     EmitUnstowICValues(masm, 2);
-    masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
     // Unstow R0 and R1
     masm.bind(&failureUnstow);
     masm.setFramePushed(framePushed);
     EmitUnstowICValues(masm, 2);
 
     // Failure case - jump to next stub
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -36,16 +36,18 @@ CacheRegisterAllocator::useValueRegister
         masm.moveValue(loc.constant(), reg);
         loc.setValueReg(reg);
         return reg;
       }
 
       case OperandLocation::PayloadReg: {
         ValueOperand reg = allocateValueRegister(masm);
         masm.tagValue(loc.payloadType(), loc.payloadReg(), reg);
+        MOZ_ASSERT(!currentOpRegs_.has(loc.payloadReg()), "Payload register shouldn't be in use");
+        availableRegs_.add(loc.payloadReg());
         loc.setValueReg(reg);
         return reg;
       }
 
       case OperandLocation::PayloadStack: {
         ValueOperand reg = allocateValueRegister(masm);
         popPayload(masm, &loc, reg.scratchReg());
         masm.tagValue(loc.payloadType(), reg.scratchReg(), reg);
--- a/js/src/jit/InlinableNatives.h
+++ b/js/src/jit/InlinableNatives.h
@@ -116,17 +116,16 @@
     _(IntrinsicSubstringKernel)     \
     _(IntrinsicDefineDataProperty)  \
     _(IntrinsicObjectHasPrototype)  \
                                     \
     _(IntrinsicIsArrayIterator)     \
     _(IntrinsicIsMapIterator)       \
     _(IntrinsicIsSetIterator)       \
     _(IntrinsicIsStringIterator)    \
-    _(IntrinsicIsListIterator)      \
                                     \
     _(IntrinsicGetNextMapEntryForIterator) \
                                     \
     _(IntrinsicGetNextSetEntryForIterator) \
                                     \
     _(IntrinsicArrayBufferByteLength) \
     _(IntrinsicPossiblyWrappedArrayBufferByteLength) \
                                     \
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3175,24 +3175,27 @@ IonBuilder::binaryArithTryConcat(bool* e
     trackOptimizationAttempt(TrackedStrategy::BinaryArith_Concat);
 
     // Make sure one of the inputs is a string.
     if (left->type() != MIRType::String && right->type() != MIRType::String) {
         trackOptimizationOutcome(TrackedOutcome::OperandNotString);
         return Ok();
     }
 
-    // The none-string input (if present) should be atleast a numerical type.
-    // Which we can easily coerce to string.
-    if (right->type() != MIRType::String && !IsNumberType(right->type())) {
-        trackOptimizationOutcome(TrackedOutcome::OperandNotStringOrNumber);
-        return Ok();
-    }
-    if (left->type() != MIRType::String && !IsNumberType(left->type())) {
-        trackOptimizationOutcome(TrackedOutcome::OperandNotStringOrNumber);
+    // The non-string input (if present) should be atleast easily coercible to string.
+    if (right->type() != MIRType::String &&
+        (right->mightBeType(MIRType::Symbol) || right->mightBeType(MIRType::Object)))
+    {
+        trackOptimizationOutcome(TrackedOutcome::OperandNotEasilyCoercibleToString);
+        return Ok();
+    }
+    if (left->type() != MIRType::String &&
+        (left->mightBeType(MIRType::Symbol) || left->mightBeType(MIRType::Object)))
+    {
+        trackOptimizationOutcome(TrackedOutcome::OperandNotEasilyCoercibleToString);
         return Ok();
     }
 
     MConcat* ins = MConcat::New(alloc(), left, right);
     current->add(ins);
     current->push(ins);
 
     MOZ_TRY(maybeInsertResume());
@@ -5711,16 +5714,20 @@ IonBuilder::newArrayTrySharedStub(bool* 
         return Ok();
 
     MInstruction* stub = MNullarySharedStub::New(alloc());
     current->add(stub);
     current->push(stub);
 
     MOZ_TRY(resumeAfter(stub));
 
+    MUnbox* unbox = MUnbox::New(alloc(), current->pop(), MIRType::Object, MUnbox::Infallible);
+    current->add(unbox);
+    current->push(unbox);
+
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length)
 {
     MOZ_ASSERT(*emitted == false);
@@ -5849,16 +5856,20 @@ IonBuilder::newObjectTrySharedStub(bool*
         return Ok();
 
     MInstruction* stub = MNullarySharedStub::New(alloc());
     current->add(stub);
     current->push(stub);
 
     MOZ_TRY(resumeAfter(stub));
 
+    MUnbox* unbox = MUnbox::New(alloc(), current->pop(), MIRType::Object, MUnbox::Infallible);
+    current->add(unbox);
+    current->push(unbox);
+
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newObjectTryVM(bool* emitted, JSObject* templateObject)
 {
     // Emit a VM call.
@@ -6051,17 +6062,17 @@ IonBuilder::jsop_initprop(PropertyName* 
                     useSlowPath = true;
             } else {
                 MOZ_ASSERT(templateObject->as<UnboxedPlainObject>().layout().lookup(name));
             }
         } else {
             useSlowPath = true;
         }
     } else {
-        MOZ_ASSERT(obj->isNullarySharedStub());
+        MOZ_ASSERT(obj->isUnbox() && obj->getOperand(0)->isNullarySharedStub());
         useSlowPath = true;
     }
 
     if (useSlowPath) {
         current->pop();
         MInitProp* init = MInitProp::New(alloc(), obj, name, value);
         current->add(init);
         return resumeAfter(init);
@@ -12342,33 +12353,37 @@ IonBuilder::inTryFold(bool* emitted, MDe
 
     pushConstant(BooleanValue(false));
     obj->setImplicitlyUsedUnchecked();
     id->setImplicitlyUsedUnchecked();
     return Ok();
 }
 
 AbortReasonOr<bool>
-IonBuilder::hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject)
+IonBuilder::hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject, bool* onProto)
 {
     MOZ_ASSERT(protoObject);
 
     while (true) {
         if (!alloc().ensureBallast())
             return abort(AbortReason::Alloc);
 
         if (!key->hasStableClassAndProto(constraints()) || !key->clasp()->isNative())
-            return abort(AbortReason::Disable, "Cannot inspect prototype chain.");
+            return false;
 
         JSObject* proto = checkNurseryObject(key->proto().toObjectOrNull());
-        if (!proto)
-            return false;
-
-        if (proto == protoObject)
+        if (!proto) {
+            *onProto = false;
             return true;
+        }
+
+        if (proto == protoObject) {
+            *onProto = true;
+            return true;
+        }
 
         key = TypeSet::ObjectKey::get(proto);
     }
 
     MOZ_CRASH("Unreachable");
 }
 
 AbortReasonOr<Ok>
@@ -12394,18 +12409,21 @@ IonBuilder::tryFoldInstanceOf(bool* emit
     bool isFirst = true;
     bool knownIsInstance = false;
 
     for (unsigned i = 0; i < lhsTypes->getObjectCount(); i++) {
         TypeSet::ObjectKey* key = lhsTypes->getObject(i);
         if (!key)
             continue;
 
+        bool checkSucceeded;
         bool isInstance;
-        MOZ_TRY_VAR(isInstance, hasOnProtoChain(key, protoObject));
+        MOZ_TRY_VAR(checkSucceeded, hasOnProtoChain(key, protoObject, &isInstance));
+        if (!checkSucceeded)
+            return Ok();
 
         if (isFirst) {
             knownIsInstance = isInstance;
             isFirst = false;
         } else if (knownIsInstance != isInstance) {
             // Some of the objects have protoObject on their proto chain and
             // others don't, so we can't optimize this.
             return Ok();
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -477,17 +477,17 @@ class IonBuilder
 
     MDefinition* getCallee();
     MDefinition* getAliasedVar(EnvironmentCoordinate ec);
     AbortReasonOr<MDefinition*> addLexicalCheck(MDefinition* input);
 
     MDefinition* convertToBoolean(MDefinition* input);
 
     AbortReasonOr<Ok> tryFoldInstanceOf(bool* emitted, MDefinition* lhs, JSObject* protoObject);
-    AbortReasonOr<bool> hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject);
+    AbortReasonOr<bool> hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject, bool* onProto);
 
     AbortReasonOr<Ok> jsop_add(MDefinition* left, MDefinition* right);
     AbortReasonOr<Ok> jsop_bitnot();
     AbortReasonOr<Ok> jsop_bitop(JSOp op);
     AbortReasonOr<Ok> jsop_binary_arith(JSOp op);
     AbortReasonOr<Ok> jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right);
     AbortReasonOr<Ok> jsop_pow();
     AbortReasonOr<Ok> jsop_pos();
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -434,17 +434,18 @@ jit::CheckLogging()
             "  safepoints    Safepoints\n"
             "  pools         Literal Pools (ARM only for now)\n"
             "  cacheflush    Instruction Cache flushes (ARM only for now)\n"
             "  range         Range Analysis\n"
             "  unroll        Loop unrolling\n"
             "  logs          C1 and JSON visualization logging\n"
             "  logs-sync     Same as logs, but flushes between each pass (sync. compiled functions only).\n"
             "  profiling     Profiling-related information\n"
-            "  trackopts     Optimization tracking information\n"
+            "  trackopts     Optimization tracking information gathered by SPS. "
+                            "(Note: call enableSPSProfiling() in your script to enable it).\n"
             "  dump-mir-expr Dump the MIR expressions\n"
             "  cfg           Control flow graph generation\n"
             "  all           Everything\n"
             "\n"
             "  bl-aborts     Baseline compiler abort messages\n"
             "  bl-scripts    Baseline script-compilation\n"
             "  bl-op         Baseline compiler detailed op-specific messages\n"
             "  bl-ic         Baseline inline-cache messages\n"
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -283,18 +283,16 @@ IonBuilder::inlineNativeCall(CallInfo& c
       case InlinableNative::IntrinsicIsArrayIterator:
         return inlineHasClass(callInfo, &ArrayIteratorObject::class_);
       case InlinableNative::IntrinsicIsMapIterator:
         return inlineHasClass(callInfo, &MapIteratorObject::class_);
       case InlinableNative::IntrinsicIsSetIterator:
         return inlineHasClass(callInfo, &SetIteratorObject::class_);
       case InlinableNative::IntrinsicIsStringIterator:
         return inlineHasClass(callInfo, &StringIteratorObject::class_);
-      case InlinableNative::IntrinsicIsListIterator:
-        return inlineHasClass(callInfo, &ListIteratorObject::class_);
       case InlinableNative::IntrinsicDefineDataProperty:
         return inlineDefineDataProperty(callInfo);
       case InlinableNative::IntrinsicObjectHasPrototype:
         return inlineObjectHasPrototype(callInfo);
 
       // Map intrinsics.
       case InlinableNative::IntrinsicGetNextMapEntryForIterator:
         return inlineGetNextEntryForIterator(callInfo, MGetNextEntryForIterator::Map);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -498,17 +498,17 @@ MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE,  0
 MSG_DEF(JSMSG_MISSING_PAREN,           0, JSEXN_SYNTAXERR, "unterminated parenthetical")
 MSG_DEF(JSMSG_NEWREGEXP_FLAGGED,       0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
 MSG_DEF(JSMSG_NOTHING_TO_REPEAT,       0, JSEXN_SYNTAXERR, "nothing to repeat")
 MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER,    0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.")
 MSG_DEF(JSMSG_RANGE_WITH_CLASS_ESCAPE, 0, JSEXN_SYNTAXERR, "character class escape cannot be used in class range in regular expression")
 MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP,      0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag")
 MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP,    0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
 MSG_DEF(JSMSG_TOO_MANY_PARENS,         0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
-MSG_DEF(JSMSG_UNICODE_OVERFLOW,        0, JSEXN_SYNTAXERR, "unicode codepoint should not be greater than 0x10FFFF in regular expression")
+MSG_DEF(JSMSG_UNICODE_OVERFLOW,        1, JSEXN_SYNTAXERR, "Unicode codepoint must not be greater than 0x10FFFF in {0}")
 MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN,   0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
 MSG_DEF(JSMSG_UNTERM_CLASS,            0, JSEXN_SYNTAXERR, "unterminated character class")
 
 // Self-hosting
 MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR,    0, JSEXN_ERR, "internal error getting the default locale")
 MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP,1, JSEXN_ERR, "No such property on self-hosted object: {0}")
 
 // Typed object / SIMD
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -279,30 +279,34 @@ CallerGetterImpl(JSContext* cx, const Ca
         ++iter;
 
     if (iter.done() || !iter.isFunctionFrame()) {
         args.rval().setNull();
         return true;
     }
 
     RootedObject caller(cx, iter.callee(cx));
+    if (caller->is<JSFunction>() && caller->as<JSFunction>().isAsync())
+        caller = GetWrappedAsyncFunction(&caller->as<JSFunction>());
     if (!cx->compartment()->wrap(cx, &caller))
         return false;
 
     // Censor the caller if we don't have full access to it.  If we do, but the
     // caller is a function with strict mode code, throw a TypeError per ES5.
     // If we pass these checks, we can return the computed caller.
     {
         JSObject* callerObj = CheckedUnwrap(caller);
         if (!callerObj) {
             args.rval().setNull();
             return true;
         }
 
         JSFunction* callerFun = &callerObj->as<JSFunction>();
+        if (IsWrappedAsyncFunction(callerFun))
+            callerFun = GetUnwrappedAsyncFunction(callerFun);
         MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
 
         if (callerFun->strict()) {
             JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
                                               JSMSG_CALLER_IS_STRICT);
             return false;
         }
     }
@@ -346,16 +350,20 @@ CallerSetterImpl(JSContext* cx, const Ca
     ++iter;
     while (!iter.done() && iter.isEvalFrame())
         ++iter;
 
     if (iter.done() || !iter.isFunctionFrame())
         return true;
 
     RootedObject caller(cx, iter.callee(cx));
+    // |caller| is only used for security access-checking and for its
+    // strictness.  An unwrapped async function has its wrapped async
+    // function's security access and strictness, so don't bother calling
+    // |GetUnwrappedAsyncFunction|.
     if (!cx->compartment()->wrap(cx, &caller)) {
         cx->clearPendingException();
         return true;
     }
 
     // If we don't have full access to the caller, or the caller is not strict,
     // return undefined.  Otherwise throw a TypeError.
     JSObject* callerObj = CheckedUnwrap(caller);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1151,28 +1151,16 @@ const Class StringIteratorObject::class_
     JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount)
 };
 
 static const JSFunctionSpec string_iterator_methods[] = {
     JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
     JS_FS_END
 };
 
-enum {
-    ListIteratorSlotIteratedObject,
-    ListIteratorSlotNextIndex,
-    ListIteratorSlotNextMethod,
-    ListIteratorSlotCount
-};
-
-const Class ListIteratorObject::class_ = {
-    "List Iterator",
-    JSCLASS_HAS_RESERVED_SLOTS(ListIteratorSlotCount)
-};
-
 JSObject*
 js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp)
 {
     /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
     MOZ_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
 
     RootedObject obj(cx);
     if (vp.isObject()) {
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -146,22 +146,16 @@ class ArrayIteratorObject : public JSObj
 };
 
 class StringIteratorObject : public JSObject
 {
   public:
     static const Class class_;
 };
 
-class ListIteratorObject : public JSObject
-{
-  public:
-    static const Class class_;
-};
-
 bool
 GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp);
 
 JSObject*
 GetIteratorObject(JSContext* cx, HandleObject obj, unsigned flags);
 
 /*
  * Creates either a key or value iterator, depending on flags. For a value
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3870,16 +3870,17 @@ StackDump(JSContext* cx, unsigned argc, 
 
     bool showArgs = ToBoolean(args.get(0));
     bool showLocals = ToBoolean(args.get(1));
     bool showThisProps = ToBoolean(args.get(2));
 
     char* buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
     if (!buf) {
         fputs("Failed to format JavaScript stack for dump\n", gOutFile->fp);
+        JS_ClearPendingException(cx);
     } else {
         fputs(buf, gOutFile->fp);
         JS_smprintf_free(buf);
     }
 
     args.rval().setUndefined();
     return true;
 }
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_2017/AsyncFunctions/inner-caller.js
@@ -0,0 +1,26 @@
+var BUGNUMBER = 1185106;
+var summary = "caller property of function inside async function should return wrapped async function";
+
+print(BUGNUMBER + ": " + summary);
+
+(async function f() {
+  var inner = (function g() {
+      return g.caller;
+  })();
+  assertEq(inner, f);
+})();
+
+(async function f() {
+  "use strict";
+  try {
+    (function g() {
+        return g.caller;
+    })();
+    assertEq(true, false);
+  } catch (e) {
+    assertEq(e instanceof TypeError, true);
+  }
+})();
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
--- a/js/src/vm/Scope.cpp
+++ b/js/src/vm/Scope.cpp
@@ -919,23 +919,26 @@ GlobalScope::XDR(XDRState<mode>* xdr, Sc
         return false;
 
     {
         auto freeOnLeave = MakeScopeExit([&data]() {
             if (mode == XDR_DECODE)
                 js_free(data);
         });
 
+        if (!xdr->codeUint32(&data->varStart))
+            return false;
         if (!xdr->codeUint32(&data->letStart))
             return false;
         if (!xdr->codeUint32(&data->constStart))
             return false;
 
         if (mode == XDR_DECODE) {
             if (!data->length) {
+                MOZ_ASSERT(!data->varStart);
                 MOZ_ASSERT(!data->letStart);
                 MOZ_ASSERT(!data->constStart);
                 js_free(data);
                 data = nullptr;
             }
 
             scope.set(create(cx, kind, data));
             if (!scope)
@@ -1335,17 +1338,20 @@ js::DumpBindings(JSContext* cx, Scope* s
     RootedScope scope(cx, scopeArg);
     for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++) {
         JSAutoByteString bytes;
         if (!AtomToPrintableString(cx, bi.name(), &bytes))
             return;
         fprintf(stderr, "%s %s ", BindingKindString(bi.kind()), bytes.ptr());
         switch (bi.location().kind()) {
           case BindingLocation::Kind::Global:
-            fprintf(stderr, "global\n");
+            if (bi.isTopLevelFunction())
+                fprintf(stderr, "global function\n");
+            else
+                fprintf(stderr, "global\n");
             break;
           case BindingLocation::Kind::Argument:
             fprintf(stderr, "arg slot %u\n", bi.location().argumentSlot());
             break;
           case BindingLocation::Kind::Frame:
             fprintf(stderr, "frame slot %u\n", bi.location().slot());
             break;
           case BindingLocation::Kind::Environment:
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -836,47 +836,16 @@ intrinsic_NewStringIterator(JSContext* c
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
 static bool
-intrinsic_NewListIterator(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 0);
-
-    RootedObject proto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, cx->global()));
-    if (!proto)
-        return false;
-
-    RootedObject iterator(cx);
-    iterator = NewObjectWithGivenProto(cx, &ListIteratorObject::class_, proto);
-    if (!iterator)
-        return false;
-
-    args.rval().setObject(*iterator);
-    return true;
-}
-
-static bool
-intrinsic_ActiveFunction(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 0);
-
-    ScriptFrameIter iter(cx);
-    MOZ_ASSERT(iter.isFunctionFrame());
-    args.rval().setObject(*iter.callee(cx));
-    return true;
-}
-
-static bool
 intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
 
     RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
     MOZ_ASSERT(fun->isSelfHostedBuiltin());
     RootedAtom atom(cx, AtomizeString(cx, args[1].toString()));
@@ -2323,38 +2292,30 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("IsPackedArray",           intrinsic_IsPackedArray,           1,0),
 
     JS_FN("GetIteratorPrototype",    intrinsic_GetIteratorPrototype,    0,0),
 
     JS_FN("NewArrayIterator",        intrinsic_NewArrayIterator,        0,0),
     JS_FN("CallArrayIteratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>,      2,0),
 
-    JS_FN("NewListIterator",         intrinsic_NewListIterator,         0,0),
-    JS_FN("CallListIteratorMethodIfWrapped",
-          CallNonGenericSelfhostedMethod<Is<ListIteratorObject>>,       2,0),
-    JS_FN("ActiveFunction",          intrinsic_ActiveFunction,          0,0),
-
     JS_FN("_SetCanonicalName",       intrinsic_SetCanonicalName,        2,0),
 
     JS_INLINABLE_FN("IsArrayIterator",
                     intrinsic_IsInstanceOfBuiltin<ArrayIteratorObject>, 1,0,
                     IntrinsicIsArrayIterator),
     JS_INLINABLE_FN("IsMapIterator",
                     intrinsic_IsInstanceOfBuiltin<MapIteratorObject>,   1,0,
                     IntrinsicIsMapIterator),
     JS_INLINABLE_FN("IsSetIterator",
                     intrinsic_IsInstanceOfBuiltin<SetIteratorObject>,   1,0,
                     IntrinsicIsSetIterator),
     JS_INLINABLE_FN("IsStringIterator",
                     intrinsic_IsInstanceOfBuiltin<StringIteratorObject>, 1,0,
                     IntrinsicIsStringIterator),
-    JS_INLINABLE_FN("IsListIterator",
-                    intrinsic_IsInstanceOfBuiltin<ListIteratorObject>,  1,0,
-                    IntrinsicIsListIterator),
 
     JS_FN("_CreateMapIterationResultPair", intrinsic_CreateMapIterationResultPair, 0, 0),
     JS_INLINABLE_FN("_GetNextMapEntryForIterator", intrinsic_GetNextMapEntryForIterator, 2,0,
                     IntrinsicGetNextMapEntryForIterator),
     JS_FN("CallMapIteratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>,        2,0),
 
     JS_FN("_CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
@@ -2565,17 +2526,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
     JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
     JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
     JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
     JS_FN("InstantiateModuleFunctionDeclarations",
           intrinsic_InstantiateModuleFunctionDeclarations, 1, 0),
     JS_FN("SetModuleState", intrinsic_SetModuleState, 1, 0),
     JS_FN("EvaluateModule", intrinsic_EvaluateModule, 1, 0),
-    JS_FN("IsModuleNamespace", intrinsic_IsInstanceOfBuiltin<ModuleNamespaceObject>, 1, 0),
     JS_FN("NewModuleNamespace", intrinsic_NewModuleNamespace, 2, 0),
     JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0),
     JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0),
 
     JS_FS_END
 };
 
 void
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -1650,16 +1650,21 @@ DataViewNewObjectKind(JSContext* cx, uin
         return SingletonObject;
     return GenericObject;
 }
 
 DataViewObject*
 DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
                        Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, JSObject* protoArg)
 {
+    if (arrayBuffer->isDetached()) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
+        return nullptr;
+    }
+
     MOZ_ASSERT(byteOffset <= INT32_MAX);
     MOZ_ASSERT(byteLength <= INT32_MAX);
     MOZ_ASSERT(byteOffset + byteLength < UINT32_MAX);
 
     RootedObject proto(cx, protoArg);
     RootedObject obj(cx);
 
     NewObjectKind newKind = DataViewNewObjectKind(cx, byteLength, proto);
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -107,16 +107,17 @@
 #include "wasm/WasmGenerator.h"
 #include "wasm/WasmSignalHandlers.h"
 #include "wasm/WasmValidate.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using mozilla::DebugOnly;
 using mozilla::FloatingPoint;
+using mozilla::FloorLog2;
 using mozilla::IsPowerOfTwo;
 using mozilla::SpecificNaN;
 
 namespace js {
 namespace wasm {
 
 using namespace js::jit;
 using JS::GenericNaN;
@@ -1704,16 +1705,46 @@ class BaseCompiler
         Stk& v = stk_.back();
         if (v.kind() != Stk::ConstI64)
             return false;
         c = v.i64val();
         stk_.popBack();
         return true;
     }
 
+    MOZ_MUST_USE bool popConstPositivePowerOfTwoI32(int32_t& c,
+                                                    uint_fast8_t& power,
+                                                    int32_t cutoff)
+    {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI32)
+            return false;
+        c = v.i32val();
+        if (c <= cutoff || !IsPowerOfTwo(static_cast<uint32_t>(c)))
+            return false;
+        power = FloorLog2(c);
+        stk_.popBack();
+        return true;
+    }
+
+    MOZ_MUST_USE bool popConstPositivePowerOfTwoI64(int64_t& c,
+                                                    uint_fast8_t& power,
+                                                    int64_t cutoff)
+    {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI64)
+            return false;
+        c = v.i64val();
+        if (c <= cutoff || !IsPowerOfTwo(static_cast<uint64_t>(c)))
+            return false;
+        power = FloorLog2(c);
+        stk_.popBack();
+        return true;
+    }
+
     // TODO / OPTIMIZE (Bug 1316818): At the moment we use ReturnReg
     // for JoinReg.  It is possible other choices would lead to better
     // register allocation, as ReturnReg is often first in the
     // register set and will be heavily wanted by the register
     // allocator that uses takeFirst().
     //
     // Obvious options:
     //  - pick a register at the back of the register set
@@ -4177,131 +4208,235 @@ BaseCompiler::emitMultiplyF64()
     masm.mulDouble(r1, r0);
     freeF64(r1);
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitQuotientI32()
 {
-    // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
-
-    Label done;
-    checkDivideByZeroI32(r1, r0, &done);
-    checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
-    masm.quotient32(r1, r0, IsUnsigned(false));
-    masm.bind(&done);
-
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI32(c, power, 0)) {
+        if (power != 0) {
+            RegI32 r = popI32();
+            Label positive;
+            masm.branchTest32(Assembler::NotSigned, r, r, &positive);
+            masm.add32(Imm32(c-1), r);
+            masm.bind(&positive);
+
+            masm.rshift32Arithmetic(Imm32(power & 31), r);
+            pushI32(r);
+        }
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForIntMulDiv(&r0, &r1);
+
+        Label done;
+        checkDivideByZeroI32(r1, r0, &done);
+        checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
+        masm.quotient32(r1, r0, IsUnsigned(false));
+        masm.bind(&done);
+
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitQuotientU32()
 {
-    // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
-
-    Label done;
-    checkDivideByZeroI32(r1, r0, &done);
-    masm.quotient32(r1, r0, IsUnsigned(true));
-    masm.bind(&done);
-
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI32(c, power, 0)) {
+        if (power != 0) {
+            RegI32 r = popI32();
+            masm.rshift32(Imm32(power & 31), r);
+            pushI32(r);
+        }
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForIntMulDiv(&r0, &r1);
+
+        Label done;
+        checkDivideByZeroI32(r1, r0, &done);
+        masm.quotient32(r1, r0, IsUnsigned(true));
+        masm.bind(&done);
+
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitRemainderI32()
 {
-    // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
-
-    Label done;
-    checkDivideByZeroI32(r1, r0, &done);
-    checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
-    masm.remainder32(r1, r0, IsUnsigned(false));
-    masm.bind(&done);
-
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI32(c, power, 1)) {
+        RegI32 r = popI32();
+        RegI32 temp = needI32();
+        moveI32(r, temp);
+
+        Label positive;
+        masm.branchTest32(Assembler::NotSigned, temp, temp, &positive);
+        masm.add32(Imm32(c-1), temp);
+        masm.bind(&positive);
+
+        masm.rshift32Arithmetic(Imm32(power & 31), temp);
+        masm.lshift32(Imm32(power & 31), temp);
+        masm.sub32(temp, r);
+        freeI32(temp);
+
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForIntMulDiv(&r0, &r1);
+
+        Label done;
+        checkDivideByZeroI32(r1, r0, &done);
+        checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
+        masm.remainder32(r1, r0, IsUnsigned(false));
+        masm.bind(&done);
+
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitRemainderU32()
 {
-    // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
-
-    Label done;
-    checkDivideByZeroI32(r1, r0, &done);
-    masm.remainder32(r1, r0, IsUnsigned(true));
-    masm.bind(&done);
-
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI32(c, power, 1)) {
+        RegI32 r = popI32();
+        masm.and32(Imm32(c-1), r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForIntMulDiv(&r0, &r1);
+
+        Label done;
+        checkDivideByZeroI32(r1, r0, &done);
+        masm.remainder32(r1, r0, IsUnsigned(true));
+        masm.bind(&done);
+
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 #ifndef INT_DIV_I64_CALLOUT
 void
 BaseCompiler::emitQuotientI64()
 {
 # ifdef JS_PUNBOX64
-    RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
-    quotientI64(r1, r0, IsUnsigned(false));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI64(c, power, 0)) {
+        if (power != 0) {
+            RegI64 r = popI64();
+            Label positive;
+            masm.branchTest64(Assembler::NotSigned, r, r, Register::Invalid(),
+                              &positive);
+            masm.add64(Imm32(c-1), r);
+            masm.bind(&positive);
+
+            masm.rshift64Arithmetic(Imm32(power & 63), r);
+            pushI64(r);
+        }
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForIntDiv(&r0, &r1);
+        quotientI64(r1, r0, IsUnsigned(false));
+        freeI64(r1);
+        pushI64(r0);
+    }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientI64");
 # endif
 }
 
 void
 BaseCompiler::emitQuotientU64()
 {
 # ifdef JS_PUNBOX64
-    RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
-    quotientI64(r1, r0, IsUnsigned(true));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI64(c, power, 0)) {
+        if (power != 0) {
+            RegI64 r = popI64();
+            masm.rshift64(Imm32(power & 63), r);
+            pushI64(r);
+        }
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForIntDiv(&r0, &r1);
+        quotientI64(r1, r0, IsUnsigned(true));
+        freeI64(r1);
+        pushI64(r0);
+    }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientU64");
 # endif
 }
 
 void
 BaseCompiler::emitRemainderI64()
 {
 # ifdef JS_PUNBOX64
-    RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
-    remainderI64(r1, r0, IsUnsigned(false));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI64(c, power, 1)) {
+        RegI64 r = popI64();
+        RegI64 temp = needI64();
+        moveI64(r, temp);
+
+        Label positive;
+        masm.branchTest64(Assembler::NotSigned, temp, temp,
+                          Register::Invalid(), &positive);
+        masm.add64(Imm64(c-1), temp);
+        masm.bind(&positive);
+
+        masm.rshift64Arithmetic(Imm32(power & 63), temp);
+        masm.lshift64(Imm32(power & 63), temp);
+        masm.sub64(temp, r);
+        freeI64(temp);
+
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForIntDiv(&r0, &r1);
+        remainderI64(r1, r0, IsUnsigned(false));
+        freeI64(r1);
+        pushI64(r0);
+    }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderI64");
 # endif
 }
 
 void
 BaseCompiler::emitRemainderU64()
 {
 # ifdef JS_PUNBOX64
-    RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
-    remainderI64(r1, r0, IsUnsigned(true));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    uint_fast8_t power;
+    if (popConstPositivePowerOfTwoI64(c, power, 1)) {
+        RegI64 r = popI64();
+        masm.and64(Imm64(c-1), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForIntDiv(&r0, &r1);
+        remainderI64(r1, r0, IsUnsigned(true));
+        freeI64(r1);
+        pushI64(r0);
+    }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderU64");
 # endif
 }
 #endif // INT_DIV_I64_CALLOUT
 
 void
 BaseCompiler::emitDivideF32()
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -153,18 +153,16 @@ class FunctionCompiler
     const ValTypeVector&       locals_;
     size_t                     lastReadCallSite_;
 
     TempAllocator&             alloc_;
     MIRGraph&                  graph_;
     const CompileInfo&         info_;
     MIRGenerator&              mirGen_;
 
-    MInstruction*              dummyIns_;
-
     MBasicBlock*               curBlock_;
     CallCompileStateVector     callStack_;
     uint32_t                   maxStackArgBytes_;
 
     uint32_t                   loopDepth_;
     uint32_t                   blockDepth_;
     ControlFlowPatchsVector    blockPatches_;
 
@@ -181,17 +179,16 @@ class FunctionCompiler
         iter_(decoder, func.lineOrBytecode()),
         func_(func),
         locals_(locals),
         lastReadCallSite_(0),
         alloc_(mirGen.alloc()),
         graph_(mirGen.graph()),
         info_(mirGen.info()),
         mirGen_(mirGen),
-        dummyIns_(nullptr),
         curBlock_(nullptr),
         maxStackArgBytes_(0),
         loopDepth_(0),
         blockDepth_(0),
         tlsPointer_(nullptr)
     {}
 
     const ModuleEnvironment&   env() const   { return env_; }
@@ -273,19 +270,16 @@ class FunctionCompiler
             }
 
             curBlock_->add(ins);
             curBlock_->initSlot(info().localSlot(i), ins);
             if (!mirGen_.ensureBallast())
                 return false;
         }
 
-        dummyIns_ = MConstant::New(alloc(), Int32Value(0), MIRType::Int32);
-        curBlock_->add(dummyIns_);
-
         addInterruptCheck();
 
         return true;
     }
 
     void finish()
     {
         mirGen().initWasmMaxStackArgBytes(maxStackArgBytes_);
@@ -1157,55 +1151,23 @@ class FunctionCompiler
     {
         if (inDeadCode())
             return;
         MOZ_ASSERT(!hasPushed(curBlock_));
         if (def && def->type() != MIRType::None)
             curBlock_->push(def);
     }
 
-    MDefinition* popDefIfPushed(bool shouldReturn = true)
+    MDefinition* popDefIfPushed()
     {
         if (!hasPushed(curBlock_))
             return nullptr;
         MDefinition* def = curBlock_->pop();
-        MOZ_ASSERT_IF(def->type() == MIRType::Value, !shouldReturn);
-        return shouldReturn ? def : nullptr;
-    }
-
-    template <typename GetBlock>
-    bool ensurePushInvariants(const GetBlock& getBlock, size_t numBlocks)
-    {
-        // Preserve the invariant that, for every iterated MBasicBlock, either:
-        // every MBasicBlock has a pushed expression with the same type (to
-        // prevent creating used phis with type Value) OR no MBasicBlock has any
-        // pushed expression. This is required by MBasicBlock::addPredecessor.
-        if (numBlocks < 2)
-            return true;
-
-        MBasicBlock* block = getBlock(0);
-
-        bool allPushed = hasPushed(block);
-        if (allPushed) {
-            MIRType type = peekPushedDef(block)->type();
-            for (size_t i = 1; allPushed && i < numBlocks; i++) {
-                block = getBlock(i);
-                allPushed = hasPushed(block) && peekPushedDef(block)->type() == type;
-            }
-        }
-
-        if (!allPushed) {
-            for (size_t i = 0; i < numBlocks; i++) {
-                block = getBlock(i);
-                if (!hasPushed(block))
-                    block->push(dummyIns_);
-            }
-        }
-
-        return allPushed;
+        MOZ_ASSERT(def->type() != MIRType::Value);
+        return def;
     }
 
   private:
     void addJoinPredecessor(MDefinition* def, MBasicBlock** joinPred)
     {
         *joinPred = curBlock_;
         if (inDeadCode())
             return;
@@ -1265,34 +1227,31 @@ class FunctionCompiler
 
             mozilla::Array<MBasicBlock*, 2> blocks;
             size_t numJoinPreds = 0;
             if (thenJoinPred)
                 blocks[numJoinPreds++] = thenJoinPred;
             if (elseJoinPred)
                 blocks[numJoinPreds++] = elseJoinPred;
 
-            auto getBlock = [&](size_t i) -> MBasicBlock* { return blocks[i]; };
-            bool yieldsValue = ensurePushInvariants(getBlock, numJoinPreds);
-
             if (numJoinPreds == 0) {
                 *def = nullptr;
                 return true;
             }
 
             MBasicBlock* join;
             if (!goToNewBlock(blocks[0], &join))
                 return false;
             for (size_t i = 1; i < numJoinPreds; ++i) {
                 if (!goToExistingBlock(blocks[i], join))
                     return false;
             }
 
             curBlock_ = join;
-            *def = popDefIfPushed(yieldsValue);
+            *def = popDefIfPushed();
         }
 
         return true;
     }
 
     bool startBlock()
     {
         MOZ_ASSERT_IF(blockDepth_ < blockPatches_.length(), blockPatches_[blockDepth_].empty());
@@ -1586,28 +1545,20 @@ class FunctionCompiler
     bool bindBranches(uint32_t absolute, MDefinition** def)
     {
         if (absolute >= blockPatches_.length() || blockPatches_[absolute].empty()) {
             *def = inDeadCode() ? nullptr : popDefIfPushed();
             return true;
         }
 
         ControlFlowPatchVector& patches = blockPatches_[absolute];
-
-        auto getBlock = [&](size_t i) -> MBasicBlock* {
-            if (i < patches.length())
-                return patches[i].ins->block();
-            return curBlock_;
-        };
-
-        bool yieldsValue = ensurePushInvariants(getBlock, patches.length() + !!curBlock_);
+        MControlInstruction* ins = patches[0].ins;
+        MBasicBlock* pred = ins->block();
 
         MBasicBlock* join = nullptr;
-        MControlInstruction* ins = patches[0].ins;
-        MBasicBlock* pred = ins->block();
         if (!newBlock(pred, &join))
             return false;
 
         pred->mark();
         ins->replaceSuccessor(patches[0].index, join);
 
         for (size_t i = 1; i < patches.length(); i++) {
             ins = patches[i].ins;
@@ -1626,17 +1577,17 @@ class FunctionCompiler
         for (uint32_t i = 0; i < join->numPredecessors(); i++)
             join->getPredecessor(i)->unmark();
 
         if (curBlock_ && !goToExistingBlock(curBlock_, join))
             return false;
 
         curBlock_ = join;
 
-        *def = popDefIfPushed(yieldsValue);
+        *def = popDefIfPushed();
 
         patches.clear();
         return true;
     }
 };
 
 template <>
 MDefinition* FunctionCompiler::unary<MToFloat32>(MDefinition* op)
@@ -1825,33 +1776,45 @@ EmitBrTable(FunctionCompiler& f)
     MDefinition* index;
     if (!f.iter().readBrTable(&tableLength, &type, &value, &index))
         return false;
 
     Uint32Vector depths;
     if (!depths.reserve(tableLength))
         return false;
 
-    uint32_t depth;
     for (size_t i = 0; i < tableLength; ++i) {
+        uint32_t depth;
         if (!f.iter().readBrTableEntry(&type, &value, &depth))
             return false;
         depths.infallibleAppend(depth);
     }
 
     // Read the default label.
-    if (!f.iter().readBrTableDefault(&type, &value, &depth))
+    uint32_t defaultDepth;
+    if (!f.iter().readBrTableDefault(&type, &value, &defaultDepth))
         return false;
 
     MDefinition* maybeValue = IsVoid(type) ? nullptr : value;
 
-    if (tableLength == 0)
-        return f.br(depth, maybeValue);
-
-    return f.brTable(index, depth, depths, maybeValue);
+    // If all the targets are the same, or there are no targets, we can just
+    // use a goto. This is not just an optimization: MaybeFoldConditionBlock
+    // assumes that tables have more than one successor.
+    bool allSameDepth = true;
+    for (uint32_t depth : depths) {
+        if (depth != defaultDepth) {
+            allSameDepth = false;
+            break;
+        }
+    }
+
+    if (allSameDepth)
+        return f.br(defaultDepth, maybeValue);
+
+    return f.brTable(index, defaultDepth, depths, maybeValue);
 }
 
 static bool
 EmitReturn(FunctionCompiler& f)
 {
     MDefinition* value;
     if (!f.iter().readReturn(&value))
         return false;
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -73,17 +73,17 @@ load 321058-2.xul
 load 321077-1.xul
 load 321077-2.xul
 load 322436-1.html
 load 325967-1.html
 load 325984-1.xhtml
 load 325984-2.html
 load 328944-1.xul
 load 329900-1.html
-skip-if(stylo) load 330015-1.html # bug 1323678
+load 330015-1.html
 load 331204-1.html
 load 331679-1.xhtml
 load 331679-2.xml
 load 331679-3.xml
 asserts-if(stylo,186) load 331883-1.html # bug 1324673
 load 335140-1.html
 load 336291-1.html
 load 336999-1.xul
@@ -177,17 +177,17 @@ load 386476.html
 load 387195-1.html
 load 387195-2.xhtml
 load 388715-1.html
 skip-if(stylo) load 390976-1.html # bug 1323649
 load 393326-1.html
 load 393326-2.html
 load 393661-1.html
 load 393801-1.html
-skip-if(stylo) load 394014-1.html # bug 1323678
+load 394014-1.html
 load 394014-2.html
 load 394150-1.xhtml
 load 397011-1.xhtml
 load 398510-1.xhtml
 load 398733-1.html
 load 398733-2.html
 asserts-if(stylo,4) load 399132-1.xhtml # bug 1324663
 load 399219-1.xhtml
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -15,16 +15,17 @@ with Files('nsChangeHint.h'):
 
 with Files('nsBidi*'):
     BUG_COMPONENT = ('Core', 'Layout: Text')
 
 with Files('AccessibleCaret*'):
     BUG_COMPONENT = ('Core', 'Selection')
 
 XPIDL_SOURCES += [
+    'nsIPreloadedStyleSheet.idl',
     'nsIStyleSheetService.idl',
 ]
 
 if CONFIG['MOZ_DEBUG']:
     UNIFIED_SOURCES += [
         'nsAutoLayoutPhase.cpp',
     ]
 
new file mode 100644
--- /dev/null
+++ b/layout/base/nsIPreloadedStyleSheet.idl
@@ -0,0 +1,16 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/**
+ * The nsIPreloadedStyleSheet interface is an opaque interface for
+ * style sheets returned by nsIStyleSheetService.preloadSheet, and
+ * which can be passed to nsIDOMWindowUtils.addSheet.
+ */
+[scriptable, builtinclass, uuid(2e2a84d0-2102-4b9e-9b78-1670623a582d)]
+interface nsIPreloadedStyleSheet : nsISupports
+{
+};
--- a/layout/base/nsIStyleSheetService.idl
+++ b/layout/base/nsIStyleSheetService.idl
@@ -2,18 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* interface for managing user and user-agent style sheets */
 
 #include "nsISupports.idl"
 
+interface nsIPreloadedStyleSheet;
 interface nsIURI;
-interface nsIDOMStyleSheet;
 
 /*
  * nsIStyleSheetService allows extensions or embeddors to add to the
  * built-in list of user or agent style sheets.
  */
 
 [scriptable, uuid(4de68896-e8eb-41de-8237-a797b570ac4a)]
 interface nsIStyleSheetService : nsISupports
@@ -46,17 +46,18 @@ interface nsIStyleSheetService : nsISupp
    * added to the list of style sheets specified by |type|.
    */
   boolean sheetRegistered(in nsIURI sheetURI, in unsigned long type);
 
   /**
    * Synchronously loads a style sheet from |sheetURI| and returns the
    * new style sheet object. Can be used with nsIDOMWindowUtils.addSheet.
    */
-  nsIDOMStyleSheet preloadSheet(in nsIURI sheetURI, in unsigned long type);
+  nsIPreloadedStyleSheet preloadSheet(in nsIURI sheetURI,
+                                      in unsigned long type);
 
   /**
    * Remove the style sheet at |sheetURI| from the list of style sheets
    * specified by |type|.  The removal takes effect immediately, even for
    * already-loaded documents.
    */
   void unregisterSheet(in nsIURI sheetURI, in unsigned long type);
 };
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* implementation of interface for managing user and user-agent style sheets */
 
 #include "nsStyleSheetService.h"
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/PreloadedStyleSheet.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/Unused.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
@@ -257,21 +258,24 @@ nsStyleSheetService::SheetRegistered(nsI
   NS_PRECONDITION(_retval, "Null out param");
 
   *_retval = (FindSheetByURI(mSheets[aSheetType], sheetURI) >= 0);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsStyleSheetService::PreloadSheet(nsIURI *aSheetURI, uint32_t aSheetType,
-                                  nsIDOMStyleSheet **aSheet)
+nsStyleSheetService::PreloadSheet(nsIURI* aSheetURI, uint32_t aSheetType,
+                                  nsIPreloadedStyleSheet** aSheet)
 {
   NS_PRECONDITION(aSheet, "Null out param");
   NS_ENSURE_ARG_POINTER(aSheetURI);
+
+  *aSheet = nullptr;
+
   css::SheetParsingMode parsingMode;
   switch (aSheetType) {
     case AGENT_SHEET:
       parsingMode = css::eAgentSheetFeatures;
       break;
 
     case USER_SHEET:
       parsingMode = css::eUserSheetFeatures;
@@ -281,31 +285,22 @@ nsStyleSheetService::PreloadSheet(nsIURI
       parsingMode = css::eAuthorSheetFeatures;
       break;
 
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
-  // XXXheycam PreloadSheet can't support ServoStyleSheets until they implement
-  // nsIDOMStyleSheet.
-
-  RefPtr<css::Loader> loader = new css::Loader(StyleBackendType::Gecko);
-
-  RefPtr<StyleSheet> sheet;
-  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
+  RefPtr<PreloadedStyleSheet> sheet;
+  nsresult rv = PreloadedStyleSheet::Create(aSheetURI, parsingMode,
+                                            getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  MOZ_ASSERT(sheet->IsGecko(),
-             "stylo: didn't expect Loader to create a ServoStyleSheet");
-
-  RefPtr<CSSStyleSheet> cssSheet = sheet->AsGecko();
-  cssSheet.forget(aSheet);
-
+  sheet.forget(aSheet);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -2205,17 +2205,17 @@ nsImageFrame::LoadIcon(const nsAString& 
   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
   nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
 
   return il->LoadImage(realURI,     /* icon URI */
                        nullptr,      /* initial document URI; this is only
                                        relevant for cookies, so does not
                                        apply to icons. */
                        nullptr,      /* referrer (not relevant for icons) */
-                       mozilla::net::RP_Default,
+                       mozilla::net::RP_Unset,
                        nullptr,      /* principal (not relevant for icons) */
                        loadGroup,
                        gIconLoad,
                        nullptr,      /* No context */
                        nullptr,      /* Not associated with any particular document */
                        loadFlags,
                        nullptr,
                        contentPolicyType,
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -367,17 +367,17 @@ public:
    * not-yet-loaded sheet.
    */
   nsresult LoadSheet(nsIURI* aURL,
                      bool aIsPreload,
                      nsIPrincipal* aOriginPrincipal,
                      const nsCString& aCharset,
                      nsICSSLoaderObserver* aObserver,
                      CORSMode aCORSMode = CORS_NONE,
-                     ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Default,
+                     ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
                      const nsAString& aIntegrity = EmptyString());
 
   /**
    * Stop loading all sheets.  All nsICSSLoaderObservers involved will be
    * notified with NS_BINDING_ABORTED as the status, possibly synchronously.
    */
   nsresult Stop(void);
 
@@ -495,17 +495,17 @@ private:
                                         bool aIsPreload,
                                         SheetParsingMode aParsingMode,
                                         bool aUseSystemPrincipal,
                                         nsIPrincipal* aOriginPrincipal,
                                         const nsCString& aCharset,
                                         RefPtr<StyleSheet>* aSheet,
                                         nsICSSLoaderObserver* aObserver,
                                         CORSMode aCORSMode = CORS_NONE,
-                                        ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Default,
+                                        ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Unset,
                                         const nsAString& aIntegrity = EmptyString());
 
   // Post a load event for aObserver to be notified about aSheet.  The
   // notification will be sent with status NS_OK unless the load event is
   // canceled at some point (in which case it will be sent with
   // NS_BINDING_ABORTED).  aWasAlternate indicates the state when the load was
   // initiated, not the state at some later time.  aURI should be the URI the
   // sheet was loaded from (may be null for inline sheets).  aElement is the
new file mode 100644
--- /dev/null
+++ b/layout/style/PreloadedStyleSheet.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=2:expandtab:shiftwidth=2:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* a CSS style sheet returned from nsIStyleSheetService.preloadSheet */
+
+#include "PreloadedStyleSheet.h"
+
+namespace mozilla {
+
+PreloadedStyleSheet::PreloadedStyleSheet(nsIURI* aURI,
+                                         css::SheetParsingMode aParsingMode)
+  : mURI(aURI)
+  , mParsingMode(aParsingMode)
+{
+}
+
+/* static */ nsresult
+PreloadedStyleSheet::Create(nsIURI* aURI,
+                            css::SheetParsingMode aParsingMode,
+                            PreloadedStyleSheet** aResult)
+{
+  *aResult = nullptr;
+
+  // The nsIStyleSheetService.preloadSheet API doesn't tell us which backend
+  // the sheet will be used with, and it seems wasteful to eagerly create
+  // both a CSSStyleSheet and a ServoStyleSheet.  So instead, we guess that
+  // the sheet type we will want matches the current value of the stylo pref,
+  // and preload a sheet of that type.
+  //
+  // If we guess wrong, we will re-load the sheet later with the requested type,
+  // and we won't really have front loaded the loading time as the name
+  // "preload" might suggest.  Also, in theory we could get different data from
+  // fetching the URL again, but for the usage patterns of this API this is
+  // unlikely, and it doesn't seem worth trying to store the contents of the URL
+  // and duplicating a bunch of css::Loader's logic.
+
+  RefPtr<PreloadedStyleSheet> preloadedSheet =
+    new PreloadedStyleSheet(aURI, aParsingMode);
+  auto type = nsLayoutUtils::StyloEnabled() ? StyleBackendType::Servo
+                                            : StyleBackendType::Gecko;
+  StyleSheet* sheet;
+  nsresult rv = preloadedSheet->GetSheet(type, &sheet);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  preloadedSheet.forget(aResult);
+  return NS_OK;
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PreloadedStyleSheet)
+  NS_INTERFACE_MAP_ENTRY(nsIPreloadedStyleSheet)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PreloadedStyleSheet)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PreloadedStyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION(PreloadedStyleSheet, mGecko, mServo)
+
+nsresult
+PreloadedStyleSheet::GetSheet(StyleBackendType aType, StyleSheet** aResult)
+{
+  *aResult = nullptr;
+
+  RefPtr<StyleSheet>& sheet =
+    aType == StyleBackendType::Gecko ? mGecko : mServo;
+
+  if (!sheet) {
+    RefPtr<css::Loader> loader = new css::Loader(aType);
+    nsresult rv = loader->LoadSheetSync(mURI, mParsingMode, true, &sheet);
+    NS_ENSURE_SUCCESS(rv, rv);
+    MOZ_ASSERT(sheet);
+  }
+
+  *aResult = sheet;
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/PreloadedStyleSheet.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:tabstop=2:expandtab:shiftwidth=2:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* a CSS style sheet returned from nsIStyleSheetService.preloadSheet */
+
+#ifndef mozilla_PreloadedStyleSheet_h
+#define mozilla_PreloadedStyleSheet_h
+
+#include "mozilla/css/SheetParsingMode.h"
+#include "mozilla/Result.h"
+#include "nsIPreloadedStyleSheet.h"
+
+namespace mozilla {
+
+class PreloadedStyleSheet : public nsIPreloadedStyleSheet
+{
+public:
+  // *aResult is addrefed.
+  static nsresult Create(nsIURI* aURI, css::SheetParsingMode aParsingMode,
+                         PreloadedStyleSheet** aResult);
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(PreloadedStyleSheet)
+
+  // *aResult is not addrefed, since the PreloadedStyleSheet holds a strong
+  // reference to the sheet.
+  nsresult GetSheet(StyleBackendType aType, StyleSheet** aResult);
+
+protected:
+  virtual ~PreloadedStyleSheet() {}
+
+private:
+  PreloadedStyleSheet(nsIURI* aURI, css::SheetParsingMode aParsingMode);
+
+  RefPtr<StyleSheet> mGecko;
+  RefPtr<StyleSheet> mServo;
+
+  nsCOMPtr<nsIURI> mURI;
+  css::SheetParsingMode mParsingMode;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_PreloadedStyleSheet_h
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -274,25 +274,33 @@ Gecko_CalcStyleDifference(nsStyleContext
                                           &samePointerStructs);
 
   return result;
 }
 
 ServoElementSnapshotOwned
 Gecko_CreateElementSnapshot(RawGeckoElementBorrowed aElement)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return new ServoElementSnapshot(aElement);
 }
 
 void
 Gecko_DropElementSnapshot(ServoElementSnapshotOwned aSnapshot)
 {
-  MOZ_ASSERT(NS_IsMainThread(),
-             "ServoAttrSnapshots can only be dropped on the main thread");
-  delete aSnapshot;
+  // Proxy deletes have a lot of overhead, so Servo tries hard to only drop
+  // snapshots on the main thread. However, there are certain cases where
+  // it's unavoidable (i.e. synchronously dropping the style data for the
+  // descendants of a new display:none root).
+  if (MOZ_UNLIKELY(!NS_IsMainThread())) {
+    nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() { delete aSnapshot; });
+    NS_DispatchToMainThread(task.forget());
+  } else {
+    delete aSnapshot;
+  }
 }
 
 RawServoDeclarationBlockStrongBorrowedOrNull
 Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
 {
   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::style);
   if (!attr || attr->Type() != nsAttrValue::eCSSDeclaration) {
     return nullptr;
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -565,10 +565,10 @@ ServoStyleSet::RestyleWithAddedDeclarati
                                            aPreviousStyle);
 }
 
 
 already_AddRefed<ServoComputedValues>
 ServoStyleSet::ResolveServoStyle(Element* aElement,
                                  ConsumeStyleBehavior aConsume)
 {
-  return Servo_ResolveStyle(aElement, mRawSet.get(), aConsume).Consume();  
+  return Servo_ResolveStyle(aElement, mRawSet.get(), aConsume).Consume();
 }
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Utilities for animation of computed style values */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "mozilla/StyleAnimationValue.h"
+#include "mozilla/StyleSetHandle.h"
+#include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/UniquePtr.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsIStyleRule.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsString.h"
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -87,16 +87,17 @@ EXPORTS.mozilla += [
     'CSSVariableResolver.h',
     'CSSVariableValues.h',
     'DeclarationBlock.h',
     'DeclarationBlockInlines.h',
     'DocumentStyleRootIterator.h',
     'HandleRefPtr.h',
     'IncrementalClearCOMRuleArray.h',
     'LayerAnimationInfo.h',
+    'PreloadedStyleSheet.h',
     'RuleNodeCacheConditions.h',
     'RuleProcessorCache.h',
     'ServoArcTypeList.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
     'ServoCSSRuleList.h',
     'ServoDeclarationBlock.h',
@@ -192,16 +193,17 @@ UNIFIED_SOURCES += [
     'nsRuleNode.cpp',
     'nsStyleContext.cpp',
     'nsStyleCoord.cpp',
     'nsStyleSet.cpp',
     'nsStyleStruct.cpp',
     'nsStyleTransformMatrix.cpp',
     'nsStyleUtil.cpp',
     'nsTransitionManager.cpp',
+    'PreloadedStyleSheet.cpp',
     'RuleNodeCacheConditions.cpp',
     'RuleProcessorCache.cpp',
     'ServoBindings.cpp',
     'ServoCSSRuleList.cpp',
     'ServoDeclarationBlock.cpp',
     'ServoElementSnapshot.cpp',
     'ServoStyleRule.cpp',
     'ServoStyleSet.cpp',
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -864,20 +864,20 @@ nsLayoutStylesheetCache::InvalidatePrefe
 }
 
 void
 nsLayoutStylesheetCache::BuildPreferenceSheet(RefPtr<StyleSheet>* aSheet,
                                               nsPresContext* aPresContext)
 {
   if (mBackendType == StyleBackendType::Gecko) {
     *aSheet = new CSSStyleSheet(eAgentSheetFeatures, CORS_NONE,
-                                mozilla::net::RP_Default);
+                                mozilla::net::RP_Unset);
   } else {
     *aSheet = new ServoStyleSheet(eAgentSheetFeatures, CORS_NONE,
-                                  mozilla::net::RP_Default, dom::SRIMetadata());
+                                  mozilla::net::RP_Unset, dom::SRIMetadata());
   }
 
   StyleSheet* sheet = *aSheet;
 
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nullptr);
   MOZ_ASSERT(uri, "URI creation shouldn't fail");
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1456,16 +1456,19 @@ pref("network.http.request.max-start-del
 pref("network.http.request.max-attempts", 10);
 
 // Headers
 pref("network.http.accept.default", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
 
 // Prefs allowing granular control of referers
 // 0=don't send any, 1=send only on clicks, 2=send on image requests as well
 pref("network.http.sendRefererHeader",      2);
+// 0=no referrer, 1=same origin, 2=strict-origin-when-cross-origin,
+// 3=no-referre-when-downgrade(default)
+pref("network.http.referer.userControlPolicy", 3);
 // false=real referer, true=spoof referer (use target URI as referer)
 pref("network.http.referer.spoofSource", false);
 // 0=full URI, 1=scheme+host+port+path, 2=scheme+host+port
 pref("network.http.referer.trimmingPolicy", 0);
 // 0=full URI, 1=scheme+host+port+path, 2=scheme+host+port
 pref("network.http.referer.XOriginTrimmingPolicy", 0);
 // 0=always send, 1=send iff base domains match, 2=send iff hosts match
 pref("network.http.referer.XOriginPolicy", 0);
--- a/netwerk/base/ReferrerPolicy.h
+++ b/netwerk/base/ReferrerPolicy.h
@@ -15,17 +15,16 @@ enum ReferrerPolicy {
   /* spec tokens: never no-referrer */
   RP_No_Referrer                 = nsIHttpChannel::REFERRER_POLICY_NO_REFERRER,
 
   /* spec tokens: origin */
   RP_Origin                      = nsIHttpChannel::REFERRER_POLICY_ORIGIN,
 
   /* spec tokens: default no-referrer-when-downgrade */
   RP_No_Referrer_When_Downgrade  = nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE,
-  RP_Default                     = nsIHttpChannel::REFERRER_POLICY_DEFAULT,
 
   /* spec tokens: origin-when-cross-origin */
   RP_Origin_When_Crossorigin     = nsIHttpChannel::REFERRER_POLICY_ORIGIN_WHEN_XORIGIN,
 
   /* spec tokens: always unsafe-url */
   RP_Unsafe_URL                  = nsIHttpChannel::REFERRER_POLICY_UNSAFE_URL,
 
   /* spec tokens: same-origin */
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -75,16 +75,20 @@
 #include "nsThreadUtils.h" // for NS_IsMainThread
 #endif
 
 #include <limits>
 
 using namespace mozilla;
 using namespace mozilla::net;
 
+#define DEFAULT_USER_CONTROL_RP 3
+
+static uint32_t sUserControlRp = DEFAULT_USER_CONTROL_RP;
+
 nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
 NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
                                      nsIURI                *aUri,
                                      nsINode               *aLoadingNode,
                                      nsIPrincipal          *aTriggeringPrincipal,
                                      nsSecurityFlags        aSecurityFlags,
                                      nsContentPolicyType    aContentPolicyType,
                                      nsILoadGroup          *aLoadGroup /* = nullptr */,
@@ -2365,16 +2369,40 @@ NS_CompareLoadInfoAndLoadContext(nsIChan
   MOZ_ASSERT(originAttrsLoadInfo.mPrivateBrowsingId ==
              originAttrsLoadContext.mPrivateBrowsingId,
              "The value of mPrivateBrowsingId in the loadContext and in the "
              "loadInfo are not the same!");
 
   return NS_OK;
 }
 
+uint32_t
+NS_GetDefaultReferrerPolicy()
+{
+  static bool preferencesInitialized = false;
+
+  if (!preferencesInitialized) {
+    mozilla::Preferences::AddUintVarCache(&sUserControlRp,
+                                          "network.http.referer.userControlPolicy",
+                                          DEFAULT_USER_CONTROL_RP);
+    preferencesInitialized = true;
+  }
+
+  switch (sUserControlRp) {
+    case 0:
+      return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER;
+    case 1:
+      return nsIHttpChannel::REFERRER_POLICY_SAME_ORIGIN;
+    case 2:
+      return nsIHttpChannel::REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN;
+  }
+
+  return nsIHttpChannel::REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE;
+}
+
 namespace mozilla {
 namespace net {
 
 bool
 InScriptableRange(int64_t val)
 {
     return (val <= kJS_MAX_SAFE_INTEGER) && (val >= kJS_MIN_SAFE_INTEGER);
 }
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -958,16 +958,22 @@ nsresult NS_ShouldSecureUpgrade(nsIURI* 
 
 /**
  * Returns an https URI for channels that need to go through secure upgrades.
  */
 nsresult NS_GetSecureUpgradedURI(nsIURI* aURI, nsIURI** aUpgradedURI);
 
 nsresult NS_CompareLoadInfoAndLoadContext(nsIChannel *aChannel);
 
+/**
+ * Return default referrer policy which is controlled by user
+ * pref network.http.referer.userControlPolicy
+ */
+uint32_t NS_GetDefaultReferrerPolicy();
+
 namespace mozilla {
 namespace net {
 
 const static uint64_t kJS_MAX_SAFE_UINTEGER = +9007199254740991ULL;
 const static  int64_t kJS_MIN_SAFE_INTEGER  = -9007199254740991LL;
 const static  int64_t kJS_MAX_SAFE_INTEGER  = +9007199254740991LL;
 
 // Make sure a 64bit value can be captured by JS MAX_SAFE_INTEGER
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -97,17 +97,17 @@ HttpBaseChannel::HttpBaseChannel()
   , mBlockAuthPrompt(false)
   , mAllowStaleCacheContent(false)
   , mSuspendCount(0)
   , mInitialRwin(0)
   , mProxyResolveFlags(0)
   , mProxyURI(nullptr)
   , mContentDispositionHint(UINT32_MAX)
   , mHttpHandler(gHttpHandler)
-  , mReferrerPolicy(REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE)
+  , mReferrerPolicy(NS_GetDefaultReferrerPolicy())
   , mRedirectCount(0)
   , mForcePending(false)
   , mCorsIncludeCredentials(false)
   , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS)
   , mRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW)
   , mFetchCacheMode(nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT)
   , mOnStartRequestCalled(false)
   , mOnStopRequestCalled(false)
@@ -1299,17 +1299,17 @@ HttpBaseChannel::GetReferrer(nsIURI **re
   *referrer = mReferrer;
   NS_IF_ADDREF(*referrer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::SetReferrer(nsIURI *referrer)
 {
-  return SetReferrerWithPolicy(referrer, REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE);
+  return SetReferrerWithPolicy(referrer, NS_GetDefaultReferrerPolicy());
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetReferrerPolicy(uint32_t *referrerPolicy)
 {
   NS_ENSURE_ARG_POINTER(referrerPolicy);
   *referrerPolicy = mReferrerPolicy;
   return NS_OK;
@@ -1324,16 +1324,20 @@ HttpBaseChannel::SetReferrerWithPolicy(n
   // clear existing referrer, if any
   mReferrer = nullptr;
   nsresult rv = mRequestHead.ClearHeader(nsHttp::Referer);
   if(NS_FAILED(rv)) {
     return rv;
   }
   mReferrerPolicy = referrerPolicy;
 
+  if (referrerPolicy == REFERRER_POLICY_UNSET) {
+    mReferrerPolicy = NS_GetDefaultReferrerPolicy();
+  }
+
   if (!referrer) {
     return NS_OK;
   }
 
   // Don't send referrer at all when the meta referrer setting is "no-referrer"
   if (referrerPolicy == REFERRER_POLICY_NO_REFERRER) {
     return NS_OK;
   }
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1710,17 +1710,17 @@ HttpChannelChild::CompleteRedirectSetup(
 
 NS_IMETHODIMP
 HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
 {
   LOG(("HttpChannelChild::OnRedirectVerifyCallback [this=%p]\n", this));
   nsresult rv;
   OptionalURIParams redirectURI;
 
-  uint32_t referrerPolicy = REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE;
+  uint32_t referrerPolicy = REFERRER_POLICY_UNSET;
   OptionalURIParams referrerURI;
   SerializeURI(nullptr, referrerURI);
 
   nsCOMPtr<nsIHttpChannel> newHttpChannel =
       do_QueryInterface(mRedirectChannelChild);
 
   if (NS_SUCCEEDED(result) && !mRedirectChannelChild) {
     // mRedirectChannelChild doesn't exist means we're redirecting to a protocol
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -61,18 +61,16 @@ interface nsIHttpChannel : nsIChannel
      * Referrer policies. See ReferrerPolicy.h for more details.
      */
 
 
     /*   The undefined state, or no referrer policy, usually causing a fallback
          to a referrer policy definded elsewhere */
     const unsigned long REFERRER_POLICY_UNSET                      = 0;
 
-    /*   default state, a shorter name for no-referrer-when-downgrade   */
-    const unsigned long REFERRER_POLICY_DEFAULT                    = 1;
     /*   default state, doesn't send referrer from https->http          */
     const unsigned long REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE = 1;
     /*   sends no referrer                                              */
     const unsigned long REFERRER_POLICY_NO_REFERRER                = 2;
     /*   only sends the origin of the referring URL                     */
     const unsigned long REFERRER_POLICY_ORIGIN                     = 3;
     /*   same as default, but reduced to ORIGIN when cross-origin.      */
     const unsigned long REFERRER_POLICY_ORIGIN_WHEN_XORIGIN        = 4;
--- a/netwerk/test/unit/test_referrer.js
+++ b/netwerk/test/unit/test_referrer.js
@@ -42,16 +42,32 @@ function run_test() {
   prefs.setIntPref("network.http.sendRefererHeader", 0);
   do_check_null(getTestReferrer(server_uri, referer_uri));
   prefs.setIntPref("network.http.sendRefererHeader", 2);
   do_check_eq(getTestReferrer(server_uri, referer_uri), referer_uri);
 
   // test that https ref is not sent to http
   do_check_null(getTestReferrer(server_uri_2, referer_uri_https));
 
+  // tests for referer.userControlPolicy
+  prefs.setIntPref("network.http.referer.userControlPolicy", 0);
+  do_check_null(getTestReferrer(server_uri, referer_uri));
+  prefs.setIntPref("network.http.referer.userControlPolicy", 1);
+  do_check_null(getTestReferrer(server_uri, referer_uri));
+  do_check_eq(getTestReferrer(server_uri, referer_uri_2), referer_uri_2);
+  prefs.setIntPref("network.http.referer.userControlPolicy", 2);
+  do_check_null(getTestReferrer(server_uri, referer_uri_https));
+  do_check_eq(getTestReferrer(server_uri_https, referer_uri_https), referer_uri_https);
+  do_check_eq(getTestReferrer(server_uri_https, referer_uri_2_https), "https://bar.examplesite.com/");
+  do_check_eq(getTestReferrer(server_uri, referer_uri_2), referer_uri_2);
+  do_check_eq(getTestReferrer(server_uri, referer_uri), "http://foo.example.com/");
+  prefs.setIntPref("network.http.referer.userControlPolicy", 3);
+  do_check_eq(getTestReferrer(server_uri, referer_uri), referer_uri);
+  do_check_null(getTestReferrer(server_uri_2, referer_uri_https));
+
   // tests for referer.spoofSource
   prefs.setBoolPref("network.http.referer.spoofSource", true);
   do_check_eq(getTestReferrer(server_uri, referer_uri), server_uri);
   prefs.setBoolPref("network.http.referer.spoofSource", false);
   do_check_eq(getTestReferrer(server_uri, referer_uri), referer_uri);
 
   // tests for referer.XOriginPolicy
   prefs.setIntPref("network.http.referer.XOriginPolicy", 2);
--- a/netwerk/test/unit/test_referrer_policy.js
+++ b/netwerk/test/unit/test_referrer_policy.js
@@ -24,29 +24,29 @@ function test_policy(test) {
     do_check_eq(header, test.expectedReferrerSpec);
     do_check_eq(chan.referrer.asciiSpec, test.expectedReferrerSpec);
   }
 }
 
 const nsIHttpChannel = Ci.nsIHttpChannel;
 var gTests = [
   {
-    policy: nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+    policy: nsIHttpChannel.REFERRER_POLICY_UNSET,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
     expectedReferrerSpec: "https://test.example/referrer"
   },
   {
-    policy: nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+    policy: nsIHttpChannel.REFERRER_POLICY_UNSET,
     url: "https://sub1.\xe4lt.example/foo",
     referrer: "https://sub1.\xe4lt.example/referrer",
     expectedReferrerSpec: "https://sub1.xn--lt-uia.example/referrer"
   },
   {
-    policy: nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+    policy: nsIHttpChannel.REFERRER_POLICY_UNSET,
     url: "http://test.example/foo",
     referrer: "https://test.example/referrer",
     expectedReferrerSpec: undefined
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_NO_REFERRER,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -61,17 +61,17 @@ class nsHtml5ExecutorReflusher : public 
 };
 
 static mozilla::LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
 static nsITimer* gFlushTimer = nullptr;
 
 nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
   : nsHtml5DocumentBuilder(false)
   , mPreloadedURLs(23)  // Mean # of preloadable resources per page on dmoz
-  , mSpeculationReferrerPolicy(mozilla::net::RP_Default)
+  , mSpeculationReferrerPolicy(mozilla::net::RP_Unset)
 {
   // zeroing operator new for everything else
 }
 
 nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor()
 {
   if (gBackgroundFlushList && isInList()) {
     mOpQueue.Clear();
@@ -1053,17 +1053,17 @@ nsHtml5TreeOpExecutor::AddSpeculationCSP
   // to be joined together.
   rv = preloadCsp->AppendPolicy(aCSP,
                                 false, // csp via meta tag can not be report only
                                 true); // delivered through the meta tag
   NS_ENSURE_SUCCESS_VOID(rv);
 
   // Record "speculated" referrer policy for preloads
   bool hasReferrerPolicy = false;
-  uint32_t referrerPolicy = mozilla::net::RP_Default;
+  uint32_t referrerPolicy = mozilla::net::RP_Unset;
   rv = preloadCsp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (hasReferrerPolicy) {
     SetSpeculationReferrerPolicy(static_cast<ReferrerPolicy>(referrerPolicy));
   }
 
   mDocument->ApplySettingsFromCSP(true);
 }
--- a/taskcluster/ci/toolchain/kind.yml
+++ b/taskcluster/ci/toolchain/kind.yml
@@ -6,9 +6,10 @@ implementation: taskgraph.task.transform
 
 transforms:
    - taskgraph.transforms.build_attrs:transforms
    - taskgraph.transforms.job:transforms
    - taskgraph.transforms.task:transforms
 
 jobs-from:
    - linux.yml
+   - macosx.yml
    - windows.yml
--- a/taskcluster/ci/toolchain/linux.yml
+++ b/taskcluster/ci/toolchain/linux.yml
@@ -7,27 +7,54 @@ linux64-clang/opt:
     treeherder:
         kind: build
         platform: linux64/opt
         symbol: Cc(Clang)
         tier: 1
     run:
         using: toolchain-script
         script: build-clang-linux.sh
+        tooltool-downloads: public
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         implementation: docker-worker
         docker-image: {in-tree: desktop-build}
         max-run-time: 36000
     when:
         files-changed:
             - 'build/build-clang/**'
             - 'taskcluster/scripts/misc/build-clang-linux.sh'
             - 'taskcluster/taskgraph/transforms/job/toolchain.py'
 
+linux64-clang-tidy/opt:
+    description: "Clang-tidy build"
+    index:
+        product: static-analysis
+        job-name: linux64-clang-tidy
+    treeherder:
+        kind: build
+        platform: linux64/opt
+        symbol: Cc(Clang-Tidy)
+        tier: 1
+    run:
+        using: toolchain-script
+        script: build-clang-tidy-linux.sh
+        tooltool-downloads: public
+    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
+    worker:
+        implementation: docker-worker
+        docker-image: {in-tree: desktop-build}
+        max-run-time: 36000
+    when:
+        files-changed:
+            - 'build/clang-plugin/**'
+            - 'build/build-clang/**'
+            - 'taskcluster/scripts/misc/build-clang-tidy-linux.sh'
+            - 'taskcluster/taskgraph/transforms/job/toolchain.py'
+
 linux64-gcc/opt:
     description: "GCC toolchain build"
     treeherder:
         kind: build
         platform: linux64/opt
         symbol: Cc(GCC)
         tier: 1
     run:
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/toolchain/macosx.yml
@@ -0,0 +1,30 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+macosx64-clang-tidy/opt:
+    description: "Clang-tidy build"
+    index:
+        product: static-analysis
+        job-name: macosx64-clang-tidy
+    treeherder:
+        kind: build
+        platform: osx-10-10/opt
+        symbol: Cc(Clang-Tidy)
+        tier: 1
+    run:
+        using: toolchain-script
+        script: build-clang-tidy-macosx.sh
+        tooltool-downloads: internal
+    worker-type: aws-provisioner-v1/gecko-{level}-b-macosx64
+    worker:
+        implementation: docker-worker
+        docker-image: {in-tree: desktop-build}
+        max-run-time: 36000
+    when:
+        files-changed:
+            - 'build/clang-plugin/**'
+            - 'build/build-clang/**'
+            - 'taskcluster/scripts/misc/build-clang-tidy-macosx.sh'
+            - 'taskcluster/taskgraph/transforms/job/toolchain.py'
+
--- a/taskcluster/ci/toolchain/windows.yml
+++ b/taskcluster/ci/toolchain/windows.yml
@@ -39,16 +39,19 @@ win64-clang-cl/opt:
     when:
         files-changed:
             - 'build/build-clang/**'
             - 'taskcluster/scripts/misc/build-clang64-windows.sh'
             - 'taskcluster/taskgraph/transforms/job/toolchain.py'
 
 win32-clang-tidy/opt:
     description: "Clang-tidy toolchain build"
+    index:
+        product: static-analysis
+        job-name: win32-clang-tidy
     treeherder:
         kind: build
         platform: windows-2012-32/opt
         symbol: Cc(Clang-Tidy)
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-win2012
     worker:
         implementation: generic-worker
@@ -59,16 +62,19 @@ win32-clang-tidy/opt:
     when:
         files-changed:
             - 'build/build-clang/**'
             - 'taskcluster/scripts/misc/build-clang-tidy32-windows.sh'
             - 'taskcluster/taskgraph/transforms/job/toolchain.py'
 
 win64-clang-tidy/opt:
     description: "Clang-tidy toolchain build"
+    index:
+        product: static-analysis
+        job-name: win64-clang-tidy
     treeherder:
         kind: build
         platform: windows-2012-64/opt
         symbol: Cc(Clang-Tidy)
         tier: 2
     worker-type: aws-provisioner-v1/gecko-{level}-b-win2012
     worker:
         implementation: generic-worker
--- a/taskcluster/docker/desktop-build/Dockerfile
+++ b/taskcluster/docker/desktop-build/Dockerfile
@@ -22,16 +22,19 @@ ADD topsrcdir/testing/mozharness/externa
 ADD topsrcdir/taskcluster/docker/recipes/common.sh /setup/common.sh
 
 # %include taskcluster/docker/recipes/install-mercurial.sh
 ADD topsrcdir/taskcluster/docker/recipes/install-mercurial.sh /setup/install-mercurial.sh
 
 # %include taskcluster/docker/recipes/install-make.sh
 ADD topsrcdir/taskcluster/docker/recipes/install-make.sh /setup/install-make.sh
 
+# %include taskcluster/docker/recipes/install-cmake.sh
+ADD topsrcdir/taskcluster/docker/recipes/install-cmake.sh /setup/install-cmake.sh
+
 # %include taskcluster/docker/recipes/centos6-build-system-setup.sh
 ADD topsrcdir/taskcluster/docker/recipes/centos6-build-system-setup.sh /setup/system-setup.sh
 
 # TODO remove once base image doesn't install Mercurial
 RUN pip uninstall -y Mercurial
 
 RUN bash /setup/system-setup.sh
 
--- a/taskcluster/docker/recipes/centos6-build-system-setup.sh
+++ b/taskcluster/docker/recipes/centos6-build-system-setup.sh
@@ -3,10 +3,11 @@
 # 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/.
 
 cd /setup
 
 . /setup/common.sh
 . /setup/install-mercurial.sh
 . /setup/install-make.sh
+. /setup/install-cmake.sh
 
 rm -rf /setup
new file mode 100644
--- /dev/null
+++ b/taskcluster/docker/recipes/install-cmake.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# 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/.
+
+# This script installs CMake 3.7.1.
+tooltool_fetch <<'EOF'
+[
+  {
+    "size": 7361172,
+    "digest": "0539d70ce3ac77042a45d638443b09fbf368e253622db980bc6fb15988743eacd031ab850a45c821ec3e9f0f5f886b9c9cb0668aeda184cd457b78abbfe7b629",
+    "algorithm": "sha512",
+    "filename": "cmake-3.7.1.tar.gz",
+    "unpack": true
+  }
+]
+EOF
+cd cmake-3.7.1
+./bootstrap && make install
+cd ..
+rm -rf cmake-3.7.1
--- a/taskcluster/scripts/misc/build-clang-linux.sh
+++ b/taskcluster/scripts/misc/build-clang-linux.sh
@@ -2,24 +2,20 @@
 set -x -e -v
 
 # This script is for building clang for Linux.
 
 WORKSPACE=$HOME/workspace
 HOME_DIR=$WORKSPACE/build
 UPLOAD_DIR=$WORKSPACE/artifacts
 
-# Fetch our toolchain from tooltool
-cd $HOME_DIR
-wget -O tooltool.py https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py
-chmod +x tooltool.py
-: TOOLTOOL_CACHE                ${TOOLTOOL_CACHE:=/home/worker/tooltool-cache}
-export TOOLTOOL_CACHE
-cd src
-$HOME_DIR/tooltool.py -m browser/config/tooltool-manifests/linux64/releng.manifest fetch
+cd $HOME_DIR/src
+
+TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/linux64/releng.manifest
+. taskcluster/scripts/misc/tooltool-download.sh
 
 # gets a bit too verbose here
 set +x
 
 cd build/build-clang
 # |mach python| sets up a virtualenv for us!
 ../../mach python ./build-clang.py -c clang-static-analysis-linux64.json
 
new file mode 100755
--- /dev/null
+++ b/taskcluster/scripts/misc/build-clang-tidy-linux.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -x -e -v
+
+# This script is for building clang for Linux.
+
+WORKSPACE=$HOME/workspace
+HOME_DIR=$WORKSPACE/build
+UPLOAD_DIR=$WORKSPACE/artifacts
+
+cd $HOME_DIR/src
+
+TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/linux64/releng.manifest
+. taskcluster/scripts/misc/tooltool-download.sh
+
+# gets a bit too verbose here
+set +x
+
+cd build/build-clang
+# |mach python| sets up a virtualenv for us!
+../../mach python ./build-clang.py -c clang-tidy-linux64.json
+
+set -x
+
+# Put a tarball in the artifacts dir
+mkdir -p $UPLOAD_DIR
+cp clang.tar.* $UPLOAD_DIR
new file mode 100755
--- /dev/null
+++ b/taskcluster/scripts/misc/build-clang-tidy-macosx.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+set -x -e -v
+
+# This script is for building clang for Mac OS X on Linux.
+
+WORKSPACE=$HOME/workspace
+HOME_DIR=$WORKSPACE/build
+UPLOAD_DIR=$WORKSPACE/artifacts
+
+cd $HOME_DIR/src
+
+TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/macosx64/cross-clang.manifest
+. taskcluster/scripts/misc/tooltool-download.sh
+
+# ld needs libLTO.so from llvm
+export LD_LIBRARY_PATH=$HOME_DIR/src/clang/lib
+# these variables are used in build-clang.py
+export CROSS_CCTOOLS_PATH=$HOME_DIR/src/cctools
+export CROSS_SYSROOT=$HOME_DIR/src/MacOSX10.10.sdk
+export LIBCXX_INCLUDE_PATH=$HOME_DIR/src/clang/include/c++/v1
+# cmake doesn't allow us to specify a path to lipo on the command line.
+ln -sf $CROSS_CCTOOLS_PATH/bin/x86_64-apple-darwin10-lipo /usr/bin/lipo
+
+# gets a bit too verbose here
+set +x
+
+cd build/build-clang
+# |mach python| sets up a virtualenv for us!
+../../mach python ./build-clang.py -c clang-tidy-macosx64.json
+
+set -x
+
+# Put a tarball in the artifacts dir
+mkdir -p $UPLOAD_DIR
+cp clang.tar.* $UPLOAD_DIR
new file mode 100644
--- /dev/null
+++ b/taskcluster/scripts/misc/tooltool-download.sh
@@ -0,0 +1,11 @@
+# Fetch a tooltool manifest.
+
+cd $HOME/workspace/build/src
+
+chmod +x taskcluster/docker/recipes/tooltool.py
+: TOOLTOOL_CACHE                ${TOOLTOOL_CACHE:=/home/worker/tooltool-cache}
+export TOOLTOOL_CACHE
+
+./taskcluster/docker/recipes/tooltool.py --url=http://relengapi/tooltool/ -m "${TOOLTOOL_MANIFEST}" fetch
+
+cd $OLDPWD
--- a/taskcluster/taskgraph/transforms/gecko_v2_whitelist.py
+++ b/taskcluster/taskgraph/transforms/gecko_v2_whitelist.py
@@ -27,28 +27,30 @@ JOB_NAME_WHITELIST = set([
     'aries-debug',
     'aries-eng-opt',
     'browser-haz-debug',
     'linux32-l10n-opt',
     'linux64-artifact-opt',
     'linux64-asan-debug',
     'linux64-asan-opt',
     'linux64-ccov-opt',
+    'linux64-clang-tidy',
     'linux64-debug',
     'linux64-jsdcov-opt',
     'linux64-l10n-opt',
     'linux64-opt',
     'linux64-pgo',
     'linux64-st-an-opt',
     'linux64-stylo-debug',
     'linux64-stylo-opt',
     'linux64-valgrind-opt',
     'linux-debug',
     'linux-opt',
     'linux-pgo',
+    'macosx64-clang-tidy',
     'macosx64-debug',
     'macosx64-opt',
     'macosx64-st-an-opt',
     'nexus-5-l-eng-debug',
     'nexus-5-l-eng-opt',
     'osx-10-10',
     'shell-haz-debug',
     'sm-arm64-sim-debug',
@@ -60,21 +62,23 @@ JOB_NAME_WHITELIST = set([
     'sm-nonunified-debug',
     'sm-package-opt',
     'sm-plaindebug-debug',
     'sm-plain-opt',
     'sm-rootanalysis-debug',
     'sm-tsan-opt',
     'win32-st-an-debug',
     'win32-st-an-opt',
+    'win32-clang-tidy',
     'win32-debug',
     'win32-opt',
     'win32-pgo',
     'win64-st-an-debug',
     'win64-st-an-opt',
+    'win64-clang-tidy',
     'win64-debug',
     'win64-opt',
     'win64-pgo',
 ])
 
 JOB_NAME_WHITELIST_ERROR = """\
 The gecko-v2 job name {} is not in the whitelist in gecko_v2_whitelist.py.
 If this job runs on Buildbot, please ensure that the job names match between
--- a/taskcluster/taskgraph/transforms/task.py
+++ b/taskcluster/taskgraph/transforms/task.py
@@ -81,17 +81,17 @@ task_description_schema = Schema({
         # treeherder environments (defaults to both staging and production)
         Required('environments', default=['production', 'staging']): ['production', 'staging'],
     },
 
     # information for indexing this build so its artifacts can be discovered;
     # if omitted, the build will not be indexed.
     Optional('index'): {
         # the name of the product this build produces
-        'product': Any('firefox', 'mobile'),
+        'product': Any('firefox', 'mobile', 'static-analysis'),
 
         # the names to use for this job in the TaskCluster index
         'job-name': basestring,
 
         # The rank that the task will receive in the TaskCluster
         # index.  A newly completed task supercedes the currently
         # indexed task iff it has a higher rank.  If unspecified,
         # 'by-tier' behavior will be used.
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -1866,17 +1866,17 @@ nsDownloadManager::RetryDownload(nsDownl
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Creates a cycle that will be broken when the download finishes
   dl->mCancelable = wbp;
   (void)wbp->SetProgressListener(dl);
 
   // referrer policy can be anything since referrer is nullptr
   rv = wbp->SavePrivacyAwareURI(dl->mSource, nullptr,
-                                nullptr, mozilla::net::RP_Default,
+                                nullptr, mozilla::net::RP_Unset,
                                 nullptr, nullptr,
                                 dl->mTarget, dl->mPrivate);
   if (NS_FAILED(rv)) {
     dl->mCancelable = nullptr;
     (void)wbp->SetProgressListener(nullptr);
     return rv;
   }
 
--- a/toolkit/components/remotebrowserutils/RemoteWebNavigation.js
+++ b/toolkit/components/remotebrowserutils/RemoteWebNavigation.js
@@ -64,17 +64,17 @@ RemoteWebNavigation.prototype = {
   goForward() {
     this._sendMessage("WebNavigation:GoForward", {});
   },
   gotoIndex(aIndex) {
     this._sendMessage("WebNavigation:GotoIndex", {index: aIndex});
   },
   loadURI(aURI, aLoadFlags, aReferrer, aPostData, aHeaders) {
     this.loadURIWithOptions(aURI, aLoadFlags, aReferrer,
-                            Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+                            Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                             aPostData, aHeaders, null);
   },
   loadURIWithOptions(aURI, aLoadFlags, aReferrer, aReferrerPolicy,
                                aPostData, aHeaders, aBaseURI) {
     this._sendMessage("WebNavigation:LoadURI", {
       uri: aURI,
       flags: aLoadFlags,
       referrer: aReferrer ? aReferrer.spec : null,
--- a/toolkit/components/viewsource/content/viewSource-content.js
+++ b/toolkit/components/viewsource/content/viewSource-content.js
@@ -386,17 +386,17 @@ var ViewSourceContent = {
         // to the generic page describing phishing/malware protection.
         let URL = Services.urlFormatter.formatURLPref("app.support.baseURL");
         sendAsyncMessage("ViewSource:OpenURL", { URL })
       } else if (target == errorDoc.getElementById("ignoreWarningButton")) {
         // Allow users to override and continue through to the site
         docShell.QueryInterface(Ci.nsIWebNavigation)
                 .loadURIWithOptions(content.location.href,
                                     Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
-                                    null, Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
+                                    null, Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                                     null, null, null);
       }
     }
   },
 
   /**
    * Handler for the pageshow event.
    *
@@ -765,17 +765,17 @@ var ViewSourceContent = {
    * @param drawSelection true to highlight the selection
    * @param baseURI base URI of the original document
    */
   viewSourceWithSelection(uri, drawSelection, baseURI) {
     this.needsDrawSelection = drawSelection;
 
     // all our content is held by the data:URI and URIs are internally stored as utf-8 (see nsIURI.idl)
     let loadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
-    let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT;
+    let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     webNav.loadURIWithOptions(uri, loadFlags,
                               null, referrerPolicy,  // referrer
                               null, null,  // postData, headers
                               Services.io.newURI(baseURI, null, null));
   },
 
   /**
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -554,17 +554,17 @@ function internalPersist(persistArgs) {
 
     const kWrapColumn = 80;
     persist.saveDocument(persistArgs.sourceDocument, targetFileURL, filesFolder,
                          persistArgs.targetContentType, encodingFlags, kWrapColumn);
   } else {
     persist.savePrivacyAwareURI(persistArgs.sourceURI,
                                 persistArgs.sourceCacheKey,
                                 persistArgs.sourceReferrer,
-                                Components.interfaces.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE,
+                                Components.interfaces.nsIHttpChannel.REFERRER_POLICY_UNSET,
                                 persistArgs.sourcePostData,
                                 null,
                                 targetFileURL,
                                 persistArgs.isPrivate);
   }
 }
 
 /**
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -128,17 +128,17 @@
         <parameter name="aReferrerURI"/>
         <parameter name="aCharset"/>
         <parameter name="aPostData"/>
         <body>
           <![CDATA[
             if (!aURI)
               aURI = "about:blank";
 
-            var aReferrerPolicy = Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT;
+            var aReferrerPolicy = Components.interfaces.nsIHttpChannel.REFERRER_POLICY_UNSET;
 
             // Check for loadURIWithFlags(uri, { ... });
             var params = arguments[1];
             if (params && typeof(params) == "object") {
               aFlags = params.flags;
               aReferrerURI = params.referrerURI;
               if ('referrerPolicy' in params) {
                 aReferrerPolicy = params.referrerPolicy;
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -42,16 +42,19 @@ def Libxul(name):
         DELAYLOAD_DLLS += ['msdmo.dll']
 
     if CONFIG['OS_ARCH'] == 'WINNT':
         DELAYLOAD_DLLS += [
             'api-ms-win-core-winrt-l1-1-0.dll',
             'api-ms-win-core-winrt-string-l1-1-0.dll',
         ]
 
+    if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['ACCESSIBILITY']:
+        LOCAL_INCLUDES += ['!/accessible/interfaces/gecko/']
+
     if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
         LOCAL_INCLUDES += [
             '/widget/windows',
             '/xpcom/base',
         ]
         # config/version.mk says $(srcdir)/$(RCINCLUDE), and this needs to
         # be valid in both toolkit/library and toolkit/library/gtest.
         # Eventually, the make backend would do its own path canonicalization
--- a/toolkit/library/xulrunner.rc
+++ b/toolkit/library/xulrunner.rc
@@ -1,5 +1,8 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "widget.rc"
+#ifdef ACCESSIBILITY
+1 typelib IGeckoCustom.tlb
+#endif
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -863,17 +863,17 @@ function _persistImage(sourceURL, localF
     Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION |
     (PERSIST_BYPASS_CACHE ?
        Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE :
        Ci.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE);
 
   persist.progressListener = new _persistProgressListener(successCallback);
 
   persist.saveURI(sourceURI, null,
-                  null, Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE,
+                  null, Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
                   null, null, targetURI, null);
 }
 
 function _persistProgressListener(successCallback) {
   this.onLocationChange = function() {};
   this.onProgressChange = function() {};
   this.onStatusChange   = function() {};
   this.onSecurityChange = function() {};
--- a/widget/cocoa/nsMenuItemIconX.mm
+++ b/widget/cocoa/nsMenuItemIconX.mm
@@ -305,17 +305,17 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconU
 
     if (!sPlaceholderIconImage) return NS_ERROR_FAILURE;
 
     if (mNativeMenuItem)
       [mNativeMenuItem setImage:sPlaceholderIconImage];
   }
 
   nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr,
-                                  mozilla::net::RP_Default,
+                                  mozilla::net::RP_Unset,
                                   nullptr, loadGroup, this,
                                   nullptr, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
                                   nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(),
                                   getter_AddRefs(mIconRequest));
   if (NS_FAILED(rv)) return rv;
 
   return NS_OK;