merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 09 Sep 2016 12:02:43 +0200
changeset 313394 feff79e5b1374439f17c5ea10a559acf1380a8d5
parent 313320 b13e7776b612f4507e9a394070622285f7a9fd20 (current diff)
parent 313393 3f507148324c43e50bacf5c36ce27e0c94cfbea7 (diff)
child 313395 68ae5adc423221684ad87a2dc94f7cb864a148f4
child 313416 644b3de5d7a18b101d44a003bc27d50853dee4c9
child 313418 2b2dda648fde70cedb9a0d486e730fdec592b5e6
child 313424 02824c83b371ab04aa7cb5d35c569d668cc299e6
push id32169
push usercbook@mozilla.com
push dateFri, 09 Sep 2016 10:20:44 +0000
treeherderautoland@68ae5adc4232 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
first release with
nightly linux32
feff79e5b137 / 51.0a1 / 20160909030428 / files
nightly linux64
feff79e5b137 / 51.0a1 / 20160909030428 / files
nightly mac
feff79e5b137 / 51.0a1 / 20160909030428 / files
nightly win32
feff79e5b137 / 51.0a1 / 20160909030428 / files
nightly win64
feff79e5b137 / 51.0a1 / 20160909030428 / 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 mozilla-inbound to mozilla-central a=merge
build/autoconf/rust.m4
dom/media/platforms/agnostic/VPXDecoder.cpp
layout/base/nsDisplayList.cpp
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
modules/libpref/init/all.js
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_helper.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping.html
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2630,16 +2630,55 @@ ContentPermissionPrompt.prototype = {
     }
 
     secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST);
 
     this._showPrompt(aRequest, message, "geo", actions, "geolocation",
                      "geo-notification-icon", options);
   },
 
+  _promptFlyWebPublishServer : function(aRequest) {
+    var message = "Would you like to let this site start a server accessible to nearby devices and people?";
+    var actions = [
+      {
+        stringId: "flyWebPublishServer.allowPublishServer",
+        action: Ci.nsIPermissionManager.ALLOW_ACTION,
+        expireType: Ci.nsIPermissionManager.EXPIRE_SESSION
+      },
+      {
+        stringId: "flyWebPublishServer.denyPublishServer",
+        action: Ci.nsIPermissionManager.DENY_ACTION,
+        expireType: Ci.nsIPermissionManager.EXPIRE_SESSION
+      }
+    ];
+
+    let options = {
+      learnMoreURL: "https://flyweb.github.io",
+      popupIconURL: "chrome://flyweb/skin/icon-64.png"
+    };
+
+    let browser = this._getBrowserForRequest(aRequest);
+    let chromeDoc = browser.ownerDocument;
+    let iconElem = chromeDoc.getElementById("flyweb-publish-server-notification-icon");
+    if (!iconElem) {
+      let notificationPopupBox = chromeDoc.getElementById("notification-popup-box");
+      let notificationIcon = chromeDoc.createElement("image");
+      notificationIcon.setAttribute("id", "flyweb-publish-server-notification-icon");
+      notificationIcon.setAttribute("src", "chrome://flyweb/skin/icon-64.png");
+      notificationIcon.setAttribute("class", "notification-anchor-icon flyweb-publish-server-icon");
+      notificationIcon.setAttribute("style", "filter: url(chrome://browser/skin/filters.svg#fill); fill: currentColor; opacity: .4;");
+      notificationIcon.setAttribute("role", "button");
+      notificationIcon.setAttribute("aria-label", "View the publish-server request");
+      notificationPopupBox.appendChild(notificationIcon);
+    }
+
+    this._showPrompt(aRequest, message, "flyweb-publish-server", actions, "flyweb-publish-server",
+                     "flyweb-publish-server-notification-icon", options);
+  },
+
   _promptWebNotifications : function(aRequest) {
     var message = gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
 
     var actions;
 
     var browser = this._getBrowserForRequest(aRequest);
     // Only show "allow for session" in PB mode, we don't
     // support "allow for session" in non-PB mode.
@@ -2694,17 +2733,18 @@ ContentPermissionPrompt.prototype = {
     let types = request.types.QueryInterface(Ci.nsIArray);
     if (types.length != 1) {
       request.cancel();
       return;
     }
     let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
 
     const kFeatureKeys = { "geolocation" : "geo",
-                           "desktop-notification" : "desktop-notification"
+                           "desktop-notification" : "desktop-notification",
+                           "flyweb-publish-server": "flyweb-publish-server"
                          };
 
     // Make sure that we support the request.
     if (!(perm.type in kFeatureKeys)) {
       return;
     }
 
     var requestingPrincipal = request.principal;
@@ -2737,16 +2777,21 @@ ContentPermissionPrompt.prototype = {
     // Show the prompt.
     switch (perm.type) {
     case "geolocation":
       this._promptGeo(request);
       break;
     case "desktop-notification":
       this._promptWebNotifications(request);
       break;
+    case "flyweb-publish-server":
+      if (AppConstants.NIGHTLY_BUILD) {
+        this._promptFlyWebPublishServer(request);
+      }
+      break;
     }
   },
 
 };
 
 var DefaultBrowserCheck = {
   get OPTIONPOPUP() { return "defaultBrowserNotificationPopup" },
   _setAsDefaultTimer: null,
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -373,16 +373,26 @@ geolocation.shareLocation=Share Location
 geolocation.shareLocation.accesskey=a
 geolocation.alwaysShareLocation=Always Share Location
 geolocation.alwaysShareLocation.accesskey=A
 geolocation.neverShareLocation=Never Share Location
 geolocation.neverShareLocation.accesskey=N
 geolocation.shareWithSite2=Would you like to share your location with this site?
 geolocation.shareWithFile2=Would you like to share your location with this file?
 
+# FlyWeb UI
+# LOCALIZATION NOTE (flyWebPublishServer.allowPublishServer): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.allowPublishServer=Allow Server
+# LOCALIZATION NOTE (flyWebPublishServer.allowPublishServer.accessKey): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.allowPublishServer.accesskey=A
+# LOCALIZATION NOTE (flyWebPublishServer.denyPublishServer): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.denyPublishServer=Block Server
+# LOCALIZATION NOTE (flyWebPublishServer.denyPublishServer.accessKey): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.denyPublishServer.accesskey=B
+
 webNotifications.receiveForSession=Receive for this session
 webNotifications.receiveForSession.accesskey=s
 webNotifications.alwaysReceive=Always Receive Notifications
 webNotifications.alwaysReceive.accesskey=A
 webNotifications.neverShow=Always Block Notifications
 webNotifications.neverShow.accesskey=N
 webNotifications.receiveFromSite=Would you like to receive notifications from this site?
 # LOCALIZATION NOTE (webNotifications.upgradeTitle): When using native notifications on OS X, the title may be truncated around 32 characters.
deleted file mode 100644
--- a/build/autoconf/rust.m4
+++ /dev/null
@@ -1,152 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-AC_DEFUN([MOZ_RUST_SUPPORT], [
-  MOZ_PATH_PROG(RUSTC, rustc)
-  if test -n "$RUSTC"; then
-    AC_MSG_CHECKING([rustc version])
-    RUSTC_VERSION=`$RUSTC --version | cut -d ' ' -f 2`
-    # Parse out semversion elements.
-    _RUSTC_MAJOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 1`
-    _RUSTC_MINOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 2`
-    _RUSTC_EXTRA_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 3 | cut -d + -f 1`
-    _RUSTC_PATCH_VERSION=`echo ${_RUSTC_EXTRA_VERSION} | cut -d '-' -f 1`
-    AC_MSG_RESULT([${_RUSTC_MAJOR_VERSION}.${_RUSTC_MINOR_VERSION}.${_RUSTC_PATCH_VERSION} ($RUSTC_VERSION)])
-  fi
-  MOZ_ARG_ENABLE_BOOL([rust],
-                      [  --enable-rust           Include Rust language sources],
-                      [MOZ_RUST=1],
-                      [MOZ_RUST= ])
-  if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
-    AC_MSG_ERROR([Rust compiler not found.
-      To compile rust language sources, you must have 'rustc' in your path.
-      See http://www.rust-lang.org/ for more information.])
-  fi
-  if test -n "$MOZ_RUST" && test -z "$_RUSTC_MAJOR_VERSION" -o \
-    "$_RUSTC_MAJOR_VERSION" -lt 1 -o \
-    \( "$_RUSTC_MAJOR_VERSION" -eq 1 -a "$_RUSTC_MINOR_VERSION" -lt 5 \); then
-    AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old.
-      To compile Rust language sources please install at least
-      version 1.5 of the 'rustc' toolchain and make sure it is
-      first in your path.
-      You can verify this by typing 'rustc --version'.])
-  fi
-
-  if test -n "$RUSTC" -a -n "$MOZ_RUST"; then
-    # Rust's --target options are similar to, but not exactly the same
-    # as, the autoconf-derived targets we use.  An example would be that
-    # Rust uses distinct target triples for targetting the GNU C++ ABI
-    # and the MSVC C++ ABI on Win32, whereas autoconf has a single
-    # triple and relies on the user to ensure that everything is
-    # compiled for the appropriate ABI.  We need to perform appropriate
-    # munging to get the correct option to rustc.
-    #
-    # The canonical list of targets supported can be derived from:
-    #
-    # https://github.com/rust-lang/rust/tree/master/mk/cfg
-    rust_target=
-    case "$target" in
-      # Bitrig
-      x86_64-*-bitrig*)
-          rust_target=x86_64-unknown-bitrig
-          ;;
-
-      # DragonFly
-      x86_64-*-dragonfly*)
-          rust_target=x86_64-unknown-dragonfly
-          ;;
-
-      # FreeBSD, GNU/kFreeBSD
-      i*86-*-*freebsd*)
-          rust_target=i686-unknown-freebsd
-          ;;
-      x86_64-*-*freebsd*)
-          rust_target=x86_64-unknown-freebsd
-          ;;
-
-      # NetBSD
-      x86_64-*-netbsd*)
-          rust_target=x86_64-unknown-netbsd
-          ;;
-
-      # OpenBSD
-      x86_64-*-openbsd*)
-          rust_target=x86_64-unknown-openbsd
-          ;;
-
-      # Linux
-      i*86*linux-gnu)
-          rust_target=i686-unknown-linux-gnu
-          ;;
-      x86_64*linux-gnu)
-          rust_target=x86_64-unknown-linux-gnu
-          ;;
-
-      # OS X and iOS
-      i*86-apple-darwin*)
-          rust_target=i686-apple-darwin
-          ;;
-      i*86-apple-ios*)
-          rust_target=i386-apple-ios
-          ;;
-      x86_64-apple-darwin*)
-          rust_target=x86_64-apple-darwin
-          ;;
-
-      # Android
-      i*86*linux-android)
-          rust_target=i686-linux-android
-          ;;
-      arm*linux-android*)
-          rust_target=arm-linux-androideabi
-          ;;
-
-      # Windows
-      i*86-pc-mingw32)
-          # XXX better detection of CXX needed here, to figure out whether
-          # we need i686-pc-windows-gnu instead, since mingw32 builds work.
-          rust_target=i686-pc-windows-msvc
-          ;;
-      x86_64-pc-mingw32)
-          # XXX and here as well
-          rust_target=x86_64-pc-windows-msvc
-          ;;
-      *)
-          # Fall back to implicit (native) target when not cross-compiling
-          if test -n "$CROSS_COMPILE"; then
-            AC_ERROR([don't know how to translate $target for rustc])
-          fi
-          ;;
-    esac
-
-    if test -n "$rust_target"; then
-      # Check to see whether we need to pass --target to RUSTC.  This can
-      # happen when building Firefox on Windows: js's configure will receive
-      # a RUSTC from the toplevel configure that already has --target added to
-      # it.
-      rustc_target_arg=
-      case "$RUSTC" in
-        *--target=${rust_target}*)
-          ;;
-        *)
-          rustc_target_arg=--target=${rust_target}
-          ;;
-      esac
-    fi
-
-    # Check to see whether our rustc has a reasonably functional stdlib
-    # for our chosen target.
-    echo 'pub extern fn hello() { println!("Hello world"); }' > conftest.rs
-    if AC_TRY_COMMAND(${RUSTC} --crate-type staticlib ${rustc_target_arg} -o conftest.rlib conftest.rs > /dev/null) && test -s conftest.rlib; then
-      RUSTC="${RUSTC} ${rustc_target_arg}"
-    else
-      AC_ERROR([cannot compile for ${rust_target} with ${RUSTC}])
-    fi
-    rm -f conftest.rs conftest.rlib
-  fi
-
-  # TODO: separate HOST_RUSTC and RUSTC variables
-
-  AC_SUBST(MOZ_RUST)
-])
--- a/caps/nsJSPrincipals.cpp
+++ b/caps/nsJSPrincipals.cpp
@@ -83,18 +83,19 @@ nsJSPrincipals::Destroy(JSPrincipals *js
 #ifdef DEBUG
 
 // Defined here so one can do principals->dump() in the debugger
 JS_PUBLIC_API(void)
 JSPrincipals::dump()
 {
     if (debugToken == nsJSPrincipals::DEBUG_TOKEN) {
       nsAutoCString str;
-      static_cast<nsJSPrincipals *>(this)->GetScriptLocation(str);
-      fprintf(stderr, "nsIPrincipal (%p) = %s\n", static_cast<void*>(this), str.get());
+      nsresult rv = static_cast<nsJSPrincipals *>(this)->GetScriptLocation(str);
+      fprintf(stderr, "nsIPrincipal (%p) = %s\n", static_cast<void*>(this),
+              NS_SUCCEEDED(rv) ? str.get() : "(unknown)");
     } else if (debugToken == dom::workers::kJSPrincipalsDebugToken) {
         fprintf(stderr, "Web Worker principal singleton (%p)\n", this);
     } else {
         fprintf(stderr,
                 "!!! JSPrincipals (%p) is not nsJSPrincipals instance - bad token: "
                 "actual=0x%x expected=0x%x\n",
                 this, unsigned(debugToken), unsigned(nsJSPrincipals::DEBUG_TOKEN));
     }
--- a/caps/nsJSPrincipals.h
+++ b/caps/nsJSPrincipals.h
@@ -48,17 +48,17 @@ public:
   nsJSPrincipals() {
     refcount = 0;
     setDebugToken(DEBUG_TOKEN);
   }
 
   /**
    * Return a string that can be used as JS script filename in error reports.
    */
-  virtual void GetScriptLocation(nsACString &aStr) = 0;
+  virtual nsresult GetScriptLocation(nsACString &aStr) = 0;
   static const uint32_t DEBUG_TOKEN = 0x0bf41760;
 
 protected:
   virtual ~nsJSPrincipals() {
     setDebugToken(0);
   }
 
 };
--- a/caps/nsNullPrincipal.cpp
+++ b/caps/nsNullPrincipal.cpp
@@ -73,20 +73,20 @@ nsNullPrincipal::Init(const PrincipalOri
   mOriginAttributes = aOriginAttributes;
 
   mURI = nsNullPrincipalURI::Create();
   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_AVAILABLE);
 
   return NS_OK;
 }
 
-void
+nsresult
 nsNullPrincipal::GetScriptLocation(nsACString &aStr)
 {
-  mURI->GetSpec(aStr);
+  return mURI->GetSpec(aStr);
 }
 
 /**
  * nsIPrincipal implementation
  */
 
 NS_IMETHODIMP
 nsNullPrincipal::GetHashValue(uint32_t *aResult)
--- a/caps/nsNullPrincipal.h
+++ b/caps/nsNullPrincipal.h
@@ -52,17 +52,17 @@ public:
 
   static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIDocShell* aDocShell);
 
   static already_AddRefed<nsNullPrincipal>
   Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
 
   nsresult Init(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
 
-  virtual void GetScriptLocation(nsACString &aStr) override;
+  virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
   PrincipalKind Kind() override { return eNullPrincipal; }
 
  protected:
   virtual ~nsNullPrincipal() {}
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
   {
--- a/caps/nsNullPrincipalURI.cpp
+++ b/caps/nsNullPrincipalURI.cpp
@@ -91,17 +91,18 @@ nsNullPrincipalURI::GetAsciiHostPort(nsA
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
 {
   nsAutoCString buffer;
-  (void)GetSpec(buffer);
+  // Ignore the return value -- nsNullPrincipalURI::GetSpec() is infallible.
+  Unused << GetSpec(buffer);
   NS_EscapeURL(buffer, esc_OnlyNonASCII | esc_AlwaysCopy, _spec);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNullPrincipalURI::GetHost(nsACString &_host)
 {
   _host.Truncate();
--- a/caps/nsPrincipal.cpp
+++ b/caps/nsPrincipal.cpp
@@ -94,20 +94,20 @@ nsPrincipal::Init(nsIURI *aCodebase, con
 
   mCodebase = NS_TryToMakeImmutable(aCodebase);
   mCodebaseImmutable = URIIsImmutable(mCodebase);
   mOriginAttributes = aOriginAttributes;
 
   return NS_OK;
 }
 
-void
+nsresult
 nsPrincipal::GetScriptLocation(nsACString &aStr)
 {
-  mCodebase->GetSpec(aStr);
+  return mCodebase->GetSpec(aStr);
 }
 
 /* static */ nsresult
 nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
 {
   if (!aURI) {
     return NS_ERROR_FAILURE;
   }
@@ -801,32 +801,34 @@ bool
 nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
 {
   // CSS Unprefixing Whitelist is a per-origin thing; doesn't really make sense
   // for an expanded principal. (And probably shouldn't be needed.)
   return false;
 }
 
 
-void
+nsresult
 nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
 {
   aStr.Assign("[Expanded Principal [");
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (i != 0) {
       aStr.AppendLiteral(", ");
     }
 
     nsAutoCString spec;
-    nsJSPrincipals::get(mPrincipals.ElementAt(i))->GetScriptLocation(spec);
+    nsresult rv =
+      nsJSPrincipals::get(mPrincipals.ElementAt(i))->GetScriptLocation(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     aStr.Append(spec);
-
   }
   aStr.Append("]]");
+  return NS_OK;
 }
 
 //////////////////////////////////////////
 // Methods implementing nsISerializable //
 //////////////////////////////////////////
 
 NS_IMETHODIMP
 nsExpandedPrincipal::Read(nsIObjectInputStream* aStream)
--- a/caps/nsPrincipal.h
+++ b/caps/nsPrincipal.h
@@ -29,17 +29,17 @@ public:
   bool IsCodebasePrincipal() const override { return true; }
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   nsPrincipal();
 
   // Init() must be called before the principal is in a usable state.
   nsresult Init(nsIURI* aCodebase, const mozilla::PrincipalOriginAttributes& aOriginAttributes);
 
-  virtual void GetScriptLocation(nsACString& aStr) override;
+  virtual nsresult GetScriptLocation(nsACString& aStr) override;
   void SetURI(nsIURI* aURI);
 
   /**
    * Computes the puny-encoded origin of aURI.
    */
   static nsresult GetOriginForURI(nsIURI* aURI, nsACString& aOrigin);
 
   /**
@@ -76,17 +76,17 @@ public:
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   virtual bool AddonHasPermission(const nsAString& aPerm) override;
   virtual bool IsOnCSSUnprefixingWhitelist() override;
-  virtual void GetScriptLocation(nsACString &aStr) override;
+  virtual nsresult GetScriptLocation(nsACString &aStr) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   PrincipalKind Kind() override { return eExpandedPrincipal; }
 
 protected:
   virtual ~nsExpandedPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override;
--- a/caps/nsSystemPrincipal.cpp
+++ b/caps/nsSystemPrincipal.cpp
@@ -26,20 +26,21 @@ NS_IMPL_QUERY_INTERFACE_CI(nsSystemPrinc
                            nsIPrincipal,
                            nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER(nsSystemPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 
 #define SYSTEM_PRINCIPAL_SPEC "[System Principal]"
 
-void
+nsresult
 nsSystemPrincipal::GetScriptLocation(nsACString &aStr)
 {
     aStr.AssignLiteral(SYSTEM_PRINCIPAL_SPEC);
+    return NS_OK;
 }
 
 ///////////////////////////////////////
 // Methods implementing nsIPrincipal //
 ///////////////////////////////////////
 
 NS_IMETHODIMP
 nsSystemPrincipal::GetHashValue(uint32_t *result)
--- a/caps/nsSystemPrincipal.h
+++ b/caps/nsSystemPrincipal.h
@@ -33,17 +33,17 @@ public:
   NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
   NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
   NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   nsSystemPrincipal() {}
 
-  virtual void GetScriptLocation(nsACString &aStr) override;
+  virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
 protected:
   virtual ~nsSystemPrincipal(void) {}
 
   bool SubsumesInternal(nsIPrincipal *aOther, DocumentDomainConsideration aConsideration) override
   {
     return true;
   }
--- a/chrome/nsChromeRegistryChrome.cpp
+++ b/chrome/nsChromeRegistryChrome.cpp
@@ -421,17 +421,18 @@ nsChromeRegistryChrome::SendRegisteredCh
     NS_ENSURE_TRUE_VOID(io);
 
     nsCOMPtr<nsIProtocolHandler> ph;
     nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
     NS_ENSURE_SUCCESS_VOID(rv);
 
     nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
     nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
-    rph->CollectSubstitutions(resources);
+    rv = rph->CollectSubstitutions(resources);
+    NS_ENSURE_SUCCESS_VOID(rv);
   }
 
   for (auto iter = mOverrideTable.Iter(); !iter.Done(); iter.Next()) {
     SerializedURI chromeURI, overrideURI;
 
     SerializeURI(iter.Key(), chromeURI);
     SerializeURI(iter.UserData(), overrideURI);
 
--- a/devtools/client/webide/test/chrome.ini
+++ b/devtools/client/webide/test/chrome.ini
@@ -61,10 +61,11 @@ skip-if = true # Bug 1201392 - Update ad
 [test_telemetry.html]
 skip-if = true # Bug 1201392 - Update add-ons after migration
 [test_device_preferences.html]
 [test_device_settings.html]
 [test_fullscreenToolbox.html]
 [test_zoom.html]
 [test_build.html]
 [test_simulators.html]
+skip-if = true # Bug 1281138 - intermittent failures
 [test_toolbox.html]
 [test_app_validator.html]
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -12270,27 +12270,35 @@ nsDocShell::AddToSessionHistory(nsIURI* 
       nsCOMPtr<nsISHEntry> newEntry;
       CloneAndReplace(mOSHE, this, cloneID, entry, true,
                       getter_AddRefs(newEntry));
       NS_ASSERTION(entry == newEntry,
                    "The new session history should be in the new entry");
     }
 
     // This is the root docshell
-    if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
+    bool addToSHistory = !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY);
+    if (!addToSHistory) {
       // Replace current entry in session history.
       int32_t index = 0;
       mSessionHistory->GetIndex(&index);
       nsCOMPtr<nsISHistoryInternal> shPrivate =
         do_QueryInterface(mSessionHistory);
       // Replace the current entry with the new entry
-      if (shPrivate) {
-        rv = shPrivate->ReplaceEntry(index, entry);
-      }
-    } else {
+      if (index >= 0) {
+        if (shPrivate) {
+          rv = shPrivate->ReplaceEntry(index, entry);
+        }
+      } else {
+        // If we're trying to replace an inexistant shistory entry, append.
+        addToSHistory = true;
+      }
+    }
+
+    if (addToSHistory) {
       // Add to session history
       nsCOMPtr<nsISHistoryInternal> shPrivate =
         do_QueryInterface(mSessionHistory);
       NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
       mSessionHistory->GetIndex(&mPreviousTransIndex);
       rv = shPrivate->AddEntry(entry, shouldPersist);
       mSessionHistory->GetIndex(&mLoadedTransIndex);
 #ifdef DEBUG_PAGE_CACHE
--- a/dom/base/DOMMatrix.cpp
+++ b/dom/base/DOMMatrix.cpp
@@ -202,43 +202,43 @@ DOMMatrixReadOnly::TransformPoint(const 
 
   if (mMatrix3D) {
     gfx::Point4D transformedPoint;
     transformedPoint.x = point.mX;
     transformedPoint.y = point.mY;
     transformedPoint.z = point.mZ;
     transformedPoint.w = point.mW;
 
-    transformedPoint = *mMatrix3D * transformedPoint;
+    transformedPoint = mMatrix3D->TransformPoint(transformedPoint);
 
     retval->SetX(transformedPoint.x);
     retval->SetY(transformedPoint.y);
     retval->SetZ(transformedPoint.z);
     retval->SetW(transformedPoint.w);
   } else if (point.mZ != 0 || point.mW != 1.0) {
     gfx::Matrix4x4 tempMatrix(gfx::Matrix4x4::From2D(*mMatrix2D));
 
     gfx::Point4D transformedPoint;
     transformedPoint.x = point.mX;
     transformedPoint.y = point.mY;
     transformedPoint.z = point.mZ;
     transformedPoint.w = point.mW;
 
-    transformedPoint = tempMatrix * transformedPoint;
+    transformedPoint = tempMatrix.TransformPoint(transformedPoint);
 
     retval->SetX(transformedPoint.x);
     retval->SetY(transformedPoint.y);
     retval->SetZ(transformedPoint.z);
     retval->SetW(transformedPoint.w);
   } else {
     gfx::Point transformedPoint;
     transformedPoint.x = point.mX;
     transformedPoint.y = point.mY;
 
-    transformedPoint = *mMatrix2D * transformedPoint;
+    transformedPoint = mMatrix2D->TransformPoint(transformedPoint);
 
     retval->SetX(transformedPoint.x);
     retval->SetY(transformedPoint.y);
     retval->SetZ(point.mZ);
     retval->SetW(point.mW);
   }
   return retval.forget();
 }
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1854,17 +1854,17 @@ static const char* kNSURIs[] = {
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     uint32_t nsid = tmp->GetNameSpaceID();
     nsAtomCString localName(tmp->NodeInfo()->NameAtom());
     nsAutoCString uri;
     if (tmp->OwnerDoc()->GetDocumentURI()) {
-      tmp->OwnerDoc()->GetDocumentURI()->GetSpec(uri);
+      uri = tmp->OwnerDoc()->GetDocumentURI()->GetSpecOrDefault();
     }
 
     nsAutoString id;
     nsIAtom* idAtom = tmp->GetID();
     if (idAtom) {
       id.AppendLiteral(" id='");
       id.Append(nsDependentAtomString(idAtom));
       id.Append('\'');
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -80,17 +80,18 @@ private:
                  nsIPrincipal* aPrincipal);
   nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
                                     DataTransfer* aDataTransfer);
   static nsresult GetDraggableSelectionData(nsISelection* inSelection,
                                             nsIContent* inRealTargetNode,
                                             nsIContent **outImageOrLinkNode,
                                             bool* outDragSelectedText);
   static already_AddRefed<nsIContent> FindParentLinkNode(nsIContent* inNode);
-  static void GetAnchorURL(nsIContent* inNode, nsAString& outURL);
+  static MOZ_MUST_USE nsresult
+  GetAnchorURL(nsIContent* inNode, nsAString& outURL);
   static void GetNodeString(nsIContent* inNode, nsAString & outNodeString);
   static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
                               nsAString& outLinkText);
 
   nsCOMPtr<nsPIDOMWindowOuter> mWindow;
   nsCOMPtr<nsIContent> mTarget;
   nsCOMPtr<nsIContent> mSelectionTargetNode;
   bool mIsAltKeyPressed;
@@ -290,29 +291,31 @@ DragDataProducer::FindParentLinkNode(nsI
 
   return nullptr;
 }
 
 
 //
 // GetAnchorURL
 //
-void
+nsresult
 DragDataProducer::GetAnchorURL(nsIContent* inNode, nsAString& outURL)
 {
   nsCOMPtr<nsIURI> linkURI;
   if (!inNode || !inNode->IsLink(getter_AddRefs(linkURI))) {
     // Not a link
     outURL.Truncate();
-    return;
+    return NS_OK;
   }
 
   nsAutoCString spec;
-  linkURI->GetSpec(spec);
+  nsresult rv = linkURI->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
   CopyUTF8toUTF16(spec, outURL);
+  return NS_OK;
 }
 
 
 //
 // CreateLinkText
 //
 // Creates the html for an anchor in the form
 //  <a href="inURL">inText</a>
@@ -516,17 +519,18 @@ DragDataProducer::Produce(DataTransfer* 
           // this can be a relative link
           areaElem->GetAttribute(NS_LITERAL_STRING("href"), mTitleString);
         }
 
         // we'll generate HTML like <a href="absurl">alt text</a>
         mIsAnchor = true;
 
         // gives an absolute link
-        GetAnchorURL(draggedNode, mUrlString);
+        nsresult rv = GetAnchorURL(draggedNode, mUrlString);
+        NS_ENSURE_SUCCESS(rv, rv);
 
         mHtmlString.AssignLiteral("<a href=\"");
         mHtmlString.Append(mUrlString);
         mHtmlString.AppendLiteral("\">");
         mHtmlString.Append(mTitleString);
         mHtmlString.AppendLiteral("</a>");
 
         dragNode = draggedNode;
@@ -534,17 +538,18 @@ DragDataProducer::Produce(DataTransfer* 
         mIsAnchor = true;
         // grab the href as the url, use alt text as the title of the
         // area if it's there.  the drag data is the image tag and src
         // attribute.
         nsCOMPtr<nsIURI> imageURI;
         image->GetCurrentURI(getter_AddRefs(imageURI));
         if (imageURI) {
           nsAutoCString spec;
-          imageURI->GetSpec(spec);
+          rv = imageURI->GetSpec(spec);
+          NS_ENSURE_SUCCESS(rv, rv);
           CopyUTF8toUTF16(spec, mUrlString);
         }
 
         nsCOMPtr<nsIDOMElement> imageElement(do_QueryInterface(image));
         // XXXbz Shouldn't we use the "title" attr for title?  Using
         // "alt" seems very wrong....
         if (imageElement) {
           imageElement->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
@@ -579,17 +584,18 @@ DragDataProducer::Produce(DataTransfer* 
             imgRequest->GetMimeType(getter_Copies(mimeType));
 
             nsCOMPtr<nsIMIMEInfo> mimeInfo;
             mimeService->GetFromTypeAndExtension(mimeType, EmptyCString(),
                                                  getter_AddRefs(mimeInfo));
 
             if (mimeInfo) {
               nsAutoCString spec;
-              imgUrl->GetSpec(spec);
+              rv = imgUrl->GetSpec(spec);
+              NS_ENSURE_SUCCESS(rv, rv);
 
               // pass out the image source string
               CopyUTF8toUTF16(spec, mImageSourceString);
 
               bool validExtension;
               if (extension.IsEmpty() || 
                   NS_FAILED(mimeInfo->ExtensionExists(extension,
                                                       &validExtension)) ||
@@ -642,17 +648,18 @@ DragDataProducer::Produce(DataTransfer* 
         nodeToSerialize = linkNode;
       } else if (!haveSelectedContent) {
         // nothing draggable
         return NS_OK;
       }
 
       if (linkNode) {
         mIsAnchor = true;
-        GetAnchorURL(linkNode, mUrlString);
+        rv = GetAnchorURL(linkNode, mUrlString);
+        NS_ENSURE_SUCCESS(rv, rv);
         dragNode = linkNode;
       }
     }
   }
 
   if (nodeToSerialize || *aSelection) {
     mHtmlString.Truncate();
     mContextString.Truncate();
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3588,17 +3588,17 @@ nsContentUtils::ReportToConsoleNonLocali
   nsAutoCString spec;
   if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
     JSContext *cx = GetCurrentJSContext();
     if (cx) {
       nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
     }
   }
   if (spec.IsEmpty() && aURI) {
-    aURI->GetSpec(spec);
+    spec = aURI->GetSpecOrDefault();
   }
 
   nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = errorObject->InitWithWindowID(aErrorText,
                                      NS_ConvertUTF8toUTF16(spec), // file name
@@ -3670,17 +3670,18 @@ nsContentUtils::IsPlainTextType(const ns
 }
 
 bool
 nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument *aDocument,
                                              nsIURI *aURI,
                                              nsACString& aScriptURI)
 {
   bool scriptFileNameModified = false;
-  aURI->GetSpec(aScriptURI);
+  // XXX: should handle GetSpec() failure properly. See bug 1301251.
+  Unused << aURI->GetSpec(aScriptURI);
 
   if (IsChromeDoc(aDocument)) {
     nsCOMPtr<nsIChromeRegistry> chromeReg =
       mozilla::services::GetChromeRegistryService();
 
     if (!chromeReg) {
       // If we're running w/o a chrome registry we won't modify any
       // script file names.
@@ -3698,17 +3699,18 @@ nsContentUtils::GetWrapperSafeScriptFile
     if (docURI && docWrappersEnabled && !uriWrappersEnabled) {
       // aURI is a script from a URL that doesn't get wrapper
       // automation. aDocument is a chrome document that does get
       // wrapper automation. Prepend the chrome document's URI
       // followed by the string " -> " to the URI of the script we're
       // loading here so that script in that URI gets the same wrapper
       // automation that the chrome document expects.
       nsAutoCString spec;
-      docURI->GetSpec(spec);
+      // XXX: should handle GetSpec() failure properly. See bug 1301251.
+      Unused << docURI->GetSpec(spec);
       spec.AppendLiteral(" -> ");
       spec.Append(aScriptURI);
 
       aScriptURI = spec;
 
       scriptFileNameModified = true;
     }
   }
@@ -9232,17 +9234,16 @@ nsContentUtils::IsSpecificAboutPage(JSOb
   MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
 
   // Make sure the global is a window
   nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
   if (!win) {
     return false;
   }
 
-  // Make sure that the principal is about:feeds.
   nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
   NS_ENSURE_TRUE(principal, false);
   nsCOMPtr<nsIURI> uri;
   principal->GetURI(getter_AddRefs(uri));
   if (!uri) {
     return false;
   }
 
@@ -9250,17 +9251,17 @@ nsContentUtils::IsSpecificAboutPage(JSOb
   bool isAbout = false;
   uri->SchemeIs("about", &isAbout);
   if (!isAbout) {
     return false;
   }
 
   // Now check the spec itself
   nsAutoCString spec;
-  uri->GetSpec(spec);
+  uri->GetSpecIgnoringRef(spec);
   return spec.EqualsASCII(aUri);
 }
 
 /* static */ void
 nsContentUtils::SetScrollbarsVisibility(nsIDocShell* aDocShell, bool aVisible)
 {
   nsCOMPtr<nsIScrollable> scroller = do_QueryInterface(aDocShell);
 
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -250,17 +250,18 @@ SelectionCopyHelper(nsISelection *aSel, 
           rv = AppendString(trans, textPlainBuf, kUnicodeMime);
           NS_ENSURE_SUCCESS(rv, rv);
         }
 
         // Try and get source URI of the items that are being dragged
         nsIURI *uri = aDoc->GetDocumentURI();
         if (uri) {
           nsAutoCString spec;
-          uri->GetSpec(spec);
+          nsresult rv = uri->GetSpec(spec);
+          NS_ENSURE_SUCCESS(rv, rv);
           if (!spec.IsEmpty()) {
             nsAutoString shortcut;
             AppendUTF8toUTF16(spec, shortcut);
 
             // Add the URL DataFlavor to the transferable. Don't use kURLMime, as it will
             // cause an unnecessary UniformResourceLocator to be added which confuses
             // some apps eg. Outlook 2000 - (See Bug 315370). Don't use
             // kURLDataMime, as it will cause a bogus 'url ' flavor to
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -7076,17 +7076,18 @@ nsDocument::GetDocumentURI(nsAString& aD
   return NS_OK;
 }
 
 void
 nsIDocument::GetDocumentURI(nsString& aDocumentURI) const
 {
   if (mDocumentURI) {
     nsAutoCString uri;
-    mDocumentURI->GetSpec(uri);
+    // XXX: should handle GetSpec() failure properly. See bug 1301249.
+    Unused << mDocumentURI->GetSpec(uri);
     CopyUTF8toUTF16(uri, aDocumentURI);
   } else {
     aDocumentURI.Truncate();
   }
 }
 
 // Alias of above
 NS_IMETHODIMP
@@ -7097,24 +7098,28 @@ nsDocument::GetURL(nsAString& aURL)
 
 void
 nsIDocument::GetURL(nsString& aURL) const
 {
   return GetDocumentURI(aURL);
 }
 
 void
-nsIDocument::GetDocumentURIFromJS(nsString& aDocumentURI) const
+nsIDocument::GetDocumentURIFromJS(nsString& aDocumentURI, ErrorResult& aRv) const
 {
   if (!mChromeXHRDocURI || !nsContentUtils::IsCallerChrome()) {
     return GetDocumentURI(aDocumentURI);
   }
 
   nsAutoCString uri;
-  mChromeXHRDocURI->GetSpec(uri);
+  nsresult res = mChromeXHRDocURI->GetSpec(uri);
+  if (NS_FAILED(res)) {
+    aRv.Throw(res);
+    return;
+  }
   CopyUTF8toUTF16(uri, aDocumentURI);
 }
 
 nsIURI*
 nsIDocument::GetDocumentURIObject() const
 {
   if (!mChromeXHRDocURI) {
     return GetDocumentURI();
@@ -9592,17 +9597,21 @@ nsDocument::SetScrollToRef(nsIURI *aDocu
 
   nsAutoCString ref;
 
   // Since all URI's that pass through here aren't URL's we can't
   // rely on the nsIURI implementation for providing a way for
   // finding the 'ref' part of the URI, we'll haveto revert to
   // string routines for finding the data past '#'
 
-  aDocumentURI->GetSpec(ref);
+  nsresult rv = aDocumentURI->GetSpec(ref);
+  if (NS_FAILED(rv)) {
+    Unused << aDocumentURI->GetRef(mScrollToRef);
+    return;
+  }
 
   nsReadingIterator<char> start, end;
 
   ref.BeginReading(start);
   ref.EndReading(end);
 
   if (FindCharInReadable('#', start, end)) {
     ++start; // Skip over the '#'
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2157,16 +2157,17 @@ nsGlobalWindow::SetInitialPrincipalToSub
   MOZ_ASSERT(IsOuterWindow());
 
   // First, grab the subject principal.
   nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
 
   // We should never create windows with an expanded principal.
   // If we have a system principal, make sure we're not using it for a content
   // docshell.
+  // NOTE: Please keep this logic in sync with nsWebShellWindow::Initialize().
   if (nsContentUtils::IsExpandedPrincipal(newWindowPrincipal) ||
       (nsContentUtils::IsSystemPrincipal(newWindowPrincipal) &&
        GetDocShell()->ItemType() != nsIDocShellTreeItem::typeChrome)) {
     newWindowPrincipal = nullptr;
   }
 
   // If there's an existing document, bail if it either:
   if (mDoc) {
@@ -10167,18 +10168,20 @@ nsGlobalWindow::DispatchAsyncHashchange(
   bool oldHasHash, newHasHash;
   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&
                   NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&
                   NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&
                   NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&
                   (oldHasHash != newHasHash || !oldHash.Equals(newHash)));
 
   nsAutoCString oldSpec, newSpec;
-  aOldURI->GetSpec(oldSpec);
-  aNewURI->GetSpec(newSpec);
+  nsresult rv = aOldURI->GetSpec(oldSpec);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = aNewURI->GetSpec(newSpec);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
   NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
 
   nsCOMPtr<nsIRunnable> callback =
     new HashchangeCallback(oldWideSpec, newWideSpec, this);
   return NS_DispatchToMainThread(callback);
 }
--- a/dom/base/nsHostObjectProtocolHandler.cpp
+++ b/dom/base/nsHostObjectProtocolHandler.cpp
@@ -897,17 +897,18 @@ nsFontTableProtocolHandler::NewURI(const
 
     uri->SetRef(aSpec);
   } else {
     // Relative URIs (other than #ref) are not meaningful within the
     // fonttable: scheme.
     // If aSpec is a relative URI -other- than a bare #ref,
     // this will leave uri empty, and we'll return a failure code below.
     uri = new mozilla::net::nsSimpleURI();
-    uri->SetSpec(aSpec);
+    nsresult rv = uri->SetSpec(aSpec);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   bool schemeIs;
   if (NS_FAILED(uri->SchemeIs(FONTTABLEURI_SCHEME, &schemeIs)) || !schemeIs) {
     NS_WARNING("Non-fonttable spec in nsFontTableProtocolHander");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2467,17 +2467,18 @@ public:
   virtual mozilla::dom::DOMImplementation*
     GetImplementation(mozilla::ErrorResult& rv) = 0;
   void GetURL(nsString& retval) const;
   void GetDocumentURI(nsString& retval) const;
   // Return the URI for the document.
   // The returned value may differ if the document is loaded via XHR, and
   // when accessed from chrome privileged script and
   // from content privileged script for compatibility.
-  void GetDocumentURIFromJS(nsString& aDocumentURI) const;
+  void GetDocumentURIFromJS(nsString& aDocumentURI,
+                            mozilla::ErrorResult& aRv) const;
   void GetCompatMode(nsString& retval) const;
   void GetCharacterSet(nsAString& retval) const;
   // Skip GetContentType, because our NS_IMETHOD version above works fine here.
   // GetDoctype defined above
   Element* GetDocumentElement() const
   {
     return GetRootElement();
   }
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -689,29 +689,34 @@ nsINode::Normalize()
 
 void
 nsINode::GetBaseURI(nsAString &aURI) const
 {
   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
 
   nsAutoCString spec;
   if (baseURI) {
-    baseURI->GetSpec(spec);
+    // XXX: should handle GetSpec() failure properly. See bug 1301254.
+    Unused << baseURI->GetSpec(spec);
   }
 
   CopyUTF8toUTF16(spec, aURI);
 }
 
 void
-nsINode::GetBaseURIFromJS(nsAString& aURI) const
+nsINode::GetBaseURIFromJS(nsAString& aURI, ErrorResult& aRv) const
 {
   nsCOMPtr<nsIURI> baseURI = GetBaseURI(nsContentUtils::IsCallerChrome());
   nsAutoCString spec;
   if (baseURI) {
-    baseURI->GetSpec(spec);
+    nsresult res = baseURI->GetSpec(spec);
+    if (NS_FAILED(res)) {
+      aRv.Throw(res);
+      return;
+    }
   }
   CopyUTF8toUTF16(spec, aURI);
 }
 
 already_AddRefed<nsIURI>
 nsINode::GetBaseURIObject() const
 {
   return GetBaseURI(true);
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -1826,17 +1826,17 @@ public:
     aNodeName.SetStringBuffer(nsStringBuffer::FromString(nodeName),
                               nodeName.Length());
   }
   void GetBaseURI(nsAString& aBaseURI) const;
   // Return the base URI for the document.
   // The returned value may differ if the document is loaded via XHR, and
   // when accessed from chrome privileged script and
   // from content privileged script for compatibility.
-  void GetBaseURIFromJS(nsAString& aBaseURI) const;
+  void GetBaseURIFromJS(nsAString& aBaseURI, mozilla::ErrorResult& aRv) const;
   bool HasChildNodes() const
   {
     return HasChildren();
   }
   uint16_t CompareDocumentPosition(nsINode& aOther) const;
   void GetNodeValue(nsAString& aNodeValue)
   {
     GetNodeValueInternal(aNodeValue);
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -293,17 +293,18 @@ nsInProcessTabChildGlobal::InitTabChildG
 {
   // If you change this, please change GetCompartmentName() in XPCJSRuntime.cpp
   // accordingly.
   nsAutoCString id;
   id.AssignLiteral("inProcessTabChildGlobal");
   nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
   if (uri) {
     nsAutoCString u;
-    uri->GetSpec(u);
+    nsresult rv = uri->GetSpec(u);
+    NS_ENSURE_SUCCESS(rv, rv);
     id.AppendLiteral("?ownedBy=");
     id.Append(u);
   }
   nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
   NS_ENSURE_STATE(InitChildGlobalInternal(scopeSupports, id));
   return NS_OK;
 }
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -535,17 +535,23 @@ IsSupportedImage(const nsCString& aMimeT
 static void
 GetExtensionFromURI(nsIURI* uri, nsCString& ext)
 {
   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
   if (url) {
     url->GetFileExtension(ext);
   } else {
     nsCString spec;
-    uri->GetSpec(spec);
+    nsresult rv = uri->GetSpec(spec);
+    if (NS_FAILED(rv)) {
+      // This means we could incorrectly think a plugin is not enabled for
+      // the URI when it is, but that's not so bad.
+      ext.Truncate();
+      return;
+    }
 
     int32_t offset = spec.RFindChar('.');
     if (offset != kNotFound) {
       ext = Substring(spec, offset + 1, spec.Length());
     }
   }
 }
 
@@ -990,22 +996,22 @@ nsObjectLoadingContent::GetNestedParams(
         continue;
       }
 
       aParams.AppendElement(param);
     }
   }
 }
 
-void
+nsresult
 nsObjectLoadingContent::BuildParametersArray()
 {
   if (mCachedAttributes.Length() || mCachedParameters.Length()) {
     MOZ_ASSERT(false, "Parameters array should be empty.");
-    return;
+    return NS_OK;
   }
 
   nsCOMPtr<nsIContent> content =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   int32_t start = 0, end = content->GetAttrCount(), step = 1;
   // HTML attributes are stored in reverse order.
   if (content->IsHTMLElement() && content->IsInHTMLDocument()) {
@@ -1022,17 +1028,18 @@ nsObjectLoadingContent::BuildParametersA
     atom->ToString(param.mName);
     mCachedAttributes.AppendElement(param);
   }
 
   bool isJava = IsJavaMIME(mContentType);
 
   nsCString codebase;
   if (isJava) {
-      mBaseURI->GetSpec(codebase);
+      nsresult rv = mBaseURI->GetSpec(codebase);
+      NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsAdoptingCString wmodeOverride = Preferences::GetCString("plugins.force.wmode");
   for (uint32_t i = 0; i < mCachedAttributes.Length(); i++) {
     if (!wmodeOverride.IsEmpty() && mCachedAttributes[i].mName.EqualsIgnoreCase("wmode")) {
       CopyASCIItoUTF16(wmodeOverride, mCachedAttributes[i].mValue);
       wmodeOverride.Truncate();
     } else if (!codebase.IsEmpty() && mCachedAttributes[i].mName.EqualsIgnoreCase("codebase")) {
@@ -1066,16 +1073,18 @@ nsObjectLoadingContent::BuildParametersA
     content->GetAttr(kNameSpaceID_None, nsGkAtoms::data, param.mValue);
     if (!param.mValue.IsEmpty()) {
       param.mName = NS_LITERAL_STRING("SRC");
       mCachedAttributes.AppendElement(param);
     }
   }
 
   GetNestedParams(mCachedParameters, isJava);
+
+  return NS_OK;
 }
 
 void
 nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
 {
   // XXX(johns): We cannot touch plugins or run arbitrary script from this call,
   //             as nsDocument is in a non-reentrant state.
 
@@ -1545,17 +1554,21 @@ nsObjectLoadingContent::MaybeRewriteYout
   nsAutoCString path;
   aURI->GetPath(path);
   if (!StringBeginsWith(path, NS_LITERAL_CSTRING("/v/"))) {
     return;
   }
 
   // See if requester is planning on using the JS API.
   nsAutoCString uri;
-  aURI->GetSpec(uri);
+  nsresult rv = aURI->GetSpec(uri);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
   if (uri.Find("enablejsapi=1", true, 0, -1) != kNotFound) {
     Telemetry::Accumulate(Telemetry::YOUTUBE_NONREWRITABLE_EMBED_SEEN, 1);
     return;
   }
 
   // Some YouTube urls have parameters in path components, e.g.
   // http://youtube.com/embed/7LcUOEP7Brc&start=35. These URLs work with flash,
   // but break iframe/object embedding. If this situation occurs with rewritten
@@ -1590,20 +1603,20 @@ nsObjectLoadingContent::MaybeRewriteYout
     // Replace the first ampersand with a question mark.
     uri.SetCharAt('?', ampIndex);
   }
   // Switch out video access url formats, which should possibly allow HTML5
   // video loading.
   uri.ReplaceSubstring(NS_LITERAL_CSTRING("/v/"),
                        NS_LITERAL_CSTRING("/embed/"));
   nsAutoString utf16URI = NS_ConvertUTF8toUTF16(uri);
-  nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aOutURI,
-                                                          utf16URI,
-                                                          thisContent->OwnerDoc(),
-                                                          aBaseURI);
+  rv = nsContentUtils::NewURIWithDocumentCharset(aOutURI,
+                                                 utf16URI,
+                                                 thisContent->OwnerDoc(),
+                                                 aBaseURI);
   if (NS_FAILED(rv)) {
     return;
   }
   const char16_t* params[] = { utf16OldURI.get(), utf16URI.get() };
   const char* msgName;
   // If there's no query to rewrite, just notify in the developer console
   // that we're changing the embed.
   if (!replaceQuery) {
@@ -2392,17 +2405,18 @@ nsObjectLoadingContent::LoadObject(bool 
 
   ///
   /// Attempt to load new type
   ///
 
 
   // Cache the current attributes and parameters.
   if (mType == eType_Plugin || mType == eType_Null) {
-    BuildParametersArray();
+    rv = BuildParametersArray();
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // We don't set mFinalListener until OnStartRequest has been called, to
   // prevent re-entry ugliness with CloseChannel()
   nsCOMPtr<nsIStreamListener> finalListener;
   // If we decide to synchronously spawn a plugin, we do it after firing
   // notifications to avoid re-entry causing notifications to fire out of order.
   bool doSpawnPlugin = false;
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -375,17 +375,17 @@ class nsObjectLoadingContent : public ns
      *                        from nested <param> objects.
      * @param aIgnoreCodebase Flag for ignoring the "codebase" param when
      *                        building the array. This is useful when loading
      *                        java.
      */
     void GetNestedParams(nsTArray<mozilla::dom::MozPluginParameter>& aParameters,
                          bool aIgnoreCodebase);
 
-    void BuildParametersArray();
+    MOZ_MUST_USE nsresult BuildParametersArray();
 
     /**
      * Loads fallback content with the specified FallbackType
      *
      * @param aType   FallbackType value for type of fallback we're loading
      * @param aNotify Send notifications and events. If false, caller is
      *                responsible for doing so
      */
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3305,17 +3305,17 @@ CanvasRenderingContext2D::ArcTo(double a
   if (mPathBuilder) {
     p0 = mPathBuilder->CurrentPoint();
   } else {
     Matrix invTransform = mTarget->GetTransform();
     if (!invTransform.Invert()) {
       return;
     }
 
-    p0 = invTransform * mDSPathBuilder->CurrentPoint();
+    p0 = invTransform.TransformPoint(mDSPathBuilder->CurrentPoint());
   }
 
   Point p1(aX1, aY1);
   Point p2(aX2, aY2);
 
   // Execute these calculations in double precision to avoid cumulative
   // rounding errors.
   double dir, a2, b2, c2, cosx, sinx, d, anx, any,
@@ -3388,20 +3388,20 @@ CanvasRenderingContext2D::Rect(double aX
 
   if (mPathBuilder) {
     mPathBuilder->MoveTo(Point(aX, aY));
     mPathBuilder->LineTo(Point(aX + aW, aY));
     mPathBuilder->LineTo(Point(aX + aW, aY + aH));
     mPathBuilder->LineTo(Point(aX, aY + aH));
     mPathBuilder->Close();
   } else {
-    mDSPathBuilder->MoveTo(mTarget->GetTransform() * Point(aX, aY));
-    mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(aX + aW, aY));
-    mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(aX + aW, aY + aH));
-    mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(aX, aY + aH));
+    mDSPathBuilder->MoveTo(mTarget->GetTransform().TransformPoint(Point(aX, aY)));
+    mDSPathBuilder->LineTo(mTarget->GetTransform().TransformPoint(Point(aX + aW, aY)));
+    mDSPathBuilder->LineTo(mTarget->GetTransform().TransformPoint(Point(aX + aW, aY + aH)));
+    mDSPathBuilder->LineTo(mTarget->GetTransform().TransformPoint(Point(aX, aY + aH)));
     mDSPathBuilder->Close();
   }
 }
 
 void
 CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
                                   double aRotation, double aStartAngle, double aEndAngle,
                                   bool aAnticlockwise, ErrorResult& aError)
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -300,18 +300,18 @@ public:
 
   void MoveTo(double aX, double aY)
   {
     EnsureWritablePath();
 
     if (mPathBuilder) {
       mPathBuilder->MoveTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
     } else {
-      mDSPathBuilder->MoveTo(mTarget->GetTransform() *
-                             mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
+      mDSPathBuilder->MoveTo(mTarget->GetTransform().TransformPoint(
+                             mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))));
     }
   }
 
   void LineTo(double aX, double aY)
   {
     EnsureWritablePath();
 
     LineTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
@@ -321,20 +321,20 @@ public:
   {
     EnsureWritablePath();
 
     if (mPathBuilder) {
       mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(ToFloat(aCpx), ToFloat(aCpy)),
                                       mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
     } else {
       mozilla::gfx::Matrix transform = mTarget->GetTransform();
-      mDSPathBuilder->QuadraticBezierTo(transform *
-                                        mozilla::gfx::Point(ToFloat(aCpx), ToFloat(aCpy)),
-                                        transform *
-                                        mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
+      mDSPathBuilder->QuadraticBezierTo(transform.TransformPoint(
+                                          mozilla::gfx::Point(ToFloat(aCpx), ToFloat(aCpy))),
+                                        transform.TransformPoint(
+                                          mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))));
     }
   }
 
   void BezierCurveTo(double aCp1x, double aCp1y, double aCp2x, double aCp2y, double aX, double aY)
   {
     EnsureWritablePath();
 
     BezierTo(mozilla::gfx::Point(ToFloat(aCp1x), ToFloat(aCp1y)),
@@ -512,31 +512,31 @@ public:
     return mCanvasElement;
   }
 
   void LineTo(const mozilla::gfx::Point& aPoint)
   {
     if (mPathBuilder) {
       mPathBuilder->LineTo(aPoint);
     } else {
-      mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
+      mDSPathBuilder->LineTo(mTarget->GetTransform().TransformPoint(aPoint));
     }
   }
 
   void BezierTo(const mozilla::gfx::Point& aCP1,
                 const mozilla::gfx::Point& aCP2,
                 const mozilla::gfx::Point& aCP3)
   {
     if (mPathBuilder) {
       mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
     } else {
       mozilla::gfx::Matrix transform = mTarget->GetTransform();
-      mDSPathBuilder->BezierTo(transform * aCP1,
-                                transform * aCP2,
-                                transform * aCP3);
+      mDSPathBuilder->BezierTo(transform.TransformPoint(aCP1),
+                               transform.TransformPoint(aCP2),
+                               transform.TransformPoint(aCP3));
     }
   }
 
   friend class CanvasRenderingContext2DUserData;
 
   virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override;
 
 
--- a/dom/canvas/WebGLExtensionDrawBuffers.cpp
+++ b/dom/canvas/WebGLExtensionDrawBuffers.cpp
@@ -43,18 +43,21 @@ WebGLExtensionDrawBuffers::DrawBuffersWE
     mContext->DrawBuffers(buffers);
 }
 
 bool
 WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
 {
     gl::GLContext* gl = webgl->GL();
 
-    if (!gl->IsSupported(gl::GLFeature::draw_buffers))
+    if (!gl->IsExtensionSupported(gl::GLContext::ARB_draw_buffers) &&
+        !gl->IsExtensionSupported(gl::GLContext::EXT_draw_buffers))
+    {
         return false;
+    }
 
     // WEBGL_draw_buffers requires at least 4 color attachments.
     if (webgl->mGLMaxDrawBuffers < webgl->kMinMaxDrawBuffers ||
         webgl->mGLMaxColorAttachments < webgl->kMinMaxColorAttachments)
     {
         return false;
     }
 
--- a/dom/flyweb/FlyWebPublishedServer.cpp
+++ b/dom/flyweb/FlyWebPublishedServer.cpp
@@ -166,16 +166,26 @@ NS_IMPL_ISUPPORTS_INHERITED0(FlyWebPubli
 
 FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(nsPIDOMWindowInner* aOwner,
                                                      const nsAString& aName,
                                                      const FlyWebPublishOptions& aOptions)
   : FlyWebPublishedServer(aOwner, aName, aOptions)
   , mHttpServer(new HttpServer())
 {
   LOG_I("FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(%p)", this);
+}
+
+void
+FlyWebPublishedServerImpl::PermissionGranted(bool aGranted)
+{
+  LOG_I("FlyWebPublishedServerImpl::PermissionGranted(%b)", aGranted);
+  if (!aGranted) {
+    PublishedServerStarted(NS_ERROR_FAILURE);
+    return;
+  }
 
   mHttpServer->Init(-1, Preferences::GetBool("flyweb.use-tls", false), this);
 }
 
 void
 FlyWebPublishedServerImpl::Close()
 {
   FlyWebPublishedServer::Close();
@@ -247,72 +257,84 @@ FlyWebPublishedServerImpl::OnWebSocketAc
 }
 
 /******** FlyWebPublishedServerChild ********/
 
 FlyWebPublishedServerChild::FlyWebPublishedServerChild(nsPIDOMWindowInner* aOwner,
                                                        const nsAString& aName,
                                                        const FlyWebPublishOptions& aOptions)
   : FlyWebPublishedServer(aOwner, aName, aOptions)
-  , mActorDestroyed(false)
+  , mActorExists(false)
 {
   LOG_I("FlyWebPublishedServerChild::FlyWebPublishedServerChild(%p)", this);
 
-  ContentChild::GetSingleton()->
-    SendPFlyWebPublishedServerConstructor(this,
-                                          PromiseFlatString(aName),
-                                          aOptions);
-
   // The matching release happens when the actor is destroyed, in
   // ContentChild::DeallocPFlyWebPublishedServerChild
   NS_ADDREF_THIS();
 }
 
+void
+FlyWebPublishedServerChild::PermissionGranted(bool aGranted)
+{
+  if (!aGranted) {
+    PublishedServerStarted(NS_ERROR_FAILURE);
+    return;
+  }
+
+  mActorExists = true;
+  FlyWebPublishOptions options;
+  options.mUiUrl = mUiUrl;
+
+  // Proceed with initialization.
+  ContentChild::GetSingleton()->
+    SendPFlyWebPublishedServerConstructor(this, mName, options);
+}
+
 bool
 FlyWebPublishedServerChild::RecvServerReady(const nsresult& aStatus)
 {
   LOG_I("FlyWebPublishedServerChild::RecvServerReady(%p)", this);
-  MOZ_ASSERT(!mActorDestroyed);
+  MOZ_ASSERT(mActorExists);
 
   PublishedServerStarted(aStatus);
   return true;
 }
 
 bool
 FlyWebPublishedServerChild::RecvServerClose()
 {
   LOG_I("FlyWebPublishedServerChild::RecvServerClose(%p)", this);
-  MOZ_ASSERT(!mActorDestroyed);
+  MOZ_ASSERT(mActorExists);
 
   Close();
 
   return true;
 }
 
 bool
 FlyWebPublishedServerChild::RecvFetchRequest(const IPCInternalRequest& aRequest,
                                              const uint64_t& aRequestId)
 {
   LOG_I("FlyWebPublishedServerChild::RecvFetchRequest(%p)", this);
-  MOZ_ASSERT(!mActorDestroyed);
+  MOZ_ASSERT(mActorExists);
 
   RefPtr<InternalRequest> request = new InternalRequest(aRequest);
   mPendingRequests.Put(request, aRequestId);
   FireFetchEvent(request);
 
   return true;
 }
 
 bool
 FlyWebPublishedServerChild::RecvWebSocketRequest(const IPCInternalRequest& aRequest,
                                                  const uint64_t& aRequestId,
                                                  PTransportProviderChild* aProvider)
 {
   LOG_I("FlyWebPublishedServerChild::RecvWebSocketRequest(%p)", this);
-  MOZ_ASSERT(!mActorDestroyed);
+  MOZ_ASSERT(mActorExists);
 
   RefPtr<InternalRequest> request = new InternalRequest(aRequest);
   mPendingRequests.Put(request, aRequestId);
 
   // Not addreffing here. The addref was already done when the
   // PTransportProvider child constructor original ran.
   mPendingTransportProviders.Put(aRequestId,
     dont_AddRef(static_cast<TransportProviderChild*>(aProvider)));
@@ -322,26 +344,26 @@ FlyWebPublishedServerChild::RecvWebSocke
   return true;
 }
 
 void
 FlyWebPublishedServerChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG_I("FlyWebPublishedServerChild::ActorDestroy(%p)", this);
 
-  mActorDestroyed = true;
+  mActorExists = false;
 }
 
 void
 FlyWebPublishedServerChild::OnFetchResponse(InternalRequest* aRequest,
                                             InternalResponse* aResponse)
 {
   LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p)", this);
 
-  if (mActorDestroyed) {
+  if (!mActorExists) {
     LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p) - No actor!", this);
     return;
   }
 
   uint64_t id = mPendingRequests.Get(aRequest);
   MOZ_ASSERT(id);
   mPendingRequests.Remove(aRequest);
 
@@ -356,17 +378,17 @@ FlyWebPublishedServerChild::OnFetchRespo
 
 already_AddRefed<nsITransportProvider>
 FlyWebPublishedServerChild::OnWebSocketAcceptInternal(InternalRequest* aRequest,
                                                       const Optional<nsAString>& aProtocol,
                                                       ErrorResult& aRv)
 {
   LOG_I("FlyWebPublishedServerChild::OnWebSocketAcceptInternal(%p)", this);
 
-  if (mActorDestroyed) {
+  if (!mActorExists) {
     LOG_I("FlyWebPublishedServerChild::OnWebSocketAcceptInternal(%p) - No actor!", this);
     return nullptr;
   }
 
   uint64_t id = mPendingRequests.Get(aRequest);
   MOZ_ASSERT(id);
   mPendingRequests.Remove(aRequest);
 
@@ -395,17 +417,17 @@ FlyWebPublishedServerChild::OnWebSocketA
 }
 
 void
 FlyWebPublishedServerChild::OnWebSocketResponse(InternalRequest* aRequest,
                                                 InternalResponse* aResponse)
 {
   LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p)", this);
 
-  if (mActorDestroyed) {
+  if (!mActorExists) {
     LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p) - No actor!", this);
     return;
   }
 
   uint64_t id = mPendingRequests.Get(aRequest);
   MOZ_ASSERT(id);
   mPendingRequests.Remove(aRequest);
 
@@ -423,17 +445,17 @@ FlyWebPublishedServerChild::OnWebSocketR
 
 void
 FlyWebPublishedServerChild::Close()
 {
   LOG_I("FlyWebPublishedServerChild::Close(%p)", this);
 
   FlyWebPublishedServer::Close();
 
-  if (!mActorDestroyed) {
+  if (mActorExists) {
     LOG_I("FlyWebPublishedServerChild::Close - sending __delete__ (%p)", this);
 
     Send__delete__(this);
   }
 }
 
 /******** FlyWebPublishedServerParent ********/
 
--- a/dom/flyweb/FlyWebPublishedServer.h
+++ b/dom/flyweb/FlyWebPublishedServer.h
@@ -52,16 +52,18 @@ public:
     return mName;
   }
 
   void GetUiUrl(nsAString& aUiUrl)
   {
     aUiUrl = mUiUrl;
   }
 
+  virtual void PermissionGranted(bool aGranted) = 0;
+
   virtual void OnFetchResponse(InternalRequest* aRequest,
                                InternalResponse* aResponse) = 0;
   already_AddRefed<WebSocket>
     OnWebSocketAccept(InternalRequest* aConnectRequest,
                       const Optional<nsAString>& aProtocol,
                       ErrorResult& aRv);
   virtual void OnWebSocketResponse(InternalRequest* aConnectRequest,
                                    InternalResponse* aResponse) = 0;
--- a/dom/flyweb/FlyWebPublishedServerIPC.h
+++ b/dom/flyweb/FlyWebPublishedServerIPC.h
@@ -45,16 +45,17 @@ public:
   void GetCertKey(nsACString& aKey) {
     if (mHttpServer) {
       mHttpServer->GetCertKey(aKey);
     } else {
       aKey.Truncate();
     }
   }
 
+  virtual void PermissionGranted(bool aGranted) override;
   virtual void OnFetchResponse(InternalRequest* aRequest,
                                InternalResponse* aResponse) override;
   virtual void OnWebSocketResponse(InternalRequest* aConnectRequest,
                                    InternalResponse* aResponse) override;
   virtual already_AddRefed<nsITransportProvider>
     OnWebSocketAcceptInternal(InternalRequest* aConnectRequest,
                               const Optional<nsAString>& aProtocol,
                               ErrorResult& aRv) override;
@@ -93,16 +94,17 @@ private:
 class FlyWebPublishedServerChild final : public FlyWebPublishedServer
                                        , public PFlyWebPublishedServerChild
 {
 public:
   FlyWebPublishedServerChild(nsPIDOMWindowInner* aOwner,
                              const nsAString& aName,
                              const FlyWebPublishOptions& aOptions);
 
+  virtual void PermissionGranted(bool aGranted) override;
   virtual bool RecvServerReady(const nsresult& aStatus) override;
   virtual bool RecvServerClose() override;
   virtual bool RecvFetchRequest(const IPCInternalRequest& aRequest,
                                 const uint64_t& aRequestId) override;
   virtual bool RecvWebSocketRequest(const IPCInternalRequest& aRequest,
                                     const uint64_t& aRequestId,
                                     PTransportProviderChild* aProvider) override;
 
@@ -120,17 +122,17 @@ public:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   ~FlyWebPublishedServerChild() {}
 
   nsDataHashtable<nsRefPtrHashKey<InternalRequest>, uint64_t> mPendingRequests;
   nsRefPtrHashtable<nsUint64HashKey, TransportProviderChild>
     mPendingTransportProviders;
-  bool mActorDestroyed;
+  bool mActorExists;
 };
 
 class FlyWebPublishedServerParent final : public PFlyWebPublishedServerParent
                                         , public nsIDOMEventListener
 {
 public:
   FlyWebPublishedServerParent(const nsAString& aName,
                               const FlyWebPublishOptions& aOptions);
--- a/dom/flyweb/FlyWebService.cpp
+++ b/dom/flyweb/FlyWebService.cpp
@@ -4,46 +4,160 @@
  * 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 "mozilla/dom/FlyWebService.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/FlyWebPublishedServerIPC.h"
+#include "mozilla/AddonPathService.h"
 #include "nsISocketTransportService.h"
 #include "mdns/libmdns/nsDNSServiceInfo.h"
 #include "nsIUUIDGenerator.h"
 #include "nsStandardURL.h"
 #include "mozilla/Services.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/dom/FlyWebDiscoveryManagerBinding.h"
 #include "prnetdb.h"
 #include "DNS.h"
+#include "nsContentPermissionHelper.h"
 #include "nsSocketTransportService2.h"
 #include "nsSocketTransport2.h"
 #include "nsHashPropertyBag.h"
 #include "nsNetUtil.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIProperty.h"
 #include "nsICertOverrideService.h"
 
 namespace mozilla {
 namespace dom {
 
 struct FlyWebPublishOptions;
 
 static LazyLogModule gFlyWebServiceLog("FlyWebService");
 #undef LOG_I
 #define LOG_I(...) MOZ_LOG(mozilla::dom::gFlyWebServiceLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+
 #undef LOG_E
 #define LOG_E(...) MOZ_LOG(mozilla::dom::gFlyWebServiceLog, mozilla::LogLevel::Error, (__VA_ARGS__))
+
 #undef LOG_TEST_I
 #define LOG_TEST_I(...) MOZ_LOG_TEST(mozilla::dom::gFlyWebServiceLog, mozilla::LogLevel::Debug)
 
+class FlyWebPublishServerPermissionCheck final
+  : public nsIContentPermissionRequest
+  , public nsIRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  FlyWebPublishServerPermissionCheck(const nsCString& aServiceName, uint64_t aWindowID,
+                                     FlyWebPublishedServer* aServer)
+    : mServiceName(aServiceName)
+    , mWindowID(aWindowID)
+    , mServer(aServer)
+  {}
+
+  uint64_t WindowID() const
+  {
+    return mWindowID;
+  }
+
+  NS_IMETHOD Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsGlobalWindow* globalWindow = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
+    if (!globalWindow) {
+      return Cancel();
+    }
+    mWindow = globalWindow->AsInner();
+    if (NS_WARN_IF(!mWindow)) {
+      return Cancel();
+    }
+
+    nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
+    if (NS_WARN_IF(!doc)) {
+      return Cancel();
+    }
+
+    mPrincipal = doc->NodePrincipal();
+    MOZ_ASSERT(mPrincipal);
+
+    mRequester = new nsContentPermissionRequester(mWindow);
+    return nsContentPermissionUtils::AskPermission(this, mWindow);
+  }
+
+  NS_IMETHOD Cancel() override
+  {
+    Resolve(false);
+    return NS_OK;
+  }
+
+  NS_IMETHOD Allow(JS::HandleValue aChoices) override
+  {
+    MOZ_ASSERT(aChoices.isUndefined());
+    Resolve(true);
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetTypes(nsIArray** aTypes) override
+  {
+    nsTArray<nsString> emptyOptions;
+    return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("flyweb-publish-server"),
+                                                           NS_LITERAL_CSTRING("unused"), emptyOptions, aTypes);
+  }
+
+  NS_IMETHOD GetRequester(nsIContentPermissionRequester** aRequester) override
+  {
+    NS_ENSURE_ARG_POINTER(aRequester);
+    nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
+    requester.forget(aRequester);
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetPrincipal(nsIPrincipal** aRequestingPrincipal) override
+  {
+    NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetWindow(mozIDOMWindow** aRequestingWindow) override
+  {
+    NS_IF_ADDREF(*aRequestingWindow = mWindow);
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetElement(nsIDOMElement** aRequestingElement) override
+  {
+    *aRequestingElement = nullptr;
+    return NS_OK;
+  }
+
+private:
+  void Resolve(bool aResolve)
+  {
+    mServer->PermissionGranted(aResolve);
+  }
+
+  virtual ~FlyWebPublishServerPermissionCheck() = default;
+
+  nsCString mServiceName;
+  uint64_t mWindowID;
+  RefPtr<FlyWebPublishedServer> mServer;
+  nsCOMPtr<nsPIDOMWindowInner> mWindow;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCOMPtr<nsIContentPermissionRequester> mRequester;
+};
+
+NS_IMPL_ISUPPORTS(FlyWebPublishServerPermissionCheck,
+                  nsIContentPermissionRequest,
+                  nsIRunnable)
+
 class FlyWebMDNSService final
   : public nsIDNSServiceDiscoveryListener
   , public nsIDNSServiceResolveListener
   , public nsIDNSRegistrationListener
   , public nsITimerCallback
 {
   friend class FlyWebService;
 
@@ -836,39 +950,88 @@ FlyWebService::Init()
       mMDNSFlywebService = nullptr;
       rv.SuppressException();
     }
   }
 
   return ErrorResult(NS_OK);
 }
 
+static already_AddRefed<FlyWebPublishPromise>
+MakeRejectionPromise(const char* name)
+{
+    MozPromiseHolder<FlyWebPublishPromise> holder;
+    RefPtr<FlyWebPublishPromise> promise = holder.Ensure(name);
+    holder.Reject(NS_ERROR_FAILURE, name);
+    return promise.forget();
+}
+
 already_AddRefed<FlyWebPublishPromise>
 FlyWebService::PublishServer(const nsAString& aName,
                              const FlyWebPublishOptions& aOptions,
                              nsPIDOMWindowInner* aWindow)
 {
   // Scan uiUrl for illegal characters
 
   RefPtr<FlyWebPublishedServer> existingServer =
     FlyWebService::GetOrCreate()->FindPublishedServerByName(aName);
   if (existingServer) {
     LOG_I("PublishServer: Trying to publish server with already-existing name %s.",
           NS_ConvertUTF16toUTF8(aName).get());
-    MozPromiseHolder<FlyWebPublishPromise> holder;
-    RefPtr<FlyWebPublishPromise> promise = holder.Ensure(__func__);
-    holder.Reject(NS_ERROR_FAILURE, __func__);
-    return promise.forget();
+    return MakeRejectionPromise(__func__);
   }
 
   RefPtr<FlyWebPublishedServer> server;
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     server = new FlyWebPublishedServerChild(aWindow, aName, aOptions);
   } else {
     server = new FlyWebPublishedServerImpl(aWindow, aName, aOptions);
+
+    // Before proceeding, ensure that the FlyWeb system addon exists.
+    nsresult rv;
+    nsCOMPtr<nsIURI> uri;
+    rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("chrome://flyweb/skin/icon-64.png"));
+    if (NS_FAILED(rv)) {
+      return MakeRejectionPromise(__func__);
+    }
+
+    JSAddonId *addonId = MapURIToAddonID(uri);
+    if (!addonId) {
+      LOG_E("PublishServer: Failed to find FlyWeb system addon.");
+      return MakeRejectionPromise(__func__);
+    }
+
+    JSFlatString* flat = JS_ASSERT_STRING_IS_FLAT(JS::StringOfAddonId(addonId));
+    nsAutoString addonIdString;
+    AssignJSFlatString(addonIdString, flat);
+    if (!addonIdString.EqualsLiteral("flyweb@mozilla.org")) {
+      nsCString addonIdCString = NS_ConvertUTF16toUTF8(addonIdString);
+      LOG_E("PublishServer: FlyWeb resource found on wrong system addon: %s.", addonIdCString.get());
+      return MakeRejectionPromise(__func__);
+    }
+  }
+
+  if (aWindow) {
+    nsresult rv;
+
+    MOZ_ASSERT(NS_IsMainThread());
+    rv = NS_DispatchToCurrentThread(
+      MakeAndAddRef<FlyWebPublishServerPermissionCheck>(
+        NS_ConvertUTF16toUTF8(aName), aWindow->WindowID(), server));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      LOG_E("PublishServer: Failed to dispatch permission check runnable for %s",
+            NS_ConvertUTF16toUTF8(aName).get());
+      return MakeRejectionPromise(__func__);
+    }
+  } else {
+    // If aWindow is null, we're definitely in the e10s parent process.
+    // In this case, we know that permission has already been granted
+    // by the user because of content-process prompt.
+    MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+    server->PermissionGranted(true);
   }
 
   mServers.AppendElement(server);
 
   return server->GetPublishPromise();
 }
 
 already_AddRefed<FlyWebPublishedServer>
--- a/dom/grid/test/chrome/test_grid_track_state.html
+++ b/dom/grid/test/chrome/test_grid_track_state.html
@@ -7,67 +7,143 @@
 <style>
 body {
 	margin: 40px;
 }
 .wrapper {
 	display: grid;
 	width: 600px;
 	grid-gap: 0px;
-	grid-template-columns: 50px repeat(auto-fit, 100px);
 	background-color: #f00;
 }
-.wrapper2 {
-	display: grid;
-	width: 600px;
-	grid-gap: 0px;
+.grid1 {
+	grid-template-columns: 50px 0 repeat(auto-fit, 100px);
+}
+.grid2 {
+	grid-template-columns: 50px 0 [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
+}
+.grid3 {
+	grid-template-columns: repeat(3, 66px) [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
+}
+.grid4 {
 	grid-template-columns: repeat(2, 100px) repeat(auto-fill, 50px);
-	background-color: #f00;
+}
+.grid5 {
+	grid-template-columns: [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
 }
 .box {
 	background-color: #444;
 	color: #fff;
 }
 .a {
-	grid-column: 3;
+	grid-column: auto;
+}
+.b {
+	grid-column: 4;
 }
+.c {
+	grid-column: 6;
+}
+.d {
+	grid-column: 7;
+}
+
 </style>
 
 <script>
 'use strict';
 
 SimpleTest.waitForExplicitFinish();
 
 function runTests() {
-	var wrapper = document.getElementById("wrapper");
-	var grid = wrapper.getGridFragments()[0];
+	let wrapper = document.getElementById("wrapper1");
+	let grid = wrapper.getGridFragments()[0];
 	
 	// test auto-fit count after removal
-	is(grid.cols.tracks.length, 2, "Grid column track array compensates for removed auto-fit columns.");
+	is(grid.cols.tracks.length, 3, "Grid column track array compensates for removed auto-fit columns.");
+	
+	// test resolved value of grid-template-columns
+	let templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
+	is(templateColumnsText, "50px 0px 0px 100px 0px 0px 0px",
+		"Resolved value of grid-template-columns reports removed auto-fits as '0px'.");
+	
+	is(grid.cols.tracks[0].breadth, 50, "Column 1 is breadth 50.");
+	is(grid.cols.tracks[1].breadth, 0, "Column 2 is breadth 0.");
+	is(grid.cols.tracks[2].breadth, 100, "Column 3 is breadth 100.");
+
+	
+	wrapper = document.getElementById("wrapper2");
+	grid = wrapper.getGridFragments()[0];
 	
-	var wrapper2 = document.getElementById("wrapper2");
-	var grid2 = wrapper2.getGridFragments()[0];
+	// test resolved value of grid-template-columns
+	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
+	is(templateColumnsText, "50px 0px [real-before before] 0px [after before] 100px [after before] 0px [after before] 100px [after before] 0px [after real-after]",
+		"Resolved value of grid-template-columns reports lines for removed tracks.");
+	
+	
+	wrapper = document.getElementById("wrapper3");
+	grid = wrapper.getGridFragments()[0];
+	
+	// test resolved value of grid-template-columns
+	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
+	is(templateColumnsText, "66px 66px 66px [real-before before] 100px [after before] 0px [after before] 100px [after before] 100px [after real-after]",
+		"Resolved value of grid-template-columns reports lines for removed tracks.");
+	
+	
+	wrapper = document.getElementById("wrapper4");
+	grid = wrapper.getGridFragments()[0];
 	
 	// test auto-fill count of tracks
-	is(grid2.cols.tracks.length, 10, "Grid column track array respects auto-fill columns.");
+	is(grid.cols.tracks.length, 10, "Grid column track array respects auto-fill columns.");
 	
-	if (grid2.cols.tracks.length == 10) {
+	if (grid.cols.tracks.length == 10) {
 		// test for static and repeat
-		is(grid2.cols.tracks[1].state, "static", "Grid column track 2 is marked as static.");
-		is(grid2.cols.tracks[2].state, "repeat", "Grid column track 3 is marked as repeat.");
+		is(grid.cols.tracks[1].state, "static", "Grid column track 2 is marked as static.");
+		is(grid.cols.tracks[2].state, "repeat", "Grid column track 3 is marked as repeat.");
 	}
 	
+	
+	wrapper = document.getElementById("wrapper5");
+	grid = wrapper.getGridFragments()[0];
+	
+	// test resolved value of grid-template-columns
+	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
+	is(templateColumnsText, "[real-before before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after real-after]",
+		"Resolved value of grid-template-columns no longer lists 'none' when all auto-fit tracks are empty.");
+	
 	SimpleTest.finish();
 }
 </script>
 </head>
 <body onLoad="runTests();">
 
-	<div id="wrapper" class="wrapper">
+	<div id="wrapper1" class="wrapper grid1">
+		<div id="boxB" class="box b">B</div>
+	</div>
+		
+	<br/>
+	
+	<div id="wrapper2" class="wrapper grid2">
+		<div id="boxB" class="box b">B</div>
+		<div id="boxC" class="box c">C</div>
+	</div>
+		
+	<br/>
+	
+	<div id="wrapper3" class="wrapper grid3">
+		<div id="boxB" class="box b">B</div>
+		<div id="boxC" class="box c">C</div>
+		<div id="boxD" class="box d">D</div>
+	</div>
+		
+	<br/>
+	
+	<div id="wrapper4" class="wrapper grid4">
 		<div id="boxA" class="box a">A</div>
 	</div>
 	
-	<div id="wrapper2" class="wrapper2">
-		<div id="boxB" class="box b">B</div>
+	<br/>
+	
+	<div id="wrapper5" class="wrapper grid5">
 	</div>
 	
 </body>
 </html>
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -212,16 +212,17 @@ const Decimal HTMLInputElement::kStepSca
 const Decimal HTMLInputElement::kStepScaleFactorMonth = Decimal(1);
 const Decimal HTMLInputElement::kDefaultStepBase = Decimal(0);
 const Decimal HTMLInputElement::kDefaultStep = Decimal(1);
 const Decimal HTMLInputElement::kDefaultStepTime = Decimal(60);
 const Decimal HTMLInputElement::kStepAny = Decimal(0);
 
 const double HTMLInputElement::kMaximumYear = 275760;
 const double HTMLInputElement::kMinimumYear = 1;
+const double HTMLInputElement::kMaximumWeekInYear = 53;
 
 #define NS_INPUT_ELEMENT_STATE_IID                 \
 { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */       \
   0xdc3b3d14,                                      \
   0x23e2,                                          \
   0x4479,                                          \
   {0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
 }
@@ -5042,16 +5043,23 @@ HTMLInputElement::SanitizeValue(nsAStrin
       break;
     case NS_FORM_INPUT_MONTH:
       {
         if (!aValue.IsEmpty() && !IsValidMonth(aValue)) {
           aValue.Truncate();
         }
       }
       break;
+    case NS_FORM_INPUT_WEEK:
+      {
+        if (!aValue.IsEmpty() && !IsValidWeek(aValue)) {
+          aValue.Truncate();
+        }
+      }
+      break;
     case NS_FORM_INPUT_COLOR:
       {
         if (IsValidSimpleColor(aValue)) {
           ToLowerCase(aValue);
         } else {
           // Set default (black) color, if aValue wasn't parsed correctly.
           aValue.AssignLiteral("#000000");
         }
@@ -5072,16 +5080,53 @@ bool HTMLInputElement::IsValidSimpleColo
         !(aValue[i] >= 'A' && aValue[i] <= 'F')) {
       return false;
     }
   }
   return true;
 }
 
 bool
+HTMLInputElement::IsLeapYear(uint32_t aYear) const
+{
+  if ((aYear % 4 == 0 && aYear % 100 != 0) || ( aYear % 400 == 0)) {
+    return true;
+  }
+  return false;
+}
+
+uint32_t
+HTMLInputElement::DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay) const
+{
+  // Tomohiko Sakamoto algorithm.
+  int monthTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
+  aYear -= aMonth < 3;
+
+  return (aYear + aYear / 4 - aYear / 100 + aYear / 400 +
+          monthTable[aMonth - 1] + aDay) % 7;
+}
+
+uint32_t
+HTMLInputElement::MaximumWeekInYear(uint32_t aYear) const
+{
+  int day = DayOfWeek(aYear, 1, 1); // January 1.
+  // A year starting on Thursday or a leap year starting on Wednesday has 53
+  // weeks. All other years have 52 weeks.
+  return day == 4 || (day == 3 && IsLeapYear(aYear)) ? kMaximumWeekInYear
+                                                     : kMaximumWeekInYear - 1;
+}
+
+bool
+HTMLInputElement::IsValidWeek(const nsAString& aValue) const
+{
+  uint32_t year, week;
+  return ParseWeek(aValue, &year, &week);
+}
+
+bool
 HTMLInputElement::IsValidMonth(const nsAString& aValue) const
 {
   uint32_t year, month;
   return ParseMonth(aValue, &year, &month);
 }
 
 bool
 HTMLInputElement::IsValidDate(const nsAString& aValue) const
@@ -5118,16 +5163,44 @@ bool HTMLInputElement::ParseMonth(const 
   if (!ParseYear(yearStr, aYear)) {
     return false;
   }
 
   return DigitSubStringToNumber(aValue, endOfYearOffset + 1, 2, aMonth) &&
          *aMonth > 0 && *aMonth <= 12;
 }
 
+bool HTMLInputElement::ParseWeek(const nsAString& aValue,
+                                 uint32_t* aYear,
+                                 uint32_t* aWeek) const
+{
+  // Parse the year, month values out a string formatted as 'yyyy-Www'.
+  if (aValue.Length() < 8) {
+    return false;
+  }
+
+  uint32_t endOfYearOffset = aValue.Length() - 4;
+  if (aValue[endOfYearOffset] != '-') {
+    return false;
+  }
+
+  if (aValue[endOfYearOffset + 1] != 'W') {
+    return false;
+  }
+
+  const nsAString& yearStr = Substring(aValue, 0, endOfYearOffset);
+  if (!ParseYear(yearStr, aYear)) {
+    return false;
+  }
+
+  return DigitSubStringToNumber(aValue, endOfYearOffset + 2, 2, aWeek) &&
+         *aWeek > 0 && *aWeek <= MaximumWeekInYear(*aYear);
+
+}
+
 bool HTMLInputElement::ParseDate(const nsAString& aValue,
                                  uint32_t* aYear,
                                  uint32_t* aMonth,
                                  uint32_t* aDay) const
 {
 /*
  * Parse the year, month, day values out a date string formatted as 'yyyy-mm-dd'.
  * -The year must be 4 or more digits long, and year > 0
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -1160,17 +1160,25 @@ protected:
    * Parse a color string of the form #XXXXXX where X should be hexa characters
    * @param the string to be parsed.
    * @return whether the string is a valid simple color.
    * Note : this function does not consider the empty string as valid.
    */
   bool IsValidSimpleColor(const nsAString& aValue) const;
 
   /**
-   * Parse a date string of the form yyyy-mm
+   * Parse a week string of the form yyyy-Www
+   * @param the string to be parsed.
+   * @return whether the string is a valid week.
+   * Note : this function does not consider the empty string as valid.
+   */
+  bool IsValidWeek(const nsAString& aValue) const;
+
+  /**
+   * Parse a month string of the form yyyy-mm
    * @param the string to be parsed.
    * @return whether the string is a valid month.
    * Note : this function does not consider the empty string as valid.
    */
   bool IsValidMonth(const nsAString& aValue) const;
 
   /**
    * Parse a date string of the form yyyy-mm-dd
@@ -1197,16 +1205,26 @@ protected:
    * @return the year and month in aYear and aMonth.
    * @return whether the parsing was successful.
    */
   bool ParseMonth(const nsAString& aValue,
                   uint32_t* aYear,
                   uint32_t* aMonth) const;
 
   /**
+   * Parse a week string of the form yyyy-Www
+   *
+   * @param the string to be parsed.
+   * @return the year and week in aYear and aWeek.
+   * @return whether the parsing was successful.
+   */
+  bool ParseWeek(const nsAString& aValue,
+                 uint32_t* aYear,
+                 uint32_t* aWeek) const;
+  /**
    * Parse a date string of the form yyyy-mm-dd
    *
    * @param the string to be parsed.
    * @return the date in aYear, aMonth, aDay.
    * @return whether the parsing was successful.
    */
   bool ParseDate(const nsAString& aValue,
                  uint32_t* aYear,
@@ -1220,16 +1238,32 @@ protected:
 
   /**
    * This methods returns the number of months between January 1970 and the
    * given year and month.
    */
   int32_t MonthsSinceJan1970(uint32_t aYear, uint32_t aMonth) const;
 
   /**
+   * This methods returns the day of the week given a date, note that 0 = Sunday.
+   */
+  uint32_t DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay) const;
+
+  /**
+   * This methods returns the maximum number of week in a given year, the
+   * result is either 52 or 53.
+   */
+  uint32_t MaximumWeekInYear(uint32_t aYear) const;
+
+  /**
+   * This methods returns true if it's a leap year.
+   */
+  bool IsLeapYear(uint32_t aYear) const;
+
+  /**
    * Returns whether aValue is a valid time as described by HTML specifications:
    * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
    *
    * @param aValue the string to be tested.
    * @return Whether the string is a valid time per HTML specifications.
    */
   bool IsValidTime(const nsAString& aValue) const;
 
@@ -1455,16 +1489,18 @@ protected:
 
   // Float value returned by GetStep() when the step attribute is set to 'any'.
   static const Decimal kStepAny;
 
   // Maximum year limited by ECMAScript date object range, year <= 275760.
   static const double kMaximumYear;
   // Minimum year limited by HTML standard, year >= 1.
   static const double kMinimumYear;
+  // Long years in a ISO calendar have 53 weeks in them.
+  static const double kMaximumWeekInYear;
 
   /**
    * The type of this input (<input type=...>) as an integer.
    * @see nsIFormControl.h (specifically NS_FORM_INPUT_*)
    */
   uint8_t                  mType;
   nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
   bool                     mDisabledChanged     : 1;
--- a/dom/html/test/forms/test_input_sanitization.html
+++ b/dom/html/test/forms/test_input_sanitization.html
@@ -69,17 +69,17 @@ function flushDelayedTests(description)
 }
 
 // We are excluding "file" because it's too different from the other types.
 // And it has no sanitizing algorithm.
 var inputTypes =
 [
   "text", "password", "search", "tel", "hidden", "checkbox", "radio",
   "submit", "image", "reset", "button", "email", "url", "number", "date",
-  "time", "range", "color", "month"
+  "time", "range", "color", "month", "week"
 ];
 
 var todoTypes =
 [
   "datetime", "datetime-local",
 ];
 
 var valueModeValue =
@@ -186,16 +186,46 @@ function sanitizeValue(aType, aValue)
         return "";
       }
       var month = Number(match[2]);
       if (month > 12 || month < 1) {
         return "";
       }
       return aValue;
     case "week":
+      // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-week-string
+      function isLeapYear(aYear) {
+        return ((aYear % 4 == 0) && (aYear % 100 != 0)) || (aYear % 400 == 0);
+      }
+      function getDayofWeek(aYear, aMonth, aDay) { /* 0 = Sunday */
+        // Tomohiko Sakamoto algorithm.
+        var monthTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
+        aYear -= Number(aMonth < 3);
+
+        return (aYear + parseInt(aYear / 4) - parseInt(aYear / 100) +
+                parseInt(aYear / 400) + monthTable[aMonth - 1] + aDay) % 7;
+      }
+      function getMaximumWeekInYear(aYear) {
+        var day = getDayofWeek(aYear, 1, 1);
+        return day == 4 || (day == 3 && isLeapYear(aYear)) ? 53 : 52;
+      }
+
+      var match = /^([0-9]{4,})-W([0-9]{2})$/.exec(aValue);
+      if (!match) {
+        return "";
+      }
+      var year = Number(match[1]);
+      if (year === 0) {
+        return "";
+      }
+      var week = Number(match[2]);
+      if (week > 53 || month < 1) {
+        return "";
+      }
+      return 1 <= week && week <= getMaximumWeekInYear(year) ? aValue : "";
     case "datetime":
     case "datetime-local":
       // TODO: write the sanitize algorithm.
       ok(false);
       return "";
     case "color":
       return /^#[0-9A-Fa-f]{6}$/.exec(aValue) ? aValue.toLowerCase() : "#000000";
     default:
@@ -360,16 +390,37 @@ function checkSanitizing(element, inputT
     "2013-03-13",
     "december",
     "abcdef",
     "12",
     "  2013-03",
     "2013 - 03",
     "2013 03",
     "2013/03",
+    // For week
+    "1970-W01",
+    "1970-W53",
+    "1964-W53",
+    "1900-W10",
+    "2004-W53",
+    "2065-W53",
+    "2099-W53",
+    "2010-W53",
+    "2016-W30",
+    "1900-W3",
+    "2016-w30",
+    "2016-30",
+    "16-W30",
+    "2016-Week30",
+    "2000-100",
+    "0000-W01",
+    "00-W01",
+    "123456-W05",
+    "1985-W100",
+    "week",
   ];
 
   for (value of testData) {
     element.setAttribute('value', value);
     delayed_is(element.value, sanitizeValue(type, value),
        "The value has not been correctly sanitized for type=" + type);
     delayed_is(element.getAttribute('value'), value,
        "The content value should not have been sanitized");
--- a/dom/html/test/forms/test_input_typing_sanitization.html
+++ b/dom/html/test/forms/test_input_typing_sanitization.html
@@ -193,16 +193,34 @@ function runTest()
         '-',
         'december',
         '2012-dec',
         '2012/12',
         '2012-99',
         '2012-1',
       ]
     },
+    {
+      type: 'week',
+      validData: [
+        '0001-W01',
+        '1970-W53',
+        '100000-W52',
+        '2016-W30',
+      ],
+      invalidData: [
+        '1-W01',
+        'week',
+        '2016-30',
+        '2010-W80',
+        '2000/W30',
+        '1985-W00',
+        '1000-W'
+      ]
+    },
     { type: 'datetime', todo: true },
     { type: 'datetime-local', todo: true },
   ];
 
   for (test of data) {
     gCurrentTest = test;
 
     if (test.todo) {
--- a/dom/html/test/test_bug590363.html
+++ b/dom/html/test/test_bug590363.html
@@ -43,55 +43,58 @@ var testData = [
   [ 'week',     true ]
   // 'file' is treated separatly.
 ];
 
 var todoTypes = [
   "datetime", "datetime-local"
 ];
 
-var nonTrivialSanitizing = [ 'number', 'date', 'time', 'color', 'month' ];
+var nonTrivialSanitizing = [ 'number', 'date', 'time', 'color', 'month', 'week' ];
 
 var length = testData.length;
 for (var i=0; i<length; ++i) {
   for (var j=0; j<length; ++j) {
     var e = document.createElement('input');
     e.type = testData[i][0];
 
     var expectedValue;
 
     // range will sanitize its value to 50 (the default) if it isn't a valid
     // number. We need to handle that specially.
     if (testData[j][0] == 'range' || testData[i][0] == 'range') {
       if (testData[j][0] == 'date' || testData[j][0] == 'time' ||
-          testData[j][0] == 'month') {
+          testData[j][0] == 'month' || testData[j][0] == 'week') {
         expectedValue = '';
       } else if (testData[j][0] == 'color') {
         expectedValue = '#000000';
       } else {
         expectedValue = '50';
       }
     } else if (testData[i][0] == 'color' || testData[j][0] == 'color') {
         if (testData[j][0] == 'number' || testData[j][0] == 'date' ||
-            testData[j][0] == 'time' || testData[j][0] == 'month') {
+            testData[j][0] == 'time' || testData[j][0] == 'month' ||
+            testData[j][0] == 'week') {
           expectedValue = ''
         } else {
           expectedValue = '#000000';
         }
     } else if (nonTrivialSanitizing.indexOf(testData[i][0]) != -1 &&
                nonTrivialSanitizing.indexOf(testData[j][0]) != -1) {
       expectedValue = '';
     } else if (testData[i][0] == 'number' || testData[j][0] == 'number') {
       expectedValue = '42';
     } else if (testData[i][0] == 'date' || testData[j][0] == 'date') {
       expectedValue = '2012-12-21';
     } else if (testData[i][0] == 'time' || testData[j][0] == 'time') {
       expectedValue = '21:21';
     } else if (testData[i][0] == 'month' || testData[j][0] == 'month') {
       expectedValue = '2013-03';
+    } else if (testData[i][0] == 'week' || testData[j][0] == 'week') {
+      expectedValue = '2016-W35';
     } else {
       expectedValue = "foo";
     }
     e.value = expectedValue;
 
     e.type = testData[j][0];
     is(e.value, expectedValue, ".value should still return the same value after " +
        "changing type from " + testData[i][0] + " to " + testData[j][0]);
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -903,28 +903,24 @@ MediaFormatReader::RequestDemuxSamples(T
   LOGV("Requesting extra demux %s", TrackTypeToStr(aTrack));
   if (aTrack == TrackInfo::kVideoTrack) {
     DoDemuxVideo();
   } else {
     DoDemuxAudio();
   }
 }
 
-bool
+void
 MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
                                         MediaRawData* aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   auto& decoder = GetDecoderData(aTrack);
-  if (NS_FAILED(decoder.mDecoder->Input(aSample))) {
-      LOG("Unable to pass frame to decoder");
-      return false;
-  }
+  decoder.mDecoder->Input(aSample);
   decoder.mDecodePending = true;
-  return true;
 }
 
 void
 MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
                                         AbstractMediaDecoder::AutoNotifyDecoded& aA)
 {
   MOZ_ASSERT(OnTaskQueue());
 
@@ -1014,19 +1010,18 @@ MediaFormatReader::HandleDemuxedSamples(
     decoder.mNumSamplesInput++;
     decoder.mSizeOfQueue++;
     if (aTrack == TrackInfo::kVideoTrack) {
       aA.mStats.mParsedFrames++;
     }
 
     if (mDemuxOnly) {
       ReturnOutput(sample, aTrack);
-    } else if (!DecodeDemuxedSamples(aTrack, sample)) {
-      NotifyError(aTrack);
-      return;
+    } else {
+      DecodeDemuxedSamples(aTrack, sample);
     }
 
     decoder.mQueuedSamples.RemoveElementAt(0);
     if (mDemuxOnly) {
       // If demuxed-only case, ReturnOutput will resolve with one demuxed data.
       // Then we should stop doing the iteration.
       return;
     }
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -128,17 +128,17 @@ private:
   // Returns true if no more action is required.
   bool UpdateReceivedNewData(TrackType aTrack);
   // Called when new samples need to be demuxed.
   void RequestDemuxSamples(TrackType aTrack);
   // Handle demuxed samples by the input behavior.
   void HandleDemuxedSamples(TrackType aTrack,
                             AbstractMediaDecoder::AutoNotifyDecoded& aA);
   // Decode any pending already demuxed samples.
-  bool DecodeDemuxedSamples(TrackType aTrack,
+  void DecodeDemuxedSamples(TrackType aTrack,
                             MediaRawData* aSample);
 
   struct InternalSeekTarget {
     InternalSeekTarget(const media::TimeInterval& aTime, bool aDropTarget)
       : mTime(aTime)
       , mDropTarget(aDropTarget)
       , mWaiting(false)
       , mHasSeeked(false)
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -205,16 +205,20 @@ public:
 //
 // Don't block inside these functions, unless it's explicitly noted that you
 // should (like in Flush()).
 //
 // Decoding is done asynchronously. Any async work can be done on the
 // TaskQueue passed into the PlatformDecoderModules's Create*Decoder()
 // function. This may not be necessary for platforms with async APIs
 // for decoding.
+//
+// If an error occurs at any point after the Init promise has been
+// completed, then Error() must be called on the associated
+// MediaDataDecoderCallback.
 class MediaDataDecoder {
 protected:
   virtual ~MediaDataDecoder() {};
 
 public:
   enum class DecoderFailureReason : uint8_t {
     INIT_ERROR,
     CANCELED
@@ -230,62 +234,59 @@ public:
   // than in its constructor or PlatformDecoderModule::Create*Decoder(),
   // so that if the MediaFormatReader needs to shutdown during initialization,
   // it can call Shutdown() to cancel this operation. Any initialization
   // that requires blocking the calling thread in this function *must*
   // be done here so that it can be canceled by calling Shutdown()!
   virtual RefPtr<InitPromise> Init() = 0;
 
   // Inserts a sample into the decoder's decode pipeline.
-  virtual nsresult Input(MediaRawData* aSample) = 0;
+  virtual void Input(MediaRawData* aSample) = 0;
 
   // Causes all samples in the decoding pipeline to be discarded. When
   // this function returns, the decoder must be ready to accept new input
   // for decoding. This function is called when the demuxer seeks, before
   // decoding resumes after the seek.
   // While the reader calls Flush(), it ignores all output sent to it;
   // it is safe (but pointless) to send output while Flush is called.
   // The MediaFormatReader will not call Input() while it's calling Flush().
-  virtual nsresult Flush() = 0;
+  virtual void Flush() = 0;
 
   // Causes all complete samples in the pipeline that can be decoded to be
   // output. If the decoder can't produce samples from the current output,
   // it drops the input samples. The decoder may be holding onto samples
   // that are required to decode samples that it expects to get in future.
   // This is called when the demuxer reaches end of stream.
   // The MediaFormatReader will not call Input() while it's calling Drain().
   // This function is asynchronous. The MediaDataDecoder must call
   // MediaDataDecoderCallback::DrainComplete() once all remaining
   // samples have been output.
-  virtual nsresult Drain() = 0;
+  virtual void Drain() = 0;
 
   // Cancels all init/input/drain operations, and shuts down the
   // decoder. The platform decoder should clean up any resources it's using
   // and release memory etc. Shutdown() must block until the decoder has
   // completed shutdown. The reader calls Flush() before calling Shutdown().
   // The reader will delete the decoder once Shutdown() returns.
   // The MediaDataDecoderCallback *must* not be called after Shutdown() has
   // returned.
-  virtual nsresult Shutdown() = 0;
+  virtual void Shutdown() = 0;
 
   // Called from the state machine task queue or main thread.
   // Decoder needs to decide whether or not hardware accelearation is supported
   // after creating. It doesn't need to call Init() before calling this function.
   virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
 
   // ConfigurationChanged will be called to inform the video or audio decoder
   // that the format of the next input sample is about to change.
   // If video decoder, aConfig will be a VideoInfo object.
   // If audio decoder, aConfig will be a AudioInfo object.
   // It is not safe to store a reference to this object and the decoder must
   // make a copy.
-  virtual nsresult ConfigurationChanged(const TrackInfo& aConfig)
-  {
-    return NS_OK;
-  }
+  virtual void ConfigurationChanged(const TrackInfo& aConfig) {}
 
   // Return the name of the MediaDataDecoder, only used for decoding.
   // Only return a static const string, as the information may be accessed
   // in a non thread-safe fashion.
   virtual const char* GetDescriptionName() const = 0;
 
   // Set a hint of seek target time to decoder. Decoder will drop any decoded
   // data which pts is smaller than this value. This threshold needs to be clear
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -39,47 +39,40 @@ public:
     , mType(aParams.mConfig.GetType())
   {
   }
 
   RefPtr<InitPromise> Init() override {
     return InitPromise::CreateAndResolve(mType, __func__);
   }
 
-  nsresult Shutdown() override {
-    return NS_OK;
-  }
+  void Shutdown() override {}
 
-  nsresult Input(MediaRawData* aSample) override
+  void Input(MediaRawData* aSample) override
   {
     RefPtr<MediaData> data =
       mCreator->Create(media::TimeUnit::FromMicroseconds(aSample->mTime),
                        media::TimeUnit::FromMicroseconds(aSample->mDuration),
                        aSample->mOffset);
 
     OutputFrame(data);
-
-    return NS_OK;
   }
 
-  nsresult Flush() override
+  void Flush() override
   {
     mReorderQueue.Clear();
-
-    return NS_OK;
   }
 
-  nsresult Drain() override
+  void Drain() override
   {
     while (!mReorderQueue.IsEmpty()) {
       mCallback->Output(mReorderQueue.Pop().get());
     }
 
     mCallback->DrainComplete();
-    return NS_OK;
   }
 
   const char* GetDescriptionName() const override
   {
     return "blank media data decoder";
   }
 
 private:
--- a/dom/media/platforms/agnostic/OpusDecoder.cpp
+++ b/dom/media/platforms/agnostic/OpusDecoder.cpp
@@ -36,20 +36,19 @@ OpusDataDecoder::OpusDataDecoder(const C
 OpusDataDecoder::~OpusDataDecoder()
 {
   if (mOpusDecoder) {
     opus_multistream_decoder_destroy(mOpusDecoder);
     mOpusDecoder = nullptr;
   }
 }
 
-nsresult
+void
 OpusDataDecoder::Shutdown()
 {
-  return NS_OK;
 }
 
 void
 OpusDataDecoder::AppendCodecDelay(MediaByteBuffer* config, uint64_t codecDelayUS)
 {
   uint8_t buffer[sizeof(uint64_t)];
   BigEndian::writeUint64(buffer, codecDelayUS);
   config->AppendElements(buffer, sizeof(uint64_t));
@@ -133,23 +132,21 @@ OpusDataDecoder::DecodeHeader(const unsi
     // Should never get here as vorbis layout is always convertible to SMPTE
     // default layout.
     PodCopy(mMappingTable, mOpusParser->mMappingTable, MAX_AUDIO_CHANNELS);
   }
 
   return NS_OK;
 }
 
-nsresult
+void
 OpusDataDecoder::Input(MediaRawData* aSample)
 {
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
                        this, &OpusDataDecoder::ProcessDecode, aSample));
-
-  return NS_OK;
 }
 
 void
 OpusDataDecoder::ProcessDecode(MediaRawData* aSample)
 {
   if (mIsFlushing) {
     return;
   }
@@ -318,41 +315,39 @@ OpusDataDecoder::DoDecode(MediaRawData* 
 }
 
 void
 OpusDataDecoder::ProcessDrain()
 {
   mCallback->DrainComplete();
 }
 
-nsresult
+void
 OpusDataDecoder::Drain()
 {
   mTaskQueue->Dispatch(NewRunnableMethod(this, &OpusDataDecoder::ProcessDrain));
-  return NS_OK;
 }
 
-nsresult
+void
 OpusDataDecoder::Flush()
 {
   if (!mOpusDecoder) {
-    return NS_OK;
+    return;
   }
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([this] () {
     MOZ_ASSERT(mOpusDecoder);
     // Reset the decoder.
     opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
     mSkip = mOpusParser->mPreSkip;
     mPaddingDiscarded = false;
     mLastFrameTime.reset();
   });
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
-  return NS_OK;
 }
 
 /* static */
 bool
 OpusDataDecoder::IsOpus(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("audio/webm; codecs=opus") ||
          aMimeType.EqualsLiteral("audio/ogg; codecs=opus") ||
--- a/dom/media/platforms/agnostic/OpusDecoder.h
+++ b/dom/media/platforms/agnostic/OpusDecoder.h
@@ -16,20 +16,20 @@ namespace mozilla {
 
 class OpusDataDecoder : public MediaDataDecoder
 {
 public:
   explicit OpusDataDecoder(const CreateDecoderParams& aParams);
   ~OpusDataDecoder();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "opus audio decoder";
   }
 
   // Return true if mimetype is Opus
   static bool IsOpus(const nsACString& aMimeType);
 
--- a/dom/media/platforms/agnostic/TheoraDecoder.cpp
+++ b/dom/media/platforms/agnostic/TheoraDecoder.cpp
@@ -53,24 +53,23 @@ TheoraDecoder::TheoraDecoder(const Creat
 TheoraDecoder::~TheoraDecoder()
 {
   MOZ_COUNT_DTOR(TheoraDecoder);
   th_setup_free(mTheoraSetupInfo);
   th_comment_clear(&mTheoraComment);
   th_info_clear(&mTheoraInfo);
 }
 
-nsresult
+void
 TheoraDecoder::Shutdown()
 {
   if (mTheoraDecoderContext) {
     th_decode_free(mTheoraDecoderContext);
     mTheoraDecoderContext = nullptr;
   }
-  return NS_OK;
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 TheoraDecoder::Init()
 {
   th_comment_init(&mTheoraComment);
   th_info_init(&mTheoraInfo);
 
@@ -94,27 +93,26 @@ TheoraDecoder::Init()
   if (mTheoraDecoderContext) {
     return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
   } else {
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
 }
 
-nsresult
+void
 TheoraDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([this] () {
     // nothing to do for now.
   });
   SyncRunnable::DispatchToThread(mTaskQueue, r);
   mIsFlushing = false;
-  return NS_OK;
 }
 
 nsresult
 TheoraDecoder::DoDecodeHeader(const unsigned char* aData, size_t aLength)
 {
   bool bos = mPacketCount == 0;
   ogg_packet pkt = InitTheoraPacket(aData, aLength, bos, false, 0, mPacketCount++);
 
@@ -202,40 +200,36 @@ TheoraDecoder::ProcessDecode(MediaRawDat
   }
   if (DoDecode(aSample) == -1) {
     mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
   } else {
     mCallback->InputExhausted();
   }
 }
 
-nsresult
+void
 TheoraDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
                        this, &TheoraDecoder::ProcessDecode, aSample));
-
-  return NS_OK;
 }
 
 void
 TheoraDecoder::ProcessDrain()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   mCallback->DrainComplete();
 }
 
-nsresult
+void
 TheoraDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod(this, &TheoraDecoder::ProcessDrain));
-
-  return NS_OK;
 }
 
 /* static */
 bool
 TheoraDecoder::IsTheora(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("video/ogg; codecs=theora");
 }
--- a/dom/media/platforms/agnostic/TheoraDecoder.h
+++ b/dom/media/platforms/agnostic/TheoraDecoder.h
@@ -19,20 +19,20 @@ namespace mozilla {
 class TheoraDecoder : public MediaDataDecoder
 {
 public:
   explicit TheoraDecoder(const CreateDecoderParams& aParams);
 
   ~TheoraDecoder();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
 
   // Return true if mimetype is a Theora codec
   static bool IsTheora(const nsACString& aMimeType);
 
   const char* GetDescriptionName() const override
   {
     return "theora video decoder";
   }
--- a/dom/media/platforms/agnostic/VPXDecoder.cpp
+++ b/dom/media/platforms/agnostic/VPXDecoder.cpp
@@ -46,21 +46,20 @@ VPXDecoder::VPXDecoder(const CreateDecod
   PodZero(&mVPX);
 }
 
 VPXDecoder::~VPXDecoder()
 {
   MOZ_COUNT_DTOR(VPXDecoder);
 }
 
-nsresult
+void
 VPXDecoder::Shutdown()
 {
   vpx_codec_destroy(&mVPX);
-  return NS_OK;
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 VPXDecoder::Init()
 {
   int decode_threads = 2;
 
   vpx_codec_iface_t* dx = nullptr;
@@ -81,27 +80,26 @@ VPXDecoder::Init()
   config.w = config.h = 0; // set after decode
 
   if (!dx || vpx_codec_dec_init(&mVPX, dx, &config, 0)) {
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
   return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
 }
 
-nsresult
+void
 VPXDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([this] () {
     // nothing to do for now.
   });
   SyncRunnable::DispatchToThread(mTaskQueue, r);
   mIsFlushing = false;
-  return NS_OK;
 }
 
 int
 VPXDecoder::DoDecode(MediaRawData* aSample)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
 #if defined(DEBUG)
   vpx_codec_stream_info_t si;
@@ -194,40 +192,36 @@ VPXDecoder::ProcessDecode(MediaRawData* 
   }
   if (DoDecode(aSample) == -1) {
     mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
   } else {
     mCallback->InputExhausted();
   }
 }
 
-nsresult
+void
 VPXDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
                        this, &VPXDecoder::ProcessDecode, aSample));
-
-  return NS_OK;
 }
 
 void
 VPXDecoder::ProcessDrain()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   mCallback->DrainComplete();
 }
 
-nsresult
+void
 VPXDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod(this, &VPXDecoder::ProcessDrain));
-
-  return NS_OK;
 }
 
 /* static */
 bool
 VPXDecoder::IsVPX(const nsACString& aMimeType, uint8_t aCodecMask)
 {
   return ((aCodecMask & VPXDecoder::VP8) &&
           aMimeType.EqualsLiteral("video/webm; codecs=vp8")) ||
--- a/dom/media/platforms/agnostic/VPXDecoder.h
+++ b/dom/media/platforms/agnostic/VPXDecoder.h
@@ -20,20 +20,20 @@ using namespace layers;
 
 class VPXDecoder : public MediaDataDecoder
 {
 public:
   explicit VPXDecoder(const CreateDecoderParams& aParams);
   ~VPXDecoder();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "libvpx video decoder";
   }
 
   enum Codec: uint8_t {
     VP8 = 1 << 0,
     VP9 = 1 << 1
--- a/dom/media/platforms/agnostic/VorbisDecoder.cpp
+++ b/dom/media/platforms/agnostic/VorbisDecoder.cpp
@@ -49,21 +49,19 @@ VorbisDataDecoder::VorbisDataDecoder(con
 VorbisDataDecoder::~VorbisDataDecoder()
 {
   vorbis_block_clear(&mVorbisBlock);
   vorbis_dsp_clear(&mVorbisDsp);
   vorbis_info_clear(&mVorbisInfo);
   vorbis_comment_clear(&mVorbisComment);
 }
 
-nsresult
+void
 VorbisDataDecoder::Shutdown()
 {
-  //mReader = nullptr;
-  return NS_OK;
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 VorbisDataDecoder::Init()
 {
   vorbis_info_init(&mVorbisInfo);
   vorbis_comment_init(&mVorbisComment);
   PodZero(&mVorbisDsp);
@@ -119,24 +117,22 @@ VorbisDataDecoder::DecodeHeader(const un
   MOZ_ASSERT(mPacketCount <= 3);
 
   int r = vorbis_synthesis_headerin(&mVorbisInfo,
                                     &mVorbisComment,
                                     &pkt);
   return r == 0 ? NS_OK : NS_ERROR_FAILURE;
 }
 
-nsresult
+void
 VorbisDataDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
                        this, &VorbisDataDecoder::ProcessDecode, aSample));
-
-  return NS_OK;
 }
 
 void
 VorbisDataDecoder::ProcessDecode(MediaRawData* aSample)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   if (mIsFlushing) {
     return;
@@ -250,39 +246,37 @@ VorbisDataDecoder::DoDecode(MediaRawData
 
 void
 VorbisDataDecoder::ProcessDrain()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   mCallback->DrainComplete();
 }
 
-nsresult
+void
 VorbisDataDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mTaskQueue->Dispatch(NewRunnableMethod(this, &VorbisDataDecoder::ProcessDrain));
-  return NS_OK;
 }
 
-nsresult
+void
 VorbisDataDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([this] () {
     // Ignore failed results from vorbis_synthesis_restart. They
     // aren't fatal and it fails when ResetDecode is called at a
     // time when no vorbis data has been read.
     vorbis_synthesis_restart(&mVorbisDsp);
     mLastFrameTime.reset();
   });
   SyncRunnable::DispatchToThread(mTaskQueue, r);
   mIsFlushing = false;
-  return NS_OK;
 }
 
 /* static */
 bool
 VorbisDataDecoder::IsVorbis(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("audio/webm; codecs=vorbis") ||
          aMimeType.EqualsLiteral("audio/ogg; codecs=vorbis");
--- a/dom/media/platforms/agnostic/VorbisDecoder.h
+++ b/dom/media/platforms/agnostic/VorbisDecoder.h
@@ -20,20 +20,20 @@ namespace mozilla {
 
 class VorbisDataDecoder : public MediaDataDecoder
 {
 public:
   explicit VorbisDataDecoder(const CreateDecoderParams& aParams);
   ~VorbisDataDecoder();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "vorbis audio decoder";
   }
 
   // Return true if mimetype is Vorbis
   static bool IsVorbis(const nsACString& aMimeType);
   static const AudioConfig::Channel* VorbisLayout(uint32_t aChannels);
--- a/dom/media/platforms/agnostic/WAVDecoder.cpp
+++ b/dom/media/platforms/agnostic/WAVDecoder.cpp
@@ -46,37 +46,35 @@ DecodeULawSample(uint8_t aValue)
 }
 
 WaveDataDecoder::WaveDataDecoder(const CreateDecoderParams& aParams)
   : mInfo(aParams.AudioConfig())
   , mCallback(aParams.mCallback)
 {
 }
 
-nsresult
+void
 WaveDataDecoder::Shutdown()
 {
-  return NS_OK;
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 WaveDataDecoder::Init()
 {
   return InitPromise::CreateAndResolve(TrackInfo::kAudioTrack, __func__);
 }
 
-nsresult
+void
 WaveDataDecoder::Input(MediaRawData* aSample)
 {
   if (!DoDecode(aSample)) {
     mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
   } else {
     mCallback->InputExhausted();
   }
-  return NS_OK;
 }
 
 bool
 WaveDataDecoder::DoDecode(MediaRawData* aSample)
 {
   size_t aLength = aSample->Size();
   ByteReader aReader(aSample->Data(), aLength);
   int64_t aOffset = aSample->mOffset;
@@ -126,27 +124,25 @@ WaveDataDecoder::DoDecode(MediaRawData* 
                                   frames,
                                   Move(buffer),
                                   mInfo.mChannels,
                                   mInfo.mRate));
 
   return true;
 }
 
-nsresult
+void
 WaveDataDecoder::Drain()
 {
   mCallback->DrainComplete();
-  return NS_OK;
 }
 
-nsresult
+void
 WaveDataDecoder::Flush()
 {
-  return NS_OK;
 }
 
 /* static */
 bool
 WaveDataDecoder::IsWave(const nsACString& aMimeType)
 {
   // Some WebAudio uses "audio/x-wav",
   // WAVdemuxer uses "audio/wave; codecs=aNum".
--- a/dom/media/platforms/agnostic/WAVDecoder.h
+++ b/dom/media/platforms/agnostic/WAVDecoder.h
@@ -16,20 +16,20 @@ class WaveDataDecoder : public MediaData
 {
 public:
   explicit WaveDataDecoder(const CreateDecoderParams& aParams);
 
   // Return true if mimetype is Wave
   static bool IsWave(const nsACString& aMimeType);
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "wave audio decoder";
   }
 
 private:
   bool DoDecode(MediaRawData* aSample);
 
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -40,36 +40,36 @@ public:
   {
   }
 
   RefPtr<InitPromise> Init() override {
     MOZ_ASSERT(!mIsShutdown);
     return mDecoder->Init();
   }
 
-  nsresult Input(MediaRawData* aSample) override {
+  void Input(MediaRawData* aSample) override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     if (mIsShutdown) {
       NS_WARNING("EME encrypted sample arrived after shutdown");
-      return NS_OK;
+      return;
     }
     if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
-      return NS_OK;
+      return;
     }
 
     nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter());
     mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId,
                                   writer->mCrypto.mSessionIds);
 
     mDecrypts.Put(aSample, new DecryptPromiseRequestHolder());
     mDecrypts.Get(aSample)->Begin(mProxy->Decrypt(aSample)->Then(
       mTaskQueue, __func__, this,
       &EMEDecryptor::Decrypted,
       &EMEDecryptor::Decrypted));
-    return NS_OK;
+    return;
   }
 
   void Decrypted(const DecryptResult& aDecrypted) {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(aDecrypted.mSample);
 
     nsAutoPtr<DecryptPromiseRequestHolder> holder;
     mDecrypts.RemoveAndForget(aDecrypted.mSample, holder);
@@ -99,60 +99,53 @@ public:
       MOZ_ASSERT(!mIsShutdown);
       // The Adobe GMP AAC decoder gets confused if we pass it non-encrypted
       // samples with valid crypto data. So clear the crypto data, since the
       // sample should be decrypted now anyway. If we don't do this and we're
       // using the Adobe GMP for unencrypted decoding of data that is decrypted
       // by gmp-clearkey, decoding will fail.
       UniquePtr<MediaRawDataWriter> writer(aDecrypted.mSample->CreateWriter());
       writer->mCrypto = CryptoSample();
-      nsresult rv = mDecoder->Input(aDecrypted.mSample);
-      Unused << NS_WARN_IF(NS_FAILED(rv));
+      mDecoder->Input(aDecrypted.mSample);
     }
   }
 
-  nsresult Flush() override {
+  void Flush() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
     for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) {
       nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data();
       holder->DisconnectIfExists();
       iter.Remove();
     }
-    nsresult rv = mDecoder->Flush();
-    Unused << NS_WARN_IF(NS_FAILED(rv));
+    mDecoder->Flush();
     mSamplesWaitingForKey->Flush();
-    return rv;
   }
 
-  nsresult Drain() override {
+  void Drain() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
     for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) {
       nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data();
       holder->DisconnectIfExists();
       iter.Remove();
     }
-    nsresult rv = mDecoder->Drain();
-    Unused << NS_WARN_IF(NS_FAILED(rv));
-    return rv;
+    mDecoder->Drain();
   }
 
-  nsresult Shutdown() override {
+  void Shutdown() override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(!mIsShutdown);
     mIsShutdown = true;
-    nsresult rv = mDecoder->Shutdown();
-    Unused << NS_WARN_IF(NS_FAILED(rv));
+    mDecoder->Shutdown();
     mSamplesWaitingForKey->BreakCycles();
     mSamplesWaitingForKey = nullptr;
     mDecoder = nullptr;
     mProxy = nullptr;
     mCallback = nullptr;
-    return rv;
   }
 
   const char* GetDescriptionName() const override {
     return mDecoder->GetDescriptionName();
   }
 
 private:
 
@@ -173,48 +166,46 @@ public:
                            TaskQueue* aTaskQueue)
    : MediaDataDecoderProxy(Move(aProxyThread), aCallback)
    , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aCallback,
                                                     aTaskQueue, aProxy))
    , mProxy(aProxy)
   {
   }
 
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Shutdown() override;
 
 private:
   RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
   RefPtr<CDMProxy> mProxy;
 };
 
-nsresult
+void
 EMEMediaDataDecoderProxy::Input(MediaRawData* aSample)
 {
   if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
-    return NS_OK;
+    return;
   }
 
   nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter());
   mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId,
                                 writer->mCrypto.mSessionIds);
 
-  return MediaDataDecoderProxy::Input(aSample);
+  MediaDataDecoderProxy::Input(aSample);
 }
 
-nsresult
+void
 EMEMediaDataDecoderProxy::Shutdown()
 {
-  nsresult rv = MediaDataDecoderProxy::Shutdown();
+  MediaDataDecoderProxy::Shutdown();
 
   mSamplesWaitingForKey->BreakCycles();
   mSamplesWaitingForKey = nullptr;
   mProxy = nullptr;
-
-  return rv;
 }
 
 EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM)
   : mProxy(aProxy)
   , mPDM(aPDM)
 {
 }
 
--- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp
@@ -234,71 +234,62 @@ GMPAudioDecoder::Init()
   UniquePtr<GetGMPAudioDecoderCallback> callback(new GMPInitDoneCallback(this));
   if (NS_FAILED(mMPS->GetGMPAudioDecoder(mCrashHelper, &tags, GetNodeId(), Move(callback)))) {
     mInitPromise.Reject(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   return promise;
 }
 
-nsresult
+void
 GMPAudioDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   RefPtr<MediaRawData> sample(aSample);
   if (!mGMP) {
     mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    return NS_ERROR_FAILURE;
+    return;
   }
 
   mAdapter->SetLastStreamOffset(sample->mOffset);
 
   gmp::GMPAudioSamplesImpl samples(sample, mConfig.mChannels, mConfig.mRate);
   nsresult rv = mGMP->Decode(samples);
   if (NS_FAILED(rv)) {
     mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
-    return rv;
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPAudioDecoder::Flush()
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   if (!mGMP || NS_FAILED(mGMP->Reset())) {
     // Abort the flush.
     mCallback->FlushComplete();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPAudioDecoder::Drain()
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   if (!mGMP || NS_FAILED(mGMP->Drain())) {
     mCallback->DrainComplete();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPAudioDecoder::Shutdown()
 {
   mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::CANCELED, __func__);
   if (!mGMP) {
-    return NS_ERROR_FAILURE;
+    return;
   }
   // Note this unblocks flush and drain operations waiting for callbacks.
   mGMP->Close();
   mGMP = nullptr;
-
-  return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h
+++ b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h
@@ -60,20 +60,20 @@ struct GMPAudioDecoderParams {
   RefPtr<GMPCrashHelper> mCrashHelper;
 };
 
 class GMPAudioDecoder : public MediaDataDecoder {
 public:
   explicit GMPAudioDecoder(const GMPAudioDecoderParams& aParams);
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "GMP audio decoder";
   }
 
 protected:
   virtual void InitTags(nsTArray<nsCString>& aTags);
   virtual nsCString GetNodeId();
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
@@ -308,77 +308,68 @@ GMPVideoDecoder::Init()
   UniquePtr<GetGMPVideoDecoderCallback> callback(new GMPInitDoneCallback(this));
   if (NS_FAILED(mMPS->GetGMPVideoDecoder(mCrashHelper, &tags, GetNodeId(), Move(callback)))) {
     mInitPromise.Reject(MediaDataDecoder::DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   return promise;
 }
 
-nsresult
+void
 GMPVideoDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   RefPtr<MediaRawData> sample(aSample);
   if (!mGMP) {
     mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    return NS_ERROR_FAILURE;
+    return;
   }
 
   mAdapter->SetLastStreamOffset(sample->mOffset);
 
   GMPUniquePtr<GMPVideoEncodedFrame> frame = CreateFrame(sample);
   if (!frame) {
     mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    return NS_ERROR_FAILURE;
+    return;
   }
   nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
   nsresult rv = mGMP->Decode(Move(frame), false, info, 0);
   if (NS_FAILED(rv)) {
     mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
-    return rv;
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPVideoDecoder::Flush()
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   if (!mGMP || NS_FAILED(mGMP->Reset())) {
     // Abort the flush.
     mCallback->FlushComplete();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPVideoDecoder::Drain()
 {
   MOZ_ASSERT(IsOnGMPThread());
 
   if (!mGMP || NS_FAILED(mGMP->Drain())) {
     mCallback->DrainComplete();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 GMPVideoDecoder::Shutdown()
 {
   mInitPromise.RejectIfExists(MediaDataDecoder::DecoderFailureReason::CANCELED, __func__);
   // Note that this *may* be called from the proxy thread also.
   if (!mGMP) {
-    return NS_ERROR_FAILURE;
+    return;
   }
   // Note this unblocks flush and drain operations waiting for callbacks.
   mGMP->Close();
   mGMP = nullptr;
-
-  return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
@@ -65,20 +65,20 @@ struct GMPVideoDecoderParams {
   RefPtr<GMPCrashHelper> mCrashHelper;
 };
 
 class GMPVideoDecoder : public MediaDataDecoder {
 public:
   explicit GMPVideoDecoder(const GMPVideoDecoderParams& aParams);
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   const char* GetDescriptionName() const override
   {
     return "GMP video decoder";
   }
 
 protected:
   virtual void InitTags(nsTArray<nsCString>& aTags);
   virtual nsCString GetNodeId();
--- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp
+++ b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp
@@ -33,66 +33,59 @@ RefPtr<MediaDataDecoder::InitPromise>
 MediaDataDecoderProxy::Init()
 {
   MOZ_ASSERT(!mIsShutdown);
 
   return InvokeAsync(mProxyThread, this, __func__,
                      &MediaDataDecoderProxy::InternalInit);
 }
 
-nsresult
+void
 MediaDataDecoderProxy::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   nsCOMPtr<nsIRunnable> task(new InputTask(mProxyDecoder, aSample));
   mProxyThread->Dispatch(task.forget());
-
-  return NS_OK;
 }
 
-nsresult
+void
 MediaDataDecoderProxy::Flush()
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   mFlushComplete.Set(false);
 
   mProxyThread->Dispatch(NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Flush));
 
   mFlushComplete.WaitUntil(true);
-
-  return NS_OK;
 }
 
-nsresult
+void
 MediaDataDecoderProxy::Drain()
 {
   MOZ_ASSERT(!IsOnProxyThread());
   MOZ_ASSERT(!mIsShutdown);
 
   mProxyThread->Dispatch(NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Drain));
-  return NS_OK;
 }
 
-nsresult
+void
 MediaDataDecoderProxy::Shutdown()
 {
   // Note that this *may* be called from the proxy thread also.
   MOZ_ASSERT(!mIsShutdown);
 #if defined(DEBUG)
   mIsShutdown = true;
 #endif
-  nsresult rv = mProxyThread->AsXPCOMThread()->Dispatch(NewRunnableMethod(mProxyDecoder,
-                                                                          &MediaDataDecoder::Shutdown),
-                                                        NS_DISPATCH_SYNC);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
+  mProxyThread->AsXPCOMThread()->Dispatch(NewRunnableMethod(mProxyDecoder,
+                                                            &MediaDataDecoder::Shutdown),
+                                          NS_DISPATCH_SYNC);
 }
 
 void
 MediaDataDecoderProxy::FlushComplete()
 {
   mFlushComplete.Set(true);
 }
 
--- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
+++ b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
@@ -135,20 +135,20 @@ public:
     mProxyDecoder = aProxyDecoder;
   }
 
   // These are called from the decoder thread pool.
   // Init and Shutdown run synchronously on the proxy thread, all others are
   // asynchronously and responded to via the MediaDataDecoderCallback.
   // Note: the nsresults returned by the proxied decoder are lost.
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
 
   const char* GetDescriptionName() const override
   {
     return "GMP proxy data decoder";
   }
 
   // Called by MediaDataDecoderCallbackProxy.
   void FlushComplete();
--- a/dom/media/platforms/android/MediaCodecDataDecoder.cpp
+++ b/dom/media/platforms/android/MediaCodecDataDecoder.cpp
@@ -84,21 +84,16 @@ public:
 
     return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
   }
 
   void Cleanup() override
   {
   }
 
-  nsresult Input(MediaRawData* aSample) override
-  {
-    return MediaCodecDataDecoder::Input(aSample);
-  }
-
   nsresult PostOutput(BufferInfo::Param aInfo, MediaFormat::Param aFormat,
                       const TimeUnit& aDuration) override
   {
     RefPtr<layers::Image> img =
       new SurfaceTextureImage(mSurfaceTexture.get(), mConfig.mDisplay,
                               gl::OriginPos::BottomLeft);
 
     nsresult rv;
@@ -613,71 +608,65 @@ void
 MediaCodecDataDecoder::ClearQueue()
 {
   mMonitor.AssertCurrentThreadOwns();
 
   mQueue.clear();
   mDurations.clear();
 }
 
-nsresult
+void
 MediaCodecDataDecoder::Input(MediaRawData* aSample)
 {
   MonitorAutoLock lock(mMonitor);
   mQueue.push_back(aSample);
   lock.NotifyAll();
-
-  return NS_OK;
 }
 
 nsresult
 MediaCodecDataDecoder::ResetInputBuffers()
 {
   return mDecoder->GetInputBuffers(ReturnTo(&mInputBuffers));
 }
 
 nsresult
 MediaCodecDataDecoder::ResetOutputBuffers()
 {
   return mDecoder->GetOutputBuffers(ReturnTo(&mOutputBuffers));
 }
 
-nsresult
+void
 MediaCodecDataDecoder::Flush()
 {
   MonitorAutoLock lock(mMonitor);
   if (!SetState(ModuleState::kFlushing)) {
-    return NS_OK;
+    return;
   }
   lock.Notify();
 
   while (mState == ModuleState::kFlushing) {
     lock.Wait();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 MediaCodecDataDecoder::Drain()
 {
   MonitorAutoLock lock(mMonitor);
   if (mState == ModuleState::kDrainDecoder ||
       mState == ModuleState::kDrainQueue) {
-    return NS_OK;
+    return;
   }
 
   SetState(ModuleState::kDrainQueue);
   lock.Notify();
-
-  return NS_OK;
 }
 
 
-nsresult
+void
 MediaCodecDataDecoder::Shutdown()
 {
   MonitorAutoLock lock(mMonitor);
 
   SetState(ModuleState::kStopping);
   lock.Notify();
 
   while (mThread && mState != ModuleState::kShutdown) {
@@ -689,13 +678,11 @@ MediaCodecDataDecoder::Shutdown()
     mThread = nullptr;
   }
 
   if (mDecoder) {
     mDecoder->Stop();
     mDecoder->Release();
     mDecoder = nullptr;
   }
-
-  return NS_OK;
 }
 
 } // mozilla
--- a/dom/media/platforms/android/MediaCodecDataDecoder.h
+++ b/dom/media/platforms/android/MediaCodecDataDecoder.h
@@ -28,20 +28,20 @@ public:
   static MediaDataDecoder* CreateVideoDecoder(const VideoInfo& aConfig,
                                               java::sdk::MediaFormat::Param aFormat,
                                               MediaDataDecoderCallback* aCallback,
                                               layers::ImageContainer* aImageContainer);
 
   virtual ~MediaCodecDataDecoder();
 
   RefPtr<MediaDataDecoder::InitPromise> Init() override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
-  nsresult Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
+  void Input(MediaRawData* aSample) override;
   const char* GetDescriptionName() const override
   {
     return "Android MediaCodec decoder";
   }
 
 protected:
   enum class ModuleState : uint8_t {
     kDecoding = 0,
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -211,38 +211,32 @@ public:
       return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
     }
 
     mInputDurations.Clear();
 
     return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
   }
 
-  nsresult Flush() override
+  void Flush() override
   {
     mInputDurations.Clear();
-    return RemoteDataDecoder::Flush();
+    RemoteDataDecoder::Flush();
   }
 
-  nsresult Drain() override
+  void Drain() override
   {
-    nsresult res = RemoteDataDecoder::Drain();
-    NS_ENSURE_SUCCESS(res, res);
-
+    RemoteDataDecoder::Drain();
     mInputDurations.Put(0);
-    return NS_OK;
   }
 
-  nsresult Input(MediaRawData* aSample) override
+  void Input(MediaRawData* aSample) override
   {
-    nsresult res = RemoteDataDecoder::Input(aSample);
-    NS_ENSURE_SUCCESS(res, res);
-
+    RemoteDataDecoder::Input(aSample);
     mInputDurations.Put(aSample->mDuration);
-    return NS_OK;
   }
 
 private:
   class DurationQueue {
   public:
 
     void Clear()
     {
@@ -427,70 +421,67 @@ RemoteDataDecoder::RemoteDataDecoder(Med
                                      MediaDataDecoderCallback* aCallback)
   : mType(aType)
   , mMimeType(aMimeType)
   , mFormat(aFormat)
   , mCallback(aCallback)
 {
 }
 
-nsresult
+void
 RemoteDataDecoder::Flush()
 {
   mJavaDecoder->Flush();
-  return NS_OK;
 }
 
-nsresult
+void
 RemoteDataDecoder::Drain()
 {
   BufferInfo::LocalRef bufferInfo;
   nsresult rv = BufferInfo::New(&bufferInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_SUCCESS_VOID(rv);
   bufferInfo->Set(0, 0, -1, MediaCodec::BUFFER_FLAG_END_OF_STREAM);
 
   mJavaDecoder->Input(nullptr, bufferInfo);
-  return NS_OK;
 }
 
-nsresult
+void
 RemoteDataDecoder::Shutdown()
 {
   LOG("");
   MOZ_ASSERT(mJavaDecoder && mJavaCallbacks);
 
   mJavaDecoder->Release();
   mJavaDecoder = nullptr;
 
   JavaCallbacksSupport::GetNative(mJavaCallbacks)->Cancel();
   mJavaCallbacks = nullptr;
 
   mFormat = nullptr;
-
-  return NS_OK;
 }
 
-nsresult
+void
 RemoteDataDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(aSample != nullptr);
 
   JNIEnv* const env = jni::GetEnvForThread();
 
   // Copy sample data into Java byte array.
   uint32_t length = aSample->Size();
   jbyteArray data = env->NewByteArray(length);
   env->SetByteArrayRegion(data, 0, length, reinterpret_cast<const jbyte*>(aSample->Data()));
 
   jni::ByteArray::LocalRef bytes(env);
   bytes = jni::Object::LocalRef::Adopt(env, data);
 
   BufferInfo::LocalRef bufferInfo;
   nsresult rv = BufferInfo::New(&bufferInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
+    return;
+  }
   bufferInfo->Set(0, aSample->Size(), aSample->mTime, 0);
 
   mJavaDecoder->Input(bytes, bufferInfo);
-
-  return NS_OK;
 }
 
 } // mozilla
--- a/dom/media/platforms/android/RemoteDataDecoder.h
+++ b/dom/media/platforms/android/RemoteDataDecoder.h
@@ -26,20 +26,20 @@ public:
 
   static MediaDataDecoder* CreateVideoDecoder(const VideoInfo& aConfig,
                                               java::sdk::MediaFormat::Param aFormat,
                                               MediaDataDecoderCallback* aCallback,
                                               layers::ImageContainer* aImageContainer);
 
   virtual ~RemoteDataDecoder() {}
 
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
-  nsresult Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
+  void Input(MediaRawData* aSample) override;
   const char* GetDescriptionName() const override
   {
     return "android remote decoder";
   }
 
 protected:
   RemoteDataDecoder(MediaData::Type aType,
                     const nsACString& aMimeType,
--- a/dom/media/platforms/apple/AppleATDecoder.cpp
+++ b/dom/media/platforms/apple/AppleATDecoder.cpp
@@ -58,17 +58,17 @@ AppleATDecoder::Init()
   if (!mFormatID) {
     NS_ERROR("Non recognised format");
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
 }
 
-nsresult
+void
 AppleATDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   LOG("mp4 input sample %p %lld us %lld pts%s %llu bytes audio",
       aSample,
       aSample->mDuration,
       aSample->mTime,
       aSample->mKeyframe ? " keyframe" : "",
@@ -76,77 +76,73 @@ AppleATDecoder::Input(MediaRawData* aSam
 
   // Queue a task to perform the actual decoding on a separate thread.
   nsCOMPtr<nsIRunnable> runnable =
       NewRunnableMethod<RefPtr<MediaRawData>>(
         this,
         &AppleATDecoder::SubmitSample,
         RefPtr<MediaRawData>(aSample));
   mTaskQueue->Dispatch(runnable.forget());
-
-  return NS_OK;
 }
 
 void
 AppleATDecoder::ProcessFlush()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   mQueuedSamples.Clear();
   OSStatus rv = AudioConverterReset(mConverter);
   if (rv) {
     LOG("Error %d resetting AudioConverter", rv);
   }
 }
 
-nsresult
+void
 AppleATDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   LOG("Flushing AudioToolbox AAC decoder");
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &AppleATDecoder::ProcessFlush);
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
-  return NS_OK;
 }
 
-nsresult
+void
 AppleATDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   LOG("Draining AudioToolbox AAC decoder");
   mTaskQueue->AwaitIdle();
   mCallback->DrainComplete();
-  return Flush();
+  Flush();
 }
 
-nsresult
+void
 AppleATDecoder::Shutdown()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
 
   LOG("Shutdown: Apple AudioToolbox AAC decoder");
   mQueuedSamples.Clear();
   OSStatus rv = AudioConverterDispose(mConverter);
   if (rv) {
     LOG("error %d disposing of AudioConverter", rv);
-    return NS_ERROR_FAILURE;
+    return;
   }
   mConverter = nullptr;
 
   if (mStream) {
     rv = AudioFileStreamClose(mStream);
     if (rv) {
       LOG("error %d disposing of AudioFileStream", rv);
-      return NS_ERROR_FAILURE;
+      return;
     }
     mStream = nullptr;
   }
-  return NS_OK;
 }
 
 struct PassthroughUserData {
   UInt32 mChannels;
   UInt32 mDataSize;
   const void* mData;
   AudioStreamPacketDescription mPacket;
 };
--- a/dom/media/platforms/apple/AppleATDecoder.h
+++ b/dom/media/platforms/apple/AppleATDecoder.h
@@ -22,20 +22,20 @@ class MediaDataDecoderCallback;
 class AppleATDecoder : public MediaDataDecoder {
 public:
   AppleATDecoder(const AudioInfo& aConfig,
                  TaskQueue* aTaskQueue,
                  MediaDataDecoderCallback* aCallback);
   virtual ~AppleATDecoder();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
 
   const char* GetDescriptionName() const override
   {
     return "apple CoreMedia decoder";
   }
 
   // Callbacks also need access to the config.
   const AudioInfo& mConfig;
--- a/dom/media/platforms/apple/AppleVTDecoder.cpp
+++ b/dom/media/platforms/apple/AppleVTDecoder.cpp
@@ -69,71 +69,66 @@ AppleVTDecoder::Init()
 
   if (NS_SUCCEEDED(rv)) {
     return InitPromise::CreateAndResolve(TrackType::kVideoTrack, __func__);
   }
 
   return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
 }
 
-nsresult
+void
 AppleVTDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
 
   LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
       aSample,
       aSample->mTime,
       aSample->mDuration,
       aSample->mKeyframe ? " keyframe" : "",
       aSample->Size());
 
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
     this, &AppleVTDecoder::ProcessDecode, aSample));
-  return NS_OK;
 }
 
-nsresult
+void
 AppleVTDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &AppleVTDecoder::ProcessFlush);
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
 
   mSeekTargetThreshold.reset();
-
-  return NS_OK;
 }
 
-nsresult
+void
 AppleVTDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &AppleVTDecoder::ProcessDrain);
   mTaskQueue->Dispatch(runnable.forget());
-  return NS_OK;
 }
 
-nsresult
+void
 AppleVTDecoder::Shutdown()
 {
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
   mIsShutDown = true;
   if (mTaskQueue) {
     nsCOMPtr<nsIRunnable> runnable =
       NewRunnableMethod(this, &AppleVTDecoder::ProcessShutdown);
     mTaskQueue->Dispatch(runnable.forget());
   } else {
     ProcessShutdown();
   }
-  return NS_OK;
 }
 
 nsresult
 AppleVTDecoder::ProcessDecode(MediaRawData* aSample)
 {
   AssertOnTaskQueueThread();
 
   if (mIsFlushing) {
--- a/dom/media/platforms/apple/AppleVTDecoder.h
+++ b/dom/media/platforms/apple/AppleVTDecoder.h
@@ -38,20 +38,20 @@ public:
       , duration(media::TimeUnit::FromMicroseconds(aSample.mDuration))
       , byte_offset(aSample.mOffset)
       , is_sync_point(aSample.mKeyframe)
     {
     }
   };
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   void SetSeekThreshold(const media::TimeUnit& aTime) override;
 
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override
   {
     return mIsHardwareAccelerated;
   }
 
   const char* GetDescriptionName() const override
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
@@ -85,27 +85,26 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecode
     mLib->av_freep(&mCodecContext);
     return NS_ERROR_FAILURE;
   }
 
   FFMPEG_LOG("FFmpeg init successful.");
   return NS_OK;
 }
 
-nsresult
+void
 FFmpegDataDecoder<LIBAV_VER>::Shutdown()
 {
   if (mTaskQueue) {
     nsCOMPtr<nsIRunnable> runnable =
       NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown);
     mTaskQueue->Dispatch(runnable.forget());
   } else {
     ProcessShutdown();
   }
-  return NS_OK;
 }
 
 void
 FFmpegDataDecoder<LIBAV_VER>::ProcessDecode(MediaRawData* aSample)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   if (mIsFlushing) {
     return;
@@ -121,44 +120,41 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessDec
     case DecodeResult::DECODE_FRAME:
       mCallback->InputExhausted();
       break;
     default:
       break;
   }
 }
 
-nsresult
+void
 FFmpegDataDecoder<LIBAV_VER>::Input(MediaRawData* aSample)
 {
   mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
     this, &FFmpegDataDecoder::ProcessDecode, aSample));
-  return NS_OK;
 }
 
-nsresult
+void
 FFmpegDataDecoder<LIBAV_VER>::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessFlush);
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
-  return NS_OK;
 }
 
-nsresult
+void
 FFmpegDataDecoder<LIBAV_VER>::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessDrain);
   mTaskQueue->Dispatch(runnable.forget());
-  return NS_OK;
 }
 
 void
 FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   if (mCodecContext) {
     mLib->avcodec_flush_buffers(mCodecContext);
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h
@@ -27,20 +27,20 @@ public:
   FFmpegDataDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue,
                     MediaDataDecoderCallback* aCallback,
                     AVCodecID aCodecID);
   virtual ~FFmpegDataDecoder();
 
   static bool Link();
 
   RefPtr<InitPromise> Init() override = 0;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
 
   static AVCodec* FindAVCodec(FFmpegLibWrapper* aLib, AVCodecID aCodec);
 
 protected:
   enum DecodeResult {
     DECODE_FRAME,
     DECODE_NO_FRAME,
     DECODE_ERROR,
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
+++ b/dom/media/platforms/gonk/GonkMediaDataDecoder.cpp
@@ -343,41 +343,38 @@ GonkMediaDataDecoder::~GonkMediaDataDeco
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 GonkMediaDataDecoder::Init()
 {
   return mManager->Init();
 }
 
-nsresult
+void
 GonkMediaDataDecoder::Shutdown()
 {
-  nsresult rv = mManager->Shutdown();
+  mManager->Shutdown();
 
   // Because codec allocated runnable and init promise is at reader TaskQueue,
   // so manager needs to be destroyed at reader TaskQueue to prevent racing.
   mManager = nullptr;
-  return rv;
 }
 
 // Inserts data into the decoder's pipeline.
-nsresult
+void
 GonkMediaDataDecoder::Input(MediaRawData* aSample)
 {
   mManager->Input(aSample);
-  return NS_OK;
 }
 
-nsresult
+void
 GonkMediaDataDecoder::Flush()
 {
-  return mManager->Flush();
+  mManager->Flush();
 }
 
-nsresult
+void
 GonkMediaDataDecoder::Drain()
 {
   mManager->Input(nullptr);
-  return NS_OK;
 }
 
 } // namespace mozilla
--- a/dom/media/platforms/gonk/GonkMediaDataDecoder.h
+++ b/dom/media/platforms/gonk/GonkMediaDataDecoder.h
@@ -187,23 +187,23 @@ class GonkMediaDataDecoder : public Medi
 public:
   GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
                        MediaDataDecoderCallback* aCallback);
 
   ~GonkMediaDataDecoder();
 
   RefPtr<InitPromise> Init() override;
 
-  nsresult Input(MediaRawData* aSample) override;
+  void Input(MediaRawData* aSample) override;
 
-  nsresult Flush() override;
+  void Flush() override;
 
-  nsresult Drain() override;
+  void Drain() override;
 
-  nsresult Shutdown() override;
+  void Shutdown() override;
 
   const char* GetDescriptionName() const override
   {
     return "gonk decoder";
   }
 
 private:
 
--- a/dom/media/platforms/omx/OmxDataDecoder.cpp
+++ b/dom/media/platforms/omx/OmxDataDecoder.cpp
@@ -170,17 +170,17 @@ OmxDataDecoder::Init()
       },
       [self] () {
         self->RejectInitPromise(DecoderFailureReason::INIT_ERROR, __func__);
       });
 
   return p;
 }
 
-nsresult
+void
 OmxDataDecoder::Input(MediaRawData* aSample)
 {
   LOG("sample %p", aSample);
   MOZ_ASSERT(mInitPromise.IsEmpty());
 
   RefPtr<OmxDataDecoder> self = this;
   RefPtr<MediaRawData> sample = aSample;
 
@@ -190,51 +190,45 @@ OmxDataDecoder::Input(MediaRawData* aSam
 
       // Start to fill/empty buffers.
       if (self->mOmxState == OMX_StateIdle ||
           self->mOmxState == OMX_StateExecuting) {
         self->FillAndEmptyBuffers();
       }
     });
   mOmxTaskQueue->Dispatch(r.forget());
-
-  return NS_OK;
 }
 
-nsresult
+void
 OmxDataDecoder::Flush()
 {
   LOG("");
 
   mFlushing = true;
 
   mOmxTaskQueue->Dispatch(NewRunnableMethod(this, &OmxDataDecoder::DoFlush));
 
   // According to the definition of Flush() in PDM:
   // "the decoder must be ready to accept new input for decoding".
   // So it needs to wait for the Omx to complete the flush command.
   MonitorAutoLock lock(mMonitor);
   while (mFlushing) {
     lock.Wait();
   }
-
-  return NS_OK;
 }
 
-nsresult
+void
 OmxDataDecoder::Drain()
 {
   LOG("");
 
   mOmxTaskQueue->Dispatch(NewRunnableMethod(this, &OmxDataDecoder::SendEosBuffer));
-
-  return NS_OK;
 }
 
-nsresult
+void
 OmxDataDecoder::Shutdown()
 {
   LOG("");
 
   mShuttingDown = true;
 
   mOmxTaskQueue->Dispatch(NewRunnableMethod(this, &OmxDataDecoder::DoAsyncShutdown));
 
@@ -245,18 +239,16 @@ OmxDataDecoder::Shutdown()
     MonitorAutoLock lock(mMonitor);
     while (mShuttingDown) {
       lock.Wait();
     }
   }
 
   mOmxTaskQueue->BeginShutdown();
   mOmxTaskQueue->AwaitShutdownAndIdle();
-
-  return NS_OK;
 }
 
 void
 OmxDataDecoder::DoAsyncShutdown()
 {
   LOG("");
   MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
   MOZ_ASSERT(!mFlushing);
--- a/dom/media/platforms/omx/OmxDataDecoder.h
+++ b/dom/media/platforms/omx/OmxDataDecoder.h
@@ -61,23 +61,23 @@ protected:
 
 public:
   OmxDataDecoder(const TrackInfo& aTrackInfo,
                  MediaDataDecoderCallback* aCallback,
                  layers::ImageContainer* aImageContainer);
 
   RefPtr<InitPromise> Init() override;
 
-  nsresult Input(MediaRawData* aSample) override;
+  void Input(MediaRawData* aSample) override;
 
-  nsresult Flush() override;
+  void Flush() override;
 
-  nsresult Drain() override;
+  void Drain() override;
 
-  nsresult Shutdown() override;
+  void Shutdown() override;
 
   const char* GetDescriptionName() const override
   {
     return "omx decoder";
   }
 
   // Return true if event is handled.
   bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2);
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
@@ -67,56 +67,54 @@ SendTelemetry(unsigned long hr)
 
   nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
     [sample] {
       Telemetry::Accumulate(Telemetry::MEDIA_WMF_DECODE_ERROR, sample);
     });
   NS_DispatchToMainThread(runnable);
 }
 
-nsresult
+void
 WMFMediaDataDecoder::Shutdown()
 {
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
 
   if (mTaskQueue) {
     mTaskQueue->Dispatch(NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
   } else {
     ProcessShutdown();
   }
   mIsShutDown = true;
-  return NS_OK;
 }
 
 void
 WMFMediaDataDecoder::ProcessShutdown()
 {
   if (mMFTManager) {
     mMFTManager->Shutdown();
     mMFTManager = nullptr;
     if (!mRecordedError && mHasSuccessfulOutput) {
       SendTelemetry(S_OK);
     }
   }
 }
 
 // Inserts data into the decoder's pipeline.
-nsresult
+void
 WMFMediaDataDecoder::Input(MediaRawData* aSample)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
 
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod<RefPtr<MediaRawData>>(
       this,
       &WMFMediaDataDecoder::ProcessDecode,
       RefPtr<MediaRawData>(aSample));
   mTaskQueue->Dispatch(runnable.forget());
-  return NS_OK;
 }
 
 void
 WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
 {
   if (mIsFlushing) {
     // Skip sample, to be released by runnable.
     return;
@@ -163,72 +161,68 @@ WMFMediaDataDecoder::ProcessOutput()
 void
 WMFMediaDataDecoder::ProcessFlush()
 {
   if (mMFTManager) {
     mMFTManager->Flush();
   }
 }
 
-nsresult
+void
 WMFMediaDataDecoder::Flush()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
 
   mIsFlushing = true;
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessFlush);
   SyncRunnable::DispatchToThread(mTaskQueue, runnable);
   mIsFlushing = false;
-  return NS_OK;
 }
 
 void
 WMFMediaDataDecoder::ProcessDrain()
 {
   if (!mIsFlushing && mMFTManager) {
     // Order the decoder to drain...
     mMFTManager->Drain();
     // Then extract all available output.
     ProcessOutput();
   }
   mCallback->DrainComplete();
 }
 
-nsresult
+void
 WMFMediaDataDecoder::Drain()
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
 
   mTaskQueue->Dispatch(NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessDrain));
-  return NS_OK;
 }
 
 bool
 WMFMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const {
   MOZ_ASSERT(!mIsShutDown);
 
   return mMFTManager && mMFTManager->IsHardwareAccelerated(aFailureReason);
 }
 
-nsresult
+void
 WMFMediaDataDecoder::ConfigurationChanged(const TrackInfo& aConfig)
 {
   MOZ_ASSERT(mCallback->OnReaderTaskQueue());
 
   nsCOMPtr<nsIRunnable> runnable =
     NewRunnableMethod<UniquePtr<TrackInfo>&&>(
     this,
     &WMFMediaDataDecoder::ProcessConfigurationChanged,
     aConfig.Clone());
   mTaskQueue->Dispatch(runnable.forget());
-  return NS_OK;
-
 }
 
 void
 WMFMediaDataDecoder::ProcessConfigurationChanged(UniquePtr<TrackInfo>&& aConfig)
 {
   if (mMFTManager) {
     mMFTManager->ConfigurationChanged(*aConfig);
   }
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h
@@ -81,27 +81,27 @@ class WMFMediaDataDecoder : public Media
 public:
   WMFMediaDataDecoder(MFTManager* aOutputSource,
                       TaskQueue* aTaskQueue,
                       MediaDataDecoderCallback* aCallback);
   ~WMFMediaDataDecoder();
 
   RefPtr<MediaDataDecoder::InitPromise> Init() override;
 
-  nsresult Input(MediaRawData* aSample);
+  void Input(MediaRawData* aSample);
 
-  nsresult Flush() override;
+  void Flush() override;
 
-  nsresult Drain() override;
+  void Drain() override;
 
-  nsresult Shutdown() override;
+  void Shutdown() override;
 
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
 
-  nsresult ConfigurationChanged(const TrackInfo& aConfig) override;
+  void ConfigurationChanged(const TrackInfo& aConfig) override;
 
   const char* GetDescriptionName() const override
   {
     return mMFTManager ? mMFTManager->GetDescriptionName() : "";
   }
 
   virtual void SetSeekThreshold(const media::TimeUnit& aTime) override;
 
--- a/dom/media/platforms/wrappers/FuzzingWrapper.cpp
+++ b/dom/media/platforms/wrappers/FuzzingWrapper.cpp
@@ -34,73 +34,71 @@ DecoderFuzzingWrapper::~DecoderFuzzingWr
 RefPtr<MediaDataDecoder::InitPromise>
 DecoderFuzzingWrapper::Init()
 {
   DFW_LOGV("");
   MOZ_ASSERT(mDecoder);
   return mDecoder->Init();
 }
 
-nsresult
+void
 DecoderFuzzingWrapper::Input(MediaRawData* aData)
 {
   DFW_LOGV("aData.mTime=%lld", aData->mTime);
   MOZ_ASSERT(mDecoder);
-  return mDecoder->Input(aData);
+  mDecoder->Input(aData);
 }
 
-nsresult
+void
 DecoderFuzzingWrapper::Flush()
 {
   DFW_LOGV("Calling mDecoder[%p]->Flush()", mDecoder.get());
   MOZ_ASSERT(mDecoder);
   // Flush may output some frames (though unlikely).
   // Flush may block a bit, it's ok if we output some frames in the meantime.
-  nsresult result = mDecoder->Flush();
-  DFW_LOGV("mDecoder[%p]->Flush() -> result=%u", mDecoder.get(), uint32_t(result));
+  mDecoder->Flush();
+  DFW_LOGV("mDecoder[%p]->Flush()", mDecoder.get());
   // Clear any delayed output we may have.
   mCallbackWrapper->ClearDelayedOutput();
-  return result;
 }
 
-nsresult
+void
 DecoderFuzzingWrapper::Drain()
 {
   DFW_LOGV("");
   MOZ_ASSERT(mDecoder);
   // Note: The decoder should callback DrainComplete(), we'll drain the
   // delayed output (if any) then.
-  return mDecoder->Drain();
+  mDecoder->Drain();
 }
 
-nsresult
+void
 DecoderFuzzingWrapper::Shutdown()
 {
   DFW_LOGV("");
   MOZ_ASSERT(mDecoder);
   // Both shutdowns below may block a bit.
-  nsresult result = mDecoder->Shutdown();
+  mDecoder->Shutdown();
   mCallbackWrapper->Shutdown();
-  return result;
 }
 
 bool
 DecoderFuzzingWrapper::IsHardwareAccelerated(nsACString& aFailureReason) const
 {
   DFW_LOGV("");
   MOZ_ASSERT(mDecoder);
   return mDecoder->IsHardwareAccelerated(aFailureReason);
 }
 
-nsresult
+void
 DecoderFuzzingWrapper::ConfigurationChanged(const TrackInfo& aConfig)
 {
   DFW_LOGV("");
   MOZ_ASSERT(mDecoder);
-  return mDecoder->ConfigurationChanged(aConfig);
+  mDecoder->ConfigurationChanged(aConfig);
 }
 
 
 DecoderCallbackFuzzingWrapper::DecoderCallbackFuzzingWrapper(MediaDataDecoderCallback* aCallback)
   : mCallback(aCallback)
   , mDontDelayInputExhausted(false)
   , mDraining(false)
   , mTaskQueue(new TaskQueue(SharedThreadPool::Get(NS_LITERAL_CSTRING("MediaFuzzingWrapper"), 1)))
--- a/dom/media/platforms/wrappers/FuzzingWrapper.h
+++ b/dom/media/platforms/wrappers/FuzzingWrapper.h
@@ -98,22 +98,22 @@ public: // public for the benefit of Dec
 class DecoderFuzzingWrapper : public MediaDataDecoder
 {
 public:
   DecoderFuzzingWrapper(already_AddRefed<MediaDataDecoder> aDecoder,
                         already_AddRefed<DecoderCallbackFuzzingWrapper> aCallbackWrapper);
 
   // MediaDataDecoder implementation.
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
-  nsresult ConfigurationChanged(const TrackInfo& aConfig) override;
+  void ConfigurationChanged(const TrackInfo& aConfig) override;
   const char* GetDescriptionName() const override
   {
     return mDecoder->GetDescriptionName();
   }
 
 private:
   virtual ~DecoderFuzzingWrapper();
   RefPtr<MediaDataDecoder> mDecoder;
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -44,103 +44,105 @@ H264Converter::Init()
     return mDecoder->Init();
   }
 
   // We haven't been able to initialize a decoder due to a missing SPS/PPS.
   return MediaDataDecoder::InitPromise::CreateAndResolve(
            TrackType::kVideoTrack, __func__);
 }
 
-nsresult
+void
 H264Converter::Input(MediaRawData* aSample)
 {
   if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) {
     // We need AVCC content to be able to later parse the SPS.
     // This is a no-op if the data is already AVCC.
-    return NS_ERROR_FAILURE;
+    mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
+    return;
   }
 
   if (mInitPromiseRequest.Exists()) {
     if (mNeedKeyframe) {
       if (!aSample->mKeyframe) {
         // Frames dropped, we need a new one.
         mCallback->InputExhausted();
-        return NS_OK;
+        return;
       }
       mNeedKeyframe = false;
     }
     mMediaRawSamples.AppendElement(aSample);
-    return NS_OK;
+    return;
   }
 
   nsresult rv;
   if (!mDecoder) {
     // It is not possible to create an AVCC H264 decoder without SPS.
     // As such, creation will fail if the extra_data just extracted doesn't
     // contain a SPS.
     rv = CreateDecoderAndInit(aSample);
     if (rv == NS_ERROR_NOT_INITIALIZED) {
       // We are missing the required SPS to create the decoder.
       // Ignore for the time being, the MediaRawData will be dropped.
       mCallback->InputExhausted();
-      return NS_OK;
+      return;
     }
   } else {
     rv = CheckForSPSChange(aSample);
   }
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
+    return;
+  }
 
   if (mNeedKeyframe && !aSample->mKeyframe) {
     mCallback->InputExhausted();
-    return NS_OK;
+    return;
   }
 
   if (!mNeedAVCC &&
       !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) {
-    return NS_ERROR_FAILURE;
+    mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
+    return;
   }
 
   mNeedKeyframe = false;
 
   aSample->mExtraData = mCurrentConfig.mExtraData;
 
-  return mDecoder->Input(aSample);
+  mDecoder->Input(aSample);
 }
 
-nsresult
+void
 H264Converter::Flush()
 {
   mNeedKeyframe = true;
   if (mDecoder) {
-    return mDecoder->Flush();
+    mDecoder->Flush();
   }
-  return mLastError;
 }
 
-nsresult
+void
 H264Converter::Drain()
 {
   mNeedKeyframe = true;
   if (mDecoder) {
-    return mDecoder->Drain();
+    mDecoder->Drain();
+    return;
   }
   mCallback->DrainComplete();
-  return mLastError;
 }
 
-nsresult
+void
 H264Converter::Shutdown()
 {
   if (mDecoder) {
-    nsresult rv = mDecoder->Shutdown();
+    mDecoder->Shutdown();
     mInitPromiseRequest.DisconnectIfExists();
     mDecoder = nullptr;
-    return rv;
   }
-  return NS_OK;
 }
 
 bool
 H264Converter::IsHardwareAccelerated(nsACString& aFailureReason) const
 {
   if (mDecoder) {
     return mDecoder->IsHardwareAccelerated(aFailureReason);
   }
@@ -233,19 +235,17 @@ H264Converter::OnDecoderInitDone(const T
   for (uint32_t i = 0 ; i < mMediaRawSamples.Length(); i++) {
     const RefPtr<MediaRawData>& sample = mMediaRawSamples[i];
     if (mNeedKeyframe) {
       if (!sample->mKeyframe) {
         continue;
       }
       mNeedKeyframe = false;
     }
-    if (NS_FAILED(mDecoder->Input(sample))) {
-      mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    }
+    mDecoder->Input(sample);
   }
   if (!gotInput) {
     mCallback->InputExhausted();
   }
   mMediaRawSamples.Clear();
 }
 
 void
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -21,20 +21,20 @@ namespace mozilla {
 class H264Converter : public MediaDataDecoder {
 public:
 
   H264Converter(PlatformDecoderModule* aPDM,
                 const CreateDecoderParams& aParams);
   virtual ~H264Converter();
 
   RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+  void Shutdown() override;
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
   const char* GetDescriptionName() const override
   {
     if (mDecoder) {
       return mDecoder->GetDescriptionName();
     }
     return "H264Converter decoder (pending)";
   }
--- a/dom/svg/DOMSVGPoint.cpp
+++ b/dom/svg/DOMSVGPoint.cpp
@@ -110,12 +110,12 @@ DOMSVGPoint::SetY(float aY, ErrorResult&
 }
 
 already_AddRefed<nsISVGPoint>
 DOMSVGPoint::MatrixTransform(dom::SVGMatrix& matrix)
 {
   float x = HasOwner() ? InternalItem().mX : mPt.mX;
   float y = HasOwner() ? InternalItem().mY : mPt.mY;
 
-  Point pt = ToMatrix(matrix.GetMatrix()) * Point(x, y);
+  Point pt = ToMatrix(matrix.GetMatrix()).TransformPoint(Point(x, y));
   nsCOMPtr<nsISVGPoint> newPoint = new DOMSVGPoint(pt);
   return newPoint.forget();
 }
--- a/dom/svg/SVGCircleElement.cpp
+++ b/dom/svg/SVGCircleElement.cpp
@@ -88,17 +88,17 @@ SVGCircleElement::GetGeometryBounds(Rect
                                     const Matrix& aToBoundsSpace,
                                     const Matrix* aToNonScalingStrokeSpace)
 {
   float x, y, r;
   GetAnimatedLengthValues(&x, &y, &r, nullptr);
 
   if (r <= 0.f) {
     // Rendering of the element is disabled
-    *aBounds = Rect(aToBoundsSpace * Point(x, y), Size());
+    *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
     return true;
   }
 
   if (aToBoundsSpace.IsRectilinear()) {
     // Optimize the case where we can treat the circle as a rectangle and
     // still get tight bounds.
     if (aStrokeOptions.mLineWidth > 0.f) {
       if (aToNonScalingStrokeSpace) {
--- a/dom/svg/SVGEllipseElement.cpp
+++ b/dom/svg/SVGEllipseElement.cpp
@@ -99,17 +99,17 @@ SVGEllipseElement::GetGeometryBounds(Rec
                                      const Matrix& aToBoundsSpace,
                                      const Matrix* aToNonScalingStrokeSpace)
 {
   float x, y, rx, ry;
   GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
 
   if (rx <= 0.f || ry <= 0.f) {
     // Rendering of the element is disabled
-    *aBounds = Rect(aToBoundsSpace * Point(x, y), Size());
+    *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
     return true;
   }
 
   if (aToBoundsSpace.IsRectilinear()) {
     // Optimize the case where we can treat the ellipse as a rectangle and
     // still get tight bounds.
     if (aStrokeOptions.mLineWidth > 0.f) {
       if (aToNonScalingStrokeSpace) {
--- a/dom/svg/SVGLineElement.cpp
+++ b/dom/svg/SVGLineElement.cpp
@@ -152,18 +152,18 @@ SVGLineElement::GetGeometryBounds(Rect* 
                                   const StrokeOptions& aStrokeOptions,
                                   const Matrix& aToBoundsSpace,
                                   const Matrix* aToNonScalingStrokeSpace)
 {
   float x1, y1, x2, y2;
   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
 
   if (aStrokeOptions.mLineWidth <= 0) {
-    *aBounds = Rect(aToBoundsSpace * Point(x1, y1), Size());
-    aBounds->ExpandToEnclose(aToBoundsSpace * Point(x2, y2));
+    *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x1, y1)), Size());
+    aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(Point(x2, y2)));
     return true;
   }
 
   // transform from non-scaling-stroke space to the space in which we compute
   // bounds
   Matrix nonScalingToBounds;
   if (aToNonScalingStrokeSpace) {
     MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
@@ -193,18 +193,18 @@ SVGLineElement::GetGeometryBounds(Rect* 
 
   // Handle butt and square linecap, normal and non-scaling stroke cases
   // together: start with endpoints (x1, y1), (x2, y2) in the stroke space,
   // compute the four corners of the stroked line, transform the corners to
   // bounds space, and compute bounds there.
 
   if (aToNonScalingStrokeSpace) {
     Point nonScalingSpaceP1, nonScalingSpaceP2;
-    nonScalingSpaceP1 = *aToNonScalingStrokeSpace * Point(x1, y1);
-    nonScalingSpaceP2 = *aToNonScalingStrokeSpace * Point(x2, y2);
+    nonScalingSpaceP1 = aToNonScalingStrokeSpace->TransformPoint(Point(x1, y1));
+    nonScalingSpaceP2 = aToNonScalingStrokeSpace->TransformPoint(Point(x2, y2));
     x1 = nonScalingSpaceP1.x;
     y1 = nonScalingSpaceP1.y;
     x2 = nonScalingSpaceP2.x;
     y2 = nonScalingSpaceP2.y;
   }
 
   Float length = Float(NS_hypot(x2 - x1, y2 - y1));
   Float xDelta;
@@ -240,18 +240,18 @@ SVGLineElement::GetGeometryBounds(Rect* 
       points[2] = Point(x2 + yDelta + xDelta, y2 + xDelta - yDelta);
       points[3] = Point(x2 + yDelta - xDelta, y2 + xDelta + yDelta);
     }
   }
 
   const Matrix& toBoundsSpace = aToNonScalingStrokeSpace ?
     nonScalingToBounds : aToBoundsSpace;
 
-  *aBounds = Rect(toBoundsSpace * points[0], Size());
+  *aBounds = Rect(toBoundsSpace.TransformPoint(points[0]), Size());
   for (uint32_t i = 1; i < 4; ++i) {
-    aBounds->ExpandToEnclose(toBoundsSpace * points[i]);
+    aBounds->ExpandToEnclose(toBoundsSpace.TransformPoint(points[i]));
   }
 
   return true;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGMarkerElement.cpp
+++ b/dom/svg/SVGMarkerElement.cpp
@@ -357,17 +357,17 @@ SVGMarkerElement::GetViewBoxTransform()
       SVGContentUtils::GetViewBoxTransform(viewportWidth, viewportHeight,
                                            viewbox.x, viewbox.y,
                                            viewbox.width, viewbox.height,
                                            mPreserveAspectRatio);
 
     float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx);
     float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx);
 
-    gfx::Point ref = viewBoxTM * gfx::Point(refX, refY);
+    gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY));
 
     Matrix TM = viewBoxTM;
     TM.PostTranslate(-ref.x, -ref.y);
 
     mViewBoxToViewportTransform = new gfx::Matrix(TM);
   }
 
   return *mViewBoxToViewportTransform;
--- a/dom/svg/nsSVGPolyElement.cpp
+++ b/dom/svg/nsSVGPolyElement.cpp
@@ -144,16 +144,16 @@ nsSVGPolyElement::GetGeometryBounds(Rect
     // We can avoid transforming each point and just transform the result.
     // Important for large point lists.
     Rect bounds(points[0], Size());
     for (uint32_t i = 1; i < points.Length(); ++i) {
       bounds.ExpandToEnclose(points[i]);
     }
     *aBounds = aToBoundsSpace.TransformBounds(bounds);
   } else {
-    *aBounds = Rect(aToBoundsSpace * points[0], Size());
+    *aBounds = Rect(aToBoundsSpace.TransformPoint(points[0]), Size());
     for (uint32_t i = 1; i < points.Length(); ++i) {
-      aBounds->ExpandToEnclose(aToBoundsSpace * points[i]);
+      aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(points[i]));
     }
   }
   return true;
 }
 
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -373,17 +373,17 @@ nsDeviceSensors::Notify(const mozilla::h
 
 void
 nsDeviceSensors::FireDOMLightEvent(mozilla::dom::EventTarget* aTarget,
                                    double aValue)
 {
   DeviceLightEventInit init;
   init.mBubbles = true;
   init.mCancelable = false;
-  init.mValue = aValue;
+  init.mValue = round(aValue);
   RefPtr<DeviceLightEvent> event =
     DeviceLightEvent::Constructor(aTarget, NS_LITERAL_STRING("devicelight"), init);
 
   event->SetTrusted(true);
 
   bool defaultActionEnabled;
   aTarget->DispatchEvent(event, &defaultActionEnabled);
 }
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -19,19 +19,19 @@ dictionary ElementCreationOptions {
   DOMString is;
 };
 
 /* http://dom.spec.whatwg.org/#interface-document */
 [Constructor]
 interface Document : Node {
   [Throws]
   readonly attribute DOMImplementation implementation;
-  [Pure]
+  [Pure, Throws]
   readonly attribute DOMString URL;
-  [Pure]
+  [Pure, Throws]
   readonly attribute DOMString documentURI;
   [Pure]
   readonly attribute DOMString compatMode;
   [Pure]
   readonly attribute DOMString characterSet;
   [Pure,BinaryName="characterSet"]
   readonly attribute DOMString charset; // legacy alias of .characterSet
   [Pure,BinaryName="characterSet"]
--- a/dom/webidl/Node.webidl
+++ b/dom/webidl/Node.webidl
@@ -26,17 +26,17 @@ interface Node : EventTarget {
   const unsigned short DOCUMENT_TYPE_NODE = 10;
   const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
   const unsigned short NOTATION_NODE = 12; // historical
   [Constant]
   readonly attribute unsigned short nodeType;
   [Pure]
   readonly attribute DOMString nodeName;
 
-  [Pure]
+  [Pure, Throws]
   readonly attribute DOMString? baseURI;
 
   [Pure, BinaryName=getComposedDoc]
   readonly attribute boolean isConnected;
   [Pure]
   readonly attribute Document? ownerDocument;
   [Pure, Pref="dom.node.rootNode.enabled"]
   readonly attribute Node rootNode;
--- a/dom/xbl/nsXBLProtoImpl.cpp
+++ b/dom/xbl/nsXBLProtoImpl.cpp
@@ -508,28 +508,28 @@ nsXBLProtoImpl::Write(nsIObjectOutputStr
       rv = curr->Write(aStream);
     }
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return aStream->Write8(XBLBinding_Serialize_NoMoreItems);
 }
 
-nsresult
+void
 NS_NewXBLProtoImpl(nsXBLPrototypeBinding* aBinding, 
                    const char16_t* aClassName, 
                    nsXBLProtoImpl** aResult)
 {
   nsXBLProtoImpl* impl = new nsXBLProtoImpl();
   if (aClassName) {
     impl->mClassName = aClassName;
   } else {
     nsCString spec;
-    aBinding->BindingURI()->GetSpec(spec);
+    nsresult rv = aBinding->BindingURI()->GetSpec(spec);
+    // XXX: should handle this better
+    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
     impl->mClassName = NS_ConvertUTF8toUTF16(spec);
   }
 
   aBinding->SetImplementation(impl);
   *aResult = impl;
-
-  return NS_OK;
 }
 
--- a/dom/xbl/nsXBLProtoImpl.h
+++ b/dom/xbl/nsXBLProtoImpl.h
@@ -112,14 +112,14 @@ protected:
 
   nsXBLProtoImplField* mFields; // Our fields
 
 public:
   nsXBLProtoImplAnonymousMethod* mConstructor; // Our class constructor.
   nsXBLProtoImplAnonymousMethod* mDestructor;  // Our class destructor.
 };
 
-nsresult
+void
 NS_NewXBLProtoImpl(nsXBLPrototypeBinding* aBinding,
                    const char16_t* aClassName,
                    nsXBLProtoImpl** aResult);
 
 #endif // nsXBLProtoImpl_h__
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -386,17 +386,20 @@ nsXBLProtoImplField::InstallField(JS::Ha
   // Empty fields are treated as not actually present.
   if (IsEmpty()) {
     return NS_OK;
   }
 
   nsAutoMicroTask mt;
 
   nsAutoCString uriSpec;
-  aBindingDocURI->GetSpec(uriSpec);
+  nsresult rv = aBindingDocURI->GetSpec(uriSpec);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   nsIGlobalObject* globalObject = xpc::WindowGlobalOrNull(aBoundNode);
   if (!globalObject) {
     return NS_OK;
   }
 
   // We are going to run script via EvaluateString, so we need a script entry
   // point, but as this is XBL related it does not appear in the HTML spec.
@@ -404,17 +407,17 @@ nsXBLProtoImplField::InstallField(JS::Ha
   JSContext* cx = aes.cx();
 
   NS_ASSERTION(!::JS_IsExceptionPending(cx),
                "Shouldn't get here when an exception is pending!");
 
   JSAddonId* addonId = MapURIToAddonID(aBindingDocURI);
 
   Element* boundElement = nullptr;
-  nsresult rv = UNWRAP_OBJECT(Element, aBoundNode, boundElement);
+  rv = UNWRAP_OBJECT(Element, aBoundNode, boundElement);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // First, enter the xbl scope, build the element's scope chain, and use
   // that as the scope chain for the evaluation.
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, aBoundNode, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1055,18 +1055,20 @@ nsXBLPrototypeBinding::Write(nsIObjectOu
   nsAutoCString id;
   mBindingURI->GetRef(id);
   rv = aStream->WriteStringZ(id.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // write out the extends and display attribute values
   nsAutoCString extends;
   ResolveBaseBinding();
-  if (mBaseBindingURI)
-    mBaseBindingURI->GetSpec(extends);
+  if (mBaseBindingURI) {
+    rv = mBaseBindingURI->GetSpec(extends);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   rv = aStream->WriteStringZ(extends.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = WriteNamespace(aStream, mBaseNameSpaceID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString baseTag;
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -351,35 +351,36 @@ nsXBLPrototypeHandler::EnsureEventHandle
   NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);
 
   JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
 
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
 
   nsAutoCString bindingURI;
-  mPrototypeBinding->DocURI()->GetSpec(bindingURI);
+  nsresult rv = mPrototypeBinding->DocURI()->GetSpec(bindingURI);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount,
                                    &argNames);
 
   // Compile the event handler in the xbl scope.
   JSAutoCompartment ac(cx, scopeObject);
   JS::CompileOptions options(cx);
   options.setFileAndLine(bindingURI.get(), mLineNumber)
          .setVersion(JSVERSION_LATEST);
 
   JS::Rooted<JSObject*> handlerFun(cx);
   JS::AutoObjectVector emptyVector(cx);
-  nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
-                                           nsAtomCString(aName), argCount,
-                                           argNames, handlerText,
-                                           handlerFun.address());
+  rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
+                                  nsAtomCString(aName), argCount,
+                                  argNames, handlerText,
+                                  handlerFun.address());
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);
 
   // Wrap the handler into the content scope, since we're about to stash it
   // on the DOM window and such.
   JSAutoCompartment ac2(cx, globalObject);
   bool ok = JS_WrapObject(cx, &handlerFun);
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2224,17 +2224,21 @@ XMLHttpRequestMainThread::RequestBody<ns
 
   if (mBody->IsHTMLDocument()) {
     aContentType.AssignLiteral("text/html");
 
     nsString serialized;
     if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
-    NS_ConvertUTF16toUTF8 utf8Serialized(serialized);
+
+    nsAutoCString utf8Serialized;
+    if (!AppendUTF16toUTF8(serialized, utf8Serialized, fallible)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     uint32_t written;
     rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
     NS_ENSURE_SUCCESS(rv, rv);
 
     MOZ_ASSERT(written == utf8Serialized.Length());
   } else {
     aContentType.AssignLiteral("application/xml");
@@ -2263,17 +2267,21 @@ XMLHttpRequestMainThread::RequestBody<ns
 template<> nsresult
 XMLHttpRequestMainThread::RequestBody<const nsAString>::GetAsStream(
    nsIInputStream** aResult, uint64_t* aContentLength,
    nsACString& aContentType, nsACString& aCharset) const
 {
   aContentType.AssignLiteral("text/plain");
   aCharset.AssignLiteral("UTF-8");
 
-  nsCString converted = NS_ConvertUTF16toUTF8(*mBody);
+  nsAutoCString converted;
+  if (!AppendUTF16toUTF8(*mBody, converted, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   *aContentLength = converted.Length();
   nsresult rv = NS_NewCStringInputStream(aResult, converted);
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 template<> nsresult
 XMLHttpRequestMainThread::RequestBody<nsIInputStream>::GetAsStream(
--- a/embedding/components/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/embedding/components/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -820,21 +820,21 @@ PersistNodeFixup::FixupAnchor(nsIDOMNode
 
         nsCOMPtr<nsIURI> relativeURI;
         relativeURI = IsFlagSet(IWBP::PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION)
                       ? mTargetBaseURI : mCurrentBaseURI;
         // Make a new URI to replace the current one
         nsCOMPtr<nsIURI> newURI;
         rv = NS_NewURI(getter_AddRefs(newURI), oldCValue,
                        mParent->GetCharacterSet().get(), relativeURI);
-        if (NS_SUCCEEDED(rv) && newURI)
-        {
+        if (NS_SUCCEEDED(rv) && newURI) {
             newURI->SetUserPass(EmptyCString());
             nsAutoCString uriSpec;
-            newURI->GetSpec(uriSpec);
+            rv = newURI->GetSpec(uriSpec);
+            NS_ENSURE_SUCCESS(rv, rv);
             attr->SetValue(NS_ConvertUTF8toUTF16(uriSpec));
         }
     }
 
     return NS_OK;
 }
 
 static void
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1161,24 +1161,26 @@ nsresult nsWebBrowserPersist::SendErrorS
         // Do nothing
         return NS_OK;
     }
 
     // Get the file path or spec from the supplied URI
     nsCOMPtr<nsIFile> file;
     GetLocalFileFromURI(aURI, getter_AddRefs(file));
     nsAutoString path;
+    nsresult rv;
     if (file)
     {
         file->GetPath(path);
     }
     else
     {
         nsAutoCString fileurl;
-        aURI->GetSpec(fileurl);
+        rv = aURI->GetSpec(fileurl);
+        NS_ENSURE_SUCCESS(rv, rv);
         AppendUTF8toUTF16(fileurl, path);
     }
 
     nsAutoString msgId;
     switch(aResult)
     {
     case NS_ERROR_FILE_NAME_TOO_LONG:
         // File name too long.
@@ -1208,17 +1210,16 @@ nsresult nsWebBrowserPersist::SendErrorS
         // Generic read/write error message.
         if (aIsReadError)
             msgId.AssignLiteral("readError");
         else
             msgId.AssignLiteral("writeError");
         break;
     }
     // Get properties file bundle and extract status string.
-    nsresult rv;
     nsCOMPtr<nsIStringBundleService> s = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
     NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && s, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsIStringBundle> bundle;
     rv = s->CreateBundle(kWebBrowserPersistStringBundle, getter_AddRefs(bundle));
     NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && bundle, NS_ERROR_FAILURE);
 
     nsXPIDLString msgText;
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -1048,26 +1048,29 @@ nsWindowWatcher::OpenWindowInternal(mozI
   // better have a window to use by this point
   if (!newDocShellItem) {
     return rv;
   }
 
   nsCOMPtr<nsIDocShell> newDocShell(do_QueryInterface(newDocShellItem));
   NS_ENSURE_TRUE(newDocShell, NS_ERROR_UNEXPECTED);
 
+  // If our parent is sandboxed, set it as the one permitted sandboxed navigator
+  // on the new window we're opening.
+  if (activeDocsSandboxFlags && parentWindow) {
+    newDocShell->SetOnePermittedSandboxedNavigator(
+      parentWindow->GetDocShell());
+  }
+
   // Copy sandbox flags to the new window if activeDocsSandboxFlags says to do
   // so.  Note that it's only nonzero if the window is new, so clobbering
   // sandbox flags on the window makes sense in that case.
   if (activeDocsSandboxFlags &
         SANDBOX_PROPAGATES_TO_AUXILIARY_BROWSING_CONTEXTS) {
     newDocShell->SetSandboxFlags(activeDocsSandboxFlags);
-    if (parentWindow) {
-      newDocShell->SetOnePermittedSandboxedNavigator(
-        parentWindow->GetDocShell());
-    }
   }
 
   rv = ReadyOpenedDocShellItem(newDocShellItem, parentWindow, windowIsNew, aResult);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (isNewToplevelWindow) {
@@ -1106,19 +1109,19 @@ nsWindowWatcher::OpenWindowInternal(mozI
   nsCOMPtr<nsIPrincipal> subjectPrincipal =
     nsContentUtils::GetCurrentJSContext() ? nsContentUtils::SubjectPrincipal() :
                                             nullptr;
 
   if (windowIsNew) {
     auto* docShell = static_cast<nsDocShell*>(newDocShell.get());
 
     // If this is not a chrome docShell, we apply originAttributes from the
-    // subjectPrincipal unless if it's an expanded principal.
+    // subjectPrincipal unless if it's an expanded or system principal.
     if (subjectPrincipal &&
-        !subjectPrincipal->GetIsExpandedPrincipal() &&
+        !nsContentUtils::IsSystemOrExpandedPrincipal(subjectPrincipal) &&
         docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
       DocShellOriginAttributes attrs;
       attrs.InheritFromDocToChildDocShell(BasePrincipal::Cast(subjectPrincipal)->OriginAttributesRef());
 
       docShell->SetOriginAttributes(attrs);
     }
 
     // Now set the opener principal on the new window.  Note that we need to do
@@ -1277,25 +1280,28 @@ nsWindowWatcher::OpenWindowInternal(mozI
 
     if (!windowStateHelper.DefaultEnabled()) {
       // Default to cancel not opening the modal window.
       NS_RELEASE(*aResult);
 
       return NS_OK;
     }
 
-    if (!newWindowShouldBeModal && parentIsModal) {
-      nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(newTreeOwner));
-      if (parentWindow) {
-        nsCOMPtr<nsIWidget> parentWidget;
-        parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
-        if (parentWidget) {
-          parentWidget->SetFakeModal(true);
-        }
+    bool isAppModal = false;
+    nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(newTreeOwner));
+    nsCOMPtr<nsIWidget> parentWidget;
+    if (parentWindow) {
+      parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
+      if (parentWidget) {
+        isAppModal = parentWidget->IsRunningAppModal();
       }
+    }
+    if (parentWidget &&
+        ((!newWindowShouldBeModal && parentIsModal) || isAppModal)) {
+      parentWidget->SetFakeModal(true);
     } else {
       // Reset popup state while opening a modal dialog, and firing
       // events about the dialog, to prevent the current state from
       // being active the whole time a modal dialog is open.
       nsAutoPopupStatePusher popupStatePusher(openAbused);
 
       newChrome->ShowAsModal();
     }
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1476,17 +1476,18 @@ public:
   static uint64_t GetD2DVRAMUsageDrawTarget();
   static uint64_t GetD2DVRAMUsageSourceSurface();
   static void D2DCleanup();
 
   static already_AddRefed<ScaledFont>
     CreateScaledFontForDWriteFont(IDWriteFont* aFont,
                                   IDWriteFontFamily* aFontFamily,
                                   IDWriteFontFace* aFontFace,
-                                  Float aSize);
+                                  Float aSize,
+                                  bool aUseEmbeddedBitmap);
 
 private:
   static ID2D1Device *mD2D1Device;
   static ID3D11Device *mD3D11Device;
 #endif
 
   static DrawEventRecorder *mRecorder;
 };
--- a/gfx/2d/DrawCommand.h
+++ b/gfx/2d/DrawCommand.h
@@ -203,17 +203,17 @@ public:
   {
   }
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix* aTransform) const
   {
     MOZ_ASSERT(!aTransform || !aTransform->HasNonIntegerTranslation());
     Point dest(Float(mDestination.x), Float(mDestination.y));
     if (aTransform) {
-      dest = (*aTransform) * dest;
+      dest = aTransform->TransformPoint(dest);
     }
     aDT->CopySurface(mSurface, mSourceRect, IntPoint(uint32_t(dest.x), uint32_t(dest.y)));
   }
 
 private:
   RefPtr<SourceSurface> mSurface;
   IntRect mSourceRect;
   IntPoint mDestination;
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -36,16 +36,20 @@
 #include "BorrowedContext.h"
 #include <ApplicationServices/ApplicationServices.h>
 #include "mozilla/Vector.h"
 #include "ScaledFontMac.h"
 #include "DrawTargetCG.h"
 #include "CGTextDrawing.h"
 #endif
 
+#ifdef XP_WIN
+#include "ScaledFontDWrite.h"
+#endif
+
 namespace mozilla {
 namespace gfx {
 
 class GradientStopsSkia : public GradientStops
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsSkia)
   GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode)
@@ -1286,16 +1290,24 @@ DrawTargetSkia::FillGlyphs(ScaledFont *a
     if (!shouldLCDRenderText) {
       // If we have non LCD GDI text, render the fonts as cleartype and convert them
       // to grayscale. This seems to be what Chrome and IE are doing on Windows 7.
       // This also applies if cleartype is disabled system wide.
       paint.mPaint.setFlags(paint.mPaint.getFlags() | SkPaint::kGenA8FromLCD_Flag);
     }
     break;
   }
+#ifdef XP_WIN
+  case FontType::DWRITE:
+  {
+    ScaledFontDWrite* dwriteFont = static_cast<ScaledFontDWrite*>(aFont);
+    paint.mPaint.setEmbeddedBitmapText(dwriteFont->UseEmbeddedBitmaps());
+    break;
+  }
+#endif
   default:
     break;
   }
 
   paint.mPaint.setSubpixelText(useSubpixelText);
 
   std::vector<uint16_t> indices;
   std::vector<SkPoint> offsets;
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -700,19 +700,20 @@ Factory::D2DCleanup()
   }
   DrawTargetD2D1::CleanupD2D();
 }
 
 already_AddRefed<ScaledFont>
 Factory::CreateScaledFontForDWriteFont(IDWriteFont* aFont,
                                        IDWriteFontFamily* aFontFamily,
                                        IDWriteFontFace* aFontFace,
-                                       float aSize)
+                                       float aSize,
+                                       bool aUseEmbeddedBitmap)
 {
-  return MakeAndAddRef<ScaledFontDWrite>(aFont, aFontFamily, aFontFace, aSize);
+  return MakeAndAddRef<ScaledFontDWrite>(aFont, aFontFamily, aFontFace, aSize, aUseEmbeddedBitmap);
 }
 
 #endif // XP_WIN
 
 #ifdef USE_SKIA_GPU
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
                                            const IntSize &aSize,
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -648,20 +648,20 @@ CreatePartialBitmapForSurface(DataSource
       // Scope to auto-Unmap() |mapping|.
       DataSourceSurface::ScopedMap mapping(aSurface, DataSourceSurface::READ);
       if (MOZ2D_WARN_IF(!mapping.IsMapped())) {
         return nullptr;
       }
       ImageHalfScaler scaler(mapping.GetData(), mapping.GetStride(), size);
 
       // Calculate the maximum width/height of the image post transform.
-      Point topRight = transform * Point(Float(size.width), 0);
-      Point topLeft = transform * Point(0, 0);
-      Point bottomRight = transform * Point(Float(size.width), Float(size.height));
-      Point bottomLeft = transform * Point(0, Float(size.height));
+      Point topRight = transform.TransformPoint(Point(Float(size.width), 0));
+      Point topLeft = transform.TransformPoint(Point(0, 0));
+      Point bottomRight = transform.TransformPoint(Point(Float(size.width), Float(size.height)));
+      Point bottomLeft = transform.TransformPoint(Point(0, Float(size.height)));
 
       IntSize scaleSize;
 
       scaleSize.width = int32_t(std::max(Distance(topRight, topLeft),
                                          Distance(bottomRight, bottomLeft)));
       scaleSize.height = int32_t(std::max(Distance(topRight, bottomRight),
                                           Distance(topLeft, bottomLeft)));
 
--- a/gfx/2d/Matrix.cpp
+++ b/gfx/2d/Matrix.cpp
@@ -90,20 +90,20 @@ Matrix::Rotation(Float aAngle)
 Rect
 Matrix::TransformBounds(const Rect &aRect) const
 {
   int i;
   Point quad[4];
   Float min_x, max_x;
   Float min_y, max_y;
 
-  quad[0] = *this * aRect.TopLeft();
-  quad[1] = *this * aRect.TopRight();
-  quad[2] = *this * aRect.BottomLeft();
-  quad[3] = *this * aRect.BottomRight();
+  quad[0] = TransformPoint(aRect.TopLeft());
+  quad[1] = TransformPoint(aRect.TopRight());
+  quad[2] = TransformPoint(aRect.BottomLeft());
+  quad[3] = TransformPoint(aRect.BottomRight());
 
   min_x = max_x = quad[0].x;
   min_y = max_y = quad[0].y;
 
   for (i = 1; i < 4; i++) {
     if (quad[i].x < min_x)
       min_x = quad[i].x;
     if (quad[i].x > max_x)
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -48,27 +48,27 @@ public:
 
   MOZ_ALWAYS_INLINE Matrix Copy() const
   {
     return Matrix(*this);
   }
 
   friend std::ostream& operator<<(std::ostream& aStream, const Matrix& aMatrix);
 
-  Point operator *(const Point &aPoint) const
+  Point TransformPoint(const Point &aPoint) const
   {
     Point retPoint;
 
     retPoint.x = aPoint.x * _11 + aPoint.y * _21 + _31;
     retPoint.y = aPoint.x * _12 + aPoint.y * _22 + _32;
 
     return retPoint;
   }
 
-  Size operator *(const Size &aSize) const
+  Size TransformSize(const Size &aSize) const
   {
     Size retSize;
 
     retSize.width = aSize.width * _11 + aSize.height * _21;
     retSize.height = aSize.width * _12 + aSize.height * _22;
 
     return retSize;
   }
@@ -587,17 +587,17 @@ public:
 
     // The transformed value of z is computed as:
     // z' = aPoint.x * _13 + aPoint.y * _23 + z * _33 + _43;
 
     // Solving for z when z' = 0 gives us:
     F z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
 
     // Compute the transformed point
-    return *this * Point4DTyped<SourceUnits, F>(aPoint.x, aPoint.y, z, 1);
+    return this->TransformPoint(Point4DTyped<SourceUnits, F>(aPoint.x, aPoint.y, z, 1));
   }
 
   template<class F>
   RectTyped<TargetUnits, F>
   ProjectRectBounds(const RectTyped<SourceUnits, F>& aRect, const RectTyped<TargetUnits, F>& aClip) const
   {
     // This function must never return std::numeric_limits<Float>::max() or any
     // other arbitrary large value in place of inifinity.  This often occurs when
@@ -718,20 +718,20 @@ public:
                               const RectTyped<TargetUnits, F>& aClip,
                               PointTyped<TargetUnits, F>* aVerts) const
   {
     // Initialize a double-buffered array of points in homogenous space with
     // the input rectangle, aRect.
     Point4DTyped<UnknownUnits, F> points[2][kTransformAndClipRectMaxVerts];
     Point4DTyped<UnknownUnits, F>* dstPoint = points[0];
 
-    *dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.y, 0, 1);
-    *dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.y, 0, 1);
-    *dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.YMost(), 0, 1);
-    *dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.YMost(), 0, 1);
+    *dstPoint++ = TransformPoint(Point4DTyped<UnknownUnits, F>(aRect.x, aRect.y, 0, 1));
+    *dstPoint++ = TransformPoint(Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.y, 0, 1));
+    *dstPoint++ = TransformPoint(Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.YMost(), 0, 1));
+    *dstPoint++ = TransformPoint(Point4DTyped<UnknownUnits, F>(aRect.x, aRect.YMost(), 0, 1));
 
     // View frustum clipping planes are described as normals originating from
     // the 0,0,0,0 origin.
     Point4DTyped<UnknownUnits, F> planeNormals[4];
     planeNormals[0] = Point4DTyped<UnknownUnits, F>(1.0, 0.0, 0.0, -aClip.x);
     planeNormals[1] = Point4DTyped<UnknownUnits, F>(-1.0, 0.0, 0.0, aClip.XMost());
     planeNormals[2] = Point4DTyped<UnknownUnits, F>(0.0, 1.0, 0.0, -aClip.y);
     planeNormals[3] = Point4DTyped<UnknownUnits, F>(0.0, -1.0, 0.0, aClip.YMost());
@@ -819,66 +819,65 @@ public:
       Float y = aPoint.x * _21 + aPoint.y * _22 + aPoint.z * _23 + aPoint.w * _24;
       Float z = aPoint.x * _31 + aPoint.y * _32 + aPoint.z * _33 + aPoint.w * _34;
       Float w = aPoint.x * _41 + aPoint.y * _42 + aPoint.z * _43 + aPoint.w * _44;
 
       return TargetPoint4D(x, y, z, w);
   }
 
   template<class F>
-  Point4DTyped<TargetUnits, F> operator *(const Point4DTyped<SourceUnits, F>& aPoint) const
+  Point4DTyped<TargetUnits, F> TransformPoint(const Point4DTyped<SourceUnits, F>& aPoint) const
   {
     Point4DTyped<TargetUnits, F> retPoint;
 
     retPoint.x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + aPoint.w * _41;
     retPoint.y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + aPoint.w * _42;
     retPoint.z = aPoint.x * _13 + aPoint.y * _23 + aPoint.z * _33 + aPoint.w * _43;
     retPoint.w = aPoint.x * _14 + aPoint.y * _24 + aPoint.z * _34 + aPoint.w * _44;
 
     return retPoint;
   }
 
   template<class F>
-  Point3DTyped<TargetUnits, F> operator *(const Point3DTyped<SourceUnits, F>& aPoint) const
+  Point3DTyped<TargetUnits, F> TransformPoint(const Point3DTyped<SourceUnits, F>& aPoint) const
   {
     Point3DTyped<TargetUnits, F> result;
     result.x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + _41;
     result.y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + _42;
     result.z = aPoint.x * _13 + aPoint.y * _23 + aPoint.z * _33 + _43;
 
     result /= (aPoint.x * _14 + aPoint.y * _24 + aPoint.z * _34 + _44);
 
     return result;
   }
 
   template<class F>
-  PointTyped<TargetUnits, F> operator *(const PointTyped<SourceUnits, F> &aPoint) const
+  PointTyped<TargetUnits, F> TransformPoint(const PointTyped<SourceUnits, F> &aPoint) const
   {
     Point4DTyped<SourceUnits, F> temp(aPoint.x, aPoint.y, 0, 1);
-    Point4DTyped<TargetUnits, F> result = *this * temp;
-    return result.As2DPoint();
+    return TransformPoint(temp).As2DPoint();
   }
 
   template<class F>
   GFX2D_API RectTyped<TargetUnits, F> TransformBounds(const RectTyped<SourceUnits, F>& aRect) const
   {
     Point4DTyped<TargetUnits, F> verts[4];
-    verts[0] = *this * Point4DTyped<SourceUnits, F>(aRect.x, aRect.y, 0.0, 1.0);
-    verts[1] = *this * Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.y, 0.0, 1.0);
-    verts[2] = *this * Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.YMost(), 0.0, 1.0);
-    verts[3] = *this * Point4DTyped<SourceUnits, F>(aRect.x, aRect.YMost(), 0.0, 1.0);
+    verts[0] = TransformPoint(Point4DTyped<SourceUnits, F>(aRect.x, aRect.y, 0.0, 1.0));
+    verts[1] = TransformPoint(Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.y, 0.0, 1.0));
+    verts[2] = TransformPoint(Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.YMost(), 0.0, 1.0));
+    verts[3] = TransformPoint(Point4DTyped<SourceUnits, F>(aRect.x, aRect.YMost(), 0.0, 1.0));
 
     PointTyped<TargetUnits, F> quad[4];
     F min_x, max_x;
     F min_y, max_y;
 
-    quad[0] = *this * aRect.TopLeft();
-    quad[1] = *this * aRect.TopRight();
-    quad[2] = *this * aRect.BottomLeft();
-    quad[3] = *this * aRect.BottomRight();
+    quad[0] = TransformPoint(aRect.TopLeft());
+    quad[1] = TransformPoint(aRect.TopRight());
+    quad[2] = TransformPoint(aRect.BottomLeft());
+    quad[3] = TransformPoint(aRect.BottomRight());
 
     min_x = max_x = quad[0].x;
     min_y = max_y = quad[0].y;
 
     for (int i = 1; i < 4; i++) {
       if (quad[i].x < min_x) {
         min_x = quad[i].x;
       }
@@ -1502,19 +1501,19 @@ public:
     _33 += -1.0/aDepth * _43;
     _34 += -1.0/aDepth * _44;
   }
 
   Point3D GetNormalVector() const
   {
     // Define a plane in transformed space as the transformations
     // of 3 points on the z=0 screen plane.
-    Point3D a = *this * Point3D(0, 0, 0);
-    Point3D b = *this * Point3D(0, 1, 0);
-    Point3D c = *this * Point3D(1, 0, 0);
+    Point3D a = TransformPoint(Point3D(0, 0, 0));
+    Point3D b = TransformPoint(Point3D(0, 1, 0));
+    Point3D c = TransformPoint(Point3D(1, 0, 0));
 
     // Convert to two vectors on the surface of the plane.
     Point3D ab = b - a;
     Point3D ac = c - a;
 
     return ac.CrossProduct(ab);
   }
 
--- a/gfx/2d/PathCG.cpp
+++ b/gfx/2d/PathCG.cpp
@@ -249,17 +249,17 @@ PathCG::StreamToSink(PathSink *aSink) co
   CGPathApply(mPath, aSink, StreamPathToSinkApplierFunc);
 }
 
 bool
 PathCG::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
 {
   Matrix inverse = aTransform;
   inverse.Invert();
-  Point transformedPoint = inverse*aPoint;
+  Point transformedPoint = inverse.TransformPoint(aPoint);
   // We could probably drop the input transform and just transform the point at the caller?
   CGPoint point = {transformedPoint.x, transformedPoint.y};
 
   // The transform parameter of CGPathContainsPoint doesn't seem to work properly on OS X 10.5
   // so we transform aPoint ourselves.
   return CGPathContainsPoint(mPath, nullptr, point, mFillRule == FillRule::FILL_EVEN_ODD);
 }
 
@@ -289,17 +289,17 @@ ScratchContext()
 
 bool
 PathCG::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
                             const Point &aPoint,
                             const Matrix &aTransform) const
 {
   Matrix inverse = aTransform;
   inverse.Invert();
-  Point transformedPoint = inverse*aPoint;
+  Point transformedPoint = inverse.TransformPoint(aPoint);
   // We could probably drop the input transform and just transform the point at the caller?
   CGPoint point = {transformedPoint.x, transformedPoint.y};
 
   CGContextRef cg = ScratchContext();
 
   CGContextSaveGState(cg);
 
   CGContextBeginPath(cg);
--- a/gfx/2d/PathCairo.cpp
+++ b/gfx/2d/PathCairo.cpp
@@ -171,41 +171,41 @@ PathCairo::CopyToBuilder(FillRule aFillR
 }
 
 already_AddRefed<PathBuilder>
 PathCairo::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
 {
   RefPtr<PathBuilderCairo> builder = new PathBuilderCairo(aFillRule);
 
   AppendPathToBuilder(builder, &aTransform);
-  builder->mCurrentPoint = aTransform * mCurrentPoint;
+  builder->mCurrentPoint = aTransform.TransformPoint(mCurrentPoint);
 
   return builder.forget();
 }
 
 bool
 PathCairo::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
 {
   Matrix inverse = aTransform;
   inverse.Invert();
-  Point transformed = inverse * aPoint;
+  Point transformed = inverse.TransformPoint(aPoint);
 
   EnsureContainingContext(aTransform);
 
   return cairo_in_fill(mContainingContext, transformed.x, transformed.y);
 }
 
 bool
 PathCairo::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
                                const Point &aPoint,
                                const Matrix &aTransform) const
 {
   Matrix inverse = aTransform;
   inverse.Invert();
-  Point transformed = inverse * aPoint;
+  Point transformed = inverse.TransformPoint(aPoint);
 
   EnsureContainingContext(aTransform);
 
   SetCairoStrokeOptions(mContainingContext, aStrokeOptions);
 
   return cairo_in_stroke(mContainingContext, transformed.x, transformed.y);
 }
 
@@ -308,17 +308,17 @@ PathCairo::AppendPathToBuilder(PathBuild
   if (aTransform) {
     size_t i = 0;
     while (i < mPathData.size()) {
       uint32_t pointCount = mPathData[i].header.length - 1;
       aBuilder->mPathData.push_back(mPathData[i]);
       i++;
       for (uint32_t c = 0; c < pointCount; c++) {
         cairo_path_data_t data;
-        Point newPoint = *aTransform * Point(mPathData[i].point.x, mPathData[i].point.y);
+        Point newPoint = aTransform->TransformPoint(Point(mPathData[i].point.x, mPathData[i].point.y));
         data.point.x = newPoint.x;
         data.point.y = newPoint.y;
         aBuilder->mPathData.push_back(data);
         i++;
       }
     }
   } else {
     for (size_t i = 0; i < mPathData.size(); i++) {
--- a/gfx/2d/PathD2D.cpp
+++ b/gfx/2d/PathD2D.cpp
@@ -416,17 +416,17 @@ PathD2D::TransformedCopyToBuilder(const 
   }
   if (FAILED(hr)) {
     gfxWarning() << "Failed to simplify PathGeometry to tranformed copy. Code: " << hexa(hr) << " Active: " << mEndedActive;
     return nullptr;
   }
 
   RefPtr<PathBuilderD2D> pathBuilder = new PathBuilderD2D(sink, path, aFillRule, mBackendType);
   
-  pathBuilder->mCurrentPoint = aTransform * mEndPoint;
+  pathBuilder->mCurrentPoint = aTransform.TransformPoint(mEndPoint);
   
   if (mEndedActive) {
     pathBuilder->mFigureActive = true;
   }
 
   return pathBuilder.forget();
 }
 
--- a/gfx/2d/PathHelpers.h
+++ b/gfx/2d/PathHelpers.h
@@ -36,17 +36,19 @@ inline void PartialArcToBezier(T* aSink,
                                Float aKappaFactor = kKappaFactor)
 {
   Point cp1 =
     aStartOffset + Point(-aStartOffset.y, aStartOffset.x) * aKappaFactor;
 
   Point cp2 =
     aEndOffset + Point(aEndOffset.y, -aEndOffset.x) * aKappaFactor;
 
-  aSink->BezierTo(aTransform * cp1, aTransform * cp2, aTransform * aEndOffset);
+  aSink->BezierTo(aTransform.TransformPoint(cp1),
+                  aTransform.TransformPoint(cp2),
+                  aTransform.TransformPoint(aEndOffset));
 }
 
 /**
  * Draws an acute arc (<= 90 degrees) given exact start and end points.
  * Specialized version avoiding kappa calculation.
  */
 template <typename T>
 inline void AcuteArcToBezier(T* aSink,
@@ -105,17 +107,17 @@ void ArcToBezier(T* aSink, const Point &
 
   Float currentStartAngle = aStartAngle;
   Point currentStartOffset(cosf(aStartAngle), sinf(aStartAngle));
   Matrix transform = Matrix::Scaling(aRadius.width, aRadius.height);
   if (aRotation != 0.0f) {
     transform *= Matrix::Rotation(aRotation);
   }
   transform.PostTranslate(aOrigin);
-  aSink->LineTo(transform * currentStartOffset);
+  aSink->LineTo(transform.TransformPoint(currentStartOffset));
 
   while (arcSweepLeft > 0) {
     Float currentEndAngle =
       currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection;
     Point currentEndOffset(cosf(currentEndAngle), sinf(currentEndAngle));
 
     PartialArcToBezier(aSink, currentStartOffset, currentEndOffset, transform,
                        ComputeKappaFactor(currentEndAngle - currentStartAngle));
@@ -132,17 +134,17 @@ void ArcToBezier(T* aSink, const Point &
  * inlined which vastly simplifies it and avoids a bunch of transcedental function
  * calls which should make it faster. */
 template <typename T>
 void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
 {
   Matrix transform(aRadius.width, 0, 0, aRadius.height, aOrigin.x, aOrigin.y);
   Point currentStartOffset(1, 0);
 
-  aSink->LineTo(transform * currentStartOffset);
+  aSink->LineTo(transform.TransformPoint(currentStartOffset));
 
   for (int i = 0; i < 4; i++) {
     // cos(x+pi/2) == -sin(x)
     // sin(x+pi/2) == cos(x)
     Point currentEndOffset(-currentStartOffset.y, currentStartOffset.x);
 
     PartialArcToBezier(aSink, currentStartOffset, currentEndOffset, transform);
 
@@ -358,19 +360,19 @@ inline bool UserToDevicePixelSnapped(Rec
   if (!aAllowScaleOr90DegreeRotate &&
       (!WITHIN_E(mat._11, 1.f) || !WITHIN_E(mat._22, 1.f) ||
        !WITHIN_E(mat._12, 0.f) || !WITHIN_E(mat._21, 0.f))) {
     // We have non-translation, but only translation is allowed.
     return false;
   }
 #undef WITHIN_E
 
-  Point p1 = mat * aRect.TopLeft();
-  Point p2 = mat * aRect.TopRight();
-  Point p3 = mat * aRect.BottomRight();
+  Point p1 = mat.TransformPoint(aRect.TopLeft());
+  Point p2 = mat.TransformPoint(aRect.TopRight());
+  Point p3 = mat.TransformPoint(aRect.BottomRight());
 
   // Check that the rectangle is axis-aligned. For an axis-aligned rectangle,
   // two opposite corners define the entire rectangle. So check if
   // the axis-aligned rectangle with opposite corners p1 and p3
   // define an axis-aligned rectangle whose other corners are p2 and p4.
   // We actually only need to check one of p2 and p4, since an affine
   // transform maps parallelograms to parallelograms.
   if (p2 == Point(p1.x, p3.y) || p2 == Point(p3.x, p1.y)) {
--- a/gfx/2d/PathRecording.cpp
+++ b/gfx/2d/PathRecording.cpp
@@ -98,23 +98,23 @@ PathRecording::TransformedCopyToBuilder(
 {
   RefPtr<PathBuilder> pathBuilder = mPath->TransformedCopyToBuilder(aTransform, aFillRule);
   RefPtr<PathBuilderRecording> recording = new PathBuilderRecording(pathBuilder, aFillRule);
   typedef std::vector<PathOp> pathOpVec;
   for (pathOpVec::const_iterator iter = mPathOps.begin(); iter != mPathOps.end(); iter++) {
     PathOp newPathOp;
     newPathOp.mType = iter->mType;
     if (sPointCount[newPathOp.mType] >= 1) {
-      newPathOp.mP1 = aTransform * iter->mP1;
+      newPathOp.mP1 = aTransform.TransformPoint(iter->mP1);
     }
     if (sPointCount[newPathOp.mType] >= 2) {
-      newPathOp.mP2 = aTransform * iter->mP2;
+      newPathOp.mP2 = aTransform.TransformPoint(iter->mP2);
     }
     if (sPointCount[newPathOp.mType] >= 3) {
-      newPathOp.mP3 = aTransform * iter->mP3;
+      newPathOp.mP3 = aTransform.TransformPoint(iter->mP3);
     }
     recording->mPathOps.push_back(newPathOp);
   }
   return recording.forget();
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/PathSkia.cpp
+++ b/gfx/2d/PathSkia.cpp
@@ -129,17 +129,17 @@ PathSkia::TransformedCopyToBuilder(const
 static bool
 SkPathContainsPoint(const SkPath& aPath, const Point& aPoint, const Matrix& aTransform)
 {
   Matrix inverse = aTransform;
   if (!inverse.Invert()) {
     return false;
   }
 
-  SkPoint point = PointToSkPoint(inverse * aPoint);
+  SkPoint point = PointToSkPoint(inverse.TransformPoint(aPoint));
   return aPath.contains(point.fX, point.fY);
 }
 
 bool
 PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
 {
   if (!mPath.isFinite()) {
     return false;
--- a/gfx/2d/ScaledFontDWrite.h
+++ b/gfx/2d/ScaledFontDWrite.h
@@ -18,49 +18,54 @@ class ScaledFontDWrite final : public Sc
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite)
   ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize)
     : ScaledFontBase(aSize)
     , mFont(nullptr)
     , mFontFamily(nullptr)
     , mFontFace(aFont)
+    , mUseEmbeddedBitmap(false)
   {}
 
   ScaledFontDWrite(IDWriteFont* aFont, IDWriteFontFamily* aFontFamily,
-                   IDWriteFontFace *aFontFace, Float aSize)
+                   IDWriteFontFace *aFontFace, Float aSize, bool aUseEmbeddedBitmap)
     : ScaledFontBase(aSize)
     , mFont(aFont)
     , mFontFamily(aFontFamily)
     , mFontFace(aFontFace)
+    , mUseEmbeddedBitmap(aUseEmbeddedBitmap)
   {}
 
   virtual FontType GetType() const { return FontType::DWRITE; }
 
   virtual already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget);
   virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint);
 
   void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink);
 
   virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics);
 
   virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
 
   virtual AntialiasMode GetDefaultAAMode() override;
 
+  bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; }
+
 #ifdef USE_SKIA
   virtual SkTypeface* GetSkTypeface();
   bool GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
   bool DefaultToArialFont(IDWriteFontCollection* aSystemFonts);
 #endif
 
   // The font and font family are only used with Skia
   RefPtr<IDWriteFont> mFont;
   RefPtr<IDWriteFontFamily> mFontFamily;
   RefPtr<IDWriteFontFace> mFontFace;
+  bool mUseEmbeddedBitmap;
 
 protected:
 #ifdef USE_CAIRO_SCALED_FONT
   cairo_font_face_t* GetCairoFontFace() override;
 #endif
 };
 
 class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -119,17 +119,17 @@ static const FeatureInfo sFeatureInfoArr
             // Intentionally avoid putting ANGLE_depth_texture here,
             // it does not offer quite the same functionality.
             GLContext::Extensions_End
         }
     },
     {
         "draw_buffers",
         GLVersion::GL2,
-        GLESVersion::NONE,
+        GLESVersion::ES3,
         GLContext::Extension_None,
         {
             GLContext::ARB_draw_buffers,
             GLContext::EXT_draw_buffers,
             GLContext::Extensions_End
         }
     },
     {
--- a/gfx/layers/LayerSorter.cpp
+++ b/gfx/layers/LayerSorter.cpp
@@ -41,17 +41,17 @@ enum LayerSortOrder {
  * We want to solve:
  *
  * point = normal . (p0 - l0) / normal . l
  */
 static gfxFloat RecoverZDepth(const Matrix4x4& aTransform, const gfxPoint& aPoint)
 {
     const Point3D l(0, 0, 1);
     Point3D l0 = Point3D(aPoint.x, aPoint.y, 0);
-    Point3D p0 = aTransform * Point3D(0, 0, 0);
+    Point3D p0 = aTransform.TransformPoint(Point3D(0, 0, 0));
     Point3D normal = aTransform.GetNormalVector();
 
     gfxFloat n = normal.DotProduct(p0 - l0); 
     gfxFloat d = normal.DotProduct(l);
 
     if (!d) {
         return 0;
     }
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -682,17 +682,17 @@ Layer::SnapTransformTranslation(const Ma
     // don't snap it.
     // For a perspective transform, the content is transformed in
     // non-linear, so we don't snap it too.
     return aTransform;
   }
 
   // Snap for 3D Transforms
 
-  Point3D transformedOrigin = aTransform * Point3D();
+  Point3D transformedOrigin = aTransform.TransformPoint(Point3D());
 
   // Compute the transformed snap by rounding the values of
   // transformed origin.
   auto transformedSnapXY = IntPoint::Round(transformedOrigin.x, transformedOrigin.y);
   Matrix4x4 inverse = aTransform;
   inverse.Invert();
   // see Matrix4x4::ProjectPoint()
   Float transformedSnapZ =
@@ -701,17 +701,17 @@ Layer::SnapTransformTranslation(const Ma
                               inverse._43) / inverse._33);
   Point3D transformedSnap =
     Point3D(transformedSnapXY.x, transformedSnapXY.y, transformedSnapZ);
   if (transformedOrigin == transformedSnap) {
     return aTransform;
   }
 
   // Compute the snap from the transformed snap.
-  Point3D snap = inverse * transformedSnap;
+  Point3D snap = inverse.TransformPoint(transformedSnap);
   if (snap.z > 0.001 || snap.z < -0.001) {
     // Allow some level of accumulated computation error.
     MOZ_ASSERT(inverse._33 == 0.0);
     return aTransform;
   }
 
   // The difference between the origin and snap is the residual transform.
   if (aResidualTransform) {
@@ -744,19 +744,19 @@ Layer::SnapTransform(const Matrix4x4& aT
   }
 
   Matrix matrix2D;
   Matrix4x4 result;
   if (mManager->IsSnappingEffectiveTransforms() &&
       aTransform.Is2D(&matrix2D) &&
       gfxSize(1.0, 1.0) <= aSnapRect.Size() &&
       matrix2D.PreservesAxisAlignedRectangles()) {
-    auto transformedTopLeft = IntPoint::Round(matrix2D * ToPoint(aSnapRect.TopLeft()));
-    auto transformedTopRight = IntPoint::Round(matrix2D * ToPoint(aSnapRect.TopRight()));
-    auto transformedBottomRight = IntPoint::Round(matrix2D * ToPoint(aSnapRect.BottomRight()));
+    auto transformedTopLeft = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopLeft())));
+    auto transformedTopRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.TopRight())));
+    auto transformedBottomRight = IntPoint::Round(matrix2D.TransformPoint(ToPoint(aSnapRect.BottomRight())));
 
     Matrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
       transformedTopLeft, transformedTopRight, transformedBottomRight);
 
     result = Matrix4x4::From2D(snappedMatrix);
     if (aResidualTransform && !snappedMatrix.IsSingular()) {
       // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
       // (i.e., appying snappedMatrix after aResidualTransform gives the
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1973,22 +1973,21 @@ public:
         mAllowResidualTranslation ? &residual : nullptr);
     // The residual can only be a translation because SnapTransformTranslation
     // only changes the transform if it's a translation
     NS_ASSERTION(residual.IsTranslation(),
                  "Residual transform can only be a translation");
     if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
       mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation());
       DebugOnly<mozilla::gfx::Point> transformedOrig =
-        idealTransform * mozilla::gfx::Point();
+        idealTransform.TransformPoint(mozilla::gfx::Point());
 #ifdef DEBUG
-      DebugOnly<mozilla::gfx::Point> transformed =
-        idealTransform * mozilla::gfx::Point(mResidualTranslation.x,
-                                             mResidualTranslation.y) -
-        *&transformedOrig;
+      DebugOnly<mozilla::gfx::Point> transformed = idealTransform.TransformPoint(
+        mozilla::gfx::Point(mResidualTranslation.x, mResidualTranslation.y)
+      ) - *&transformedOrig;
 #endif
       NS_ASSERTION(-0.5 <= (&transformed)->x && (&transformed)->x < 0.5 &&
                    -0.5 <= (&transformed)->y && (&transformed)->y < 0.5,
                    "Residual translation out of range");
       mValidRegion.SetEmpty();
     }
     ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
   }
--- a/gfx/layers/apz/test/gtest/TestHitTesting.cpp
+++ b/gfx/layers/apz/test/gtest/TestHitTesting.cpp
@@ -116,49 +116,49 @@ TEST_F(APZHitTestingTester, HitTesting1)
   uint32_t paintSequenceNumber = 0;
 
   // Now we have a root APZC that will match the page
   SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID);
   manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++);
   hit = GetTargetAPZC(ScreenPoint(15, 15));
   EXPECT_EQ(ApzcOf(root), hit.get());
   // expect hit point at LayerIntPoint(15, 15)
-  EXPECT_EQ(ParentLayerPoint(15, 15), transformToApzc * ScreenPoint(15, 15));
-  EXPECT_EQ(ScreenPoint(15, 15), transformToGecko * ParentLayerPoint(15, 15));
+  EXPECT_EQ(ParentLayerPoint(15, 15), transformToApzc.TransformPoint(ScreenPoint(15, 15)));
+  EXPECT_EQ(ScreenPoint(15, 15), transformToGecko.TransformPoint(ParentLayerPoint(15, 15)));
 
   // Now we have a sub APZC with a better fit
   SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 1);
   manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++);
   EXPECT_NE(ApzcOf(root), ApzcOf(layers[3]));
   hit = GetTargetAPZC(ScreenPoint(25, 25));
   EXPECT_EQ(ApzcOf(layers[3]), hit.get());
   // expect hit point at LayerIntPoint(25, 25)
-  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc * ScreenPoint(25, 25));
-  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(25, 25));
+  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc.TransformPoint(ScreenPoint(25, 25)));
+  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko.TransformPoint(ParentLayerPoint(25, 25)));
 
   // At this point, layers[4] obscures layers[3] at the point (15, 15) so
   // hitting there should hit the root APZC
   hit = GetTargetAPZC(ScreenPoint(15, 15));
   EXPECT_EQ(ApzcOf(root), hit.get());
 
   // Now test hit testing when we have two scrollable layers
   SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 2);
   manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++);
   hit = GetTargetAPZC(ScreenPoint(15, 15));
   EXPECT_EQ(ApzcOf(layers[4]), hit.get());
   // expect hit point at LayerIntPoint(15, 15)
-  EXPECT_EQ(ParentLayerPoint(15, 15), transformToApzc * ScreenPoint(15, 15));
-  EXPECT_EQ(ScreenPoint(15, 15), transformToGecko * ParentLayerPoint(15, 15));
+  EXPECT_EQ(ParentLayerPoint(15, 15), transformToApzc.TransformPoint(ScreenPoint(15, 15)));
+  EXPECT_EQ(ScreenPoint(15, 15), transformToGecko.TransformPoint(ParentLayerPoint(15, 15)));
 
   // Hit test ouside the reach of layer[3,4] but inside root
   hit = GetTargetAPZC(ScreenPoint(90, 90));
   EXPECT_EQ(ApzcOf(root), hit.get());
   // expect hit point at LayerIntPoint(90, 90)
-  EXPECT_EQ(ParentLayerPoint(90, 90), transformToApzc * ScreenPoint(90, 90));
-  EXPECT_EQ(ScreenPoint(90, 90), transformToGecko * ParentLayerPoint(90, 90));
+  EXPECT_EQ(ParentLayerPoint(90, 90), transformToApzc.TransformPoint(ScreenPoint(90, 90)));
+  EXPECT_EQ(ScreenPoint(90, 90), transformToGecko.TransformPoint(ParentLayerPoint(90, 90)));
 
   // Hit test ouside the reach of any layer
   hit = GetTargetAPZC(ScreenPoint(1000, 10));
   EXPECT_EQ(nullAPZC, hit.get());
   EXPECT_EQ(ScreenToParentLayerMatrix4x4(), transformToApzc);
   EXPECT_EQ(ParentLayerToScreenMatrix4x4(), transformToGecko);
   hit = GetTargetAPZC(ScreenPoint(-1000, 10));
   EXPECT_EQ(nullAPZC, hit.get());
@@ -183,103 +183,103 @@ TEST_F(APZHitTestingTester, HitTesting2)
 
   TestAsyncPanZoomController* apzcroot = ApzcOf(root);
   TestAsyncPanZoomController* apzc1 = ApzcOf(layers[1]);
   TestAsyncPanZoomController* apzc3 = ApzcOf(layers[3]);
 
   // Hit an area that's clearly on the root layer but not any of the child layers.
   RefPtr<AsyncPanZoomController> hit = GetTargetAPZC(ScreenPoint(75, 25));
   EXPECT_EQ(apzcroot, hit.get());
-  EXPECT_EQ(ParentLayerPoint(75, 25), transformToApzc * ScreenPoint(75, 25));
-  EXPECT_EQ(ScreenPoint(75, 25), transformToGecko * ParentLayerPoint(75, 25));
+  EXPECT_EQ(ParentLayerPoint(75, 25), transformToApzc.TransformPoint(ScreenPoint(75, 25)));
+  EXPECT_EQ(ScreenPoint(75, 25), transformToGecko.TransformPoint(ParentLayerPoint(75, 25)));
 
   // Hit an area on the root that would be on layers[3] if layers[2]
   // weren't transformed.
   // Note that if layers[2] were scrollable, then this would hit layers[2]
   // because its composition bounds would be at (10,60)-(50,100) (and the
   // scale-only transform that we set on layers[2] would be invalid because
   // it would place the layer into overscroll, as its composition bounds
   // start at x=10 but its content at x=20).
   hit = GetTargetAPZC(ScreenPoint(15, 75));
   EXPECT_EQ(apzcroot, hit.get());
-  EXPECT_EQ(ParentLayerPoint(15, 75), transformToApzc * ScreenPoint(15, 75));
-  EXPECT_EQ(ScreenPoint(15, 75), transformToGecko * ParentLayerPoint(15, 75));
+  EXPECT_EQ(ParentLayerPoint(15, 75), transformToApzc.TransformPoint(ScreenPoint(15, 75)));
+  EXPECT_EQ(ScreenPoint(15, 75), transformToGecko.TransformPoint(ParentLayerPoint(15, 75)));
 
   // Hit an area on layers[1].
   hit = GetTargetAPZC(ScreenPoint(25, 25));
   EXPECT_EQ(apzc1, hit.get());
-  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc * ScreenPoint(25, 25));
-  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(25, 25));
+  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc.TransformPoint(ScreenPoint(25, 25)));
+  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko.TransformPoint(ParentLayerPoint(25, 25)));
 
   // Hit an area on layers[3].
   hit = GetTargetAPZC(ScreenPoint(25, 75));
   EXPECT_EQ(apzc3, hit.get());
   // transformToApzc should unapply layers[2]'s transform
-  EXPECT_EQ(ParentLayerPoint(12.5, 75), transformToApzc * ScreenPoint(25, 75));
+  EXPECT_EQ(ParentLayerPoint(12.5, 75), transformToApzc.TransformPoint(ScreenPoint(25, 75)));
   // and transformToGecko should reapply it
-  EXPECT_EQ(ScreenPoint(25, 75), transformToGecko * ParentLayerPoint(12.5, 75));
+  EXPECT_EQ(ScreenPoint(25, 75), transformToGecko.TransformPoint(ParentLayerPoint(12.5, 75)));
 
   // Hit an area on layers[3] that would be on the root if layers[2]
   // weren't transformed.
   hit = GetTargetAPZC(ScreenPoint(75, 75));
   EXPECT_EQ(apzc3, hit.get());
   // transformToApzc should unapply layers[2]'s transform
-  EXPECT_EQ(ParentLayerPoint(37.5, 75), transformToApzc * ScreenPoint(75, 75));
+  EXPECT_EQ(ParentLayerPoint(37.5, 75), transformToApzc.TransformPoint(ScreenPoint(75, 75)));
   // and transformToGecko should reapply it
-  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko * ParentLayerPoint(37.5, 75));
+  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko.TransformPoint(ParentLayerPoint(37.5, 75)));
 
   // Pan the root layer upward by 50 pixels.
   // This causes layers[1] to scroll out of view, and an async transform
   // of -50 to be set on the root layer.
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
 
   // This first pan will move the APZC by 50 pixels, and dispatch a paint request.
   // Since this paint request is in the queue to Gecko, transformToGecko will
   // take it into account.
   ApzcPanNoFling(apzcroot, 100, 50);
 
   // Hit where layers[3] used to be. It should now hit the root.
   hit = GetTargetAPZC(ScreenPoint(75, 75));
   EXPECT_EQ(apzcroot, hit.get());
   // transformToApzc doesn't unapply the root's own async transform
-  EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc * ScreenPoint(75, 75));
+  EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc.TransformPoint(ScreenPoint(75, 75)));
   // and transformToGecko unapplies it and then reapplies it, because by the
   // time the event being transformed reaches Gecko the new paint request will
   // have been handled.
-  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko * ParentLayerPoint(75, 75));
+  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko.TransformPoint(ParentLayerPoint(75, 75)));
 
   // Hit where layers[1] used to be and where layers[3] should now be.
   hit = GetTargetAPZC(ScreenPoint(25, 25));
   EXPECT_EQ(apzc3, hit.get());
   // transformToApzc unapplies both layers[2]'s css transform and the root's
   // async transform
-  EXPECT_EQ(ParentLayerPoint(12.5, 75), transformToApzc * ScreenPoint(25, 25));
+  EXPECT_EQ(ParentLayerPoint(12.5, 75), transformToApzc.TransformPoint(ScreenPoint(25, 25)));
   // transformToGecko reapplies both the css transform and the async transform
   // because we have already issued a paint request with it.
-  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(12.5, 75));
+  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko.TransformPoint(ParentLayerPoint(12.5, 75)));
 
   // This second pan will move the APZC by another 50 pixels.
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
   ApzcPanNoFling(apzcroot, 100, 50);
 
   // Hit where layers[3] used to be. It should now hit the root.
   hit = GetTargetAPZC(ScreenPoint(75, 75));
   EXPECT_EQ(apzcroot, hit.get());
   // transformToApzc doesn't unapply the root's own async transform
-  EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc * ScreenPoint(75, 75));
+  EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc.TransformPoint(ScreenPoint(75, 75)));
   // transformToGecko unapplies the full async transform of -100 pixels
-  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko * ParentLayerPoint(75, 75));
+  EXPECT_EQ(ScreenPoint(75, 75), transformToGecko.TransformPoint(ParentLayerPoint(75, 75)));
 
   // Hit where layers[1] used to be. It should now hit the root.
   hit = GetTargetAPZC(ScreenPoint(25, 25));
   EXPECT_EQ(apzcroot, hit.get());
   // transformToApzc doesn't unapply the root's own async transform
-  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc * ScreenPoint(25, 25));
+  EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc.TransformPoint(ScreenPoint(25, 25)));
   // transformToGecko unapplies the full async transform of -100 pixels
-  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(25, 25));
+  EXPECT_EQ(ScreenPoint(25, 25), transformToGecko.TransformPoint(ParentLayerPoint(25, 25)));
 }
 
 TEST_F(APZHitTestingTester, ComplexMultiLayerTree) {
   CreateComplexMultiLayerTree();
   ScopedLayerTreeRegistration registration(manager, 0, root, mcc);
   manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
 
   /* The layer tree looks like this:
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -490,18 +490,18 @@ AsyncCompositionManager::AlignFixedAndSt
         LayerPoint offsetAnchor = anchor + GetLayerFixedMarginsOffset(layer, aFixedLayerMargins);
 
         // Additionally transform the anchor to compensate for the change
         // from the old cumulative transform to the new cumulative transform. We do
         // this by using the old transform to take the offset anchor back into
         // subtree root space, and then the inverse of the new cumulative transform
         // to bring it back to layer space.
         LayerPoint transformedAnchor = ViewAs<LayerPixel>(
-            newCumulativeTransform.Inverse() *
-            (oldCumulativeTransform * offsetAnchor.ToUnknownPoint()));
+            newCumulativeTransform.Inverse().TransformPoint(
+              (oldCumulativeTransform.TransformPoint(offsetAnchor.ToUnknownPoint()))));
 
         // We want to translate the layer by the difference between |transformedAnchor|
         // and |anchor|. To achieve this, we will add a translation to the layer's
         // transform. This translation will apply on top of the layer's local
         // transform, but |anchor| and |transformedAnchor| are in a coordinate space
         // where the local transform isn't applied yet, so apply it and then subtract
         // to get the desired translation.
         auto localTransformTyped = ViewAs<LayerToParentLayerMatrix4x4>(localTransform);
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -309,25 +309,25 @@ gfxAndroidPlatform::GetScaledFontForFont
 }
 
 bool
 gfxAndroidPlatform::FontHintingEnabled()
 {
     // In "mobile" builds, we sometimes use non-reflow-zoom, so we
     // might not want hinting.  Let's see.
 
-#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
-    // On android-java, we currently only use gecko to render web
+#ifdef MOZ_WIDGET_ANDROID
+    // On Android, we currently only use gecko to render web
     // content that can always be be non-reflow-zoomed.  So turn off
     // hinting.
     // 
     // XXX when gecko-android-java is used as an "app runtime", we may
     // want to re-enable hinting for non-browser processes there.
     return false;
-#endif //  MOZ_USING_ANDROID_JAVA_WIDGETS
+#endif //  MOZ_WIDGET_ANDROID
 
 #ifdef MOZ_WIDGET_GONK
     // On B2G, the UX preference is currently to keep hinting disabled
     // for all text (see bug 829523).
     return false;
 #endif
 
     // Currently, we don't have any other targets, but if/when we do,
@@ -335,18 +335,18 @@ gfxAndroidPlatform::FontHintingEnabled()
 
     NS_NOTREACHED("oops, what platform is this?");
     return gfxPlatform::FontHintingEnabled();
 }
 
 bool
 gfxAndroidPlatform::RequiresLinearZoom()
 {
-#ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
-    // On android-java, we currently only use gecko to render web
+#ifdef MOZ_WIDGET_ANDROID
+    // On Android, we currently only use gecko to render web
     // content that can always be be non-reflow-zoomed.
     //
     // XXX when gecko-android-java is used as an "app runtime", we may
     // want to treat it like B2G and use linear zoom only for the web
     // browser process, not other apps.
     return true;
 #endif
 
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -276,41 +276,35 @@ gfxMatrix
 gfxContext::CurrentMatrix() const
 {
   return ThebesMatrix(mTransform);
 }
 
 gfxPoint
 gfxContext::DeviceToUser(const gfxPoint& point) const
 {
-  Matrix matrix = mTransform;
-  matrix.Invert();
-  return ThebesPoint(matrix * ToPoint(point));
+  return ThebesPoint(mTransform.Inverse().TransformPoint(ToPoint(point)));
 }
 
 Size
 gfxContext::DeviceToUser(const Size& size) const
 {
-  Matrix matrix = mTransform;
-  matrix.Invert();
-  return matrix * size;
+  return mTransform.Inverse().TransformSize(size);
 }
 
 gfxRect
 gfxContext::DeviceToUser(const gfxRect& rect) const
 {
-  Matrix matrix = mTransform;
-  matrix.Invert();
-  return ThebesRect(matrix.TransformBounds(ToRect(rect)));
+  return ThebesRect(mTransform.Inverse().TransformBounds(ToRect(rect)));
 }
 
 gfxPoint
 gfxContext::UserToDevice(const gfxPoint& point) const
 {
-  return ThebesPoint(mTransform * ToPoint(point));
+  return ThebesPoint(mTransform.TransformPoint(ToPoint(point)));
 }
 
 Size
 gfxContext::UserToDevice(const Size& size) const
 {
   const Matrix &matrix = mTransform;
 
   Size newSize;
@@ -1153,20 +1147,20 @@ gfxContext::ChangeTransform(const Matrix
     Matrix toNewUS = mTransform * invMatrix;
 
     if (toNewUS.IsRectilinear()) {
       mRect = toNewUS.TransformBounds(mRect);
       mRect.NudgeToIntegers();
     } else {
       mPathBuilder = mDT->CreatePathBuilder(FillRule::FILL_WINDING);
 
-      mPathBuilder->MoveTo(toNewUS * mRect.TopLeft());
-      mPathBuilder->LineTo(toNewUS * mRect.TopRight());
-      mPathBuilder->LineTo(toNewUS * mRect.BottomRight());
-      mPathBuilder->LineTo(toNewUS * mRect.BottomLeft());
+      mPathBuilder->MoveTo(toNewUS.TransformPoint(mRect.TopLeft()));
+      mPathBuilder->LineTo(toNewUS.TransformPoint(mRect.TopRight()));
+      mPathBuilder->LineTo(toNewUS.TransformPoint(mRect.BottomRight()));
+      mPathBuilder->LineTo(toNewUS.TransformPoint(mRect.BottomLeft()));
       mPathBuilder->Close();
 
       mPathIsRect = false;
     }
 
     // No need to consider the transform changed now!
     mTransformChanged = false;
   } else if ((mPath || mPathBuilder) && !mTransformChanged) {
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -697,19 +697,24 @@ gfxDWriteFont::GetScaledFont(mozilla::gf
   nativeFont.mType = NativeFontType::DWRITE_FONT_FACE;
   nativeFont.mFont = GetFontFace();
 
   if (wantCairo) {
     mAzureScaledFont = Factory::CreateScaledFontWithCairo(nativeFont,
                                                         GetAdjustedSize(),
                                                         GetCairoScaledFont());
   } else if (aTarget->GetBackendType() == BackendType::SKIA) {
+    gfxDWriteFontEntry *fe =
+        static_cast<gfxDWriteFontEntry*>(mFontEntry.get());
+    bool useEmbeddedBitmap = (fe->IsCJKFont() && HasBitmapStrikeForSize(NS_lround(mAdjustedSize)));
+
     mAzureScaledFont =
             Factory::CreateScaledFontForDWriteFont(mFont, mFontFamily,
-                                                   mFontFace, GetAdjustedSize());
+                                                   mFontFace, GetAdjustedSize(),
+                                                   useEmbeddedBitmap);
   } else {
     mAzureScaledFont = Factory::CreateScaledFontForNativeFont(nativeFont,
                                                             GetAdjustedSize());
   }
 
   mAzureScaledFontIsCairo = wantCairo;
 
   RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1570,17 +1570,17 @@ public:
     }
 
     void OutputGlyph(uint32_t aGlyphID, const gfxPoint& aPt)
     {
         Glyph *glyph = AppendGlyph();
         glyph->mIndex = aGlyphID;
         glyph->mPosition.x = aPt.x;
         glyph->mPosition.y = aPt.y;
-        glyph->mPosition = mFontParams.matInv * glyph->mPosition;
+        glyph->mPosition = mFontParams.matInv.TransformPoint(glyph->mPosition);
         Flush(false); // this will flush only if the buffer is full
     }
 
     const TextRunDrawParams& mRunParams;
     const FontDrawParams& mFontParams;
 
 private:
 #define GLYPH_BUFFER_SIZE (2048/sizeof(Glyph))
@@ -1761,17 +1761,17 @@ private:
 // doesn't appear bolded, it appears as if a bad text shadow exists
 // when a non-identity transform exists.  Use an offset factor so that
 // the second draw occurs at a constant offset in device pixels.
 
 double
 gfxFont::CalcXScale(DrawTarget* aDrawTarget)
 {
     // determine magnitude of a 1px x offset in device space
-    Size t = aDrawTarget->GetTransform() * Size(1.0, 0.0);
+    Size t = aDrawTarget->GetTransform().TransformSize(Size(1.0, 0.0));
     if (t.width == 1.0 && t.height == 0.0) {
         // short-circuit the most common case to avoid sqrt() and division
         return 1.0;
     }
 
     double m = sqrt(t.width * t.width + t.height * t.height);
 
     NS_ASSERTION(m != 0.0, "degenerate transform while synthetic bolding");
@@ -1829,17 +1829,17 @@ gfxFont::DrawOneGlyph(uint32_t aGlyphID,
             return;
         }
     }
 
     if (fontParams.haveColorGlyphs &&
         RenderColorGlyph(runParams.dt, runParams.context,
                          fontParams.scaledFont, fontParams.renderingOptions,
                          fontParams.drawOptions,
-                         fontParams.matInv * gfx::Point(devPt.x, devPt.y),
+                         fontParams.matInv.TransformPoint(gfx::Point(devPt.x, devPt.y)),
                          aGlyphID)) {
         return;
     }
 
     aBuffer.OutputGlyph(aGlyphID, devPt);
 
     // Synthetic bolding (if required) by multi-striking.
     for (int32_t i = 0; i < fontParams.extraStrikes; ++i) {
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -275,21 +275,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-    # This is set for "normal Android", that is, when Gecko is running on
-    # top of the android java runtime.
-    DEFINES['MOZ_USING_ANDROID_JAVA_WIDGETS'] = True
-
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
 
 LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
 
 DEFINES['GRAPHITE2_STATIC'] = True
 
 if CONFIG['CLANG_CXX']:
--- a/image/ImageCacheKey.cpp
+++ b/image/ImageCacheKey.cpp
@@ -42,22 +42,25 @@ BlobSerial(ImageURL* aURI)
     return Some(blob->GetSerialNumber());
   }
 
   return Nothing();
 }
 
 ImageCacheKey::ImageCacheKey(nsIURI* aURI,
                              const PrincipalOriginAttributes& aAttrs,
-                             nsIDocument* aDocument)
-  : mURI(new ImageURL(aURI))
+                             nsIDocument* aDocument,
+                             nsresult& aRv)
+  : mURI(new ImageURL(aURI, aRv))
   , mOriginAttributes(aAttrs)
   , mControlledDocument(GetControlledDocumentToken(aDocument))
   , mIsChrome(URISchemeIs(mURI, "chrome"))
 {
+  NS_ENSURE_SUCCESS_VOID(aRv);
+
   MOZ_ASSERT(NS_IsMainThread());
 
   if (URISchemeIs(mURI, "blob")) {
     mBlobSerial = BlobSerial(mURI);
   }
 
   mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument);
 }
--- a/image/ImageCacheKey.h
+++ b/image/ImageCacheKey.h
@@ -29,17 +29,17 @@ class ImageURL;
  * canonicalization applied. See ComputeHash() for the details.
  * Controlled documents do not share their cache entries with
  * non-controlled documents, or other controlled documents.
  */
 class ImageCacheKey final
 {
 public:
   ImageCacheKey(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs,
-                nsIDocument* aDocument);
+                nsIDocument* aDocument, nsresult& aRv);
   ImageCacheKey(ImageURL* aURI, const PrincipalOriginAttributes& aAttrs,
                 nsIDocument* aDocument);
 
   ImageCacheKey(const ImageCacheKey& aOther);
   ImageCacheKey(ImageCacheKey&& aOther);
 
   bool operator==(const ImageCacheKey& aOther) const;
   uint32_t Hash() const { return mHash; }
--- a/image/ImageURL.h
+++ b/image/ImageURL.h
@@ -23,22 +23,28 @@ namespace image {
  * intentional; functionality is limited, and is only useful for imagelib code.
  * By not implementing nsIURI, external code cannot unintentionally be given an
  * nsIURI pointer with this limited class behind it; instead, conversion to a
  * fully implemented nsIURI is required (e.g. through NS_NewURI).
  */
 class ImageURL
 {
 public:
-  explicit ImageURL(nsIURI* aURI)
+  explicit ImageURL(nsIURI* aURI, nsresult& aRv)
   {
     MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
-    aURI->GetSpec(mSpec);
-    aURI->GetScheme(mScheme);
-    aURI->GetRef(mRef);
+
+    aRv = aURI->GetSpec(mSpec);
+    NS_ENSURE_SUCCESS_VOID(aRv);
+
+    aRv = aURI->GetScheme(mScheme);
+    NS_ENSURE_SUCCESS_VOID(aRv);
+
+    aRv = aURI->GetRef(mRef);
+    NS_ENSURE_SUCCESS_VOID(aRv);
   }
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageURL)
 
   nsresult GetSpec(nsACString& result)
   {
     result = mSpec;
     return NS_OK;
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -382,24 +382,28 @@ NS_IMETHODIMP
 nsMozIconURI::SetRef(const nsACString& aRef)
 {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsMozIconURI::Equals(nsIURI* other, bool* result)
 {
+  *result = false;
   NS_ENSURE_ARG_POINTER(other);
   NS_PRECONDITION(result, "null pointer");
 
   nsAutoCString spec1;
   nsAutoCString spec2;
 
-  other->GetSpec(spec2);
-  GetSpec(spec1);
+  nsresult rv = GetSpec(spec1);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = other->GetSpec(spec2);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   if (!PL_strcasecmp(spec1.get(), spec2.get())) {
     *result = true;
   } else {
     *result = false;
   }
   return NS_OK;
 }
 
--- a/image/imgICache.idl
+++ b/image/imgICache.idl
@@ -40,17 +40,19 @@ interface imgICache : nsISupports
    * succeed, but come back empty.
    *
    * Hopefully this will be removed with bug 805119
    *
    * @param uri The URI to look up.
    * @param doc Optional pointer to the document that the cache entry belongs to.
    * @returns NULL if the URL was not found in the cache
    */
-  nsIProperties findEntryProperties(in nsIURI uri, [optional] in nsIDOMDocument doc);
+  [must_use]
+  nsIProperties findEntryProperties(in nsIURI uri,
+                                    [optional] in nsIDOMDocument doc);
 
   /**
    * Make this cache instance respect private browsing notifications. This
    * entails clearing the chrome and content caches whenever the
    * last-pb-context-exited notification is observed.
    */
   void respectPrivacyNotifications();
 
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -1308,17 +1308,19 @@ imgLoader::FindEntryProperties(nsIURI* u
   PrincipalOriginAttributes attrs;
   if (doc) {
     nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
     if (principal) {
       attrs = BasePrincipal::Cast(principal)->OriginAttributesRef();
     }
   }
 
-  ImageCacheKey key(uri, attrs, doc);
+  nsresult rv;
+  ImageCacheKey key(uri, attrs, doc, rv);
+  NS_ENSURE_SUCCESS(rv, rv);
   imgCacheTable& cache = GetCache(key);
 
   RefPtr<imgCacheEntry> entry;
   if (cache.Get(key, getter_AddRefs(entry)) && entry) {
     if (mCacheTracker && entry->HasNoProxies()) {
       mCacheTracker->MarkUsed(entry);
     }
 
@@ -2066,17 +2068,18 @@ imgLoader::LoadImage(nsIURI* aURI,
   // Look in the cache for our URI, and then validate it.
   // XXX For now ignore aCacheKey. We will need it in the future
   // for correctly dealing with image load requests that are a result
   // of post data.
   PrincipalOriginAttributes attrs;
   if (aLoadingPrincipal) {
     attrs = BasePrincipal::Cast(aLoadingPrincipal)->OriginAttributesRef();
   }
-  ImageCacheKey key(aURI, attrs, aLoadingDocument);
+  ImageCacheKey key(aURI, attrs, aLoadingDocument, rv);
+  NS_ENSURE_SUCCESS(rv, rv);
   imgCacheTable& cache = GetCache(key);
 
   if (cache.Get(key, getter_AddRefs(entry)) && entry) {
     if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
                       aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
                       requestFlags, aContentPolicyType, true, _retval,
                       aLoadingPrincipal, corsmode)) {
       request = entry->GetRequest();
@@ -2137,19 +2140,22 @@ imgLoader::LoadImage(nsIURI* aURI,
                        getter_AddRefs(entry));
 
     MOZ_LOG(gImgLog, LogLevel::Debug,
            ("[this=%p] imgLoader::LoadImage -- Created new imgRequest"
             " [request=%p]\n", this, request.get()));
 
     nsCOMPtr<nsILoadGroup> channelLoadGroup;
     newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
-    request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
-                  channelLoadGroup, newChannel, entry, aLoadingDocument,
-                  aLoadingPrincipal, corsmode, aReferrerPolicy);
+    rv = request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
+                       channelLoadGroup, newChannel, entry, aLoadingDocument,
+                       aLoadingPrincipal, corsmode, aReferrerPolicy);
+    if (NS_FAILED(rv)) {
+      return NS_ERROR_FAILURE;
+    }
 
     // Add the initiator type for this image load
     nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(newChannel);
     if (timedChannel) {
       timedChannel->SetInitiatorType(initiatorType);
     }
 
     // create the proxy listener
@@ -2275,17 +2281,19 @@ imgLoader::LoadImageWithChannel(nsIChann
   NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
   nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
 
   PrincipalOriginAttributes attrs;
   if (loadInfo) {
     attrs.InheritFromNecko(loadInfo->GetOriginAttributes());
   }
 
-  ImageCacheKey key(uri, attrs, doc);
+  nsresult rv;
+  ImageCacheKey key(uri, attrs, doc, rv);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;
   channel->GetLoadFlags(&requestFlags);
 
   RefPtr<imgCacheEntry> entry;
 
   if (requestFlags & nsIRequest::LOAD_BYPASS_CACHE) {
     RemoveFromCache(key);
@@ -2356,17 +2364,17 @@ imgLoader::LoadImageWithChannel(nsIChann
   }
 
   nsCOMPtr<nsILoadGroup> loadGroup;
   channel->GetLoadGroup(getter_AddRefs(loadGroup));
 
   // Filter out any load flags not from nsIRequest
   requestFlags &= nsIRequest::LOAD_REQUESTMASK;
 
-  nsresult rv = NS_OK;
+  rv = NS_OK;
   if (request) {
     // we have this in our cache already.. cancel the current (document) load
 
     // this should fire an OnStopRequest
     channel->Cancel(NS_ERROR_PARSED_DATA_CACHED);
 
     *listener = nullptr; // give them back a null nsIStreamListener
 
@@ -2377,17 +2385,18 @@ imgLoader::LoadImageWithChannel(nsIChann
     // We use originalURI here to fulfil the imgIRequest contract on GetURI.
     nsCOMPtr<nsIURI> originalURI;
     channel->GetOriginalURI(getter_AddRefs(originalURI));
 
     // XXX(seth): We should be able to just use |key| here, except that |key| is
     // constructed above with the *current URI* and not the *original URI*. I'm
     // pretty sure this is a bug, and it's preventing us from ever getting a
     // cache hit in LoadImageWithChannel when redirects are involved.
-    ImageCacheKey originalURIKey(originalURI, attrs, doc);
+    ImageCacheKey originalURIKey(originalURI, attrs, doc, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     // Default to doing a principal check because we don't know who
     // started that load and whether their principal ended up being
     // inherited on the channel.
     NewRequestAndEntry(/* aForcePrincipalCheckForCacheEntry = */ true,
                        this, originalURIKey,
                        getter_AddRefs(request),
                        getter_AddRefs(entry));
@@ -2395,19 +2404,20 @@ imgLoader::LoadImageWithChannel(nsIChann
     // No principal specified here, because we're not passed one.
     // In LoadImageWithChannel, the redirects that may have been
     // 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.
-    request->Init(originalURI, uri, /* aHadInsecureRedirect = */ false,
-                  channel, channel, entry, aCX, nullptr,
-                  imgIRequest::CORS_NONE, RP_Default);
+    rv = request->Init(originalURI, uri, /* aHadInsecureRedirect = */ false,
+                       channel, channel, entry, aCX, nullptr,
+                       imgIRequest::CORS_NONE, RP_Default);
+    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);
 
@@ -2768,18 +2778,22 @@ imgCacheValidator::OnStartRequest(nsIReq
   mRequest->RemoveFromCache();
 
   mRequest->SetValidator(nullptr);
   mRequest = nullptr;
 
   // We use originalURI here to fulfil the imgIRequest contract on GetURI.
   nsCOMPtr<nsIURI> originalURI;
   channel->GetOriginalURI(getter_AddRefs(originalURI));
-  mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
-                    mNewEntry, context, loadingPrincipal, corsmode, refpol);
+  nsresult rv =
+    mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
+                      mNewEntry, context, loadingPrincipal, corsmode, refpol);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
 
   mDestListener = new ProxyListener(mNewRequest);
 
   // Try to add the new request into the cache. Note that the entry must be in
   // the cache before the proxies' ownership changes, because adding a proxy
   // changes the caching behaviour for imgRequests.
   mImgLoader->PutIntoCache(mNewRequest->CacheKey(), mNewEntry);
 
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -285,36 +285,37 @@ public:
    * All the same, even though what these add-ons are doing is a no-op,
    * removing the nsIServiceManager.getService method of creating/getting an
    * imgLoader objects would cause an exception in these add-ons that could
    * break things.
    */
   imgLoader();
   nsresult Init();
 
-  nsresult LoadImage(nsIURI* aURI,
-                     nsIURI* aInitialDocumentURI,
-                     nsIURI* aReferrerURI,
-                     ReferrerPolicy aReferrerPolicy,
-                     nsIPrincipal* aLoadingPrincipal,
-                     nsILoadGroup* aLoadGroup,
-                     imgINotificationObserver* aObserver,
-                     nsINode* aContext,
-                     nsIDocument* aLoadingDocument,
-                     nsLoadFlags aLoadFlags,
-                     nsISupports* aCacheKey,
-                     nsContentPolicyType aContentPolicyType,
-                     const nsAString& initiatorType,
-                     imgRequestProxy** _retval);
+  MOZ_MUST_USE nsresult LoadImage(nsIURI* aURI,
+                                  nsIURI* aInitialDocumentURI,
+                                  nsIURI* aReferrerURI,
+                                  ReferrerPolicy aReferrerPolicy,
+                                  nsIPrincipal* aLoadingPrincipal,
+                                  nsILoadGroup* aLoadGroup,
+                                  imgINotificationObserver* aObserver,
+                                  nsINode* aContext,
+                                  nsIDocument* aLoadingDocument,
+                                  nsLoadFlags aLoadFlags,
+                                  nsISupports* aCacheKey,
+                                  nsContentPolicyType aContentPolicyType,
+                                  const nsAString& initiatorType,
+                                  imgRequestProxy** _retval);
 
-  nsresult LoadImageWithChannel(nsIChannel* channel,
-                                imgINotificationObserver* aObserver,
-                                nsISupports* aCX,
-                                nsIStreamListener** listener,
-                                imgRequestProxy** _retval);
+  MOZ_MUST_USE nsresult
+  LoadImageWithChannel(nsIChannel* channel,
+                       imgINotificationObserver* aObserver,
+                       nsISupports* aCX,
+                       nsIStreamListener** listener,
+                       imgRequestProxy** _retval);
 
   static nsresult GetMimeTypeFromContent(const char* aContents,
                                          uint32_t aLength,
                                          nsACString& aContentType);
 
   /**
    * Returns true if the given mime type may be interpreted as an image.
    *
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -103,17 +103,20 @@ imgRequest::Init(nsIURI *aURI,
   MOZ_ASSERT(aURI, "No uri");
   MOZ_ASSERT(aCurrentURI, "No current uri");
   MOZ_ASSERT(aRequest, "No request");
   MOZ_ASSERT(aChannel, "No channel");
 
   mProperties = do_CreateInstance("@mozilla.org/properties;1");
 
   // Use ImageURL to ensure access to URI data off main thread.
-  mURI = new ImageURL(aURI);
+  nsresult rv;
+  mURI = new ImageURL(aURI, rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   mCurrentURI = aCurrentURI;
   mRequest = aRequest;
   mChannel = aChannel;
   mTimedChannel = do_QueryInterface(mChannel);
 
   mLoadingPrincipal = aLoadingPrincipal;
   mCORSMode = aCORSMode;
   mReferrerPolicy = aReferrerPolicy;
--- a/image/imgRequest.h
+++ b/image/imgRequest.h
@@ -60,26 +60,26 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
 
-  nsresult Init(nsIURI* aURI,
-                nsIURI* aCurrentURI,
-                bool aHadInsecureRedirect,
-                nsIRequest* aRequest,
-                nsIChannel* aChannel,
-                imgCacheEntry* aCacheEntry,
-                nsISupports* aCX,
-                nsIPrincipal* aLoadingPrincipal,
-                int32_t aCORSMode,
-                ReferrerPolicy aReferrerPolicy);
+  MOZ_MUST_USE nsresult Init(nsIURI* aURI,
+                             nsIURI* aCurrentURI,
+                             bool aHadInsecureRedirect,
+                             nsIRequest* aRequest,
+                             nsIChannel* aChannel,
+                             imgCacheEntry* aCacheEntry,
+                             nsISupports* aCX,
+                             nsIPrincipal* aLoadingPrincipal,
+                             int32_t aCORSMode,
+                             ReferrerPolicy aReferrerPolicy);
 
   void ClearLoader();
 
   // Callers must call imgRequestProxy::Notify later.
   void AddProxy(imgRequestProxy* proxy);
 
   nsresult RemoveProxy(imgRequestProxy* proxy, nsresult aStatus);
 
--- a/ipc/mscom/MainThreadInvoker.cpp
+++ b/ipc/mscom/MainThreadInvoker.cpp
@@ -1,20 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/mscom/MainThreadInvoker.h"
 
+#include "GeckoProfiler.h"
 #include "MainThreadUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/HangMonitor.h"
 #include "mozilla/RefPtr.h"
 #include "private/prpriv.h" // For PR_GetThreadID
 
 #include <winternl.h> // For NTSTATUS and NTAPI
 
 namespace {
 
 class SyncRunnable : public mozilla::Runnable
@@ -133,16 +135,18 @@ MainThreadInvoker::Invoke(already_AddRef
   // dispatch this event is non-fatal, but it will delay execution of the APC.
   Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(sAlertRunnable)));
   return WaitForCompletion(aTimeout);
 }
 
 /* static */ VOID CALLBACK
 MainThreadInvoker::MainThreadAPC(ULONG_PTR aParam)
 {
+  GeckoProfilerWakeRAII wakeProfiler;
+  mozilla::HangMonitor::NotifyActivity(mozilla::HangMonitor::kGeneralActivity);
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<SyncRunnable> runnable(already_AddRefed<SyncRunnable>(
                                   reinterpret_cast<SyncRunnable*>(aParam)));
   runnable->Run();
 }
 
 } // namespace mscom
 } // namespace mozilla
--- a/ipc/mscom/Registration.cpp
+++ b/ipc/mscom/Registration.cpp
@@ -4,17 +4,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // COM registration data structures are built with C code, so we need to
 // simulate that in our C++ code by defining CINTERFACE before including
 // anything else that could possibly pull in Windows header files.
 #define CINTERFACE
 
+#include "mozilla/mscom/EnsureMTA.h"
 #include "mozilla/mscom/Registration.h"
+#include "mozilla/mscom/Utils.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Move.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Pair.h"
 #include "mozilla/StaticPtr.h"
@@ -179,41 +181,54 @@ RegisterTypelib(const wchar_t* aLeafName
 }
 
 RegisteredProxy::RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject,
                                  uint32_t aRegCookie, ITypeLib* aTypeLib)
   : mModule(aModule)
   , mClassObject(aClassObject)
   , mRegCookie(aRegCookie)
   , mTypeLib(aTypeLib)
+  , mIsRegisteredInMTA(IsCurrentThreadMTA())
 {
   MOZ_ASSERT(aClassObject);
   MOZ_ASSERT(aTypeLib);
   AddToRegistry(this);
 }
 
+// If we're initializing from a typelib, it doesn't matter which apartment we
+// run in, so mIsRegisteredInMTA may always be set to false in this case.
 RegisteredProxy::RegisteredProxy(ITypeLib* aTypeLib)
   : mModule(0)
   , mClassObject(nullptr)
   , mRegCookie(0)
   , mTypeLib(aTypeLib)
+  , mIsRegisteredInMTA(false)
 {
   MOZ_ASSERT(aTypeLib);
   AddToRegistry(this);
 }
 
 RegisteredProxy::~RegisteredProxy()
 {
   DeleteFromRegistry(this);
   if (mTypeLib) {
     mTypeLib->lpVtbl->Release(mTypeLib);
   }
   if (mClassObject) {
-    ::CoRevokeClassObject(mRegCookie);
-    mClassObject->lpVtbl->Release(mClassObject);
+    // NB: mClassObject and mRegCookie must be freed from inside the apartment
+    // which they were created in.
+    auto cleanupFn = [&]() -> void {
+      ::CoRevokeClassObject(mRegCookie);
+      mClassObject->lpVtbl->Release(mClassObject);
+    };
+    if (mIsRegisteredInMTA) {
+      EnsureMTA mta(cleanupFn);
+    } else {
+      cleanupFn();
+    }
   }
   if (mModule) {
     ::FreeLibrary(reinterpret_cast<HMODULE>(mModule));
   }
 }
 
 RegisteredProxy::RegisteredProxy(RegisteredProxy&& aOther)
 {
--- a/ipc/mscom/Registration.h
+++ b/ipc/mscom/Registration.h
@@ -49,16 +49,17 @@ private:
 private:
   // Not using Windows types here: We shouldn't #include windows.h
   // since it might pull in COM code which we want to do very carefully in
   // Registration.cpp.
   uintptr_t mModule;
   IUnknown* mClassObject;
   uint32_t  mRegCookie;
   ITypeLib* mTypeLib;
+  bool      mIsRegisteredInMTA;
 };
 
 enum class RegistrationFlags
 {
   eUseBinDirectory,
   eUseSystemDirectory
 };
 
--- a/ipc/mscom/Utils.cpp
+++ b/ipc/mscom/Utils.cpp
@@ -15,29 +15,56 @@
 #define _WIN32_WINNT 0x0601
 
 #include "DynamicallyLinkedFunctionPtr.h"
 #include "mozilla/mscom/Utils.h"
 #include "mozilla/RefPtr.h"
 
 #include <objidl.h>
 
+static bool
+IsCurrentThreadMTALegacy()
+{
+  // We don't use RefPtr for token because CoGetContextToken does *not*
+  // increment its refcount!
+  IUnknown* token = nullptr;
+  HRESULT hr =
+    CoGetContextToken(reinterpret_cast<ULONG_PTR*>(&token));
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  RefPtr<IComThreadingInfo> threadingInfo;
+  hr = token->QueryInterface(IID_IComThreadingInfo,
+                             getter_AddRefs(threadingInfo));
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  APTTYPE aptType;
+  hr = threadingInfo->GetCurrentApartmentType(&aptType);
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  return aptType == APTTYPE_MTA;
+}
+
 namespace mozilla {
 namespace mscom {
 
 bool
 IsCurrentThreadMTA()
 {
   static DynamicallyLinkedFunctionPtr<decltype(&::CoGetApartmentType)>
     pCoGetApartmentType(L"ole32.dll", "CoGetApartmentType");
 
-  // There isn't really a thread-safe way to query this on Windows XP. In that
-  // case, we'll just return false since that assumption does no harm.
   if (!pCoGetApartmentType) {
-    return false;
+    // XP and Vista do not expose the newer API.
+    return IsCurrentThreadMTALegacy();
   }
 
   APTTYPE aptType;
   APTTYPEQUALIFIER aptTypeQualifier;
   HRESULT hr = pCoGetApartmentType(&aptType, &aptTypeQualifier);
   if (FAILED(hr)) {
     return false;
   }
--- a/js/public/ProfilingFrameIterator.h
+++ b/js/public/ProfilingFrameIterator.h
@@ -111,17 +111,17 @@ class JS_PUBLIC_API(ProfilingFrameIterat
     };
 
     struct Frame
     {
         FrameKind kind;
         void* stackAddress;
         void* returnAddress;
         void* activation;
-        const char* label;
+        UniqueChars label;
     };
 
     bool isAsmJS() const;
     bool isJit() const;
 
     uint32_t extractStack(Frame* frames, uint32_t offset, uint32_t end) const;
 
     mozilla::Maybe<Frame> getPhysicalFrameWithoutLabel() const;
--- a/js/src/asmjs/WasmCompartment.cpp
+++ b/js/src/asmjs/WasmCompartment.cpp
@@ -120,18 +120,22 @@ Compartment::lookupCode(const void* pc) 
 {
     Instance* instance = lookupInstanceDeprecated(pc);
     return instance ? &instance->code() : nullptr;
 }
 
 Instance*
 Compartment::lookupInstanceDeprecated(const void* pc) const
 {
-    // See profilingEnabled().
-    MOZ_ASSERT(!mutatingInstances_);
+    // lookupInstanceDeprecated can be called asynchronously from the interrupt
+    // signal handler. In that case, the signal handler is just asking whether
+    // the pc is in wasm code. If instances_ is being mutated then we can't be
+    // executing wasm code so returning nullptr is fine.
+    if (mutatingInstances_)
+        return nullptr;
 
     size_t index;
     if (!BinarySearchIf(instances_, 0, instances_.length(), PCComparator(pc), &index))
         return nullptr;
 
     return instances_[index];
 }
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1657,17 +1657,18 @@ ReadSPSProfilingStack(JSContext* cx, uns
             }
             frameKind = NewStringCopyZ<CanGC>(cx, frameKindStr);
             if (!frameKind)
                 return false;
 
             if (!JS_DefineProperty(cx, inlineFrameInfo, "kind", frameKind, propAttrs))
                 return false;
 
-            frameLabel = NewStringCopyZ<CanGC>(cx, frames[inlineFrameNo].label);
+            auto chars = frames[inlineFrameNo].label.release();
+            frameLabel = NewString<CanGC>(cx, reinterpret_cast<Latin1Char*>(chars), strlen(chars));
             if (!frameLabel)
                 return false;
 
             if (!JS_DefineProperty(cx, inlineFrameInfo, "label", frameLabel, propAttrs))
                 return false;
 
             idx = INT_TO_JSID(inlineFrameNo);
             if (!JS_DefinePropertyById(cx, inlineStack, idx, inlineFrameInfo, 0))
--- a/js/src/gc/Memory.cpp
+++ b/js/src/gc/Memory.cpp
@@ -116,19 +116,21 @@ MapMemory(size_t length, int flags, int 
 {
     return VirtualAlloc(nullptr, length, flags, prot);
 }
 
 void*
 MapAlignedPages(size_t size, size_t alignment)
 {
     MOZ_ASSERT(size >= alignment);
+    MOZ_ASSERT(size >= allocGranularity);
     MOZ_ASSERT(size % alignment == 0);
     MOZ_ASSERT(size % pageSize == 0);
-    MOZ_ASSERT(alignment % allocGranularity == 0);
+    MOZ_ASSERT_IF(alignment < allocGranularity, allocGranularity % alignment == 0);
+    MOZ_ASSERT_IF(alignment > allocGranularity, alignment % allocGranularity == 0);
 
     void* p = MapMemory(size, MEM_COMMIT | MEM_RESERVE);
 
     /* Special case: If we want allocation alignment, no further work is needed. */
     if (alignment == allocGranularity)
         return p;
 
     if (OffsetFromAligned(p, alignment) == 0)
@@ -282,16 +284,17 @@ GetPageFaultCount()
 
 void*
 AllocateMappedContent(int fd, size_t offset, size_t length, size_t alignment)
 {
     MOZ_ASSERT(length && alignment);
 
     // The allocation granularity and the requested offset
     // must both be divisible by the requested alignment.
+    // Alignments larger than the allocation granularity are not supported.
     if (allocGranularity % alignment != 0 || offset % alignment != 0)
         return nullptr;
 
     HANDLE hFile = reinterpret_cast<HANDLE>(intptr_t(fd));
 
     // This call will fail if the file does not exist, which is what we want.
     HANDLE hMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
     if (!hMap)
@@ -340,19 +343,21 @@ DeallocateMappedContent(void* p, size_t 
 }
 
 #  else // Various APIs are unavailable.
 
 void*
 MapAlignedPages(size_t size, size_t alignment)
 {
     MOZ_ASSERT(size >= alignment);
+    MOZ_ASSERT(size >= allocGranularity);
     MOZ_ASSERT(size % alignment == 0);
     MOZ_ASSERT(size % pageSize == 0);
-    MOZ_ASSERT(alignment % allocGranularity == 0);
+    MOZ_ASSERT_IF(alignment < allocGranularity, allocGranularity % alignment == 0);
+    MOZ_ASSERT_IF(alignment > allocGranularity, alignment % allocGranularity == 0);
 
     void* p = _aligned_malloc(size, alignment);
 
     MOZ_ASSERT(OffsetFromAligned(p, alignment) == 0);
     return p;
 }
 
 static void*
@@ -415,19 +420,21 @@ InitMemorySubsystem()
     if (pageSize == 0)
         pageSize = allocGranularity = size_t(sysconf(_SC_PAGESIZE));
 }
 
 void*
 MapAlignedPages(size_t size, size_t alignment)
 {
     MOZ_ASSERT(size >= alignment);
+    MOZ_ASSERT(size >= allocGranularity);
     MOZ_ASSERT(size % alignment == 0);
     MOZ_ASSERT(size % pageSize == 0);
-    MOZ_ASSERT(alignment % allocGranularity == 0);
+    MOZ_ASSERT_IF(alignment < allocGranularity, allocGranularity % alignment == 0);
+    MOZ_ASSERT_IF(alignment > allocGranularity, alignment % allocGranularity == 0);
 
     int prot = PROT_READ | PROT_WRITE;
     int flags = MAP_PRIVATE | MAP_ANON | MAP_ALIGN | MAP_NOSYNC;
 
     void* p = mmap((caddr_t)alignment, size, prot, flags, -1, 0);
     if (p == MAP_FAILED)
         return nullptr;
     return p;
@@ -586,19 +593,21 @@ MapMemory(size_t length, int prot = PROT
     return region;
 #endif
 }
 
 void*
 MapAlignedPages(size_t size, size_t alignment)
 {
     MOZ_ASSERT(size >= alignment);
+    MOZ_ASSERT(size >= allocGranularity);
     MOZ_ASSERT(size % alignment == 0);
     MOZ_ASSERT(size % pageSize == 0);
-    MOZ_ASSERT(alignment % allocGranularity == 0);
+    MOZ_ASSERT_IF(alignment < allocGranularity, allocGranularity % alignment == 0);
+    MOZ_ASSERT_IF(alignment > allocGranularity, alignment % allocGranularity == 0);
 
     void* p = MapMemory(size);
 
     /* Special case: If we want page alignment, no further work is needed. */
     if (alignment == allocGranularity)
         return p;
 
     if (OffsetFromAligned(p, alignment) == 0)
@@ -779,16 +788,17 @@ GetPageFaultCount()
 
 void*
 AllocateMappedContent(int fd, size_t offset, size_t length, size_t alignment)
 {
     MOZ_ASSERT(length && alignment);
 
     // The allocation granularity and the requested offset
     // must both be divisible by the requested alignment.
+    // Alignments larger than the allocation granularity are not supported.
     if (allocGranularity % alignment != 0 || offset % alignment != 0)
         return nullptr;
 
     // Sanity check the offset and size, as mmap does not do this for us.
     struct stat st;
     if (fstat(fd, &st) || offset >= uint64_t(st.st_size) || length > uint64_t(st.st_size) - offset)
         return nullptr;
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1301191.js
@@ -0,0 +1,21 @@
+// |jit-test| exitstatus:6
+timeout(1);
+// Adapted from randomly chosen test: js/src/jit-test/tests/asm.js/testBug975182.js
+(function() {
+    g = (function(t, foreign) {
+        "use asm";
+        var ff = foreign.ff;
+        function f() {
+            ff()
+        }
+        return f
+    })(this, {
+        ff: arguments.callee
+    })
+})()
+function m(f) {
+    while (true) {
+        f();
+    }
+}
+m(g);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testStealing.js
@@ -0,0 +1,16 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+var code = USE_ASM + "var i32 = new stdlib.Int32Array(buf); function f() { return i32[0]|0 } return f";
+
+var ab = new ArrayBuffer(BUF_MIN);
+new Int32Array(ab)[0] = 42;
+
+var f = asmLink(asmCompile('stdlib', 'ffi', 'buf', code), this, null, ab);
+assertEq(f(), 42);
+
+assertThrowsInstanceOf(() => detachArrayBuffer(ab), Error);
+assertEq(f(), 42);
+
+assertThrowsInstanceOf(() => serialize(ab, [ab]), Error);
+assertEq(f(), 42);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/tracelogger/bug1300515.js
@@ -0,0 +1,15 @@
+
+
+function test1() {
+    test();
+}
+
+function test() {
+    var du = new Debugger();
+    du.setupTraceLoggerScriptCalls();
+    du.startTraceLogger();
+}
+
+var du = new Debugger();
+if (typeof du.setupTraceLoggerScriptCalls == "function")
+    test1();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/stealing.js
@@ -0,0 +1,19 @@
+load(libdir + "wasm.js");
+
+var exp = evalText(`(module
+    (memory 1)
+    (export "mem" memory)
+    (func $f (result i32) (i32.load (i32.const 0)))
+    (export "f" $f)
+)`).exports;
+
+var ab = exp.mem.buffer;
+new Int32Array(ab)[0] = 42;
+
+assertEq(exp.f(), 42);
+
+assertThrowsInstanceOf(() => detachArrayBuffer(ab), Error);
+assertEq(exp.f(), 42);
+
+assertThrowsInstanceOf(() => serialize(ab, [ab]), Error);
+assertEq(exp.f(), 42);
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -4702,17 +4702,17 @@ static void
 GenerateEnvironmentChainGuards(MacroAssembler& masm, JSObject* envChain, JSObject* holder,
                                Register outputReg, Label* failures, bool skipLastGuard = false)
 {
     JSObject* tobj = envChain;
 
     // Walk up the env chain. Note that IsCacheableEnvironmentChain guarantees the
     // |tobj == holder| condition terminates the loop.
     while (true) {
-        MOZ_ASSERT(IsCacheableNonGlobalEnvironment(tobj) || tobj->is<GlobalObject>());
+        MOZ_ASSERT(IsCacheableEnvironment(tobj) || tobj->is<GlobalObject>());
 
         if (skipLastGuard && tobj == holder)
             break;
 
         GenerateEnvironmentChainGuard(masm, tobj, outputReg, nullptr, failures);
 
         if (tobj == holder)
             break;
@@ -4723,17 +4723,17 @@ GenerateEnvironmentChainGuards(MacroAsse
                            outputReg);
     }
 }
 
 bool
 BindNameIC::attachNonGlobal(JSContext* cx, HandleScript outerScript, IonScript* ion,
                             HandleObject envChain, HandleObject holder)
 {
-    MOZ_ASSERT(IsCacheableNonGlobalEnvironment(envChain));
+    MOZ_ASSERT(IsCacheableEnvironment(envChain));
 
     MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
     StubAttacher attacher(*this);
 
     // Guard on the shape of the env chain.
     Label failures;
     attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
                                    Address(environmentChainReg(), ShapedObject::offsetOfShape()),
@@ -4763,17 +4763,17 @@ BindNameIC::attachNonGlobal(JSContext* c
 
     return linkAndAttachStub(cx, masm, attacher, ion, "non-global");
 }
 
 static bool
 IsCacheableNonGlobalEnvironmentChain(JSObject* envChain, JSObject* holder)
 {
     while (true) {
-        if (!IsCacheableNonGlobalEnvironment(envChain)) {
+        if (!IsCacheableEnvironment(envChain)) {
             JitSpew(JitSpew_IonIC, "Non-cacheable object on env chain");
             return false;
         }
 
         if (envChain == holder)
             return true;
 
         envChain = &envChain->as<EnvironmentObject>().enclosingEnvironment();
@@ -4843,17 +4843,17 @@ NameIC::attachReadSlot(JSContext* cx, Ha
                              JS::TrackedOutcome::ICNameStub_ReadSlot);
 }
 
 static bool
 IsCacheableEnvironmentChain(JSObject* envChain, JSObject* obj)
 {
     JSObject* obj2 = envChain;
     while (obj2) {
-        if (!IsCacheableNonGlobalEnvironment(obj2) && !obj2->is<GlobalObject>())
+        if (!IsCacheableEnvironment(obj2) && !obj2->is<GlobalObject>())
             return false;
 
         // Stop once we hit the global or target obj.
         if (obj2->is<GlobalObject>() || obj2 == obj)
             break;
 
         obj2 = obj2->enclosingEnvironment();
     }
--- a/js/src/jit/x86-shared/Assembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.cpp
@@ -221,16 +221,18 @@ AssemblerX86Shared::ConditionWithoutEqua
     }
 }
 
 void
 AssemblerX86Shared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
                                                 const Disassembler::HeapAccess& heapAccess)
 {
 #ifdef DEBUG
+    if (masm.oom())
+        return;
     Disassembler::VerifyHeapAccess(masm.data() + begin, masm.data() + end, heapAccess);
 #endif
 }
 
 CPUInfo::SSEVersion CPUInfo::maxSSEVersion = UnknownSSE;
 CPUInfo::SSEVersion CPUInfo::maxEnabledSSEVersion = UnknownSSE;
 bool CPUInfo::avxPresent = false;
 bool CPUInfo::avxEnabled = false;
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -362,16 +362,17 @@ MSG_DEF(JSMSG_WASM_BAD_TABLE_VALUE,    0
 MSG_DEF(JSMSG_WASM_BAD_I64,            0, JSEXN_TYPEERR,     "cannot pass i64 to or from JS")
 MSG_DEF(JSMSG_WASM_BAD_FIT,            2, JSEXN_RANGEERR,    "{0} segment does not fit in {1}")
 MSG_DEF(JSMSG_WASM_UNREACHABLE,        0, JSEXN_ERR,         "unreachable executed")
 MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW,   0, JSEXN_ERR,         "integer overflow")
 MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_ERR,         "invalid conversion to integer")
 MSG_DEF(JSMSG_WASM_INT_DIVIDE_BY_ZERO, 0, JSEXN_ERR,         "integer divide by zero")
 MSG_DEF(JSMSG_WASM_UNALIGNED_ACCESS,   0, JSEXN_ERR,         "unaligned memory access")
 MSG_DEF(JSMSG_WASM_OVERRECURSED,       0, JSEXN_INTERNALERR, "call stack exhausted")
+MSG_DEF(JSMSG_WASM_NO_TRANSFER,        0, JSEXN_INTERNALERR, "cannot transfer buffer aliasing WebAssembly Memory")
 
 // Proxy
 MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE,   2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
 MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value")
 MSG_DEF(JSMSG_INCONSISTENT_GETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler didn't return the target object's prototype")
 MSG_DEF(JSMSG_PROXY_SETPROTOTYPEOF_RETURNED_FALSE, 0, JSEXN_TYPEERR, "proxy setPrototypeOf handler returned false")
 MSG_DEF(JSMSG_PROXY_ISEXTENSIBLE_RETURNED_FALSE,0,JSEXN_TYPEERR,"proxy isExtensible handler must return the same extensibility as target")
 MSG_DEF(JSMSG_INCONSISTENT_SETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy setPrototypeOf handler returned true, even though the target's prototype is immutable because the target is non-extensible")
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -5854,25 +5854,33 @@ GCRuntime::incrementalCollectSlice(Slice
             isIncremental = false;
         }
 
         if (drainMarkStack(budget, gcstats::PHASE_MARK) == NotFinished)
             break;
 
         MOZ_ASSERT(marker.isDrained());
 
-        if (!lastMarkSlice && isIncremental && useZeal &&
-            ((initialState == State::Mark && !hasZealMode(ZealMode::IncrementalRootsThenFinish)) ||
-             hasZealMode(ZealMode::IncrementalMarkAllThenFinish)))
+        /*
+         * In incremental GCs where we have already performed more than once
+         * slice we yield after marking with the aim of starting the sweep in
+         * the next slice, since the first slice of sweeping can be expensive.
+         *
+         * This is modified by the various zeal modes.  We don't yield in
+         * IncrementalRootsThenFinish mode and we always yield in
+         * IncrementalMarkAllThenFinish mode.
+         *
+         * We will need to mark anything new on the stack when we resume, so
+         * we stay in Mark state.
+         */
+        if (!lastMarkSlice && isIncremental &&
+            ((initialState == State::Mark &&
+              !(useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))) ||
+             (useZeal && hasZealMode(ZealMode::IncrementalMarkAllThenFinish))))
         {
-            /*
-             * Yield with the aim of starting the sweep in the next
-             * slice.  We will need to mark anything new on the stack
-             * when we resume, so we stay in Mark state.
-             */
             lastMarkSlice = true;
             break;
         }
 
         incrementalState = State::Sweep;
 
         /*
          * This runs to completion, but we don't continue if the budget is
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4680,17 +4680,18 @@ SingleStepCallback(void* arg, jit::Simul
         lastStackAddress = i.stackAddress();
         JS::ProfilingFrameIterator::Frame frames[16];
         uint32_t nframes = i.extractStack(frames, 0, 16);
         for (uint32_t i = 0; i < nframes; i++) {
             if (frameNo > 0) {
                 if (!stack.append(",", 1))
                     oomUnsafe.crash("stack.append");
             }
-            if (!stack.append(frames[i].label, strlen(frames[i].label)))
+            auto chars = frames[i].label.get();
+            if (!stack.append(chars, strlen(chars)))
                 oomUnsafe.crash("stack.append");
             frameNo++;
         }
     }
 
     // Only append the stack if it differs from the last stack.
     if (stacks.empty() ||
         stacks.back().length() != stack.length() ||
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/implicit-this-in-with.js
@@ -0,0 +1,18 @@
+// Test that callees that resolve to bindings on the global object or the
+// global lexical environment get an 'undefined' this inside with scopes.
+
+let g = function () { "use strict"; assertEq(this, undefined); }
+function f() { "use strict"; assertEq(this, undefined); }
+
+with ({}) { 
+  // f is resolved on the global object
+  f();
+  // g is resolved on the global lexical environment
+  g();
+}
+
+f();
+g();
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
--- a/js/src/threading/posix/Mutex.cpp
+++ b/js/src/threading/posix/Mutex.cpp
@@ -12,17 +12,16 @@
 
 #include "threading/Mutex.h"
 #include "threading/posix/MutexPlatformData.h"
 
 #define TRY_CALL_PTHREADS(call, msg)            \
   {                                             \
     int result = (call);                        \
     if (result != 0) {                          \
-      MOZ_ASSERT(!errno);                       \
       errno = result;                           \
       perror(msg);                              \
       MOZ_CRASH(msg);                           \
     }                                           \
   }
 
 js::Mutex::Mutex()
 {
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -666,16 +666,20 @@ ArrayBufferObject::createForWasm(JSConte
     // unintentially OOMing the browser on 32-bit: they just want "a lot of
     // memory". Maintain the invariant that initialSize <= maxSize.
     if (sizeof(void*) == 4 && maxSize) {
         static const uint32_t OneGiB = 1 << 30;
         uint32_t clamp = Max(OneGiB, initialSize);
         maxSize = Some(Min(clamp, maxSize.value()));
     }
 
+    RootedArrayBufferObject buffer(cx, ArrayBufferObject::createEmpty(cx));
+    if (!buffer)
+        return nullptr;
+
     // Try to reserve the maximum requested memory
     WasmArrayRawBuffer* wasmBuf = WasmArrayRawBuffer::Allocate(initialSize, maxSize);
     if (!wasmBuf) {
 #ifdef  WASM_HUGE_MEMORY
         ReportOutOfMemory(cx);
         return nullptr;
 #else
         // If we fail, and have a maxSize, try to reserve the biggest chunk in
@@ -699,24 +703,19 @@ ArrayBufferObject::createForWasm(JSConte
         }
 
         // Try to grow our chunk as much as possible.
         for (size_t d = cur / 2; d >= wasm::PageSize; d /= 2)
             wasmBuf->tryGrowMaxSizeInPlace(ROUND_UP(d, wasm::PageSize));
 #endif
     }
 
-    void *data = wasmBuf->dataPointer();
-    BufferContents contents = BufferContents::create<WASM_MAPPED>(data);
-    ArrayBufferObject* buffer = ArrayBufferObject::create(cx, initialSize, contents);
-    if (!buffer) {
-        WasmArrayRawBuffer::Release(data);
-        return nullptr;
-    }
-
+    auto contents = BufferContents::create<WASM_MAPPED>(wasmBuf->dataPointer());
+    buffer->initialize(initialSize, contents, OwnsData);
+    cx->zone()->updateMallocCounter(wasmBuf->mappedSize());
     return buffer;
 }
 
 /* static */ bool
 ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle<ArrayBufferObject*> buffer, bool needGuard)
 {
 #ifdef WASM_HUGE_MEMORY
     MOZ_ASSERT(needGuard);
@@ -756,16 +755,17 @@ ArrayBufferObject::prepareForAsmJS(JSCon
         void* data = wasmBuf->dataPointer();
         memcpy(data, buffer->dataPointer(), length);
 
         // Swap the new elements into the ArrayBufferObject. Mark the
         // ArrayBufferObject so we don't do this again.
         BufferContents newContents = BufferContents::create<WASM_MAPPED>(data);
         buffer->changeContents(cx, newContents);
         MOZ_ASSERT(data == buffer->dataPointer());
+        cx->zone()->updateMallocCounter(wasmBuf->mappedSize());
         return true;
     }
 
     if (buffer->isAsmJSMalloced())
         return true;
 
     if (!buffer->ownsData()) {
         BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength());
@@ -1006,16 +1006,28 @@ ArrayBufferObject*
 ArrayBufferObject::create(JSContext* cx, uint32_t nbytes,
                           HandleObject proto /* = nullptr */,
                           NewObjectKind newKind /* = GenericObject */)
 {
     return create(cx, nbytes, BufferContents::createPlain(nullptr),
                   OwnsState::OwnsData, proto);
 }
 
+ArrayBufferObject*
+ArrayBufferObject::createEmpty(JSContext* cx)
+{
+    AutoSetNewObjectMetadata metadata(cx);
+    ArrayBufferObject* obj = NewObjectWithClassProto<ArrayBufferObject>(cx, nullptr);
+    if (!obj)
+        return nullptr;
+
+    obj->initEmpty();
+    return obj;
+}
+
 bool
 ArrayBufferObject::createDataViewForThisImpl(JSContext* cx, const CallArgs& args)
 {
     MOZ_ASSERT(IsArrayBuffer(args.thisv()));
 
     /*
      * This method is only called for |DataView(alienBuf, ...)| which calls
      * this as |createDataViewForThis.call(alienBuf, byteOffset, byteLength,
@@ -1508,17 +1520,17 @@ JS_DetachArrayBuffer(JSContext* cx, Hand
     if (!obj->is<ArrayBufferObject>()) {
         JS_ReportError(cx, "ArrayBuffer object required");
         return false;
     }
 
     Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
 
     if (buffer->isWasm()) {
-        JS_ReportError(cx, "Cannot detach WASM ArrayBuffer");
+        JS_ReportError(cx, "Cannot detach WebAssembly ArrayBuffer");
         return false;
     }
 
     ArrayBufferObject::BufferContents newContents =
         buffer->hasStealableContents() ? ArrayBufferObject::BufferContents::createPlain(nullptr)
                                        : buffer->contents();
 
     ArrayBufferObject::detach(cx, buffer, newContents);
@@ -1615,21 +1627,26 @@ JS_StealArrayBufferContents(JSContext* c
     }
 
     Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
     if (buffer->isDetached()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
         return nullptr;
     }
 
+    if (buffer->isWasm()) {
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_NO_TRANSFER);
+        return nullptr;
+    }
+
     // The caller assumes that a plain malloc'd buffer is returned.
     // hasStealableContents is true for mapped buffers, so we must additionally
     // require that the buffer is plain. In the future, we could consider
     // returning something that handles releasing the memory.
-    bool hasStealableContents = buffer->hasStealableContents() && buffer->hasMallocedContents();
+    bool hasStealableContents = buffer->hasStealableContents() && buffer->isPlain();
 
     AutoCompartment ac(cx, buffer);
     return ArrayBufferObject::stealContents(cx, buffer, hasStealableContents).data();
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewMappedArrayBufferWithContents(JSContext* cx, size_t nbytes, void* data)
 {
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -247,16 +247,20 @@ class ArrayBufferObject : public ArrayBu
                                      BufferContents contents,
                                      OwnsState ownsState = OwnsData,
                                      HandleObject proto = nullptr,
                                      NewObjectKind newKind = GenericObject);
     static ArrayBufferObject* create(JSContext* cx, uint32_t nbytes,
                                      HandleObject proto = nullptr,
                                      NewObjectKind newKind = GenericObject);
 
+    // Create an ArrayBufferObject that is safely finalizable and can later be
+    // initialize()d to become a real, content-visible ArrayBufferObject.
+    static ArrayBufferObject* createEmpty(JSContext* cx);
+
     static bool createDataViewForThisImpl(JSContext* cx, const CallArgs& args);
     static bool createDataViewForThis(JSContext* cx, unsigned argc, Value* vp);
 
     template<typename T>
     static bool createTypedArrayFromBufferImpl(JSContext* cx, const CallArgs& args);
 
     template<typename T>
     static bool createTypedArrayFromBuffer(JSContext* cx, unsigned argc, Value* vp);
@@ -272,22 +276,16 @@ class ArrayBufferObject : public ArrayBu
                                         Handle<ArrayBufferObject*> buffer,
                                         bool hasStealableContents);
 
     bool hasStealableContents() const {
         // Inline elements strictly adhere to the corresponding buffer.
         return ownsData();
     }
 
-    // Return whether the buffer is allocated by js_malloc and should be freed
-    // with js_free.
-    bool hasMallocedContents() const {
-        return (ownsData() && isPlain()) || isAsmJSMalloced();
-    }
-
     static void addSizeOfExcludingThis(JSObject* obj, mozilla::MallocSizeOf mallocSizeOf,
                                        JS::ClassInfo* info);
 
     // ArrayBufferObjects (strongly) store the first view added to them, while
     // later views are (weakly) stored in the compartment's InnerViewTable
     // below. Buffers usually only have one view, so this slot optimizes for
     // the common case. Avoiding entries in the InnerViewTable saves memory and
     // non-incrementalized sweep time.
@@ -391,16 +389,25 @@ class ArrayBufferObject : public ArrayBu
     void setIsDetached() { setFlags(flags() | DETACHED); }
 
     void initialize(size_t byteLength, BufferContents contents, OwnsState ownsState) {
         setByteLength(byteLength);
         setFlags(0);
         setFirstView(nullptr);
         setDataPointer(contents, ownsState);
     }
+
+    // Note: initialize() may be called after initEmpty(); initEmpty() must
+    // only initialize the ArrayBufferObject to a safe, finalizable state.
+    void initEmpty() {
+        setByteLength(0);
+        setFlags(0);
+        setFirstView(nullptr);
+        setDataPointer(BufferContents::createPlain(nullptr), DoesntOwnData);
+    }
 };
 
 typedef Rooted<ArrayBufferObject*> RootedArrayBufferObject;
 typedef Handle<ArrayBufferObject*> HandleArrayBufferObject;
 typedef MutableHandle<ArrayBufferObject*> MutableHandleArrayBufferObject;
 
 /*
  * ArrayBufferViewObject
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1330,35 +1330,35 @@ JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ 
  * (an object on the env chain).
  *
  * We can avoid computing |this| eagerly and push the implicit callee-coerced
  * |this| value, undefined, if either of these conditions hold:
  *
  * 1. The nominal |this|, obj, is a global object.
  *
  * 2. The nominal |this|, obj, has one of LexicalEnvironment or Call class (this
- *    is what IsCacheableNonGlobalEnvironment tests). Such objects-as-envs must be
+ *    is what IsCacheableEnvironment tests). Such objects-as-envs must be
  *    censored with undefined.
  *
  * Otherwise, we bind |this| to the result of GetThisValue(). Only names inside
  * |with| statements and embedding-specific environment objects fall into this
  * category.
  *
  * If the callee is a strict mode function, then code implementing JSOP_THIS
  * in the interpreter and JITs will leave undefined as |this|. If funval is a
  * function not in strict mode, JSOP_THIS code replaces undefined with funval's
  * global.
  */
 static inline Value
 ComputeImplicitThis(JSObject* obj)
 {
-    if (IsGlobalLexicalEnvironment(obj))
+    if (obj->is<GlobalObject>())
         return UndefinedValue();
 
-    if (IsCacheableNonGlobalEnvironment(obj))
+    if (IsCacheableEnvironment(obj))
         return UndefinedValue();
 
     return GetThisValue(obj);
 }
 
 static MOZ_ALWAYS_INLINE bool
 AddOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
 {
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -28,17 +28,17 @@
 namespace js {
 
 /*
  * We cache name lookup results only for the global object or for native
  * non-global objects without prototype or with prototype that never mutates,
  * see bug 462734 and bug 487039.
  */
 static inline bool
-IsCacheableNonGlobalEnvironment(JSObject* obj)
+IsCacheableEnvironment(JSObject* obj)
 {
     bool cacheable = obj->is<CallObject>() || obj->is<LexicalEnvironmentObject>();
 
     MOZ_ASSERT_IF(cacheable, !obj->getOpsLookupProperty());
     return cacheable;
 }
 
 inline HandleObject
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1867,18 +1867,17 @@ JS::ProfilingFrameIterator::getPhysicalF
     void* stackAddr = stackAddress();
 
     if (isAsmJS()) {
         Frame frame;
         frame.kind = Frame_AsmJS;
         frame.stackAddress = stackAddr;
         frame.returnAddress = nullptr;
         frame.activation = activation_;
-        frame.label = nullptr;
-        return mozilla::Some(frame);
+        return mozilla::Some(mozilla::Move(frame));
     }
 
     MOZ_ASSERT(isJit());
 
     // Look up an entry for the return address.
     void* returnAddr = jitIter().returnAddressToFp();
     jit::JitcodeGlobalTable* table = rt_->jitRuntime()->getJitcodeGlobalTable();
     if (hasSampleBufferGen())
@@ -1892,48 +1891,52 @@ JS::ProfilingFrameIterator::getPhysicalF
     if (entry->isDummy())
         return mozilla::Nothing();
 
     Frame frame;
     frame.kind = entry->isBaseline() ? Frame_Baseline : Frame_Ion;
     frame.stackAddress = stackAddr;
     frame.returnAddress = returnAddr;
     frame.activation = activation_;
-    frame.label = nullptr;
-    return mozilla::Some(frame);
+    return mozilla::Some(mozilla::Move(frame));
 }
 
 uint32_t
 JS::ProfilingFrameIterator::extractStack(Frame* frames, uint32_t offset, uint32_t end) const
 {
     if (offset >= end)
         return 0;
 
     jit::JitcodeGlobalEntry entry;
     Maybe<Frame> physicalFrame = getPhysicalFrameAndEntry(&entry);
 
     // Dummy frames produce no stack frames.
     if (physicalFrame.isNothing())
         return 0;
 
     if (isAsmJS()) {
-        frames[offset] = physicalFrame.value();
-        frames[offset].label = asmJSIter().label();
+        frames[offset] = mozilla::Move(physicalFrame.ref());
+        frames[offset].label = DuplicateString(asmJSIter().label());
+        if (!frames[offset].label)
+            return 0; // Drop stack frames silently on OOM.
         return 1;
     }
 
     // Extract the stack for the entry.  Assume maximum inlining depth is <64
     const char* labels[64];
     uint32_t depth = entry.callStackAtAddr(rt_, jitIter().returnAddressToFp(), labels, 64);
     MOZ_ASSERT(depth < 64);
     for (uint32_t i = 0; i < depth; i++) {
         if (offset + i >= end)
             return i;
-        frames[offset + i] = physicalFrame.value();
-        frames[offset + i].label = labels[i];
+        Frame& frame = frames[offset + i];
+        frame = mozilla::Move(physicalFrame.ref());
+        frame.label = DuplicateString(labels[i]);
+        if (!frame.label)
+            return i;  // Drop stack frames silently on OOM.
     }
 
     return depth;
 }
 
 Maybe<JS::ProfilingFrameIterator::Frame>
 JS::ProfilingFrameIterator::getPhysicalFrameWithoutLabel() const
 {
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1468,22 +1468,23 @@ JSStructuredCloneWriter::transferOwnersh
 
         if (cls == ESClass::ArrayBuffer) {
             // The current setup of the array buffer inheritance hierarchy doesn't
             // lend itself well to generic manipulation via proxies.
             Rooted<ArrayBufferObject*> arrayBuffer(context(), &CheckedUnwrap(obj)->as<ArrayBufferObject>());
             JSAutoCompartment ac(context(), arrayBuffer);
             size_t nbytes = arrayBuffer->byteLength();
 
-            // Structured cloning currently only has optimizations for mapped
-            // and malloc'd buffers, not asm.js-ified buffers.
+            if (arrayBuffer->isWasm()) {
+                JS_ReportErrorNumber(context(), GetErrorMessage, nullptr, JSMSG_WASM_NO_TRANSFER);
+                return false;
+            }
+
             bool hasStealableContents = arrayBuffer->hasStealableContents() &&
-                                        (arrayBuffer->isMapped() || arrayBuffer->hasMallocedContents());
-            if (scope == JS::StructuredCloneScope::DifferentProcess)
-                hasStealableContents = false;
+                                        (scope != JS::StructuredCloneScope::DifferentProcess);
 
             ArrayBufferObject::BufferContents bufContents =
                 ArrayBufferObject::stealContents(context(), arrayBuffer, hasStealableContents);
             if (!bufContents)
                 return false; // already transferred data
 
             content = bufContents.data();
             tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER;
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -528,17 +528,17 @@ void
 TraceLoggerThread::stopEvent(uint32_t id)
 {
     MOZ_ASSERT(TLTextIdIsTreeEvent(id) || id == TraceLogger_Error);
     MOZ_ASSERT(traceLoggerState);
     if (!traceLoggerState->isTextIdEnabled(id))
         return;
 
 #ifdef DEBUG
-    if (enabled_ > 0) {
+    if (enabled_ > 0 && !graphStack.empty()) {
         uint32_t prev = graphStack.popCopy();
         if (id == TraceLogger_Engine) {
             MOZ_ASSERT(prev == TraceLogger_IonMonkey || prev == TraceLogger_Baseline ||
                        prev == TraceLogger_Interpreter);
         } else if (id == TraceLogger_Scripts) {
             MOZ_ASSERT(prev >= TraceLogger_Last);
         } else if (id >= TraceLogger_Last) {
             MOZ_ASSERT(prev >= TraceLogger_Last);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -362,24 +362,24 @@ AsyncScriptLoader::OnStreamComplete(nsII
 
     if (aLength > INT32_MAX) {
         return ReportError(cx, LOAD_ERROR_CONTENTTOOBIG, uri);
     }
 
     RootedFunction function(cx);
     RootedScript script(cx);
     nsAutoCString spec;
-    uri->GetSpec(spec);
+    nsresult rv = uri->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     RootedObject target_obj(cx, mTargetObj);
 
-    nsresult rv = PrepareScript(uri, cx, target_obj, spec.get(),
-                                mCharset,
-                                reinterpret_cast<const char*>(aBuf), aLength,
-                                mReuseGlobal, &script, &function);
+    rv = PrepareScript(uri, cx, target_obj, spec.get(), mCharset,
+                       reinterpret_cast<const char*>(aBuf), aLength,
+                       mReuseGlobal, &script, &function);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
     JS::Rooted<JS::Value> retval(cx);
     rv = EvalScript(cx, target_obj, &retval, uri, mCache, script, function);
 
     if (NS_SUCCEEDED(rv)) {
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1759,17 +1759,18 @@ xpc::EvalInSandbox(JSContext* cx, Handle
     nsCOMPtr<nsIPrincipal> prin = sop->GetPrincipal();
     NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
 
     nsAutoCString filenameBuf;
     if (!filename.IsVoid() && filename.Length() != 0) {
         filenameBuf.Assign(filename);
     } else {
         // Default to the spec of the principal.
-        nsJSPrincipals::get(prin)->GetScriptLocation(filenameBuf);
+        nsresult rv = nsJSPrincipals::get(prin)->GetScriptLocation(filenameBuf);
+        NS_ENSURE_SUCCESS(rv, rv);
         lineNo = 1;
     }
 
     // We create a separate cx to do the sandbox evaluation. Scope it.
     RootedValue v(cx, UndefinedValue());
     RootedValue exn(cx, UndefinedValue());
     bool ok = true;
     {
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1663,17 +1663,20 @@ GetCompartmentName(JSCompartment* c, nsC
                    bool replaceSlashes)
 {
     if (js::IsAtomsCompartment(c)) {
         name.AssignLiteral("atoms");
     } else if (*anonymizeID && !js::IsSystemCompartment(c)) {
         name.AppendPrintf("<anonymized-%d>", *anonymizeID);
         *anonymizeID += 1;
     } else if (JSPrincipals* principals = JS_GetCompartmentPrincipals(c)) {
-        nsJSPrincipals::get(principals)->GetScriptLocation(name);
+        nsresult rv = nsJSPrincipals::get(principals)->GetScriptLocation(name);
+        if (NS_FAILED(rv)) {
+            name.AssignLiteral("(unknown)");
+        }
 
         // If the compartment's location (name) differs from the principal's
         // script location, append the compartment's location to allow
         // differentiation of multiple compartments owned by the same principal
         // (e.g. components owned by the system or null principal).
         CompartmentPrivate* compartmentPrivate = CompartmentPrivate::Get(c);
         if (compartmentPrivate) {
             const nsACString& location = compartmentPrivate->GetLocation();
--- a/layout/base/UnitTransforms.h
+++ b/layout/base/UnitTransforms.h
@@ -156,17 +156,17 @@ TypedMatrix ViewAs(const gfx::Matrix4x4&
 
 // Convenience functions for transforming an entity from one strongly-typed
 // coordinate system to another using the provided transformation matrix.
 template <typename TargetUnits, typename SourceUnits>
 static gfx::PointTyped<TargetUnits>
 TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
             const gfx::PointTyped<SourceUnits>& aPoint)
 {
-  return aTransform * aPoint;
+  return aTransform.TransformPoint(aPoint);
 }
 template <typename TargetUnits, typename SourceUnits>
 static gfx::IntPointTyped<TargetUnits>
 TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
             const gfx::IntPointTyped<SourceUnits>& aPoint)
 {
   return RoundedToInt(TransformBy(aTransform, gfx::PointTyped<SourceUnits>(aPoint)));
 }
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -6257,17 +6257,17 @@ nsDisplayTransform::GetHitDepthAtPoint(n
 
   Matrix4x4 inverse = matrix;
   inverse.Invert();
   Point4D point = inverse.ProjectPoint(Point(NSAppUnitsToFloatPixels(aPoint.x, factor),
                                              NSAppUnitsToFloatPixels(aPoint.y, factor)));
 
   Point point2d = point.As2DPoint();
 
-  Point3D transformed = matrix * Point3D(point2d.x, point2d.y, 0);
+  Point3D transformed = matrix.TransformPoint(Point3D(point2d.x, point2d.y, 0));
   return transformed.z;
 }
 
 /* The bounding rectangle for the object is the overflow rectangle translated
  * by the reference point.
  */
 nsRect
 nsDisplayTransform::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
@@ -7013,13 +7013,12 @@ nsDisplayFilter::PrintEffects(nsACString
     first = false;
     aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
   }
   if (effectProperties.HasValidFilter()) {
     if (!first) {
       aTo += ", ";
     }
     aTo += "filter";
-    first = false;
   }
   aTo += ")";
 }
 #endif
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2683,17 +2683,17 @@ nsLayoutUtils::TransformPoints(nsIFrame*
       aFromFrame->PresContext()->CSSToDevPixelScale();
   CSSToLayoutDeviceScale devPixelsPerCSSPixelToFrame =
       aToFrame->PresContext()->CSSToDevPixelScale();
   for (uint32_t i = 0; i < aPointCount; ++i) {
     LayoutDevicePoint devPixels = aPoints[i] * devPixelsPerCSSPixelFromFrame;
     // What should the behaviour be if some of the points aren't invertible
     // and others are? Just assume all points are for now.
     Point toDevPixels = downToDest.ProjectPoint(
-        (upToAncestor * Point(devPixels.x, devPixels.y))).As2DPoint();
+        (upToAncestor.TransformPoint(Point(devPixels.x, devPixels.y)))).As2DPoint();
     // Divide here so that when the devPixelsPerCSSPixels are the same, we get the correct
     // answer instead of some inaccuracy multiplying a number by its reciprocal.
     aPoints[i] = LayoutDevicePoint(toDevPixels.x, toDevPixels.y) /
         devPixelsPerCSSPixelToFrame;
   }
   return TRANSFORM_SUCCEEDED;
 }
 
@@ -2712,18 +2712,18 @@ nsLayoutUtils::TransformPoint(nsIFrame* 
   downToDest.Invert();
   Matrix4x4 upToAncestor = GetTransformToAncestor(aFromFrame, nearestCommonAncestor);
 
   float devPixelsPerAppUnitFromFrame =
     1.0f / aFromFrame->PresContext()->AppUnitsPerDevPixel();
   float devPixelsPerAppUnitToFrame =
     1.0f / aToFrame->PresContext()->AppUnitsPerDevPixel();
   Point4D toDevPixels = downToDest.ProjectPoint(
-      upToAncestor * Point(aPoint.x * devPixelsPerAppUnitFromFrame,
-                           aPoint.y * devPixelsPerAppUnitFromFrame));
+      upToAncestor.TransformPoint(Point(aPoint.x * devPixelsPerAppUnitFromFrame,
+                                        aPoint.y * devPixelsPerAppUnitFromFrame)));
   if (!toDevPixels.HasPositiveWCoord()) {
     // Not strictly true, but we failed to get a valid point in this
     // coordinate space.
     return NONINVERTIBLE_TRANSFORM;
   }
   aPoint.x = NSToCoordRound(toDevPixels.x / devPixelsPerAppUnitToFrame);
   aPoint.y = NSToCoordRound(toDevPixels.y / devPixelsPerAppUnitToFrame);
   return TRANSFORM_SUCCEEDED;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2224,19 +2224,21 @@ nsIFrame::BuildDisplayListForStackingCon
   nsRect dirtyRectOutsideSVGEffects = dirtyRect;
   nsDisplayList hoistedScrollInfoItemsStorage;
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
     aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
   }
 
-  // We build an opacity item if it's not going to be drawn by SVG content, or SVG effects.
-  // SVG effects won't handle the opacity if we want an active layer (for async animations),
-  // see nsSVGIntegrationsUtils::PaintFramesWithEffects.
+  // We build an opacity item if it's not going to be drawn by SVG content, or
+  // SVG effects. SVG effects won't handle the opacity if we want an active
+  // layer (for async animations), see
+  // nsSVGIntegrationsUtils::PaintMaskAndClipPath or
+  // nsSVGIntegrationsUtils::PaintFilter.
   bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this) &&
                     (!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
   bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
   bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
     IsScrollFrameActive(aBuilder,
                         nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
                         nsLayoutUtils::SCROLLABLE_SAME_DOC |
                         nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -948,16 +948,21 @@ struct nsGridContainerFrame::TrackSizing
    * (zero if no auto-fill/fit track was specified)
    */
   uint32_t InitRepeatTracks(const nsStyleCoord& aGridGap, nscoord aMinSize,
                             nscoord aSize, nscoord aMaxSize)
   {
     uint32_t repeatTracks =
       CalculateRepeatFillCount(aGridGap, aMinSize, aSize, aMaxSize);
     SetNumRepeatTracks(repeatTracks);
+    // Blank out the removed flags for each of these tracks.
+    mRemovedRepeatTracks.SetLength(repeatTracks);
+    for (auto& track : mRemovedRepeatTracks) {
+      track = false;
+    }
     return repeatTracks;
   }
 
   uint32_t CalculateRepeatFillCount(const nsStyleCoord& aGridGap,
                                     nscoord aMinSize,
                                     nscoord aSize,
                                     nscoord aMaxSize) const
   {
@@ -1074,33 +1079,35 @@ struct nsGridContainerFrame::TrackSizing
   }
   void SetNumRepeatTracks(uint32_t aNumRepeatTracks)
   {
     MOZ_ASSERT(mHasRepeatAuto || aNumRepeatTracks == 0);
     mRepeatAutoEnd = mRepeatAutoStart + aNumRepeatTracks;
     mRepeatEndDelta = mHasRepeatAuto ?
                         int32_t(aNumRepeatTracks) - 1 :
                         0;
-  }
+}
 
   // Some style data references, for easy access.
   const nsTArray<nsStyleCoord>& mMinSizingFunctions;
   const nsTArray<nsStyleCoord>& mMaxSizingFunctions;
   const nsStyleCoord& mAutoMinSizing;
   const nsStyleCoord& mAutoMaxSizing;
   // Offset from the start of the implicit grid to the first explicit track.
   uint32_t mExplicitGridOffset;
   // The index of the repeat(auto-fill/fit) track, or zero if there is none.
   const uint32_t mRepeatAutoStart;
   // The (hypothetical) index of the last such repeat() track.
   uint32_t mRepeatAutoEnd;
   // The difference between mExplicitGridEnd and mMinSizingFunctions.Length().
   int32_t mRepeatEndDelta;
   // True if there is a specified repeat(auto-fill/fit) track.
   const bool mHasRepeatAuto;
+  // True if this track (relative to mRepeatAutoStart) is a removed auto-fit.
+  nsTArray<bool> mRemovedRepeatTracks;
 };
 
 /**
  * State for the tracks in one dimension.
  */
 struct nsGridContainerFrame::Tracks
 {
   explicit Tracks(LogicalAxis aAxis)
@@ -3409,16 +3416,21 @@ nsGridContainerFrame::Grid::PlaceGridIte
       }
       if (col < endRepeat && mCellMap.IsEmptyCol(col)) {
         ++numEmptyCols;
         if (colAdjust.isNothing()) {
           colAdjust.emplace(numColLines);
           colAdjust->SetLength(numColLines);
           PodZero(colAdjust->Elements(), colAdjust->Length());
         }
+
+        uint32_t repeatIndex = col - aState.mColFunctions.mRepeatAutoStart;
+        MOZ_ASSERT(aState.mColFunctions.mRemovedRepeatTracks.Length() >
+                   repeatIndex);
+        aState.mColFunctions.mRemovedRepeatTracks[repeatIndex] = true;
       }
     }
   }
   Maybe<nsTArray<uint32_t>> rowAdjust;
   uint32_t numEmptyRows = 0;
   if (aState.mRowFunctions.mHasRepeatAuto &&
       !gridStyle->mGridTemplateRows.mIsAutoFill &&
       aState.mRowFunctions.NumRepeatTracks() > 0) {
@@ -3431,16 +3443,21 @@ nsGridContainerFrame::Grid::PlaceGridIte
       }
       if (row < endRepeat && mCellMap.IsEmptyRow(row)) {
         ++numEmptyRows;
         if (rowAdjust.isNothing()) {
           rowAdjust.emplace(numRowLines);
           rowAdjust->SetLength(numRowLines);
           PodZero(rowAdjust->Elements(), rowAdjust->Length());
         }
+
+        uint32_t repeatIndex = row - aState.mRowFunctions.mRepeatAutoStart;
+        MOZ_ASSERT(aState.mRowFunctions.mRemovedRepeatTracks.Length() >
+                   repeatIndex);
+        aState.mRowFunctions.mRemovedRepeatTracks[repeatIndex] = true;
       }
     }
   }
   // Remove the empty 'auto-fit' tracks we found above, if any.
   if (numEmptyCols || numEmptyRows) {
     // Adjust the line numbers in the grid areas.
     for (auto& item : aState.mGridItems) {
       GridArea& area = item.mArea;
@@ -3461,20 +3478,20 @@ nsGridContainerFrame::Grid::PlaceGridIte
       }
     }
     // Adjust the grid size.
     mGridColEnd -= numEmptyCols;
     mExplicitGridColEnd -= numEmptyCols;
     mGridRowEnd -= numEmptyRows;
     mExplicitGridRowEnd -= numEmptyRows;
     // Adjust the track mapping to unmap the removed tracks.
-    auto finalColRepeatCount = aState.mColFunctions.NumRepeatTracks() - numEmptyCols;
-    aState.mColFunctions.SetNumRepeatTracks(finalColRepeatCount);
-    auto finalRowRepeatCount = aState.mRowFunctions.NumRepeatTracks() - numEmptyRows;
-    aState.mRowFunctions.SetNumRepeatTracks(finalRowRepeatCount);
+    auto colRepeatCount = aState.mColFunctions.NumRepeatTracks();
+    aState.mColFunctions.SetNumRepeatTracks(colRepeatCount - numEmptyCols);
+    auto rowRepeatCount = aState.mRowFunctions.NumRepeatTracks();
+    aState.mRowFunctions.SetNumRepeatTracks(rowRepeatCount - numEmptyRows);
   }
 
   // Update the line boundaries of the implicit grid areas, if needed.
   if (mAreas &&
       aState.mFrame->HasAnyStateBits(NS_STATE_GRID_GENERATE_COMPUTED_VALUES)) {
     for (auto iter = mAreas->Iter(); !iter.Done(); iter.Next()) {
       auto& areaInfo = iter.Data();
 
@@ -5764,16 +5781,18 @@ nsGridContainerFrame::Reflow(nsPresConte
 
     // Now that we know column and row sizes and positions, set
     // the ComputedGridTrackInfo and related properties
 
     uint32_t colTrackCount = gridReflowInput.mCols.mSizes.Length();
     nsTArray<nscoord> colTrackPositions(colTrackCount);
     nsTArray<nscoord> colTrackSizes(colTrackCount);
     nsTArray<uint32_t> colTrackStates(colTrackCount);
+    nsTArray<bool> colRemovedRepeatTracks(
+      gridReflowInput.mColFunctions.mRemovedRepeatTracks);
     uint32_t col = 0;
     for (const TrackSize& sz : gridReflowInput.mCols.mSizes) {
       colTrackPositions.AppendElement(sz.mPosition);
       colTrackSizes.AppendElement(sz.mBase);
       bool isRepeat = ((col >= gridReflowInput.mColFunctions.mRepeatAutoStart) &&
                        (col < gridReflowInput.mColFunctions.mRepeatAutoEnd));
       colTrackStates.AppendElement(
           isRepeat ?
@@ -5785,23 +5804,26 @@ nsGridContainerFrame::Reflow(nsPresConte
     }
     ComputedGridTrackInfo* colInfo = new ComputedGridTrackInfo(
       gridReflowInput.mColFunctions.mExplicitGridOffset,
       gridReflowInput.mColFunctions.NumExplicitTracks(),
       0,
       col,
       Move(colTrackPositions),
       Move(colTrackSizes),
-      Move(colTrackStates));
+      Move(colTrackStates),
+      Move(colRemovedRepeatTracks));
     Properties().Set(GridColTrackInfo(), colInfo);
 
     uint32_t rowTrackCount = gridReflowInput.mRows.mSizes.Length();
     nsTArray<nscoord> rowTrackPositions(rowTrackCount);
     nsTArray<nscoord> rowTrackSizes(rowTrackCount);
     nsTArray<uint32_t> rowTrackStates(rowTrackCount);
+    nsTArray<bool> rowRemovedRepeatTracks(
+      gridReflowInput.mRowFunctions.mRemovedRepeatTracks);
     uint32_t row = 0;
     for (const TrackSize& sz : gridReflowInput.mRows.mSizes) {
       rowTrackPositions.AppendElement(sz.mPosition);
       rowTrackSizes.AppendElement(sz.mBase);
       bool isRepeat = ((row >= gridReflowInput.mRowFunctions.mRepeatAutoStart) &&
                        (row < gridReflowInput.mRowFunctions.mRepeatAutoEnd));
       rowTrackStates.AppendElement(
         isRepeat ?
@@ -5816,17 +5838,18 @@ nsGridContainerFrame::Reflow(nsPresConte
     // occur.
     ComputedGridTrackInfo* rowInfo = new ComputedGridTrackInfo(
       gridReflowInput.mRowFunctions.mExplicitGridOffset,
       gridReflowInput.mRowFunctions.NumExplicitTracks(),
       gridReflowInput.mStartRow,
       row,
       Move(rowTrackPositions),
       Move(rowTrackSizes),
-      Move(rowTrackStates));
+      Move(rowTrackStates),
+      Move(rowRemovedRepeatTracks));
     Properties().Set(GridRowTrackInfo(), rowInfo);
 
     if (prevInFlow) {
       // This frame is fragmenting rows from a previous frame, so patch up
       // the prior GridRowTrackInfo with a new end row.
 
       // FIXME: This can be streamlined and/or removed when bug 1151204 lands.
 
@@ -5845,17 +5868,18 @@ nsGridContainerFrame::Reflow(nsPresConte
 
       ComputedGridTrackInfo* revisedPriorRowInfo = new ComputedGridTrackInfo(
         priorRowInfo->mNumLeadingImplicitTracks,
         priorRowInfo->mNumExplicitTracks,
         priorRowInfo->mStartFragmentTrack,
         gridReflowInput.mStartRow,
         Move(priorRowInfo->mPositions),
         Move(priorRowInfo->mSizes),
-        Move(priorRowInfo->mStates));
+        Move(priorRowInfo->mStates),
+        Move(priorRowInfo->mRemovedRepeatTracks));
       prevInFlow->Properties().Set(GridRowTrackInfo(), revisedPriorRowInfo);
     }
 
     // Generate the line info properties. We need to provide the number of
     // repeat tracks produced in the reflow. Only explicit names are assigned
     // to lines here; the mozilla::dom::GridLines class will later extract
     // implicit names from grid areas and assign them to the appropriate lines.
 
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -29,32 +29,35 @@ namespace mozilla {
 struct ComputedGridTrackInfo
 {
   ComputedGridTrackInfo(uint32_t aNumLeadingImplicitTracks,
                         uint32_t aNumExplicitTracks,
                         uint32_t aStartFragmentTrack,
                         uint32_t aEndFragmentTrack,
                         nsTArray<nscoord>&& aPositions,
                         nsTArray<nscoord>&& aSizes,
-                        nsTArray<uint32_t>&& aStates)
+                        nsTArray<uint32_t>&& aStates,
+                        nsTArray<bool>&& aRemovedRepeatTracks)
     : mNumLeadingImplicitTracks(aNumLeadingImplicitTracks)
     , mNumExplicitTracks(aNumExplicitTracks)
     , mStartFragmentTrack(aStartFragmentTrack)
     , mEndFragmentTrack(aEndFragmentTrack)
     , mPositions(aPositions)
     , mSizes(aSizes)
     , mStates(aStates)
+    , mRemovedRepeatTracks(aRemovedRepeatTracks)
   {}
   uint32_t mNumLeadingImplicitTracks;
   uint32_t mNumExplicitTracks;
   uint32_t mStartFragmentTrack;
   uint32_t mEndFragmentTrack;
   nsTArray<nscoord> mPositions;
   nsTArray<nscoord> mSizes;
   nsTArray<uint32_t> mStates;
+  nsTArray<bool> mRemovedRepeatTracks;
 };
 
 struct ComputedGridLineInfo
 {
   explicit ComputedGridLineInfo(nsTArray<nsTArray<nsString>>&& aNames)
     : mNames(aNames)
   {}
   nsTArray<nsTArray<nsString>> mNames;
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -2014,21 +2014,25 @@ nsImageFrame::HandleEvent(nsPresContext*
                                        getter_AddRefs(anchorNode))) {
           // XXX if the mouse is over/clicked in the border/padding area
           // we should probably just pretend nothing happened. Nav4
           // keeps the x,y coordinates positive as we do; IE doesn't
           // bother. Both of them send the click through even when the
           // mouse is over the border.
           if (p.x < 0) p.x = 0;
           if (p.y < 0) p.y = 0;
+
           nsAutoCString spec;
-          uri->GetSpec(spec);
+          nsresult rv = uri->GetSpec(spec);
+          NS_ENSURE_SUCCESS(rv, rv);
+
           spec += nsPrintfCString("?%d,%d", p.x, p.y);
-          uri->SetSpec(spec);                
-          
+          rv = uri->SetSpec(spec);
+          NS_ENSURE_SUCCESS(rv, rv);
+
           bool clicked = false;
           if (aEvent->mMessage == eMouseClick && !aEvent->DefaultPrevented()) {
             *aEventStatus = nsEventStatus_eConsumeDoDefault;
             clicked = true;
           }
           nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target,
                                       clicked, true, true);
         }
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -276,27 +276,28 @@ public:
                                          NS_LITERAL_STRING("resizevideocontrols"),
                                          false, false);
     return NS_OK;
   }
   nsCOMPtr<nsIContent> mContent;
 };
 
 void
-nsVideoFrame::Reflow(nsPresContext*           aPresContext,
-                     ReflowOutput&     aMetrics,
+nsVideoFrame::Reflow(nsPresContext* aPresContext,
+                     ReflowOutput& aMetrics,
                      const ReflowInput& aReflowInput,
-                     nsReflowStatus&          aStatus)
+                     nsReflowStatus& aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsVideoFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
-                  ("enter nsVideoFrame::Reflow: availSize=%d,%d",
-                  aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
+                 ("enter nsVideoFrame::Reflow: availSize=%d,%d",
+                  aReflowInput.AvailableWidth(),
+                  aReflowInput.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
   aStatus = NS_FRAME_COMPLETE;
 
   aMetrics.Width() = aReflowInput.ComputedWidth();
   aMetrics.Height() = aReflowInput.ComputedHeight();
 
@@ -377,17 +378,17 @@ nsVideoFrame::Reflow(nsPresContext*     
                         mBorderPadding.left, mBorderPadding.top, 0);
     }
   }
   aMetrics.SetOverflowAreasToDesiredBounds();
 
   FinishAndStoreOverflow(&aMetrics);
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
-                  ("exit nsVideoFrame::Reflow: size=%d,%d",
+                 ("exit nsVideoFrame::Reflow: size=%d,%d",
                   aMetrics.Width(), aMetrics.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
 }
 
 class nsDisplayVideo : public nsDisplayItem {
 public:
   nsDisplayVideo(nsDisplayListBuilder* aBuilder, nsVideoFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
@@ -529,17 +530,18 @@ nsVideoFrame::ComputeSize(nsRenderingCon
 
   IntrinsicSize intrinsicSize;
   intrinsicSize.width.SetCoordValue(size.width);
   intrinsicSize.height.SetCoordValue(size.height);
 
   // Only video elements have an intrinsic ratio.
   nsSize intrinsicRatio = HasVideoElement() ? size : nsSize(0, 0);
 
-  return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM, aRenderingContext,
+  return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(aWM,
+                                                           aRenderingContext,
                                                            this,
                                                            intrinsicSize,
                                                            intrinsicRatio,
                                                            aCBSize,
                                                            aMargin,
                                                            aBorder,
                                                            aPadding);
 }
--- a/layout/inspector/inCSSValueSearch.cpp
+++ b/layout/inspector/inCSSValueSearch.cpp
@@ -356,17 +356,18 @@ inCSSValueSearch::SearchStyleValue(const
       StringEndsWith(aValue, NS_LITERAL_STRING(")"))) {
     const nsASingleFragmentString &url =
       Substring(aValue, 4, aValue.Length() - 5);
     // XXXldb Need to do more with |mReturnRelativeURLs|, perhaps?
     nsCOMPtr<nsIURI> uri;
     nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, aBaseURL);
     NS_ENSURE_SUCCESS(rv, rv);
     nsAutoCString spec;
-    uri->GetSpec(spec);
+    rv = uri->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
     nsAutoString *result = new NS_ConvertUTF8toUTF16(spec);
     if (mReturnRelativeURLs)
       EqualizeURL(result);
     mResults->AppendElement(result);
     ++mResultCount;
   }
 
   return NS_OK;
--- a/layout/inspector/nsFontFace.cpp
+++ b/layout/inspector/nsFontFace.cpp
@@ -116,17 +116,18 @@ nsFontFace::GetSrcIndex(int32_t * aSrcIn
 NS_IMETHODIMP
 nsFontFace::GetURI(nsAString & aURI)
 {
   aURI.Truncate();
   if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
     NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
     if (mFontEntry->mUserFontData->mURI) {
       nsAutoCString spec;
-      mFontEntry->mUserFontData->mURI->GetSpec(spec);
+      nsresult rv = mFontEntry->mUserFontData->mURI->GetSpec(spec);
+      NS_ENSURE_SUCCESS(rv, rv);
       AppendUTF8toUTF16(spec, aURI);
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFontFace::GetLocalName(nsAString & aLocalName)
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -1213,20 +1213,20 @@ nsPrintEngine::GetDocumentTitleAndURL(ns
   if (!urifixup) return;
 
   nsCOMPtr<nsIURI> exposableURI;
   urifixup->CreateExposableURI(url, getter_AddRefs(exposableURI));
 
   if (!exposableURI) return;
 
   nsAutoCString urlCStr;
-  exposableURI->GetSpec(urlCStr);
-
-  nsresult rv;
-  nsCOMPtr<nsITextToSubURI> textToSubURI = 
+  nsresult rv = exposableURI->GetSpec(urlCStr);
+  if (NS_FAILED(rv)) return;
+
+  nsCOMPtr<nsITextToSubURI> textToSubURI =
     do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return;
 
   textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
                                  urlCStr, aURLStr);
 }
 
 //---------------------------------------------------------------------
--- a/layout/reftests/css-grid/grid-repeat-auto-fill-fit-006.html
+++ b/layout/reftests/css-grid/grid-repeat-auto-fill-fit-006.html
@@ -149,54 +149,54 @@ function testGridTemplateColumns(elem, e
   if (actual != expected) {
     var err = "FAIL: gridTemplateColumns " + elem.className +
               ", GOT=" + actual +
               ", EXPECTED=" + expected;
     document.body.appendChild(document.createTextNode(err));
   }
 }
 var a1 = [
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px",
-"[a d] 20px",
-"[a d] 20px",
-"[a d] 20px",
-"[a d] 20px",
-"[a d] 20px",
-"[a d] 20px"
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px"
 ];
 var a2 = [
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]",
-"[a b] 20px [c d]",
-"[a b] 20px [c d]",
-"[a b] 20px [c d]",
-"none",
-"none",
-"none"
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]"
 ];
 function runTest() {
  var t1 = document.querySelectorAll('.t1');
  for (var i = 0; i < t1.length; ++i) {
    testGridTemplateColumns(t1[i], a1[i]);
  }
  var t2 = document.querySelectorAll('.t2');
  for (var i = 0; i < t2.length; ++i) {
--- a/layout/reftests/css-grid/grid-repeat-auto-fill-fit-007.html
+++ b/layout/reftests/css-grid/grid-repeat-auto-fill-fit-007.html
@@ -143,42 +143,42 @@ function testGridTemplateColumns(elem, e
   if (actual != expected) {
     var err = "FAIL: gridTemplateColumns " + elem.className +
               ", GOT=" + actual +
               ", EXPECTED=" + expected;
     document.body.appendChild(document.createTextNode(err));
   }
 }
 var a1 = [
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px",
-"[a b] 20px [c d] 20px"
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 20px"
 ];
 var a2 = [
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d]"
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c d]",
+"[a b] 20px [c b] 0px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c d]",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]"
 ];
 function runTest() {
  var t1 = document.querySelectorAll('.t1');
  for (var i = 0; i < t1.length; ++i) {
    testGridTemplateColumns(t1[i], a1[i]);
  }
  var t2 = document.querySelectorAll('.t2');
  for (var i = 0; i < t2.length; ++i) {
--- a/layout/reftests/css-grid/grid-repeat-auto-fill-fit-008.html
+++ b/layout/reftests/css-grid/grid-repeat-auto-fill-fit-008.html
@@ -151,42 +151,42 @@ function testGridTemplateColumns(elem, e
   if (actual != expected) {
     var err = "FAIL: gridTemplateColumns " + elem.className +
               ", GOT=" + actual +
               ", EXPECTED=" + expected;
     document.body.appendChild(document.createTextNode(err));
   }
 }
 var a1 = [
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c d] 20px",
-"[a b] 20px [c b] 20px [c d] 20px 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c d] 20px 3px"
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c d] 20px",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c d] 20px 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c d] 20px 3px"
 ];
 var a2 = [
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c d]",
-"[a b] 20px [c b] 20px [c d] 3px",
-"3px [a b] 20px [c b] 20px [c b] 20px [c d] 3px"
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 20px [c b] 20px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d]",
+"[a b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c b] 0px [c d] 3px",
+"3px [a b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 20px [c b] 0px [c b] 0px [c d] 3px"
 ];
 function runTest() {
  var t1 = document.querySelectorAll('.t1');
  for (var i = 0; i < t1.length; ++i) {
    testGridTemplateColumns(t1[i], a1[i]);
  }
  var t2 = document.querySelectorAll('.t2');
  for (var i = 0; i < t2.length; ++i) {
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -1755,17 +1755,18 @@ CSSStyleSheet::GetParentStyleSheet(nsIDO
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CSSStyleSheet::GetHref(nsAString& aHref)
 {
   if (mInner->mOriginalSheetURI) {
     nsAutoCString str;
-    mInner->mOriginalSheetURI->GetSpec(str);
+    nsresult rv = mInner->mOriginalSheetURI->GetSpec(str);
+    NS_ENSURE_SUCCESS(rv, rv);
     CopyUTF8toUTF16(str, aHref);
   } else {
     SetDOMStringToNull(aHref);
   }
 
   return NS_OK;
 }
 
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -30,17 +30,20 @@ class ShortTermURISpecCache : public Run
 public:
   ShortTermURISpecCache() : mPending(false) {}
 
   nsString const& GetSpec(nsIURI* aURI) {
     if (mURI != aURI) {
       mURI = aURI;
 
       nsAutoCString cSpec;
-      mURI->GetSpec(cSpec);
+      nsresult rv = mURI->GetSpec(cSpec);
+      if (NS_FAILED(rv)) {
+        cSpec.AssignLiteral("[nsIURI::GetSpec failed]");
+      }
       CopyUTF8toUTF16(cSpec, mSpec);
     }
     return mSpec;
   }
 
   bool IsInUse() const { return mURI != nullptr; }
   bool IsPending() const { return mPending; }
   void SetPending() { mPending = true; }
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1258,19 +1258,17 @@ FontFaceSet::LogMessage(gfxUserFontEntry
   uint32_t line = 0;
   uint32_t column = 0;
   if (rule) {
     rv = rule->GetCssText(text);
     NS_ENSURE_SUCCESS(rv, rv);
     CSSStyleSheet* sheet = rule->GetStyleSheet();
     // if the style sheet is removed while the font is loading can be null
     if (sheet) {
-      nsAutoCString spec;
-      rv = sheet->GetSheetURI()->GetSpec(spec);
-      NS_ENSURE_SUCCESS(rv, rv);
+      nsCString spec = sheet->GetSheetURI()->GetSpecOrDefault();
       CopyUTF8toUTF16(spec, href);
     } else {
       NS_WARNING("null parent stylesheet for @font-face rule");
       href.AssignLiteral("unknown");
     }
     line = rule->GetLineNumber();
     column = rule->GetColumnNumber();
   }
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1770,20 +1770,20 @@ Loader::ParseSheet(const nsAString& aInp
   nsresult rv;
 
   if (aLoadData->mSheet->IsGecko()) {
     nsCSSParser parser(this, aLoadData->mSheet->AsGecko());
     rv = parser.ParseSheet(aInput, sheetURI, baseURI,
                            aLoadData->mSheet->Principal(),
                            aLoadData->mLineNumber);
   } else {
-    aLoadData->mSheet->AsServo()->ParseSheet(aInput, sheetURI, baseURI,
-                                             aLoadData->mSheet->Principal(),
-                                             aLoadData->mLineNumber);
-    rv = NS_OK;
+    rv =
+      aLoadData->mSheet->AsServo()->ParseSheet(aInput, sheetURI, baseURI,
+                                               aLoadData->mSheet->Principal(),
+                                               aLoadData->mLineNumber);
   }
 
   mParsingDatas.RemoveElementAt(mParsingDatas.Length() - 1);
 
   if (NS_FAILED(rv)) {
     LOG_ERROR(("  Low-level error in parser!"));
     SheetComplete(aLoadData, rv);
     return rv;
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -63,39 +63,42 @@ void
 ServoStyleSheet::AppendStyleSheet(StyleSheetHandle aSheet)
 {
   // XXXheycam: When we implement support for child sheets, we'll have
   // to fix SetOwningDocument to propagate the owning document down
   // to the children.
   MOZ_CRASH("stylo: not implemented");
 }
 
-void
+nsresult
 ServoStyleSheet::ParseSheet(const nsAString& aInput,
                             nsIURI* aSheetURI,
                             nsIURI* aBaseURI,
                             nsIPrincipal* aSheetPrincipal,
                             uint32_t aLineNumber)
 {
   DropSheet();
 
   RefPtr<ThreadSafeURIHolder> base = new ThreadSafeURIHolder(aBaseURI);
   RefPtr<ThreadSafeURIHolder> referrer = new ThreadSafeURIHolder(aSheetURI);
   RefPtr<ThreadSafePrincipalHolder> principal =
     new ThreadSafePrincipalHolder(aSheetPrincipal);
 
   nsCString baseString;
-  aBaseURI->GetSpec(baseString);
+  nsresult rv = aBaseURI->GetSpec(baseString);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ConvertUTF16toUTF8 input(aInput);
   mSheet = Servo_StyleSheet_FromUTF8Bytes(
       reinterpret_cast<const uint8_t*>(input.get()), input.Length(),
       mParsingMode,
       reinterpret_cast<const uint8_t*>(baseString.get()), baseString.Length(),
       base, referrer, principal).Consume();
+
+  return NS_OK;
 }
 
 void
 ServoStyleSheet::DropSheet()
 {
   mSheet = nullptr;
 }
 
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -35,21 +35,21 @@ public:
   bool HasRules() const;
 
   nsIDocument* GetOwningDocument() const;
   void SetOwningDocument(nsIDocument* aDocument);
 
   StyleSheetHandle GetParentSheet() const;
   void AppendStyleSheet(StyleSheetHandle aSheet);
 
-  void ParseSheet(const nsAString& aInput,
-                  nsIURI* aSheetURI,
-                  nsIURI* aBaseURI,
-                  nsIPrincipal* aSheetPrincipal,
-                  uint32_t aLineNumber);
+  MOZ_MUST_USE nsresult ParseSheet(const nsAString& aInput,
+                                   nsIURI* aSheetURI,
+                                   nsIURI* aBaseURI,
+                                   nsIPrincipal* aSheetPrincipal,
+                                   uint32_t aLineNumber);
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
 #ifdef DEBUG
   void List(FILE* aOut = stdout, int32_t aIndex = 0) const;
 #endif
 
   RawServoStyleSheet* RawSheet() const { return mSheet; }
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -1494,20 +1494,18 @@ StyleRule::List(FILE* out, int32_t aInde
     str.AppendLiteral("{ ");
     mDeclaration->ToString(buffer);
     AppendUTF16toUTF8(buffer, str);
     str.Append('}');
     CSSStyleSheet* sheet = GetStyleSheet();
     if (sheet) {
       nsIURI* uri = sheet->GetSheetURI();
       if (uri) {
-        nsAutoCString uristr;
         str.Append(" /* ");
-        uri->GetSpec(uristr);
-        str.Append(uristr);
+        str.Append(uri->GetSpecOrDefault());
         str.Append(':');
         str.AppendInt(mLineNumber);
         str.Append(" */");
       }
     }
   }
   else {
     str.AppendLiteral("{ null declaration }");
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -970,18 +970,21 @@ DocumentRule::UseForPresentation(nsPresC
 }
 
 bool
 DocumentRule::UseForPresentation(nsPresContext* aPresContext)
 {
   nsIDocument *doc = aPresContext->Document();
   nsIURI *docURI = doc->GetDocumentURI();
   nsAutoCString docURISpec;
-  if (docURI)
-    docURI->GetSpec(docURISpec);
+  if (docURI) {
+    // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
+    nsresult rv = docURI->GetSpec(docURISpec);
+    NS_ENSURE_SUCCESS(rv, false);
+  }
 
   for (URL *url = mURLs; url; url = url->next) {
     switch (url->func) {
       case eURL: {
         if (docURISpec == url->url)
           return true;
       } break;
       case eURLPrefix: {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2625,75 +2625,121 @@ nsComputedDOMStyle::GetGridTemplateColum
     MOZ_ASSERT(numExplicitTracks == numSizes ||
                (isAutoFill && numExplicitTracks >= numSizes) ||
                (isAutoFit && numExplicitTracks + 1 >= numSizes),
                "expected all explicit tracks (or possibly one less, if there's "
                "an 'auto-fit' track, since that can collapse away)");
     numSizes = aTrackInfo->mSizes.Length();
   }
 
-  // An empty <track-list> is represented as "none" in syntax.
-  if (numSizes == 0) {
+  // An empty <track-list> without repeats is represented as "none" in syntax.
+  if (numSizes == 0 && !aTrackList.HasRepeatAuto()) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_none);
     return val.forget();
   }
 
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
   if (aTrackInfo) {
     // We've done layout on the grid and have resolved the sizes of its tracks,
     // so we'll return those sizes here.  The grid spec says we MAY use
     // repeat(<positive-integer>, Npx) here for consecutive tracks with the same
     // size, but that doesn't seem worth doing since even for repeat(auto-*)
     // the resolved size might differ for the repeated tracks.
     const nsTArray<nscoord>& trackSizes = aTrackInfo->mSizes;
     const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks;
     const uint32_t numLeadingImplicitTracks = aTrackInfo->mNumLeadingImplicitTracks;
-    MOZ_ASSERT(numSizes > 0 &&
-               numSizes >= numLeadingImplicitTracks + numExplicitTracks);
+    MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks);
 
     // Add any leading implicit tracks.
     for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
       val->SetAppUnits(trackSizes[i]);
       valueList->AppendCSSValue(val.forget());
     }
 
-    // Then add any explicit tracks.
-    if (numExplicitTracks) {
+    // Then add any explicit tracks and removed auto-fit tracks.
+    if (numExplicitTracks || aTrackList.HasRepeatAuto()) {
       int32_t endOfRepeat = 0;  // first index after any repeat() tracks
       int32_t offsetToLastRepeat = 0;
       if (aTrackList.HasRepeatAuto()) {
         // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
         offsetToLastRepeat = numExplicitTracks + 1 - aTrackList.mLineNameLists.Length();
         endOfRepeat = aTrackList.mRepeatAutoIndex + offsetToLastRepeat + 1;
       }
+
+      uint32_t repeatIndex = 0;
+      uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
+      enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween };
+      auto AppendRemovedAutoFits = [this, aTrackInfo, &valueList, aTrackList,
+                                    &repeatIndex,
+                                    numRepeatTracks](LinePlacement aPlacement)
+      {
+        // Add in removed auto-fit tracks and lines here, if necessary
+        bool atLeastOneTrackReported = false;
+        while (repeatIndex < numRepeatTracks &&
+             aTrackInfo->mRemovedRepeatTracks[repeatIndex]) {
+          if ((aPlacement == LinesPrecede) ||
+              ((aPlacement == LinesBetween) && atLeastOneTrackReported)) {
+            // Precede it with the lines between repeats.
+            AppendGridLineNames(valueList,
+                                aTrackList.mRepeatAutoLineNameListAfter,
+                                aTrackList.mRepeatAutoLineNameListBefore);
+          }
+
+          // Removed 'auto-fit' tracks are reported as 0px.
+          RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+          val->SetAppUnits(0);
+          valueList->AppendCSSValue(val.forget());
+          atLeastOneTrackReported = true;
+
+          if (aPlacement == LinesFollow) {
+            // Follow it with the lines between repeats.
+            AppendGridLineNames(valueList,
+                                aTrackList.mRepeatAutoLineNameListAfter,
+                                aTrackList.mRepeatAutoLineNameListBefore);
+          }
+          repeatIndex++;
+        }
+        repeatIndex++;
+      };
+
       for (int32_t i = 0;; i++) {
         if (aTrackList.HasRepeatAuto()) {
           if (i == aTrackList.mRepeatAutoIndex) {
             const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
             if (i == endOfRepeat) {
-              // all auto-fit tracks are empty, so "[a] repeat(...) [b]"
-              // becomes "[a b]"
+              // All auto-fit tracks are empty, but we report them anyway.
               AppendGridLineNames(valueList, lineNames,
+                                  aTrackList.mRepeatAutoLineNameListBefore);
+
+              AppendRemovedAutoFits(LinesBetween);
+
+              AppendGridLineNames(valueList,
+                                  aTrackList.mRepeatAutoLineNameListAfter,
                                   aTrackList.mLineNameLists[i + 1]);
             } else {
               AppendGridLineNames(valueList, lineNames,
                                   aTrackList.mRepeatAutoLineNameListBefore);
+              AppendRemovedAutoFits(LinesFollow);
             }
           } else if (i == endOfRepeat) {
+            // Before appending the last line, finish off any removed auto-fits.
+            AppendRemovedAutoFits(LinesPrecede);
+
             const nsTArray<nsString>& lineNames =
               aTrackList.mLineNameLists[aTrackList.mRepeatAutoIndex + 1];
             AppendGridLineNames(valueList,
                                 aTrackList.mRepeatAutoLineNameListAfter,
                                 lineNames);
           } else if (i > aTrackList.mRepeatAutoIndex && i < endOfRepeat) {
             AppendGridLineNames(valueList,
                                 aTrackList.mRepeatAutoLineNameListAfter,
                                 aTrackList.mRepeatAutoLineNameListBefore);
+            AppendRemovedAutoFits(LinesFollow);
           } else {
             uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
             const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[j];
             AppendGridLineNames(valueList, lineNames);
           }
         } else {
           const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
           AppendGridLineNames(valueList, lineNames);
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -542,17 +542,17 @@ ListInterestingFiles(nsString& aAnnotati
 // sheets failing to load (bug 1194856).
 static void
 AnnotateCrashReport(nsIURI* aURI)
 {
   nsAutoCString spec;
   nsAutoCString scheme;
   nsDependentCSubstring filename;
   if (aURI) {
-    aURI->GetSpec(spec);
+    spec = aURI->GetSpecOrDefault();
     aURI->GetScheme(scheme);
     int32_t i = spec.RFindChar('/');
     if (i != -1) {
       filename.Rebind(spec, i + 1);
     }
   }
 
   nsString annotation;
@@ -598,19 +598,18 @@ AnnotateCrashReport(nsIURI* aURI)
     if (!reg) {
       annotation.AppendLiteral("(no chrome registry)\n");
     } else {
       nsCOMPtr<nsIURI> resolvedURI;
       reg->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
       if (!resolvedURI) {
         annotation.AppendLiteral("(ConvertChromeURL failed)\n");
       } else {
-        nsAutoCString resolvedSpec;
-        resolvedURI->GetSpec(resolvedSpec);
-        annotation.Append(NS_ConvertUTF8toUTF16(resolvedSpec));
+        annotation.Append(
+          NS_ConvertUTF8toUTF16(resolvedURI->GetSpecOrDefault()));
         annotation.Append('\n');
       }
     }
   }
 
   nsTArray<nsString> interestingFiles;
   interestingFiles.AppendElement(NS_LITERAL_STRING("chrome.manifest"));
   interestingFiles.AppendElement(NS_LITERAL_STRING("omni.ja"));
@@ -944,17 +943,20 @@ nsLayoutStylesheetCache::BuildPreference
 
   NS_ASSERTION(sheetText.Length() <= kPreallocSize,
                "kPreallocSize should be big enough to build preference style "
                "sheet without reallocation");
 
   if (sheet->IsGecko()) {
     sheet->AsGecko()->ReparseSheet(sheetText);
   } else {
-    sheet->AsServo()->ParseSheet(sheetText, uri, uri, nullptr, 0);
+    nsresult rv = sheet->AsServo()->ParseSheet(sheetText, uri, uri, nullptr, 0);
+    // Parsing the about:PreferenceStyleSheet URI can only fail on OOM. If we
+    // are OOM before we parsed any documents we might as well abort.
+    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   }
 
 #undef NS_GET_R_G_B
 }
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
 nsLayoutStylesheetCache::gStyleCache_Gecko;
 
--- a/layout/style/nsROCSSPrimitiveValue.cpp
+++ b/layout/style/nsROCSSPrimitiveValue.cpp
@@ -95,17 +95,18 @@ nsROCSSPrimitiveValue::GetCssText(nsAStr
       {
         tmpStr.Append(mValue.mString);
         break;
       }
     case CSS_URI :
       {
         if (mValue.mURI) {
           nsAutoCString specUTF8;
-          mValue.mURI->GetSpec(specUTF8);
+          nsresult rv = mValue.mURI->GetSpec(specUTF8);
+          NS_ENSURE_SUCCESS(rv, rv);
 
           tmpStr.AssignLiteral("url(");
           nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8),
                                               tmpStr);
           tmpStr.Append(')');
         } else {
           // http://dev.w3.org/csswg/css3-values/#attr defines
           // 'about:invalid' as the default value for url attributes,
@@ -456,20 +457,23 @@ nsROCSSPrimitiveValue::GetStringValue(ns
       CopyUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword), aReturn);
       break;
     case CSS_STRING:
     case CSS_ATTR:
       aReturn.Assign(mValue.mString);
       break;
     case CSS_URI: {
       nsAutoCString spec;
-      if (mValue.mURI)
-        mValue.mURI->GetSpec(spec);
+      if (mValue.mURI) {
+        nsresult rv = mValue.mURI->GetSpec(spec);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
       CopyUTF8toUTF16(spec, aReturn);
-      } break;
+      break;
+    }
     default:
       aReturn.Truncate();
       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
   return NS_OK;
 }
 
 void
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -180,17 +180,22 @@ FragmentOrURL::GetSourceString(nsString 
 {
   MOZ_ASSERT(mURL);
 
   nsCString cref;
   if (mIsLocalRef) {
     mURL->GetRef(cref);
     cref.Insert('#', 0);
   } else {
-    mURL->GetSpec(cref);
+    // It's not entirely clear how to best handle failure here. Ensuring the
+    // string is empty seems safest.
+    nsresult rv = mURL->GetSpec(cref);
+    if (NS_FAILED(rv)) {
+      cref.Truncate();
+    }
   }
 
   aRef = NS_ConvertUTF8toUTF16(cref);
 }
 
 already_AddRefed<nsIURI>
 FragmentOrURL::Resolve(nsIURI* aURI) const
 {
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -4222,17 +4222,17 @@ SVGTextFrame::GetEndPositionOfChar(nsICo
     advance = -advance;
   }
 
   // The end position is the start position plus the advance in the direction
   // of the glyph's rotation.
   Matrix m =
     Matrix::Rotation(mPositions[startIndex].mAngle) *
     Matrix::Translation(ToPoint(mPositions[startIndex].mPosition));
-  Point p = m * Point(advance / mFontSizeScaleFactor, 0);
+  Point p = m.TransformPoint(Point(advance / mFontSizeScaleFactor, 0));
 
   NS_ADDREF(*aResult = new DOMSVGPoint(p));
   return NS_OK;
 }
 
 /**
  * Implements the SVG DOM GetExtentOfChar method for the specified
  * text content element.
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -525,18 +525,17 @@ GenerateMaskSurface(const nsSVGIntegrati
   if (maskSurfaceRect.IsEmpty()) {
     return DrawResult::SUCCESS;
   }
 
   // Mask composition result on CoreGraphic::A8 surface is not correct
   // when mask-mode is not add(source over). Switch to skia when CG backend
   // detected.
   RefPtr<DrawTarget> maskDT =
-    (ctx.GetDrawTarget()->GetBackendType() == BackendType::COREGRAPHICS ||
-     ctx.GetDrawTarget()->GetBackendType() == BackendType::DIRECT2D1_1)
+    (ctx.GetDrawTarget()->GetBackendType() == BackendType::COREGRAPHICS)
     ? Factory::CreateDrawTarget(BackendType::SKIA, maskSurfaceRect.Size(),
                                 SurfaceFormat::A8)
     : ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
                                                    SurfaceFormat::A8);
   if (!maskDT || !maskDT->IsValid()) {
     return DrawResult::TEMPORARY_ERROR;
   }
 
@@ -572,18 +571,18 @@ GenerateMaskSurface(const nsSVGIntegrati
                                          cssPxToDevPxMatrix, aOpacity,
                                          &svgMaskMatrix,
                                          svgReset->mMask.mLayers[i].mMaskMode);
       if (svgMask) {
         gfxContextMatrixAutoSaveRestore matRestore(maskContext);
 
         maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
         Rect drawRect = IntRectToRect(IntRect(IntPoint(0, 0), svgMask->GetSize()));
-        maskDT->DrawSurface(svgMask, drawRect, drawRect, DrawSurfaceOptions(),
-                            DrawOptions(1.0f, compositionOp));
+        maskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask, drawRect.TopLeft(),
+                            DrawOptions(1.0, compositionOp));
       }
     } else {
       gfxContextMatrixAutoSaveRestore matRestore(maskContext);
 
       maskContext->Multiply(gfxMatrix::Translation(-devPixelOffsetToUserSpace));
       nsRenderingContext rc(maskContext);
       nsCSSRendering::PaintBGParams  params =
         nsCSSRendering::PaintBGParams::ForSingleLayer(*presContext,
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -146,21 +146,24 @@ public:
                                bool aHandleOpacity)
       : ctx(aCtx), frame(aFrame), dirtyRect(aDirtyRect),
         borderArea(aBorderArea), builder(aBuilder),
         layerManager(aLayerManager), handleOpacity(aHandleOpacity)
     { }
   };
 
   /**
-   * Paint non-SVG frame with SVG effects.
+   * Paint non-SVG frame with mask, clipPath and opacity effect.
    */
   static DrawResult
   PaintMaskAndClipPath(const PaintFramesParams& aParams);
 
+  /**
+   * Paint non-SVG frame with filter and opacity effect.
+   */
   static DrawResult
   PaintFilter(const PaintFramesParams& aParams);
 
   /**
    * SVG frames expect to paint in SVG user units, which are equal to CSS px
    * units. This method provides a transform matrix to multiply onto a
    * gfxContext's current transform to convert the context's current units from
    * its usual dev pixels to SVG user units/CSS px to keep the SVG code happy.
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -361,17 +361,17 @@ nsSVGPathGeometryFrame::GetFrameForPoint
     SVGContentUtils::AutoStrokeOptions stroke;
     SVGContentUtils::GetStrokeOptions(&stroke, content, StyleContext(), nullptr);
     gfxMatrix userToOuterSVG;
     if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
       // We need to transform the path back into the appropriate ancestor
       // coordinate system in order for non-scaled stroke to be correct.
       // Naturally we also need to transform the point into the same
       // coordinate system in order to hit-test against the path.
-      point = ToMatrix(userToOuterSVG) * point;
+      point = ToMatrix(userToOuterSVG).TransformPoint(point);
       RefPtr<PathBuilder> builder =
         path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
       path = builder->Finish();
     }
     isHit = path->StrokeContainsPoint(stroke, point, Matrix());
   }
 
   if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -872,17 +872,17 @@ nsSVGUtils::HitTestRect(const gfx::Matri
                         float aX, float aY)
 {
   gfx::Rect rect(aRX, aRY, aRWidth, aRHeight);
   if (rect.IsEmpty() || aMatrix.IsSingular()) {
     return false;
   }
   gfx::Matrix toRectSpace = aMatrix;
   toRectSpace.Invert();
-  gfx::Point p = toRectSpace * gfx::Point(aX, aY);
+  gfx::Point p = toRectSpace.TransformPoint(gfx::Point(aX, aY));
   return rect.x <= p.x && p.x <= rect.XMost() &&
          rect.y <= p.y && p.y <= rect.YMost();
 }
 
 gfxRect
 nsSVGUtils::GetClipRectForFrame(nsIFrame *aFrame,
                                 float aX, float aY, float aWidth, float aHeight)
 {
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2114,17 +2114,18 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn
     // Obtain the URL from the style context.
     aAllowImageRegions = true;
     styleRequest = aStyleContext->StyleList()->GetListStyleImage();
     if (!styleRequest)
       return NS_OK;
     nsCOMPtr<nsIURI> uri;
     styleRequest->GetURI(getter_AddRefs(uri));
     nsAutoCString spec;
-    uri->GetSpec(spec);
+    nsresult rv = uri->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
     CopyUTF8toUTF16(spec, imageSrc);
   }
 
   // Look the image up in our cache.
   nsTreeImageCacheEntry entry;
   if (mImageCache.Get(imageSrc, &entry)) {
     // Find out if the image has loaded.
     uint32_t status;
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -912,17 +912,17 @@ public class BrowserApp extends GeckoApp
             // in the firstrun pane being shown.
             return;
         }
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
 
         try {
             final SharedPreferences prefs = GeckoSharedPrefs.forProfile(this);
 
-            if (prefs.getBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, false)) {
+            if (prefs.getBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, true)) {
                 if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
                     showFirstrunPager();
 
                     if (HardwareUtils.isTablet()) {
                         mTabStrip.setOnTabChangedListener(new TabStripInterface.OnTabAddedOrRemovedListener() {
                             @Override
                             public void onTabChanged() {
                                 hideFirstrunPager(TelemetryContract.Method.BUTTON);
--- a/mobile/android/chrome/content/PermissionsHelper.js
+++ b/mobile/android/chrome/content/PermissionsHelper.js
@@ -1,27 +1,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 var PermissionsHelper = {
   _permissonTypes: ["password", "geolocation", "popup", "indexedDB",
-                    "offline-app", "desktop-notification", "plugins", "native-intent"],
+                    "offline-app", "desktop-notification", "plugins", "native-intent",
+                    "flyweb-publish-server"],
   _permissionStrings: {
     "password": {
       label: "password.logins",
       allowed: "password.save",
       denied: "password.dontSave"
     },
     "geolocation": {
       label: "geolocation.location",
       allowed: "geolocation.allow",
       denied: "geolocation.dontAllow"
     },
+    "flyweb-publish-server": {
+      label: "flyWebPublishServer.publishServer",
+      allowed: "flyWebPublishServer.allow",
+      denied: "flyWebPublishServer.dontAllow"
+    },
     "popup": {
       label: "blockPopups.label2",
       allowed: "popup.show",
       denied: "popup.dontShow"
     },
     "indexedDB": {
       label: "offlineApps.offlineData",
       allowed: "offlineApps.allow",
--- a/mobile/android/components/ContentPermissionPrompt.js
+++ b/mobile/android/components/ContentPermissionPrompt.js
@@ -13,22 +13,24 @@ Cu.import("resource://gre/modules/Servic
 const kEntities = {
   "contacts": "contacts",
   "desktop-notification": "desktopNotification2",
   "device-storage:music": "deviceStorageMusic",
   "device-storage:pictures": "deviceStoragePictures",
   "device-storage:sdcard": "deviceStorageSdcard",
   "device-storage:videos": "deviceStorageVideos",
   "geolocation": "geolocation",
+  "flyweb-publish-server": "flyWebPublishServer",
 };
 
 // For these types, prompt for permission if action is unknown.
 const PROMPT_FOR_UNKNOWN = [
   "desktop-notification",
   "geolocation",
+  "flyweb-publish-server",
 ];
 
 function ContentPermissionPrompt() {}
 
 ContentPermissionPrompt.prototype = {
   classID: Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java
@@ -16,17 +16,16 @@ import android.util.Log;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
 import org.mozilla.gecko.GeckoProfileDirectories.NoSuchProfileException;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.StubBrowserDB;
-import org.mozilla.gecko.firstrun.FirstrunAnimationContainer;
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.INIParser;
 import org.mozilla.gecko.util.INISection;
 import org.mozilla.gecko.util.IntentUtils;
 
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -968,20 +967,16 @@ public final class GeckoProfile {
             Log.w(LOGTAG, "Couldn't write " + TIMES_PATH, e);
         }
 
         // Create the client ID file before Gecko starts (we assume this method
         // is called before Gecko starts). If we let Gecko start, the JS telemetry
         // code may try to write to the file at the same time Java does.
         persistClientId(generateNewClientId());
 
-        // Initialize pref flag for displaying the start pane for a new profile.
-        final SharedPreferences prefs = GeckoSharedPrefs.forProfile(mApplicationContext);
-        prefs.edit().putBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, true).apply();
-
         return profileDir;
     }
 
     /**
      * This method is called once, immediately before creation of the profile
      * directory completes.
      *
      * It queues up work to be done in the background to prepare the profile,
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -126,16 +126,28 @@ geolocation.dontAskAgain=Don't ask again
 # Desktop notification UI
 desktopNotification2.allow=Always
 desktopNotification2.dontAllow=Never
 desktopNotification2.ask=Would you like to receive notifications from this site?
 # LOCALIZATION NOTE (desktopNotification.notifications): Label that will be
 # used in site settings dialog.
 desktopNotification.notifications=Notifications
 
+# FlyWeb UI
+# LOCALIZATION NOTE (flyWebPublishServer.allow): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.allow=Allow
+# LOCALIZATION NOTE (flyWebPublishServer.dontAllow): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.dontAllow=Deny
+# LOCALIZATION NOTE (flyWebPublishServer.ask): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.ask=Would you like to let this site start a server accessible to nearby devices and people?
+# LOCALIZATION NOTE (flyWebPublishServer.dontAskAgain): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.dontAskAgain=Don't ask again for this site
+# LOCALIZATION NOTE (flyWebPublishServer.publishServer): This is an experimental feature only shipping in Nightly, and doesn't need translation.
+flyWebPublishServer.publishServer=Publish Server
+
 # Imageblocking
 imageblocking.downloadedImage=Image unblocked
 imageblocking.showAllImages=Show All
 
 # Device Storage API
 deviceStorageMusic.allow=Allow
 deviceStorageMusic.dontAllow=Don't allow
 deviceStorageMusic.ask=Allow %S access to your music?
--- a/netwerk/base/nsPACMan.cpp
+++ b/netwerk/base/nsPACMan.cpp
@@ -448,17 +448,18 @@ nsPACMan::StartLoading()
     nsCOMPtr<nsIIOService> ios = do_GetIOService();
     if (ios) {
       nsCOMPtr<nsIChannel> channel;
       nsCOMPtr<nsIURI> pacURI;
       NS_NewURI(getter_AddRefs(pacURI), mPACURISpec);
 
       // NOTE: This results in GetProxyForURI being called
       if (pacURI) {
-        pacURI->GetSpec(mNormalPACURISpec);
+        nsresult rv = pacURI->GetSpec(mNormalPACURISpec);
+        MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
         NS_NewChannel(getter_AddRefs(channel),
                       pacURI,
                       nsContentUtils::GetSystemPrincipal(),
                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                       nsIContentPolicy::TYPE_OTHER,
                       nullptr, // aLoadGroup
                       nullptr, // aCallbacks
                       nsIRequest::LOAD_NORMAL,
--- a/netwerk/base/nsPACMan.h
+++ b/netwerk/base/nsPACMan.h
@@ -156,21 +156,26 @@ public:
    */
   bool IsPACURI(const nsACString &spec)
   {
     return mPACURISpec.Equals(spec) || mPACURIRedirectSpec.Equals(spec) ||
       mNormalPACURISpec.Equals(spec);
   }
 
   bool IsPACURI(nsIURI *uri) {
-    if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty())
+    if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty()) {
       return false;
+    }
 
     nsAutoCString tmp;
-    uri->GetSpec(tmp);
+    nsresult rv = uri->GetSpec(tmp);
+    if (NS_FAILED(rv)) {
+      return false;
+    }
+
     return IsPACURI(tmp);
   }
 
   nsresult Init(nsISystemProxySettings *);
   static nsPACMan *sInstance;
 
   // PAC thread operations only
   void ProcessPendingQ();
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -397,17 +397,17 @@ nsStandardURL::IsValidOfBase(unsigned ch
     } else if (c == '8' || c== '9') {
         return base != 8;
     } else if (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) {
         return base == 16;
     }
     return false;
 }
 
-/* static */ nsresult
+/* static */ inline nsresult
 nsStandardURL::ParseIPv4Number(nsCString &input, uint32_t &number)
 {
     if (input.Length() == 0) {
         return NS_ERROR_FAILURE;
     }
     uint32_t base;
     uint32_t prefixLength = 0;
 
@@ -467,24 +467,26 @@ nsStandardURL::ParseIPv4Number(nsCString
     }
     return NS_ERROR_FAILURE;
 }
 
 // IPv4 parser spec: https://url.spec.whatwg.org/#concept-ipv4-parser
 /* static */ nsresult
 nsStandardURL::NormalizeIPv4(const nsCSubstring &host, nsCString &result)
 {
-    if (FindInReadable(NS_LITERAL_CSTRING(".."), host)) {
+    if (host.Length() == 0 ||
+        host[0] < '0' || '9' < host[0] || // bail-out fast
+        FindInReadable(NS_LITERAL_CSTRING(".."), host)) {
         return NS_ERROR_FAILURE;
     }
+
     nsTArray<nsCString> parts;
     if (!ParseString(host, '.', parts) ||
-        parts.Length() == 0 /* implies host.Length() == 0 */ ||
-        parts.Length() > 4 ||
-        host[0] == '.') {
+        parts.Length() == 0 ||
+        parts.Length() > 4) {
         return NS_ERROR_FAILURE;
     }
     uint32_t n = 0;
     nsTArray<int32_t> numbers;
     for (uint32_t i = 0; i < parts.Length(); ++i) {
         if (NS_FAILED(ParseIPv4Number(parts[i], n))) {
             return NS_ERROR_FAILURE;
         }
--- a/netwerk/base/nsURIHashKey.h
+++ b/netwerk/base/nsURIHashKey.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsURIHashKey_h__
 #define nsURIHashKey_h__
 
 #include "PLDHashTable.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 #include "nsHashKeys.h"
+#include "mozilla/Unused.h"
 
 /**
  * Hashtable key class to use with nsTHashtable/nsBaseHashtable
  */
 class nsURIHashKey : public PLDHashEntryHdr
 {
 public:
     typedef nsIURI* KeyType;
@@ -40,17 +41,19 @@ public:
 
     static const nsIURI* KeyToPointer(nsIURI* aKey) { return aKey; }
     static PLDHashNumber HashKey(const nsIURI* aKey) {
         if (!aKey) {
             // If the key is null, return hash for empty string.
             return mozilla::HashString(EmptyCString());
         }
         nsAutoCString spec;
-        const_cast<nsIURI*>(aKey)->GetSpec(spec);
+        // If GetSpec() fails, ignoring the failure and proceeding with an
+        // empty |spec| seems like the best thing to do.
+        mozilla::Unused << const_cast<nsIURI*>(aKey)->GetSpec(spec);
         return mozilla::HashString(spec);
     }
 
     enum { ALLOW_MEMMOVE = true };
 
 protected:
     nsCOMPtr<nsIURI> mKey;
 };
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -423,21 +423,21 @@ NeckoChild::RecvAppOfflineStatus(const u
   if (gIOService) {
     gIOService->SetAppOfflineInternal(aId, aOffline ?
       nsIAppOfflineInfo::OFFLINE : nsIAppOfflineInfo::ONLINE);
   }
   return true;
 }
 
 bool
-NeckoChild::RecvSpeculativeConnectRequest(const nsCString& aNotificationData)
+NeckoChild::RecvSpeculativeConnectRequest()
 {
   nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
   if (obsService) {
     obsService->NotifyObservers(nullptr, "speculative-connect-request",
-                                NS_ConvertUTF8toUTF16(aNotificationData).get());
+                                nullptr);
   }
   return true;
 }
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -89,17 +89,17 @@ protected:
   virtual bool DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild*) override;
 
   /* Predictor Messsages */
   virtual bool RecvPredOnPredictPrefetch(const URIParams& aURI,
                                          const uint32_t& aHttpStatus) override;
   virtual bool RecvPredOnPredictPreconnect(const URIParams& aURI) override;
   virtual bool RecvPredOnPredictDNS(const URIParams& aURI) override;
 
-  virtual bool RecvSpeculativeConnectRequest(const nsCString& aNotificationData) override;
+  virtual bool RecvSpeculativeConnectRequest() override;
 };
 
 /**
  * Reference to the PNecko Child protocol.
  * Null if this is not a content process.
  */
 extern PNeckoChild *gNeckoChild;
 
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -127,17 +127,17 @@ child:
   // Notifies child that a given app is now offline (or online)
   async AppOfflineStatus(uint32_t appId, bool offline);
 
   /* Predictor Methods */
   async PredOnPredictPrefetch(URIParams uri, uint32_t httpStatus);
   async PredOnPredictPreconnect(URIParams uri);
   async PredOnPredictDNS(URIParams uri);
 
-  async SpeculativeConnectRequest(nsCString notificationData);
+  async SpeculativeConnectRequest();
 
   async PTransportProvider();
 
 both:
   // Actually we need PTCPSocket() for parent. But ipdl disallows us having different
   // signatures on parent and child. So when constructing the parent side object, we just 
   // leave host/port unused.
   async PTCPSocket(nsString host, uint16_t port);
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -140,17 +140,18 @@ RemoteOpenFileChild::Init(nsIURI* aRemot
 
   // scheme of URI is not file:// so this is not a nsIFileURL.  Convert to one.
   nsCOMPtr<nsIURI> clonedURI;
   rv = aRemoteOpenUri->Clone(getter_AddRefs(clonedURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   clonedURI->SetScheme(NS_LITERAL_CSTRING("file"));
   nsAutoCString spec;
-  clonedURI->GetSpec(spec);
+  rv = clonedURI->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   rv = NS_NewURI(getter_AddRefs(mURI), spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get nsIFile
   nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mURI);
   if (!fileURL) {
     return NS_ERROR_UNEXPECTED;
--- a/netwerk/protocol/device/nsDeviceChannel.cpp
+++ b/netwerk/protocol/device/nsDeviceChannel.cpp
@@ -76,17 +76,18 @@ nsDeviceChannel::OpenContentStream(bool 
 
   nsCOMPtr<nsIURI> uri = nsBaseChannel::URI();
   *aStream = nullptr;
   *aChannel = nullptr;
   NS_NAMED_LITERAL_CSTRING(width, "width=");
   NS_NAMED_LITERAL_CSTRING(height, "height=");
 
   nsAutoCString spec;
-  uri->GetSpec(spec);
+  nsresult rv = uri->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString type;
 
   RefPtr<nsDeviceCaptureProvider> capture;
   nsCaptureParams captureParams;
   captureParams.camera = 0;
   if (kNotFound != spec.Find(NS_LITERAL_CSTRING("type=image/png"),
                              true,
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp
+++ b/netwerk/protocol/ftp/FTPChannelChild.cpp
@@ -315,21 +315,28 @@ FTPChannelChild::DoOnStartRequest(const 
 
   mContentLength = aContentLength;
   SetContentType(aContentType);
   mLastModifiedTime = aLastModified;
   mEntityID = aEntityID;
 
   nsCString spec;
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
-  uri->GetSpec(spec);
-  nsBaseChannel::URI()->SetSpec(spec);
+  nsresult rv = uri->GetSpec(spec);
+  if (NS_SUCCEEDED(rv)) {
+    rv = nsBaseChannel::URI()->SetSpec(spec);
+    if (NS_FAILED(rv)) {
+      Cancel(rv);
+    }
+  } else {
+    Cancel(rv);
+  }
 
   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
-  nsresult rv = mListener->OnStartRequest(this, mListenerContext);
+  rv = mListener->OnStartRequest(this, mListenerContext);
   if (NS_FAILED(rv))
     Cancel(rv);
 
   if (mDivertingToParent) {
     mListener = nullptr;
     mListenerContext = nullptr;
     if (mLoadGroup) {
       mLoadGroup->RemoveRequest(this, nullptr, mStatus);
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -2201,17 +2201,17 @@ HttpBaseChannel::AddSecurityMessage(cons
   rv = nsContentUtils::GetLocalizedString(
           nsContentUtils::eSECURITY_PROPERTIES,
           NS_ConvertUTF16toUTF8(aMessageTag).get(),
           errorText);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString spec;
   if (mURI) {
-    mURI->GetSpec(spec);
+    spec = mURI->GetSpecOrDefault();
   }
 
   nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
   error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec),
                           EmptyString(), 0, 0, nsIScriptError::warningFlag,
                           NS_ConvertUTF16toUTF8(aMessageCategory),
                           innerWindowID);
   console->LogMessage(error);
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -74,17 +74,17 @@ LogBlockedRequest(nsIRequest* aRequest,
     return;
   }
 
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   nsCOMPtr<nsIURI> aUri;
   channel->GetURI(getter_AddRefs(aUri));
   nsAutoCString spec;
   if (aUri) {
-    aUri->GetSpec(spec);
+    spec = aUri->GetSpecOrDefault();
   }
 
   // Generate the error message
   nsXPIDLString blockedMessage;
   NS_ConvertUTF8toUTF16 specUTF16(spec);
   const char16_t* params[] = { specUTF16.get(), aParam };
   rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eSECURITY_PROPERTIES,
                                              aProperty,
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -940,19 +940,17 @@ CallTypeSniffers(void *aClosure, const u
 
 // Helper Function to report messages to the console when loading
 // a resource was blocked due to a MIME type mismatch.
 void
 ReportTypeBlocking(nsIURI* aURI,
                    nsILoadInfo* aLoadInfo,
                    const char* aMessageName)
 {
-    nsAutoCString spec;
-    aURI->GetSpec(spec);
-    NS_ConvertUTF8toUTF16 specUTF16(spec);
+    NS_ConvertUTF8toUTF16 specUTF16(aURI->GetSpecOrDefault());
     const char16_t* params[] = { specUTF16.get() };
     nsCOMPtr<nsIDocument> doc;
     if (aLoadInfo) {
         nsCOMPtr<nsIDOMDocument> domDoc;
         aLoadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
         if (domDoc) {
             doc = do_QueryInterface(domDoc);
         }
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2207,25 +2207,22 @@ nsHttpHandler::SpeculativeConnectInterna
     }
 
     if (!mHandlerActive)
         return NS_OK;
 
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
     if (mDebugObservations && obsService) {
-        // this is basically used for test coverage of an otherwise 'hintable' feature
-        nsAutoCString spec;
-        aURI->GetSpec(spec);
-        spec.Append(anonymous ? NS_LITERAL_CSTRING("[A]") : NS_LITERAL_CSTRING("[.]"));
-        obsService->NotifyObservers(nullptr,
-                                    "speculative-connect-request",
-                                    NS_ConvertUTF8toUTF16(spec).get());
+        // this is basically used for test coverage of an otherwise 'hintable'
+        // feature
+        obsService->NotifyObservers(nullptr, "speculative-connect-request",
+                                    nullptr);
         if (!IsNeckoChild() && gNeckoParent) {
-            Unused << gNeckoParent->SendSpeculativeConnectRequest(spec);
+            Unused << gNeckoParent->SendSpeculativeConnectRequest();
         }
     }
 
     nsISiteSecurityService* sss = gHttpHandler->GetSSService();
     bool isStsHost = false;
     if (!sss)
         return NS_OK;
 
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.cpp
@@ -108,55 +108,61 @@ SubstitutingProtocolHandler::ConstructIn
   mIOService = do_GetIOService(&rv);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOService);
 }
 
 //
 // IPC marshalling.
 //
 
-void
+nsresult
 SubstitutingProtocolHandler::CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aMappings)
 {
   for (auto iter = mSubstitutions.ConstIter(); !iter.Done(); iter.Next()) {
     nsCOMPtr<nsIURI> uri = iter.Data();
     SerializedURI serialized;
     if (uri) {
-      uri->GetSpec(serialized.spec);
+      nsresult rv = uri->GetSpec(serialized.spec);
+      NS_ENSURE_SUCCESS(rv, rv);
       uri->GetOriginCharset(serialized.charset);
     }
     SubstitutionMapping substitution = { mScheme, nsCString(iter.Key()), serialized };
     aMappings.AppendElement(substitution);
   }
+
+  return NS_OK;
 }
 
-void
+nsresult
 SubstitutingProtocolHandler::SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI)
 {
   if (GeckoProcessType_Content == XRE_GetProcessType()) {
-    return;
+    return NS_OK;
   }
 
   nsTArray<ContentParent*> parents;
   ContentParent::GetAll(parents);
   if (!parents.Length()) {
-    return;
+    return NS_OK;
   }
 
   SubstitutionMapping mapping;
   mapping.scheme = mScheme;
   mapping.path = aRoot;
   if (aBaseURI) {
-    aBaseURI->GetSpec(mapping.resolvedURI.spec);
+    nsresult rv = aBaseURI->GetSpec(mapping.resolvedURI.spec);
+    NS_ENSURE_SUCCESS(rv, rv);
     aBaseURI->GetOriginCharset(mapping.resolvedURI.charset);
   }
 
   for (uint32_t i = 0; i < parents.Length(); i++) {
     Unused << parents[i]->SendRegisterChromeItem(mapping);
   }
+
+  return NS_OK;
 }
 
 //----------------------------------------------------------------------------
 // nsIProtocolHandler
 //----------------------------------------------------------------------------
 
 nsresult
 SubstitutingProtocolHandler::GetScheme(nsACString &result)
@@ -278,48 +284,45 @@ SubstitutingProtocolHandler::AllowPort(i
 // nsISubstitutingProtocolHandler
 //----------------------------------------------------------------------------
 
 nsresult
 SubstitutingProtocolHandler::SetSubstitution(const nsACString& root, nsIURI *baseURI)
 {
   if (!baseURI) {
     mSubstitutions.Remove(root);
-    SendSubstitution(root, baseURI);
-    return NS_OK;
+    return SendSubstitution(root, baseURI);
   }
 
   // If baseURI isn't a same-scheme URI, we can set the substitution immediately.
   nsAutoCString scheme;
   nsresult rv = baseURI->GetScheme(scheme);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!scheme.Equals(mScheme)) {
     if (mEnforceFileOrJar && !scheme.EqualsLiteral("file") && !scheme.EqualsLiteral("jar")
         && !scheme.EqualsLiteral("app")) {
       NS_WARNING("Refusing to create substituting URI to non-file:// target");
       return NS_ERROR_INVALID_ARG;
     }
 
     mSubstitutions.Put(root, baseURI);
-    SendSubstitution(root, baseURI);
-    return NS_OK;
+    return SendSubstitution(root, baseURI);
   }
 
   // baseURI is a same-type substituting URI, let's resolve it first.
   nsAutoCString newBase;
   rv = ResolveURI(baseURI, newBase);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> newBaseURI;
   rv = mIOService->NewURI(newBase, nullptr, nullptr, getter_AddRefs(newBaseURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mSubstitutions.Put(root, newBaseURI);
-  SendSubstitution(root, newBaseURI);
-  return NS_OK;
+  return SendSubstitution(root, newBaseURI);
 }
 
 nsresult
 SubstitutingProtocolHandler::GetSubstitution(const nsACString& root, nsIURI **result)
 {
   NS_ENSURE_ARG_POINTER(result);
 
   if (mSubstitutions.Get(root, result))
--- a/netwerk/protocol/res/SubstitutingProtocolHandler.h
+++ b/netwerk/protocol/res/SubstitutingProtocolHandler.h
@@ -32,23 +32,23 @@ public:
   explicit SubstitutingProtocolHandler(const char* aScheme);
 
   NS_INLINE_DECL_REFCOUNTING(SubstitutingProtocolHandler);
   NS_DECL_NON_VIRTUAL_NSIPROTOCOLHANDLER;
   NS_DECL_NON_VIRTUAL_NSISUBSTITUTINGPROTOCOLHANDLER;
 
   bool HasSubstitution(const nsACString& aRoot) const { return mSubstitutions.Get(aRoot, nullptr); }
 
-  void CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aResources);
+  nsresult CollectSubstitutions(InfallibleTArray<SubstitutionMapping>& aResources);
 
 protected:
   virtual ~SubstitutingProtocolHandler() {}
   void ConstructInternal();
 
-  void SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI);
+  nsresult SendSubstitution(const nsACString& aRoot, nsIURI* aBaseURI);
 
   // Override this in the subclass to try additional lookups after checking
   // mSubstitutions.
   virtual nsresult GetSubstitutionInternal(const nsACString& aRoot, nsIURI** aResult)
   {
     *aResult = nullptr;
     return NS_ERROR_NOT_AVAILABLE;
   }
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -234,17 +234,20 @@ nsViewSourceChannel::GetURI(nsIURI* *aUR
 
     // protect ourselves against broken channel implementations
     if (!uri) {
       NS_ERROR("inner channel returned NS_OK and a null URI");
       return NS_ERROR_UNEXPECTED;
     }
 
     nsAutoCString spec;
-    uri->GetSpec(spec);
+    rv = uri->GetSpec(spec);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
 
     /* XXX Gross hack -- NS_NewURI goes into an infinite loop on
        non-flat specs.  See bug 136980 */
     return NS_NewURI(aURI, nsAutoCString(NS_LITERAL_CSTRING("view-source:")+spec), nullptr);
 }
 
 NS_IMETHODIMP
 nsViewSourceChannel::Open(nsIInputStream **_retval)
--- a/netwerk/test/gtest/TestStandardURL.cpp
+++ b/netwerk/test/gtest/TestStandardURL.cpp
@@ -47,18 +47,18 @@ TEST(TestStandardURL, Simple) {
 #define COUNT 10000
 
 MOZ_GTEST_BENCH(TestStandardURL, Perf, [] {
     nsCOMPtr<nsIURL> url( do_CreateInstance(NS_STANDARDURL_CONTRACTID) );
     ASSERT_TRUE(url);
     nsAutoCString out;
 
     for (int i = COUNT; i; --i) {
-        url->SetSpec(NS_LITERAL_CSTRING("http://example.com"));
-        url->GetSpec(out);
+        ASSERT_EQ(url->SetSpec(NS_LITERAL_CSTRING("http://example.com")), NS_OK);
+        ASSERT_EQ(url->GetSpec(out), NS_OK);
         url->Resolve(NS_LITERAL_CSTRING("foo.html?q=45"), out);
         url->SetScheme(NS_LITERAL_CSTRING("foo"));
         url->GetScheme(out);
         url->SetHost(NS_LITERAL_CSTRING("www.yahoo.com"));
         url->GetHost(out);
         url->SetPath(NS_LITERAL_CSTRING("/some-path/one-the-net/about.html?with-a-query#for-you"));
         url->GetPath(out);
         url->SetQuery(NS_LITERAL_CSTRING("a=b&d=c&what-ever-you-want-to-be-called=45"));
--- a/netwerk/test/urltest.cpp
+++ b/netwerk/test/urltest.cpp
@@ -49,17 +49,22 @@ nsresult writeoutto(const char* i_pURL, 
             nsIURI* url;
             result = CallCreateInstance(kStdURLCID, &url);
             if (NS_FAILED(result))
             {
                 printf("CreateInstance failed\n");
                 return NS_ERROR_FAILURE;
             }
             pURL = url;
-            pURL->SetSpec(nsDependentCString(i_pURL));
+            result = pURL->SetSpec(nsDependentCString(i_pURL));
+            if (NS_FAILED(result))
+            {
+                printf("SetSpec failed\n");
+                return NS_ERROR_FAILURE;
+            }
             break;
         }
         case URL_FACTORY_DEFAULT: {
             nsCOMPtr<nsIIOService> pService = 
                      do_GetService(kIOServiceCID, &result);
             if (NS_FAILED(result)) 
             {
                 printf("Service failed!\n");
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -281,17 +281,20 @@ nsHtml5StreamParser::SetViewSourceTitle(
     }
     bool isData;
     temp->SchemeIs("data", &isData);
     if (isData) {
       // Avoid showing potentially huge data: URLs. The three last bytes are
       // UTF-8 for an ellipsis.
       mViewSourceTitle.AssignLiteral("data:\xE2\x80\xA6");
     } else {
-      temp->GetSpec(mViewSourceTitle);
+      nsresult rv = temp->GetSpec(mViewSourceTitle);
+      if (NS_FAILED(rv)) {
+        mViewSourceTitle.AssignLiteral("\xE2\x80\xA6");
+      }
     }
   }
 }
 
 nsresult
 nsHtml5StreamParser::SetupDecodingAndWriteSniffingBufferAndCurrentSegment(const uint8_t* aFromSegment, // can be null
                                                                           uint32_t aCount,
                                                                           uint32_t* aWriteCount)
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -894,17 +894,18 @@ nsHtml5TreeOpExecutor::ConvertIfNotPrelo
 
   return nullptr;
 }
 
 bool
 nsHtml5TreeOpExecutor::ShouldPreloadURI(nsIURI *aURI)
 {
   nsAutoCString spec;
-  aURI->GetSpec(spec);
+  nsresult rv = aURI->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, false);
   if (mPreloadedURLs.Contains(spec)) {
     return false;
   }
   mPreloadedURLs.PutEntry(spec);
   return true;
 }
 
 void
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -906,25 +906,26 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
                                nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
                                &doesNotReturnData);
       NS_ENSURE_SUCCESS(rv, NS_OK);
       if (!doesNotReturnData) {
         viewSourceUrl.AssignLiteral("view-source:");
       }
 
       nsAutoCString spec;
-      uri->GetSpec(spec);
+      rv = uri->GetSpec(spec);
+      NS_ENSURE_SUCCESS(rv, rv);
 
       viewSourceUrl.Append(spec);
 
       nsAutoString utf16;
       CopyUTF8toUTF16(viewSourceUrl, utf16);
 
       node->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
-      return rv;
+      return NS_OK;
     }
     case eTreeOpAddViewSourceBase: {
       char16_t* buffer = mTwo.unicharPtr;
       int32_t length = mFour.integer;
       nsDependentString baseUrl(buffer, length);
       aBuilder->AddBase(baseUrl);
       return NS_OK;
     }
--- a/parser/html/nsParserUtils.cpp
+++ b/parser/html/nsParserUtils.cpp
@@ -155,38 +155,39 @@ nsParserUtils::ParseFragment(const nsASt
     scripts_enabled = loader->GetEnabled();
   }
   if (scripts_enabled) {
     loader->SetEnabled(false);
   }
 
   // Wrap things in a div or body for parsing, but it won't show up in
   // the fragment.
+  nsresult rv = NS_OK;
   AutoTArray<nsString, 2> tagStack;
   nsAutoCString base, spec;
   if (aIsXML) {
     // XHTML
     if (aBaseURI) {
       base.AppendLiteral(XHTML_DIV_TAG);
       base.AppendLiteral(" xml:base=\"");
-      aBaseURI->GetSpec(spec);
+      rv = aBaseURI->GetSpec(spec);
+      NS_ENSURE_SUCCESS(rv, rv);
       // nsEscapeHTML is good enough, because we only need to get
       // quotes, am