Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 10 Aug 2016 16:15:17 -0700
changeset 334692 65520f4cf4cc57b29aea6d1a0d608d2d30ecb8f5
parent 334629 ec2f0fc180b7a01a8241ef76d0715a0d8b2d7093 (current diff)
parent 334691 aba98553c77f01848867eac0bd1083081396592b (diff)
child 334709 dc8f8117d67b5ae9c7b42b72e3567ef5e754b1fa
push id10033
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:50:26 +0000
treeherdermozilla-aurora@5dddbefdf759 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
Merge inbound to central, a=merge
modules/libpref/init/all.js
taskcluster/ci/legacy/tasks/builds/dbg_linux64-asan.yml
taskcluster/ci/legacy/tasks/builds/opt_linux64-asan.yml
testing/web-platform/meta/html/syntax/serializing-html-fragments/initial-linefeed-pre.html.ini
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1457,22 +1457,23 @@ DocAccessible::DoInitialUpdate()
   // this reorder event is processed by parent document then events targeted to
   // this document may be fired prior to this reorder event. If this is
   // a problem then consider to keep event processing per tab document.
   if (!IsRoot()) {
     RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
     ParentDocument()->FireDelayedEvent(reorderEvent);
   }
 
+  TreeMutation mt(this);
   uint32_t childCount = ChildCount();
   for (uint32_t i = 0; i < childCount; i++) {
     Accessible* child = GetChildAt(i);
-    RefPtr<AccShowEvent> event = new AccShowEvent(child);
-  FireDelayedEvent(event);
+    mt.AfterInsertion(child);
   }
+  mt.Done();
 }
 
 void
 DocAccessible::ProcessLoad()
 {
   mLoadState |= eCompletelyLoaded;
 
 #ifdef A11Y_LOG
--- a/accessible/html/HTMLSelectAccessible.cpp
+++ b/accessible/html/HTMLSelectAccessible.cpp
@@ -11,16 +11,17 @@
 #include "DocAccessible.h"
 #include "nsEventShell.h"
 #include "nsTextEquivUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsCOMPtr.h"
 #include "mozilla/dom/HTMLOptionElement.h"
+#include "mozilla/dom/HTMLSelectElement.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsContainerFrame.h"
 #include "nsIListControlFrame.h"
 
 using namespace mozilla::a11y;
 using namespace mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -493,29 +494,25 @@ HTMLComboboxAccessible::SetCurrentItem(A
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLComboboxAccessible: protected
 
 Accessible*
 HTMLComboboxAccessible::SelectedOption() const
 {
-  nsIFrame* frame = GetFrame();
-  nsIComboboxControlFrame* comboboxFrame = do_QueryFrame(frame);
-  if (!comboboxFrame)
-    return nullptr;
+  HTMLSelectElement* select = HTMLSelectElement::FromContent(mContent);
+  int32_t selectedIndex = select->SelectedIndex();
 
-  nsIListControlFrame* listControlFrame =
-    do_QueryFrame(comboboxFrame->GetDropDown());
-  if (listControlFrame) {
-    nsCOMPtr<nsIContent> activeOptionNode = listControlFrame->GetCurrentOption();
-    if (activeOptionNode) {
+  if (selectedIndex >= 0) {
+    HTMLOptionElement* option = select->Item(selectedIndex);
+    if (option) {
       DocAccessible* document = Document();
       if (document)
-        return document->GetAccessible(activeOptionNode);
+        return document->GetAccessible(option);
     }
   }
 
   return nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/b2g/components/B2GPresentationDevicePrompt.js
+++ b/b2g/components/B2GPresentationDevicePrompt.js
@@ -42,23 +42,23 @@ B2GPresentationDevicePrompt.prototype = 
       SystemAppProxy.removeEventListener("mozContentEvent", contentEvent);
 
       switch (detail.type) {
         case "presentation-select-result":
           debug("device " + detail.deviceId + " is selected by user");
           let device = self._getDeviceById(detail.deviceId);
           if (!device) {
             debug("cancel request because device is not found");
-            aRequest.cancel();
+            aRequest.cancel(Cr.NS_ERROR_DOM_NOT_FOUND_ERR);
           }
           aRequest.select(device);
           break;
         case "presentation-select-deny":
           debug("request canceled by user");
-          aRequest.cancel();
+          aRequest.cancel(Cr.NS_ERROR_DOM_NOT_ALLOWED_ERR);
           break;
       }
     });
 
     let detail = {
       type: "presentation-select-device",
       origin: aRequest.origin,
       requestURL: aRequest.requestURL,
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -199,16 +199,23 @@ static int do_main(int argc, char* argv[
 
   if (appini) {
     nsXREAppData *appData;
     rv = XRE_CreateAppData(appini, &appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
     }
+#if defined(HAS_DLL_BLOCKLIST)
+    // The dll blocklist operates in the exe vs. xullib. Pass a flag to
+    // xullib so automated tests can check the result once the browser
+    // is up and running.
+    appData->flags |=
+      DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
+#endif
     // xreDirectory already has a refcount from NS_NewLocalFile
     appData->xreDirectory = xreDirectory;
     int result = XRE_main(argc, argv, appData, mainFlags);
     XRE_FreeAppData(appData);
     return result;
   }
 
   ScopedAppData appData(&sAppData);
@@ -227,16 +234,21 @@ static int do_main(int argc, char* argv[
   nsCOMPtr<nsIFile> appSubdir;
   greDir->Clone(getter_AddRefs(appSubdir));
   appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
 
   SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
   // xreDirectory already has a refcount from NS_NewLocalFile
   appData.xreDirectory = xreDirectory;
 
+#if defined(HAS_DLL_BLOCKLIST)
+  appData.flags |=
+    DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
+#endif
+
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   sandbox::BrokerServices* brokerServices =
     sandboxing::GetInitializedBrokerServices();
 #if defined(MOZ_CONTENT_SANDBOX)
   if (!brokerServices) {
     Output("Couldn't initialize the broker services.\n");
     return 255;
   }
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -62,17 +62,20 @@ var gEMEHandler = {
     }
 
     let notificationId;
     let buttonCallback;
     let params = [];
     switch (status) {
       case "available":
       case "cdm-created":
-        this.showPopupNotificationForSuccess(browser, keySystem);
+        // Only show the chain icon for proprietary CDMs. Clearkey is not one.
+        if (keySystem != "org.w3.clearkey") {
+          this.showPopupNotificationForSuccess(browser, keySystem);
+        }
         // ... and bail!
         return;
 
       case "api-disabled":
       case "cdm-disabled":
         notificationId = "drmContentDisabled";
         buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem)
         params = [this.getLearnMoreLink(notificationId)];
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1414,24 +1414,31 @@ var BookmarkingUI = {
 
     let onBookmarksMenuHidden = event => {
       if (event.target == event.currentTarget) {
         updatePlacesContextMenu(true);
 
         Services.prefs.removeObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
         PlacesUtils.bookmarks.removeObserver(this._recentlyBookmarkedObserver);
         this._recentlyBookmarkedObserver = null;
-        placesContextMenu.removeEventListener("popupshowing", onPlacesContextMenuShowing);
+        if (placesContextMenu) {
+          placesContextMenu.removeEventListener("popupshowing", onPlacesContextMenuShowing);
+        }
         bookmarksMenu.removeEventListener("popuphidden", onBookmarksMenuHidden);
       }
     };
 
     Services.prefs.addObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
     PlacesUtils.bookmarks.addObserver(this._recentlyBookmarkedObserver, true);
-    placesContextMenu.addEventListener("popupshowing", onPlacesContextMenuShowing);
+
+    // The context menu doesn't exist in non-browser windows on Mac
+    if (placesContextMenu) {
+      placesContextMenu.addEventListener("popupshowing", onPlacesContextMenuShowing);
+    }
+
     bookmarksMenu.addEventListener("popuphidden", onBookmarksMenuHidden);
   },
 
   _populateRecentBookmarks(aHeaderItem, aExtraCSSClass = "") {
     while (aHeaderItem.nextSibling &&
            aHeaderItem.nextSibling.localName == "menuitem") {
       aHeaderItem.nextSibling.remove();
     }
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -730,17 +730,17 @@ nsContextMenu.prototype = {
       else if (this.target instanceof HTMLCanvasElement) {
         this.onCanvas = true;
       }
       else if (this.target instanceof HTMLVideoElement) {
         let mediaURL = this.target.currentSrc || this.target.src;
         if (this.isMediaURLReusable(mediaURL)) {
           this.mediaURL = mediaURL;
         }
-        if (this.target.isEncrypted) {
+        if (this._isProprietaryDRM()) {
           this.onDRMMedia = true;
         }
         // Firefox always creates a HTMLVideoElement when loading an ogg file
         // directly. If the media is actually audio, be smarter and provide a
         // context menu with audio operations.
         if (this.target.readyState >= this.target.HAVE_METADATA &&
             (this.target.videoWidth == 0 || this.target.videoHeight == 0)) {
           this.onAudio = true;
@@ -749,17 +749,17 @@ nsContextMenu.prototype = {
         }
       }
       else if (this.target instanceof HTMLAudioElement) {
         this.onAudio = true;
         let mediaURL = this.target.currentSrc || this.target.src;
         if (this.isMediaURLReusable(mediaURL)) {
           this.mediaURL = mediaURL;
         }
-        if (this.target.isEncrypted) {
+        if (this._isProprietaryDRM()) {
           this.onDRMMedia = true;
         }
       }
       else if (editFlags & (SpellCheckHelper.INPUT | SpellCheckHelper.TEXTAREA)) {
         this.onTextInput = (editFlags & SpellCheckHelper.TEXTINPUT) !== 0;
         this.onNumeric = (editFlags & SpellCheckHelper.NUMERIC) !== 0;
         this.onEditableArea = (editFlags & SpellCheckHelper.EDITABLE) !== 0;
         this.onPassword = (editFlags & SpellCheckHelper.PASSWORD) !== 0;
@@ -963,16 +963,21 @@ nsContextMenu.prototype = {
     }
     if (!editable) {
       return false;
     }
     // Otherwise make sure that nothing in the parent chain disables spellchecking
     return aNode.spellcheck;
   },
 
+  _isProprietaryDRM: function() {
+    return this.target.isEncrypted && this.target.mediaKeys &&
+           this.target.mediaKeys.keySystem != "org.w3.clearkey";
+  },
+
   _openLinkInParameters : function (extra) {
     let params = { charset: gContextMenuContentData.charSet,
                    referrerURI: gContextMenuContentData.documentURIObject,
                    referrerPolicy: gContextMenuContentData.referrerPolicy,
                    noReferrer: this.linkHasNoReferrer };
     for (let p in extra) {
       params[p] = extra[p];
     }
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSingleWordNotification.js
@@ -61,23 +61,29 @@ function* runURLBarSearchTest(valueToOpe
 
 add_task(function* test_navigate_full_domain() {
   let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
   yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   yield* runURLBarSearchTest("www.mozilla.org", false, false);
   gBrowser.removeTab(tab);
 });
 
-add_task(function* test_navigate_numbers() {
+add_task(function* test_navigate_valid_numbers() {
   let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
   yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-  yield* runURLBarSearchTest("1234", true, false);
+  yield* runURLBarSearchTest("1234", true, true);
   gBrowser.removeTab(tab);
 });
 
+add_task(function* test_navigate_invalid_numbers() {
+  let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+  yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  yield* runURLBarSearchTest("123456789012345", true, false);
+  gBrowser.removeTab(tab);
+});
 function get_test_function_for_localhost_with_hostname(hostName, isPrivate) {
   return function* test_navigate_single_host() {
     const pref = "browser.fixup.domainwhitelist.localhost";
     let win;
     if (isPrivate) {
       win = yield promiseOpenAndLoadWindow({private: true}, true);
       let deferredOpenFocus = Promise.defer();
       waitForFocus(deferredOpenFocus.resolve, win);
--- a/browser/components/sessionstore/SessionStorage.jsm
+++ b/browser/components/sessionstore/SessionStorage.jsm
@@ -117,17 +117,17 @@ var SessionStorageInternal = {
       }
 
       let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
       let window = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
 
       // There is no need to pass documentURI, it's only used to fill documentURI property of
       // domstorage event, which in this case has no consumer. Prevention of events in case
       // of missing documentURI will be solved in a followup bug to bug 600307.
-      let storage = storageManager.createStorage(window, principal, "", aDocShell.usePrivateBrowsing);
+      let storage = storageManager.createStorage(window, principal, "");
 
       for (let key of Object.keys(data)) {
         try {
           storage.setItem(key, data[key]);
         } catch (e) {
           // throws e.g. for URIs that can't have sessionStorage
           console.error(e);
         }
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1719,17 +1719,17 @@ toolbarbutton.chevron > .toolbarbutton-i
 .ctrlTab-favicon[src] {
   background-color: white;
   width: 20px;
   height: 20px;
   padding: 2px;
 }
 
 .ctrlTab-preview-inner > .tabPreview-canvas {
-  box-shadow: 1px 1px 2px rgb(12%,12%,12%);
+  box-shadow: 1px 1px 2px hsl(0,0%,12%);
 }
 
 .ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner > .tabPreview-canvas {
   margin-bottom: 2px;
 }
 
 .ctrlTab-preview-inner {
   padding-bottom: 10px;
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3126,17 +3126,17 @@ menulist.translate-infobar-element > .me
 .ctrlTab-favicon[src] {
   background-color: white;
   width: 20px;
   height: 20px;
   padding: 2px;
 }
 
 .ctrlTab-preview-inner > .tabPreview-canvas {
-  box-shadow: 1px 1px 2px rgb(12%,12%,12%);
+  box-shadow: 1px 1px 2px hsl(0,0%,12%);
 }
 
 .ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner > .tabPreview-canvas {
   margin-bottom: 2px;
 }
 
 .ctrlTab-preview-inner {
   padding-bottom: 10px;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2373,17 +2373,17 @@ notification[value="translation"] {
 .ctrlTab-favicon[src] {
   background-color: white;
   width: 20px;
   height: 20px;
   padding: 2px;
 }
 
 .ctrlTab-preview-inner > .tabPreview-canvas {
-  box-shadow: 1px 1px 2px rgb(12%,12%,12%);
+  box-shadow: 1px 1px 2px hsl(0,0%,12%);
 }
 
 .ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner > .tabPreview-canvas {
   margin-bottom: 2px;
 }
 
 .ctrlTab-preview-inner {
   padding-bottom: 10px;
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -561,16 +561,23 @@ BasePrincipal::GetAddonId(nsAString& aAd
 NS_IMETHODIMP
 BasePrincipal::GetUserContextId(uint32_t* aUserContextId)
 {
   *aUserContextId = UserContextId();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId)
+{
+  *aPrivateBrowsingId = PrivateBrowsingId();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
 {
   *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -259,29 +259,31 @@ public:
   NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
   NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
   NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
   NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) final;
   NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
   NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
   NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
+  NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
 
   virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
 
   virtual bool IsCodebasePrincipal() const { return false; };
 
   static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
   static already_AddRefed<BasePrincipal>
   CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs);
   static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin);
 
   const PrincipalOriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
   uint32_t AppId() const { return mOriginAttributes.mAppId; }
   uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
+  uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
   bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
 
   enum PrincipalKind {
     eNullPrincipal,
     eCodebasePrincipal,
     eExpandedPrincipal,
     eSystemPrincipal
   };
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -303,16 +303,23 @@ interface nsIPrincipal : nsISerializable
     /**
      * Gets the id of the user context this principal is inside.  If this
      * principal is inside the default userContext, this returns
      * nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID.
      */
     [infallible] readonly attribute unsigned long userContextId;
 
     /**
+     * Gets the id of the private browsing state of the context containing
+     * this principal. If the principal has a private browsing value of 0, it
+     * is not in private browsing.
+     */
+    [infallible] readonly attribute unsigned long privateBrowsingId;
+
+    /**
      * Returns true iff the principal is inside an isolated mozbrowser element.
      * <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
      * mozbrowser elements.  <iframe mozbrowser noisolation> does not count as
      * isolated since isolation is disabled.  Isolation can only be disabled if
      * the containing document is chrome.
      */
     [infallible] readonly attribute boolean isInIsolatedMozBrowserElement;
 
--- a/config/nsinstall.py
+++ b/config/nsinstall.py
@@ -36,17 +36,17 @@ def _nsinstall_internal(argv):
                help="Link prefix (ignored)")
   p.add_option('-X', action="append", metavar="file",
                help="Ignore a file when installing a directory recursively.")
 
   # The remaining arguments are not used in our tree, thus they're not
   # implented.
   def BadArg(option, opt, value, parser):
     parser.error('option not supported: {0}'.format(opt))
-    
+
   p.add_option('-C', action="callback", metavar="CWD",
                callback=BadArg,
                help="NOT SUPPORTED")
   p.add_option('-o', action="callback", callback=BadArg,
                help="Set owner (NOT SUPPORTED)", metavar="owner")
   p.add_option('-g', action="callback", callback=BadArg,
                help="Set group (NOT SUPPORTED)", metavar="group")
 
--- a/config/tests/unit-nsinstall.py
+++ b/config/tests/unit-nsinstall.py
@@ -114,17 +114,17 @@ class TestNsinstall(unittest.TestCase):
         self.assertEqual(os.stat(testfile).st_mtime,
                          os.stat(destfile).st_mtime)
 
     if sys.platform != "win32":
         # can't run this test on windows, don't have real file modes there
         def test_nsinstall_m(self):
             "Test that nsinstall -m works (set mode)"
             testfile = self.touch("testfile")
-            mode = 0600
+            mode = 0o600
             os.chmod(testfile, mode)
             testdir = self.mkdirs("testdir")
             self.assertEqual(nsinstall(["-m", "{0:04o}"
                                         .format(mode), testfile, testdir]), 0)
             destfile = os.path.join(testdir, "testfile")
             self.assert_(os.path.isfile(destfile))
             self.assertEqual(os.stat(testfile).st_mode,
                              os.stat(destfile).st_mode)
--- a/configure.py
+++ b/configure.py
@@ -76,17 +76,17 @@ def config_status(config):
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     from mozbuild.config_status import config_status
     config_status(**args)
 ''')
 
     # Other things than us are going to run this file, so we need to give it
     # executable permissions.
-    os.chmod('config.status', 0755)
+    os.chmod('config.status', 0o755)
     if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
         os.environ['WRITE_MOZINFO'] = '1'
         # Until we have access to the virtualenv from this script, execute
         # config.status externally, with the virtualenv python.
         return subprocess.call([config['PYTHON'], 'config.status'])
     return 0
 
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2979,21 +2979,21 @@ nsDocShell::GetSessionStorageForPrincipa
     return NS_ERROR_UNEXPECTED;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow();
 
   AssertOriginAttributesMatchPrivateBrowsing();
   if (aCreate) {
     return manager->CreateStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
-                                  aDocumentURI, UsePrivateBrowsing(), aStorage);
+                                  aDocumentURI, aStorage);
   }
 
   return manager->GetStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
-                             UsePrivateBrowsing(), aStorage);
+                             aStorage);
 }
 
 nsresult
 nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal, nsIDOMStorage* aStorage)
 {
   RefPtr<DOMStorage> storage = static_cast<DOMStorage*>(aStorage);
   if (!storage) {
     return NS_ERROR_UNEXPECTED;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1,16 +1,17 @@
 /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 #include "nsIDocShellTreeItem.idl"
+#include "nsIRequest.idl"
 
 %{ C++
 #include "js/TypeDecls.h"
 class nsPresContext;
 class nsIPresShell;
 %}
 
 /**
@@ -41,18 +42,16 @@ interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 interface nsIScrollObserver;
 interface nsITabParent;
 interface nsITabChild;
 interface nsICommandManager;
 interface nsICommandParams;
 native TabChildRef(already_AddRefed<nsITabChild>);
 
-typedef unsigned long nsLoadFlags;
-
 [scriptable, builtinclass, uuid(049234fe-da10-478b-bc5d-bc6f9a1ba63d)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
--- a/docshell/test/unit/test_nsDefaultURIFixup_info.js
+++ b/docshell/test/unit/test_nsDefaultURIFixup_info.js
@@ -125,55 +125,55 @@ var testcases = [ {
     fixedURI: "http://192.168.10.110:1234/123",
     protocolChange: true,
   }, {
     input: "192.168.10.110:1234/123foo",
     fixedURI: "http://192.168.10.110:1234/123foo",
     protocolChange: true,
   }, {
     input: "1.2.3",
-    fixedURI: "http://1.2.3/",
+    fixedURI: "http://1.2.0.3/",
     protocolChange: true,
   }, {
     input: "1.2.3/",
-    fixedURI: "http://1.2.3/",
+    fixedURI: "http://1.2.0.3/",
     protocolChange: true,
   }, {
     input: "1.2.3/foo",
-    fixedURI: "http://1.2.3/foo",
+    fixedURI: "http://1.2.0.3/foo",
     protocolChange: true,
   }, {
     input: "1.2.3/123",
-    fixedURI: "http://1.2.3/123",
+    fixedURI: "http://1.2.0.3/123",
     protocolChange: true,
   }, {
     input: "1.2.3:8000",
-    fixedURI: "http://1.2.3:8000/",
+    fixedURI: "http://1.2.0.3:8000/",
     protocolChange: true,
   }, {
     input: "1.2.3:8000/",
-    fixedURI: "http://1.2.3:8000/",
+    fixedURI: "http://1.2.0.3:8000/",
     protocolChange: true,
   }, {
     input: "1.2.3:8000/foo",
-    fixedURI: "http://1.2.3:8000/foo",
+    fixedURI: "http://1.2.0.3:8000/foo",
     protocolChange: true,
   }, {
     input: "1.2.3:8000/123",
-    fixedURI: "http://1.2.3:8000/123",
+    fixedURI: "http://1.2.0.3:8000/123",
     protocolChange: true,
   }, {
     input: "http://1.2.3",
-    fixedURI: "http://1.2.3/",
+    fixedURI: "http://1.2.0.3/",
   }, {
     input: "http://1.2.3/",
-    fixedURI: "http://1.2.3/",
+    fixedURI: "http://1.2.0.3/",
   }, {
     input: "http://1.2.3/foo",
-    fixedURI: "http://1.2.3/foo",
+    fixedURI: "http://1.2.0.3/foo",
   }, {
     input: "[::1]",
     fixedURI: "http://[::1]/",
     alternateURI: "http://[::1]/",
     protocolChange: true,
   }, {
     input: "[::1]/",
     fixedURI: "http://[::1]/",
@@ -217,18 +217,17 @@ var testcases = [ {
     keywordLookup: true,
     protocolChange: true
   }, {
     input: "[::1]]",
     keywordLookup: true,
     protocolChange: true
   }, {
     input: "1234",
-    fixedURI: "http://1234/",
-    alternateURI: "http://www.1234.com/",
+    fixedURI: "http://0.0.4.210/",
     keywordLookup: true,
     protocolChange: true,
     affectedByDNSForSingleHosts: true,
   }, {
     input: "host/foo.txt",
     fixedURI: "http://host/foo.txt",
     alternateURI: "http://www.host.com/foo.txt",
     protocolChange: true,
@@ -357,32 +356,30 @@ var testcases = [ {
   }, {
     input: "-22.14,23.51-",
     fixedURI: "http://-22.14,23.51-/",
     keywordLookup: true,
     protocolChange: true,
     affectedByDNSForSingleHosts: true,
   }, {
     input: "32.7",
-    fixedURI: "http://32.7/",
-    alternateURI: "http://www.32.7/",
+    fixedURI: "http://32.0.0.7/",
     keywordLookup: true,
     protocolChange: true,
     affectedByDNSForSingleHosts: true,
   }, {
     input: "5+2",
     fixedURI: "http://5+2/",
     alternateURI: "http://www.5+2.com/",
     keywordLookup: true,
     protocolChange: true,
     affectedByDNSForSingleHosts: true,
   }, {
     input: "5/2",
-    fixedURI: "http://5/2",
-    alternateURI: "http://www.5.com/2",
+    fixedURI: "http://0.0.0.5/2",
     keywordLookup: true,
     protocolChange: true,
     affectedByDNSForSingleHosts: true,
   }, {
     input: "moz ?.::%27",
     keywordLookup: true,
     protocolChange: true
   }, {
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1691,17 +1691,17 @@ Navigator::GetFeature(const nsAString& a
 #endif
 
   // Mirror the dom.apps.developer_mode pref to let apps get it read-only.
   if (aName.EqualsLiteral("dom.apps.developer_mode")) {
     p->MaybeResolve(Preferences::GetBool("dom.apps.developer_mode", false));
     return p.forget();
   }
 
-  p->MaybeResolve(JS::UndefinedHandleValue);
+  p->MaybeResolveWithUndefined();
   return p.forget();
 }
 
 already_AddRefed<Promise>
 Navigator::HasFeature(const nsAString& aName, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
   RefPtr<Promise> p = Promise::Create(go, aRv);
@@ -1790,22 +1790,22 @@ Navigator::HasFeature(const nsAString& a
     }
 #endif
 
     if (featureName.EqualsLiteral("XMLHttpRequest.mozSystem")) {
       p->MaybeResolve(true);
       return p.forget();
     }
 
-    p->MaybeResolve(JS::UndefinedHandleValue);
+    p->MaybeResolveWithUndefined();
     return p.forget();
   }
 
   // resolve with <undefined> because the feature name is not supported
-  p->MaybeResolve(JS::UndefinedHandleValue);
+  p->MaybeResolveWithUndefined();
 
   return p.forget();
 }
 
 PowerManager*
 Navigator::GetMozPower(ErrorResult& aRv)
 {
   if (!mPowerManager) {
--- a/dom/base/ScreenOrientation.cpp
+++ b/dom/base/ScreenOrientation.cpp
@@ -167,24 +167,24 @@ ScreenOrientation::LockOrientationTask::
     // to lock orientation. There has since been another request to
     // lock orientation, thus we don't need to do anything. Old promise
     // should be been rejected.
     return NS_OK;
   }
 
   if (mDocument->Hidden()) {
     // Active orientation lock is not the document's orientation lock.
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
     mDocument->SetOrientationPendingPromise(nullptr);
     return NS_OK;
   }
 
   if (mOrientationLock == eScreenOrientation_None) {
     mScreenOrientation->UnlockDeviceOrientation();
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
     mDocument->SetOrientationPendingPromise(nullptr);
     return NS_OK;
   }
 
   ErrorResult rv;
   bool result = mScreenOrientation->LockDeviceOrientation(mOrientationLock,
                                                           mIsFullScreen, rv);
   if (NS_WARN_IF(rv.Failed())) {
@@ -196,17 +196,17 @@ ScreenOrientation::LockOrientationTask::
     mDocument->SetOrientationPendingPromise(nullptr);
     return NS_OK;
   }
 
   if (OrientationLockContains(mDocument->CurrentOrientationType()) ||
       (mOrientationLock == eScreenOrientation_Default &&
        mDocument->CurrentOrientationAngle() == 0)) {
     // Orientation lock will not cause an orientation change.
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
     mDocument->SetOrientationPendingPromise(nullptr);
   }
 
   return NS_OK;
 }
 
 already_AddRefed<Promise>
 ScreenOrientation::Lock(OrientationLockType aOrientation, ErrorResult& aRv)
@@ -545,17 +545,17 @@ ScreenOrientation::Notify(const hal::Scr
     return;
   }
 
   if (mType != doc->CurrentOrientationType()) {
     doc->SetCurrentOrientation(mType, mAngle);
 
     Promise* pendingPromise = doc->GetOrientationPendingPromise();
     if (pendingPromise) {
-      pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
+      pendingPromise->MaybeResolveWithUndefined();
       doc->SetOrientationPendingPromise(nullptr);
     }
 
     nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(this,
       &ScreenOrientation::DispatchChangeEvent);
     rv = NS_DispatchToMainThread(runnable);
     NS_WARN_IF(NS_FAILED(rv));
   }
@@ -631,17 +631,17 @@ ScreenOrientation::VisibleEventListener:
     return rv.StealNSResult();
   }
 
   if (doc->CurrentOrientationType() != orientation->DeviceType()) {
     doc->SetCurrentOrientation(orientation->DeviceType(), orientation->DeviceAngle());
 
     Promise* pendingPromise = doc->GetOrientationPendingPromise();
     if (pendingPromise) {
-      pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
+      pendingPromise->MaybeResolveWithUndefined();
       doc->SetOrientationPendingPromise(nullptr);
     }
 
     nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(orientation,
       &ScreenOrientation::DispatchChangeEvent);
     rv = NS_DispatchToMainThread(runnable);
     if (NS_WARN_IF(rv.Failed())) {
       return rv.StealNSResult();
--- a/dom/base/domerr.msg
+++ b/dom/base/domerr.msg
@@ -26,16 +26,17 @@ DOM4_MSG_DEF(SecurityError, "The operati
 DOM4_MSG_DEF(NetworkError, "A network error occurred.", NS_ERROR_DOM_NETWORK_ERR)
 DOM4_MSG_DEF(AbortError, "The operation was aborted. ", NS_ERROR_DOM_ABORT_ERR)
 DOM4_MSG_DEF(URLMismatchError, "The given URL does not match another URL.", NS_ERROR_DOM_URL_MISMATCH_ERR)
 DOM4_MSG_DEF(QuotaExceededError, "The quota has been exceeded.", NS_ERROR_DOM_QUOTA_EXCEEDED_ERR)
 DOM4_MSG_DEF(TimeoutError, "The operation timed out.", NS_ERROR_DOM_TIMEOUT_ERR)
 DOM4_MSG_DEF(InvalidNodeTypeError, "The supplied node is incorrect or has an incorrect ancestor for this operation.", NS_ERROR_DOM_INVALID_NODE_TYPE_ERR)
 DOM4_MSG_DEF(DataCloneError, "The object could not be cloned.", NS_ERROR_DOM_DATA_CLONE_ERR)
 DOM4_MSG_DEF(InvalidPointerId, "Invalid pointer id.", NS_ERROR_DOM_INVALID_POINTER_ERR)
+DOM4_MSG_DEF(NotAllowedError, "The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_NOT_ALLOWED_ERR)
 
 /* XXX Should be JavaScript native TypeError */
 DOM4_MSG_DEF(TypeError, "The method parameter is missing or invalid.", NS_ERROR_TYPE_ERR)
 DOM4_MSG_DEF(RangeError, "The method parameter is out of valid range.", NS_ERROR_RANGE_ERR)
 
 /* StringEncoding API errors from http://wiki.whatwg.org/wiki/StringEncoding */
 DOM4_MSG_DEF(EncodingError, "The given encoding is not supported.", NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR)
 
@@ -156,8 +157,13 @@ DOM4_MSG_DEF(InvalidStateError, "Invalid
 DOM4_MSG_DEF(NotAllowedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR)
 DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR)
 DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE)
 DOM4_MSG_DEF(InvalidAccessError, "Invalid raw ECDSA P-256 public key.", NS_ERROR_DOM_PUSH_INVALID_KEY_ERR)
 DOM4_MSG_DEF(InvalidStateError, "A subscription with a different application server key already exists.", NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR)
 
 DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception")
 DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown")
+
+/* Media errors */
+DOM4_MSG_DEF(AbortError,        "The fetching process for the media resource was aborted by the user agent at the user's request.", NS_ERROR_DOM_MEDIA_ABORT_ERR)
+DOM4_MSG_DEF(NotAllowedError,   "The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR)
+DOM4_MSG_DEF(NotSupportedError, "The media resource indicated by the src attribute or assigned media provider object was not suitable.", NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR)
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -274,16 +274,17 @@ bool nsContentUtils::sIsFrameTimingPrefE
 bool nsContentUtils::sIsPerformanceTimingEnabled = false;
 bool nsContentUtils::sIsResourceTimingEnabled = false;
 bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
 bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
 bool nsContentUtils::sEncodeDecodeURLHash = false;
 bool nsContentUtils::sGettersDecodeURLHash = false;
 bool nsContentUtils::sPrivacyResistFingerprinting = false;
 bool nsContentUtils::sSendPerformanceTimingNotifications = false;
+bool nsContentUtils::sAppendLFInSerialization = false;
 
 uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
 
 uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
 uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
 
 nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
 nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
@@ -588,16 +589,18 @@ nsContentUtils::Init()
   Preferences::AddUintVarCache(&sCookiesLifetimePolicy,
                                "network.cookie.lifetimePolicy",
                                nsICookieService::ACCEPT_NORMALLY);
 
   Preferences::AddUintVarCache(&sCookiesBehavior,
                                "network.cookie.cookieBehavior",
                                nsICookieService::BEHAVIOR_ACCEPT);
 
+  Preferences::AddBoolVarCache(&sAppendLFInSerialization,
+                               "dom.html_fragment_serialisation.appendLF");
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
   Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
                                "browser.dom.window.dump.enabled");
 #endif
 
   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
                                "privacy.donottrackheader.enabled", false);
 
@@ -8974,35 +8977,35 @@ StartElement(Element* aContent, StringBu
     aBuilder.Append(attName);
     aBuilder.Append("=\"");
     AppendEncodedAttributeValue(attValue, aBuilder);
     aBuilder.Append("\"");
   }
 
   aBuilder.Append(">");
 
-  /*
+
   // Per HTML spec we should append one \n if the first child of
   // pre/textarea/listing is a textnode and starts with a \n.
   // But because browsers haven't traditionally had that behavior,
   // we're not changing our behavior either - yet.
-  if (aContent->IsHTMLElement()) {
+  if (nsContentUtils::AppendLFInSerialization() && aContent->IsHTMLElement()) {
     if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
         localName == nsGkAtoms::listing) {
       nsIContent* fc = aContent->GetFirstChild();
       if (fc &&
           (fc->NodeType() == nsIDOMNode::TEXT_NODE ||
            fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
         const nsTextFragment* text = fc->GetText();
         if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
           aBuilder.Append("\n");
         }
       }
     }
-  }*/
+  }
 }
 
 static inline bool
 ShouldEscape(nsIContent* aParent)
 {
   if (!aParent || !aParent->IsHTMLElement()) {
     return true;
   }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1949,16 +1949,20 @@ public:
    *
    * @param aDoc the document for which to return a layer manager.
    * @param aAllowRetaining an outparam that states whether the returned
    * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
   PersistentLayerManagerForDocument(nsIDocument *aDoc);
 
+  /* static */
+  static bool AppendLFInSerialization()
+    { return sAppendLFInSerialization; }
+
   /**
    * Determine whether a content node is focused or not,
    *
    * @param aContent the content node to check
    * @return true if the content node is focused, false otherwise.
    */
   static bool IsFocusedContent(const nsIContent *aContent);
 
@@ -2766,16 +2770,17 @@ private:
   static bool sIsResourceTimingEnabled;
   static bool sIsUserTimingLoggingEnabled;
   static bool sIsFrameTimingPrefEnabled;
   static bool sIsExperimentalAutocompleteEnabled;
   static bool sEncodeDecodeURLHash;
   static bool sGettersDecodeURLHash;
   static bool sPrivacyResistFingerprinting;
   static bool sSendPerformanceTimingNotifications;
+  static bool sAppendLFInSerialization;
   static uint32_t sCookiesLifetimePolicy;
   static uint32_t sCookiesBehavior;
 
   static nsHtml5StringParser* sHTMLFragmentParser;
   static nsIParser* sXMLFragmentParser;
   static nsIFragmentContentSink* sXMLFragmentSink;
 
   /**
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10536,17 +10536,16 @@ nsGlobalWindow::GetSessionStorage(ErrorR
     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(docShell, &rv);
     if (NS_FAILED(rv)) {
       aError.Throw(rv);
       return nullptr;
     }
 
     nsCOMPtr<nsIDOMStorage> storage;
     aError = storageManager->CreateStorage(AsInner(), principal, documentURI,
-                                           IsPrivateBrowsing(),
                                            getter_AddRefs(storage));
     if (aError.Failed()) {
       return nullptr;
     }
 
     mSessionStorage = static_cast<DOMStorage*>(storage.get());
     MOZ_ASSERT(mSessionStorage);
 
@@ -10597,17 +10596,16 @@ nsGlobalWindow::GetLocalStorage(ErrorRes
 
     nsString documentURI;
     if (mDoc) {
       mDoc->GetDocumentURI(documentURI);
     }
 
     nsCOMPtr<nsIDOMStorage> storage;
     aError = storageManager->CreateStorage(AsInner(), principal, documentURI,
-                                           IsPrivateBrowsing(),
                                            getter_AddRefs(storage));
     if (aError.Failed()) {
       return nullptr;
     }
 
     mLocalStorage = static_cast<DOMStorage*>(storage.get());
     MOZ_ASSERT(mLocalStorage);
   }
@@ -11450,17 +11448,24 @@ nsGlobalWindow::Observe(nsISupports* aSu
     bool fireMozStorageChanged = false;
     nsAutoString eventType;
     eventType.AssignLiteral("storage");
     principal = GetPrincipal();
     if (!principal) {
       return NS_OK;
     }
 
-    if (changingStorage->IsPrivate() != IsPrivateBrowsing()) {
+    uint32_t privateBrowsingId = 0;
+    nsIPrincipal *storagePrincipal = changingStorage->GetPrincipal();
+    rv = storagePrincipal->GetPrivateBrowsingId(&privateBrowsingId);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    if ((privateBrowsingId > 0) != IsPrivateBrowsing()) {
       return NS_OK;
     }
 
     switch (changingStorage->GetType())
     {
     case DOMStorage::SessionStorage:
     {
       bool check = false;
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -149,32 +149,44 @@ nsStyledElement::ReparseStyleAttribute(b
     // want to fire off mutation events or document notifications anyway
     nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   
   return NS_OK;
 }
 
+nsICSSDeclaration*
+nsStyledElement::GetExistingStyle()
+{
+  Element::nsDOMSlots* slots = GetExistingDOMSlots();
+  if (!slots) {
+    return nullptr;
+  }
+
+  return slots->mStyle;
+}
+
 void
 nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
                                      nsAttrValue& aResult,
                                      bool aForceInDataDoc)
 {
   nsIDocument* doc = OwnerDoc();
   bool isNativeAnon = IsInNativeAnonymousSubtree();
 
   if (!isNativeAnon &&
       !nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(),
                                          doc->GetDocumentURI(), 0, aValue,
                                          nullptr))
     return;
 
   if (aForceInDataDoc ||
       !doc->IsLoadedAsData() ||
+      GetExistingStyle() ||
       doc->IsStaticDocument()) {
     bool isCSS = true; // assume CSS until proven otherwise
 
     if (!isNativeAnon) {  // native anonymous content always assumes CSS
       nsAutoString styleType;
       doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
       if (!styleType.IsEmpty()) {
         static const char textCssStr[] = "text/css";
--- a/dom/base/nsStyledElement.h
+++ b/dom/base/nsStyledElement.h
@@ -52,16 +52,18 @@ public:
                                              bool aNotify) override;
 
   nsICSSDeclaration* Style();
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_STYLED_ELEMENT_IID)
 
 protected:
 
+  nsICSSDeclaration* GetExistingStyle();
+
   /**
    * Parse a style attr value into a CSS rulestruct (or, if there is no
    * document, leave it as a string) and return as nsAttrValue.
    *
    * @param aValue the value to parse
    * @param aResult the resulting HTMLValue [OUT]
    */
   void ParseStyleAttribute(const nsAString& aValue,
--- a/dom/base/test/test_bug744830.html
+++ b/dom/base/test/test_bug744830.html
@@ -8,43 +8,43 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
 <div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
 <pre id="test">
 <script type="application/javascript">
   var t = document.getElementById('testnodes');
-  is(t.innerHTML, 
+  is(t.innerHTML,
      "<span>hi</span> there <!-- mon ami -->",
      "comment nodes should be included");
 
   var PI = document.createProcessingInstruction('foo', 'bar="1.0"');
   t.appendChild(PI);
   is(t.innerHTML, '<span>hi</span> there <!-- mon ami --><?foo bar="1.0">',
     "pi nodes should be included");
 
   t.innerHTML = null;
   t.appendChild(document.createElement("textarea"));
   t.firstChild.appendChild(document.createTextNode("\nhello"));
   // This is the old behavior. Spec requires something else.
-  is(t.innerHTML, "<textarea>\nhello</textarea>",
+  is(t.innerHTML, "<textarea>\n\nhello</textarea>",
      "No extra newlines should be inserted to the textarea!");
 
   t.innerHTML = null;
   t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"));
   t.firstChild.textContent = "<foo>";
   is(t.innerHTML, "<svg>&lt;foo&gt;</svg>");
 
   t.innerHTML = null;
   t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math:math"));
   t.firstChild.textContent = "<foo>";
   is(t.innerHTML, "<math>&lt;foo&gt;</math>");
 
-  // Prefix is serialized if element isn't HTML/SVG/MathML  
+  // Prefix is serialized if element isn't HTML/SVG/MathML
   t.innerHTML = null;
   t.appendChild(document.createElementNS("http://www.example.org", "ex:example"));
   t.firstChild.textContent = "<foo>";
   is(t.innerHTML, "<ex:example>&lt;foo&gt;</ex:example>");
 
   t.innerHTML = null;
   t.appendChild(document.createElementNS("http://www.example.org", "example"));
   t.firstChild.textContent = "<foo>";
@@ -56,17 +56,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   t.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo");
   is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo">&lt;foo&gt;</example>');
 
   t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://foo");
   is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo">&lt;foo&gt;</example>');
 
   t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:bar", "http://bar");
   is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar">&lt;foo&gt;</example>');
-  
+
   t.firstChild.setAttributeNS("http://www.helloworldns.org", "hello:world", "!");
   is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar" hello:world="!">&lt;foo&gt;</example>');
 
   t.firstChild.setAttribute("foo", '-"&\xA0-');
   is(t.innerHTML, '<example xml:lang="us-en" xlink:href="foo" xmlns="http://foo" xmlns:bar="http://bar" hello:world="!" foo="-&quot;&amp;&nbsp;-">&lt;foo&gt;</example>');
 
   t.innerHTML = null;
   t.appendChild(document.createElement("div"));
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -228,18 +228,17 @@ DOMInterfaces = {
     'headerFile': 'DOMCameraCapabilities.h'
 },
 
 'CanvasRenderingContext2D': {
     'implicitJSContext': [
         'createImageData', 'getImageData'
     ],
     'binaryNames': {
-        'mozImageSmoothingEnabled': 'imageSmoothingEnabled',
-        'mozFillRule': 'fillRule'
+        'mozImageSmoothingEnabled': 'imageSmoothingEnabled'
     }
 },
 
 'CaretPosition' : {
     'nativeType': 'nsDOMCaretPosition',
 },
 
 'CharacterData': {
--- a/dom/bluetooth/common/webapi/BluetoothGattCharacteristic.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothGattCharacteristic.cpp
@@ -401,17 +401,17 @@ BluetoothGattCharacteristic::WriteValue(
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   aValue.ComputeLengthAndData();
 
   if (mAttRole == ATT_SERVER_ROLE) {
     mValue.Clear();
     mValue.AppendElements(aValue.Data(), aValue.Length());
 
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   BT_ENSURE_TRUE_REJECT(mProperties &
                           (GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE |
                            GATT_CHAR_PROP_BIT_WRITE |
                            GATT_CHAR_PROP_BIT_SIGNED_WRITE),
                         promise,
--- a/dom/bluetooth/common/webapi/BluetoothGattDescriptor.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothGattDescriptor.cpp
@@ -276,17 +276,17 @@ BluetoothGattDescriptor::WriteValue(
                         NS_ERROR_DOM_OPERATION_ERR);
 
   aValue.ComputeLengthAndData();
 
   if (mAttRole == ATT_SERVER_ROLE) {
     mValue.Clear();
     mValue.AppendElements(aValue.Data(), aValue.Length());
 
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   nsTArray<uint8_t> value;
   value.AppendElements(aValue.Data(), aValue.Length());
 
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
--- a/dom/bluetooth/common/webapi/BluetoothGattServer.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothGattServer.cpp
@@ -545,17 +545,17 @@ BluetoothGattServer::StopAdvertising(Err
   }
 
   RefPtr<Promise> promise = Promise::Create(global, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);
 
   if (mAdvertisingAppUuid.IsCleared()) {
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
 
   bs->StopAdvertisingInternal(mAdvertisingAppUuid,
                               new StopAdvertisingTask(this, promise));
@@ -835,17 +835,17 @@ protected:
   virtual ~AddServiceTaskQueue()
   { }
 
 private:
   void OnSuccessFired() override
   {
     mServer->mPendingService = nullptr;
     mServer->mServices.AppendElement(mService);
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
   }
 
   void OnErrorFired() override
   {
     BluetoothService* bs = BluetoothService::Get();
     BT_ENSURE_TRUE_REJECT_VOID(bs, mPromise, NS_ERROR_NOT_AVAILABLE);
 
     BluetoothUuid appUuid;
--- a/dom/bluetooth/common/webapi/BluetoothGattService.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothGattService.cpp
@@ -248,12 +248,12 @@ BluetoothGattService::AddIncludedService
 
   /* The included service itself should be actively acting with the Bluetooth
    * backend. Otherwise, that service cannot be included by any services. */
   BT_ENSURE_TRUE_REJECT(aIncludedService.mActive,
                         promise,
                         NS_ERROR_UNEXPECTED);
 
   mIncludedServices.AppendElement(&aIncludedService);
-  promise->MaybeResolve(JS::UndefinedHandleValue);
+  promise->MaybeResolveWithUndefined();
 
   return promise.forget();
 }
--- a/dom/cache/Cache.cpp
+++ b/dom/cache/Cache.cpp
@@ -581,17 +581,17 @@ Cache::AddAll(const GlobalObject& aGloba
 
   // If there is no work to do, then resolve immediately
   if (aRequestList.IsEmpty()) {
     RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
     if (NS_WARN_IF(!promise)) {
       return nullptr;
     }
 
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   AutoTArray<RefPtr<Promise>, 256> fetchList;
   fetchList.SetCapacity(aRequestList.Length());
 
   // Begin fetching each request in parallel.  For now, if an error occurs just
   // abandon our previous fetch calls.  In theory we could cancel them in the
--- a/dom/cache/CacheOpChild.cpp
+++ b/dom/cache/CacheOpChild.cpp
@@ -123,17 +123,17 @@ CacheOpChild::Recv__delete__(const Error
     }
     case CacheOpResult::TCacheMatchAllResult:
     {
       HandleResponseList(aResult.get_CacheMatchAllResult().responseList());
       break;
     }
     case CacheOpResult::TCachePutAllResult:
     {
-      mPromise->MaybeResolve(JS::UndefinedHandleValue);
+      mPromise->MaybeResolveWithUndefined();
       break;
     }
     case CacheOpResult::TCacheDeleteResult:
     {
       mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success());
       break;
     }
     case CacheOpResult::TCacheKeysResult:
@@ -207,17 +207,17 @@ CacheOpChild::GetIPCManager()
 {
   MOZ_CRASH("CacheOpChild does not implement TypeUtils::GetIPCManager()");
 }
 
 void
 CacheOpChild::HandleResponse(const CacheResponseOrVoid& aResponseOrVoid)
 {
   if (aResponseOrVoid.type() == CacheResponseOrVoid::Tvoid_t) {
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
     return;
   }
 
   const CacheResponse& cacheResponse = aResponseOrVoid.get_CacheResponse();
 
   AddWorkerHolderToStreamChild(cacheResponse, GetWorkerHolder());
   RefPtr<Response> response = ToResponse(cacheResponse);
 
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -1095,17 +1095,17 @@ nsDOMCameraControl::ReleaseHardware(Erro
 
   RefPtr<Promise> promise = CreatePromise(aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   if (!mCameraControl) {
     // Always succeed if the camera instance is already closed.
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   aRv = mCameraControl->Stop();
   if (aRv.Failed()) {
     return nullptr;
   }
 
@@ -1286,17 +1286,17 @@ nsDOMCameraControl::OnHardwareStateChang
       }
       break;
 
     case CameraControlListener::kHardwareClosed:
       DOM_CAMERA_LOGI("DOM OnHardwareStateChange: closed\n");
       if (!mSetInitialConfig) {
         RefPtr<Promise> promise = mReleasePromise.forget();
         if (promise) {
-          promise->MaybeResolve(JS::UndefinedHandleValue);
+          promise->MaybeResolveWithUndefined();
         }
 
         CameraClosedEventInit eventInit;
         switch (aReason) {
           case NS_OK:
             eventInit.mReason = NS_LITERAL_STRING("HardwareReleased");
             break;
 
@@ -1404,17 +1404,17 @@ nsDOMCameraControl::OnRecorderStateChang
 
   nsString state;
 
   switch (aState) {
     case CameraControlListener::kRecorderStarted:
       {
         RefPtr<Promise> promise = mStartRecordingPromise.forget();
         if (promise) {
-          promise->MaybeResolve(JS::UndefinedHandleValue);
+          promise->MaybeResolveWithUndefined();
         }
 
         state = NS_LITERAL_STRING("Started");
       }
       break;
 
     case CameraControlListener::kRecorderStopped:
       if (mOptions.mCreatePoster) {
@@ -1635,17 +1635,17 @@ nsDOMCameraControl::OnUserError(CameraCo
       break;
 
     case CameraControlListener::kInStopCamera:
       promise = mReleasePromise.forget();
       if (aError == NS_ERROR_NOT_INITIALIZED) {
         // This value indicates that the hardware is already closed; which for
         // kInStopCamera, is not actually an error.
         if (promise) {
-          promise->MaybeResolve(JS::UndefinedHandleValue);
+          promise->MaybeResolveWithUndefined();
         }
 
         return;
       }
       break;
 
     case CameraControlListener::kInSetConfiguration:
       if (mSetInitialConfig && mCameraControl) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1516,29 +1516,46 @@ CanvasRenderingContext2D::EnsureTarget(c
   MOZ_ASSERT(mRenderingMode != RenderingMode::DefaultBackendMode);
 
   RenderingMode mode = (aRenderingMode == RenderingMode::DefaultBackendMode) ? mRenderingMode : aRenderingMode;
 
   if (mTarget && mode == mRenderingMode) {
     return mRenderingMode;
   }
 
+  // If the next drawing command covers the entire canvas, we can skip copying
+  // from the previous frame and/or clearing the canvas.
+  gfx::Rect canvasRect(0, 0, mWidth, mHeight);
+  bool canDiscardContent = aCoveredRect &&
+    CurrentState().transform.TransformBounds(*aCoveredRect).Contains(canvasRect);
+
+  // If a clip is active we don't know for sure that the next drawing command
+  // will really cover the entire canvas.
+  for (const auto& style : mStyleStack) {
+    if (!canDiscardContent) {
+      break;
+    }
+    for (const auto& clipOrTransform : style.clipsAndTransforms) {
+      if (clipOrTransform.IsClip()) {
+        canDiscardContent = false;
+        break;
+      }
+    }
+  }
+
   ScheduleStableStateCallback();
 
   // we'll do a few extra things at the end of this method if we changed the
   // buffer provider.
   RefPtr<PersistentBufferProvider> oldBufferProvider = mBufferProvider;
 
   if (mBufferProvider && mode == mRenderingMode) {
-    gfx::Rect rect(0, 0, mWidth, mHeight);
-    if (aCoveredRect && CurrentState().transform.TransformBounds(*aCoveredRect).Contains(rect)) {
-      mTarget = mBufferProvider->BorrowDrawTarget(IntRect());
-    } else {
-      mTarget = mBufferProvider->BorrowDrawTarget(IntRect(0, 0, mWidth, mHeight));
-    }
+    auto persistedRect = canDiscardContent ? IntRect()
+                                           : IntRect(0, 0, mWidth, mHeight);
+    mTarget = mBufferProvider->BorrowDrawTarget(persistedRect);
 
     mode = mRenderingMode;
   }
 
   mIsSkiaGL = false;
 
    // Check that the dimensions are sane
   IntSize size(mWidth, mHeight);
@@ -1609,43 +1626,48 @@ CanvasRenderingContext2D::EnsureTarget(c
       }
 
       gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
       JSContext* context = nsContentUtils::GetCurrentJSContext();
       if (context) {
         JS_updateMallocCounter(context, mWidth * mHeight * 4);
       }
 
-      mTarget->ClearRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+      mTarget->ClearRect(canvasRect);
 
       // Force a full layer transaction since we didn't have a layer before
       // and now we might need one.
       if (mCanvasElement) {
         mCanvasElement->InvalidateCanvas();
       }
       // Calling Redraw() tells our invalidation machinery that the entire
       // canvas is already invalid, which can speed up future drawing.
       Redraw();
     }
 
+    // Restore clips and transform.
+    mTarget->SetTransform(Matrix());
+
     if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
       // Cairo doesn't play well with huge clips. When given a very big clip it
       // will try to allocate big mask surface without taking the target
       // size into account which can cause OOM. See bug 1034593.
       // This limits the clip extents to the size of the canvas.
       // A fix in Cairo would probably be preferable, but requires somewhat
       // invasive changes.
-      mTarget->PushClipRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+      mTarget->PushClipRect(canvasRect);
     }
 
-    // Restore clip and transform.
-    for (uint32_t i = 0; i < mStyleStack.Length(); i++) {
-      mTarget->SetTransform(mStyleStack[i].transform);
-      for (uint32_t c = 0; c < mStyleStack[i].clipsPushed.Length(); c++) {
-        mTarget->PushClip(mStyleStack[i].clipsPushed[c]);
+    for (const auto& style : mStyleStack) {
+      for (const auto& clipOrTransform : style.clipsAndTransforms) {
+        if (clipOrTransform.IsClip()) {
+          mTarget->PushClip(clipOrTransform.clip);
+        } else {
+          mTarget->SetTransform(clipOrTransform.transform);
+        }
       }
     }
   } else {
     EnsureErrorTarget();
     mTarget = sErrorTarget;
     mBufferProvider = nullptr;
   }
 
@@ -1747,19 +1769,21 @@ CanvasRenderingContext2D::ClearTarget(bo
   }
 }
 
 void
 CanvasRenderingContext2D::ReturnTarget()
 {
   if (mTarget && mBufferProvider && mTarget != sErrorTarget) {
     CurrentState().transform = mTarget->GetTransform();
-    for (uint32_t i = 0; i < mStyleStack.Length(); i++) {
-      for (uint32_t c = 0; c < mStyleStack[i].clipsPushed.Length(); c++) {
-        mTarget->PopClip();
+    for (const auto& style : mStyleStack) {
+      for (const auto& clipOrTransform : style.clipsAndTransforms) {
+        if (clipOrTransform.IsClip()) {
+          mTarget->PopClip();
+        }
       }
     }
 
     if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
       // With the cairo backend we pushed an extra clip rect which we have to
       // balance out here. See the comment in EnsureDrawTarget.
       mTarget->PopClip();
     }
@@ -1929,18 +1953,20 @@ CanvasRenderingContext2D::Save()
 void
 CanvasRenderingContext2D::Restore()
 {
   if (mStyleStack.Length() - 1 == 0)
     return;
 
   TransformWillUpdate();
 
-  for (uint32_t i = 0; i < CurrentState().clipsPushed.Length(); i++) {
-    mTarget->PopClip();
+  for (const auto& clipOrTransform : CurrentState().clipsAndTransforms) {
+    if (clipOrTransform.IsClip()) {
+      mTarget->PopClip();
+    }
   }
 
   mStyleStack.RemoveElementAt(mStyleStack.Length() - 1);
 
   mTarget->SetTransform(CurrentState().transform);
 }
 
 //
@@ -1953,91 +1979,98 @@ CanvasRenderingContext2D::Scale(double a
   TransformWillUpdate();
   if (!IsTargetValid()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix = mTarget->GetTransform();
   newMatrix.PreScale(aX, aY);
-  if (!newMatrix.IsFinite()) {
-    return;
-  }
-  mTarget->SetTransform(newMatrix);
+
+  SetTransformInternal(newMatrix);
 }
 
 void
 CanvasRenderingContext2D::Rotate(double aAngle, ErrorResult& aError)
 {
   TransformWillUpdate();
   if (!IsTargetValid()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix = Matrix::Rotation(aAngle) * mTarget->GetTransform();
-  if (!newMatrix.IsFinite()) {
-    return;
-  }
-  mTarget->SetTransform(newMatrix);
+
+  SetTransformInternal(newMatrix);
 }
 
 void
 CanvasRenderingContext2D::Translate(double aX, double aY, ErrorResult& aError)
 {
   TransformWillUpdate();
   if (!IsTargetValid()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix = mTarget->GetTransform();
   newMatrix.PreTranslate(aX, aY);
-  if (!newMatrix.IsFinite()) {
-    return;
-  }
-  mTarget->SetTransform(newMatrix);
+
+  SetTransformInternal(newMatrix);
 }
 
 void
 CanvasRenderingContext2D::Transform(double aM11, double aM12, double aM21,
                                     double aM22, double aDx, double aDy,
                                     ErrorResult& aError)
 {
   TransformWillUpdate();
   if (!IsTargetValid()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix(aM11, aM12, aM21, aM22, aDx, aDy);
   newMatrix *= mTarget->GetTransform();
-  if (!newMatrix.IsFinite()) {
-    return;
-  }
-  mTarget->SetTransform(newMatrix);
+
+  SetTransformInternal(newMatrix);
 }
 
 void
 CanvasRenderingContext2D::SetTransform(double aM11, double aM12,
                                        double aM21, double aM22,
                                        double aDx, double aDy,
                                        ErrorResult& aError)
 {
   TransformWillUpdate();
   if (!IsTargetValid()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  Matrix matrix(aM11, aM12, aM21, aM22, aDx, aDy);
-  if (!matrix.IsFinite()) {
+  SetTransformInternal(Matrix(aM11, aM12, aM21, aM22, aDx, aDy));
+}
+
+void
+CanvasRenderingContext2D::SetTransformInternal(const Matrix& aTransform)
+{
+  if (!aTransform.IsFinite()) {
     return;
   }
-  mTarget->SetTransform(matrix);
+
+  // Save the transform in the clip stack to be able to replay clips properly.
+  auto& clipsAndTransforms = CurrentState().clipsAndTransforms;
+  if (clipsAndTransforms.IsEmpty() || clipsAndTransforms.LastElement().IsClip()) {
+    clipsAndTransforms.AppendElement(ClipState(aTransform));
+  } else {
+    // If the last item is a transform we can replace it instead of appending
+    // a new item.
+    clipsAndTransforms.LastElement().transform = aTransform;
+  }
+  mTarget->SetTransform(aTransform);
 }
 
 void
 CanvasRenderingContext2D::ResetTransform(ErrorResult& aError)
 {
   SetTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, aError);
 }
 
@@ -2803,17 +2836,17 @@ CanvasRenderingContext2D::FillRect(doubl
           aH = 0;
         }
       }
     }
   }
 
   CompositionOp op = UsedOperation();
   bool discardContent = PatternIsOpaque(Style::FILL)
-    && (op == CompositionOp::OP_OVER || op == CompositionOp::OP_DEST_OUT);
+    && (op == CompositionOp::OP_OVER || op == CompositionOp::OP_SOURCE);
 
   const gfx::Rect fillRect(aX, aY, aW, aH);
   EnsureTarget(discardContent ? &fillRect : nullptr);
 
   gfx::Rect bounds;
   if (NeedToCalculateBounds()) {
     bounds = mTarget->GetTransform().TransformBounds(fillRect);
   }
@@ -3097,32 +3130,32 @@ CanvasRenderingContext2D::Clip(const Can
 {
   EnsureUserSpacePath(aWinding);
 
   if (!mPath) {
     return;
   }
 
   mTarget->PushClip(mPath);
-  CurrentState().clipsPushed.AppendElement(mPath);
+  CurrentState().clipsAndTransforms.AppendElement(ClipState(mPath));
 }
 
 void
 CanvasRenderingContext2D::Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding)
 {
   EnsureTarget();
 
   RefPtr<gfx::Path> gfxpath = aPath.GetPath(aWinding, mTarget);
 
   if (!gfxpath) {
     return;
   }
 
   mTarget->PushClip(gfxpath);
-  CurrentState().clipsPushed.AppendElement(gfxpath);
+  CurrentState().clipsAndTransforms.AppendElement(ClipState(gfxpath));
 }
 
 void
 CanvasRenderingContext2D::ArcTo(double aX1, double aY1, double aX2,
                                 double aY2, double aRadius,
                                 ErrorResult& aError)
 {
   if (aRadius < 0) {
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -569,16 +569,18 @@ protected:
   /**
     * The number of living nsCanvasRenderingContexts.  When this goes down to
     * 0, we free the premultiply and unpremultiply tables, if they exist.
     */
   static uint32_t sNumLivingContexts;
 
   static mozilla::gfx::DrawTarget* sErrorTarget;
 
+  void SetTransformInternal(const mozilla::gfx::Matrix& aTransform);
+
   // Some helpers.  Doesn't modify a color on failure.
   void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& aValue,
                          Style aWhichStyle);
   void SetStyleFromString(const nsAString& aStr, Style aWhichStyle);
 
   void SetStyleFromGradient(CanvasGradient& aGradient, Style aWhichStyle)
   {
     CurrentState().SetGradientStyle(aWhichStyle, &aGradient);
@@ -912,16 +914,32 @@ protected:
                              float aX,
                              float aY,
                              const Optional<double>& aMaxWidth,
                              TextDrawOperation aOp,
                              float* aWidth);
 
   bool CheckSizeForSkiaGL(mozilla::gfx::IntSize aSize);
 
+  // A clip or a transform, recorded and restored in order.
+  struct ClipState {
+    explicit ClipState(mozilla::gfx::Path* aClip)
+      : clip(aClip)
+    {}
+
+    explicit ClipState(const mozilla::gfx::Matrix& aTransform)
+      : transform(aTransform)
+    {}
+
+    bool IsClip() const { return !!clip; }
+
+    RefPtr<mozilla::gfx::Path> clip;
+    mozilla::gfx::Matrix transform;
+  };
+
   // state stack handling
   class ContextState {
   public:
     ContextState() : textAlign(TextAlign::START),
                      textBaseline(TextBaseline::ALPHABETIC),
                      shadowColor(0),
                      lineWidth(1.0f),
                      miterLimit(10.0f),
@@ -1004,17 +1022,17 @@ protected:
       return (int32_t)floor(ShadowBlurSigma() * GAUSSIAN_SCALE_FACTOR + 0.5);
     }
 
     mozilla::gfx::Float ShadowBlurSigma() const
     {
       return std::min(SIGMA_MAX, shadowBlur / 2.0f);
     }
 
-    nsTArray<RefPtr<mozilla::gfx::Path> > clipsPushed;
+    nsTArray<ClipState> clipsAndTransforms;
 
     RefPtr<gfxFontGroup> fontGroup;
     nsCOMPtr<nsIAtom> fontLanguage;
     nsFont fontFont;
 
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasGradient>> gradientStyles;
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasPattern>> patternStyles;
     EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
--- a/dom/canvas/crashtests/crashtests.list
+++ b/dom/canvas/crashtests/crashtests.list
@@ -11,17 +11,16 @@ load 746813-1.html
 load 743499-negative-size.html
 skip-if(Android||B2G) load 745818-large-source.html # Bug XXX - Crashes Android/B2G mid-run w/o a stack
 load 767337-1.html
 skip-if(Android||B2G) load 780392-1.html # bug 833371 for B2G
 skip-if(Android||B2G) skip-if(gtkWidget&&isDebugBuild) load 789933-1.html # bug 833371 for B2G, bug 1155252 for linux
 load 794463-1.html
 load 802926-1.html
 load 896047-1.html
-load 896047-2.html
 load 916128-1.html
 load 934939-1.html
 load 1099143-1.html
 load 1161277-1.html
 load 1183363.html
 load 1190705.html
 load 1223740-1.html
 load 1225381-1.html
--- a/dom/canvas/test/mochitest.ini
+++ b/dom/canvas/test/mochitest.ini
@@ -198,17 +198,16 @@ skip-if = toolkit != 'cocoa'
 skip-if = toolkit != 'cocoa'
 # This test is bogus according to the spec; see bug 407107
 [test_2d.path.rect.zero.6.html]
 disabled = bug 407107
 [test_2d.strokeRect.zero.5.html]
 [test_bitmaprenderer.html]
 [test_bug232227.html]
 [test_bug613794.html]
-[test_bug753758.html]
 [test_bug764125.html]
 [test_bug856472.html]
 [test_bug866575.html]
 skip-if = (toolkit == 'gonk' && debug) #bug 1045153
 [test_bug902651.html]
 [test_bug1215072.html]
 subsuite = gpu
 [test_canvas.html]
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -114,16 +114,18 @@ HTMLFormElement::HTMLFormElement(already
     mDefaultSubmitElement(nullptr),
     mFirstSubmitInElements(nullptr),
     mFirstSubmitNotInElements(nullptr),
     mImageNameLookupTable(FORM_CONTROL_LIST_HASHTABLE_LENGTH),
     mPastNameLookupTable(FORM_CONTROL_LIST_HASHTABLE_LENGTH),
     mInvalidElementsCount(0),
     mEverTriedInvalidSubmit(false)
 {
+  // We start out valid.
+  AddStatesSilently(NS_EVENT_STATE_VALID);
 }
 
 HTMLFormElement::~HTMLFormElement()
 {
   if (mControls) {
     mControls->DropFormReference();
   }
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1463,17 +1463,17 @@ HTMLInputElement::AfterSetAttr(int32_t a
       UpdateValueMissingValidityState();
 
       // This *has* to be called *after* validity has changed.
       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
         UpdateBarredFromConstraintValidation();
       }
     } else if (MaxLengthApplies() && aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
-    } else if (aName == nsGkAtoms::pattern) {
+    } else if (aName == nsGkAtoms::pattern && !mParserCreating) {
       UpdatePatternMismatchValidityState();
     } else if (aName == nsGkAtoms::multiple) {
       UpdateTypeMismatchValidityState();
     } else if (aName == nsGkAtoms::max) {
       UpdateHasRange();
       if (mType == NS_FORM_INPUT_RANGE) {
         // The value may need to change when @max changes since the value may
         // have been invalid and can now change to a valid value, or vice
@@ -5607,56 +5607,64 @@ HTMLInputElement::GetTextLength(int32_t*
 }
 
 void
 HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
                                     int32_t aSelectionEnd,
                                     const Optional<nsAString>& aDirection,
                                     ErrorResult& aRv)
 {
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
+  nsresult rv = SetSelectionRange(aSelectionStart, aSelectionEnd,
+    aDirection.WasPassed() ? aDirection.Value() : NullString());
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+}
+
+NS_IMETHODIMP
+HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
+                                    int32_t aSelectionEnd,
+                                    const nsAString& aDirection)
+{
+  nsresult rv = NS_OK;
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
   nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
   if (textControlFrame) {
     // Default to forward, even if not specified.
     // Note that we don't currently support directionless selections, so
     // "none" is treated like "forward".
     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
-    if (aDirection.WasPassed() && aDirection.Value().EqualsLiteral("backward")) {
+    if (!aDirection.IsEmpty() && aDirection.EqualsLiteral("backward")) {
       dir = nsITextControlFrame::eBackward;
     }
 
-    aRv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
-    if (!aRv.Failed()) {
-      aRv = textControlFrame->ScrollSelectionIntoView();
+    rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
+    if (NS_SUCCEEDED(rv)) {
+      rv = textControlFrame->ScrollSelectionIntoView();
       RefPtr<AsyncEventDispatcher> asyncDispatcher =
         new AsyncEventDispatcher(this, NS_LITERAL_STRING("select"),
                                  true, false);
       asyncDispatcher->PostDOMEvent();
     }
   }
-}
-
-NS_IMETHODIMP
-HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
-                                    int32_t aSelectionEnd,
-                                    const nsAString& aDirection)
-{
-  ErrorResult rv;
-  Optional<nsAString> direction;
-  direction = &aDirection;
-
-  SetSelectionRange(aSelectionStart, aSelectionEnd, direction, rv);
-  return rv.StealNSResult();
+
+  return rv;
 }
 
 void
 HTMLInputElement::SetRangeText(const nsAString& aReplacement, ErrorResult& aRv)
 {
-  if (!SupportsSetRangeText()) {
-    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (aRv.Failed()) {
     nsTextEditorState* state = GetEditorState();
     if (state && state->IsSelectionCached()) {
@@ -5671,18 +5679,18 @@ HTMLInputElement::SetRangeText(const nsA
 }
 
 void
 HTMLInputElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart,
                                uint32_t aEnd, const SelectionMode& aSelectMode,
                                ErrorResult& aRv, int32_t aSelectionStart,
                                int32_t aSelectionEnd)
 {
-  if (!SupportsSetRangeText()) {
-    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   if (aStart > aEnd) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -5758,141 +5766,185 @@ HTMLInputElement::SetRangeText(const nsA
     default:
       MOZ_CRASH("Unknown mode!");
   }
 
   Optional<nsAString> direction;
   SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
 }
 
-int32_t
+Nullable<int32_t>
 HTMLInputElement::GetSelectionStart(ErrorResult& aRv)
 {
-  int32_t selEnd, selStart;
-  aRv = GetSelectionRange(&selStart, &selEnd);
-
-  if (aRv.Failed()) {
-    nsTextEditorState* state = GetEditorState();
-    if (state && state->IsSelectionCached()) {
-      aRv = NS_OK;
-      return state->GetSelectionProperties().GetStart();
-    }
-  }
-
-  return selStart;
+  if (!SupportsTextSelection()) {
+    return Nullable<int32_t>();
+  }
+
+  int32_t selStart;
+  nsresult rv = GetSelectionStart(&selStart);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+
+  return Nullable<int32_t>(selStart);
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetSelectionStart(int32_t* aSelectionStart)
 {
   NS_ENSURE_ARG_POINTER(aSelectionStart);
 
-  ErrorResult rv;
-  *aSelectionStart = GetSelectionStart(rv);
-  return rv.StealNSResult();
+  int32_t selEnd, selStart;
+  nsresult rv = GetSelectionRange(&selStart, &selEnd);
+
+  if (NS_FAILED(rv)) {
+    nsTextEditorState* state = GetEditorState();
+    if (state && state->IsSelectionCached()) {
+      *aSelectionStart = state->GetSelectionProperties().GetStart();
+      return NS_OK;
+    }
+    return rv;
+  }
+
+  *aSelectionStart = selStart;
+  return NS_OK;
 }
 
 void
-HTMLInputElement::SetSelectionStart(int32_t aSelectionStart, ErrorResult& aRv)
-{
+HTMLInputElement::SetSelectionStart(const Nullable<int32_t>& aSelectionStart,
+                                    ErrorResult& aRv)
+{
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
+  int32_t selStart = 0;
+  if (!aSelectionStart.IsNull()) {
+    selStart = aSelectionStart.Value();
+  }
+
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
-    state->GetSelectionProperties().SetStart(aSelectionStart);
+    state->GetSelectionProperties().SetStart(selStart);
     return;
   }
 
   nsAutoString direction;
   aRv = GetSelectionDirection(direction);
   if (aRv.Failed()) {
     return;
   }
 
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (aRv.Failed()) {
     return;
   }
 
-  start = aSelectionStart;
+  start = selStart;
   if (end < start) {
     end = start;
   }
 
   aRv = SetSelectionRange(start, end, direction);
 }
 
 NS_IMETHODIMP
 HTMLInputElement::SetSelectionStart(int32_t aSelectionStart)
 {
   ErrorResult rv;
-  SetSelectionStart(aSelectionStart, rv);
+  Nullable<int32_t> selStart(aSelectionStart);
+  SetSelectionStart(selStart, rv);
   return rv.StealNSResult();
 }
 
-int32_t
+Nullable<int32_t>
 HTMLInputElement::GetSelectionEnd(ErrorResult& aRv)
 {
-  int32_t selStart, selEnd;
-  aRv = GetSelectionRange(&selStart, &selEnd);
-
-  if (aRv.Failed()) {
-    nsTextEditorState* state = GetEditorState();
-    if (state && state->IsSelectionCached()) {
-      aRv = NS_OK;
-      return state->GetSelectionProperties().GetEnd();
-    }
-  }
-
-  return selEnd;
+  if (!SupportsTextSelection()) {
+    return Nullable<int32_t>();
+  }
+
+  int32_t selEnd;
+  nsresult rv = GetSelectionEnd(&selEnd);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+  }
+
+  return Nullable<int32_t>(selEnd);
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetSelectionEnd(int32_t* aSelectionEnd)
 {
   NS_ENSURE_ARG_POINTER(aSelectionEnd);
 
-  ErrorResult rv;
-  *aSelectionEnd = GetSelectionEnd(rv);
-  return rv.StealNSResult();
+  int32_t selEnd, selStart;
+  nsresult rv = GetSelectionRange(&selStart, &selEnd);
+
+  if (NS_FAILED(rv)) {
+    nsTextEditorState* state = GetEditorState();
+    if (state && state->IsSelectionCached()) {
+      *aSelectionEnd = state->GetSelectionProperties().GetEnd();
+      return NS_OK;
+    }
+    return rv;
+  }
+
+  *aSelectionEnd = selEnd;
+  return NS_OK;
 }
 
 void
-HTMLInputElement::SetSelectionEnd(int32_t aSelectionEnd, ErrorResult& aRv)
-{
+HTMLInputElement::SetSelectionEnd(const Nullable<int32_t>& aSelectionEnd,
+                                  ErrorResult& aRv)
+{
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
+  int32_t selEnd = 0;
+  if (!aSelectionEnd.IsNull()) {
+    selEnd = aSelectionEnd.Value();
+  }
+
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
-    state->GetSelectionProperties().SetEnd(aSelectionEnd);
+    state->GetSelectionProperties().SetEnd(selEnd);
     return;
   }
 
   nsAutoString direction;
   aRv = GetSelectionDirection(direction);
   if (aRv.Failed()) {
     return;
   }
 
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (aRv.Failed()) {
     return;
   }
 
-  end = aSelectionEnd;
+  end = selEnd;
   if (start > end) {
     start = end;
   }
 
   aRv = SetSelectionRange(start, end, direction);
 }
 
 NS_IMETHODIMP
 HTMLInputElement::SetSelectionEnd(int32_t aSelectionEnd)
 {
   ErrorResult rv;
-  SetSelectionEnd(aSelectionEnd, rv);
+  Nullable<int32_t> selEnd(aSelectionEnd);
+  SetSelectionEnd(selEnd, rv);
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetFiles(nsIDOMFileList** aFileList)
 {
   RefPtr<FileList> list = GetFiles();
   list.forget(aFileList);
@@ -5924,16 +5976,21 @@ DirectionToName(nsITextControlFrame::Sel
   } else {
     NS_NOTREACHED("Invalid SelectionDirection value");
   }
 }
 
 void
 HTMLInputElement::GetSelectionDirection(nsAString& aDirection, ErrorResult& aRv)
 {
+  if (!SupportsTextSelection()) {
+    aDirection.SetIsVoid(true);
+    return;
+  }
+
   nsresult rv = NS_ERROR_FAILURE;
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
   nsITextControlFrame* textControlFrame = do_QueryFrame(formControlFrame);
   if (textControlFrame) {
     nsITextControlFrame::SelectionDirection dir;
     rv = textControlFrame->GetSelectionRange(nullptr, nullptr, &dir);
     if (NS_SUCCEEDED(rv)) {
       DirectionToName(dir, aDirection);
@@ -5959,16 +6016,21 @@ HTMLInputElement::GetSelectionDirection(
   ErrorResult rv;
   GetSelectionDirection(aDirection, rv);
   return rv.StealNSResult();
 }
 
 void
 HTMLInputElement::SetSelectionDirection(const nsAString& aDirection, ErrorResult& aRv)
 {
+  if (!SupportsTextSelection()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
     if (aDirection.EqualsLiteral("forward")) {
       dir = nsITextControlFrame::eForward;
     } else if (aDirection.EqualsLiteral("backward")) {
       dir = nsITextControlFrame::eBackward;
     }
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -683,21 +683,21 @@ public:
   Decimal GetStep() const;
 
   void GetValidationMessage(nsAString& aValidationMessage, ErrorResult& aRv);
 
   // XPCOM GetCustomVisibility() is OK
 
   // XPCOM Select() is OK
 
-  int32_t GetSelectionStart(ErrorResult& aRv);
-  void SetSelectionStart(int32_t aValue, ErrorResult& aRv);
+  Nullable<int32_t> GetSelectionStart(ErrorResult& aRv);
+  void SetSelectionStart(const Nullable<int32_t>& aValue, ErrorResult& aRv);
 
-  int32_t GetSelectionEnd(ErrorResult& aRv);
-  void SetSelectionEnd(int32_t aValue, ErrorResult& aRv);
+  Nullable<int32_t> GetSelectionEnd(ErrorResult& aRv);
+  void SetSelectionEnd(const Nullable<int32_t>& aValue, ErrorResult& aRv);
 
   void GetSelectionDirection(nsAString& aValue, ErrorResult& aRv);
   void SetSelectionDirection(const nsAString& aValue, ErrorResult& aRv);
 
   void SetSelectionRange(int32_t aStart, int32_t aEnd,
                          const Optional< nsAString >& direction,
                          ErrorResult& aRv);
 
@@ -1476,19 +1476,19 @@ private:
    * Returns true if this input's type will fire a DOM "change" event when it
    * loses focus if its value has changed since it gained focus.
    */
   bool MayFireChangeOnBlur() const {
     return MayFireChangeOnBlur(mType);
   }
 
   /**
-   * Returns true if setRangeText can be called on element
+   * Returns true if selection methods can be called on element
    */
-  bool SupportsSetRangeText() const {
+  bool SupportsTextSelection() const {
     return mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_SEARCH ||
            mType == NS_FORM_INPUT_URL || mType == NS_FORM_INPUT_TEL ||
            mType == NS_FORM_INPUT_PASSWORD || mType == NS_FORM_INPUT_NUMBER;
   }
 
   static bool MayFireChangeOnBlur(uint8_t aType) {
     return IsSingleLineTextControl(false, aType) ||
            aType == NS_FORM_INPUT_RANGE ||
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5731,17 +5731,17 @@ HTMLMediaElement::SetMediaKeys(mozilla::
     promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
                          NS_LITERAL_CSTRING("EME not supported on non-MSE streams"));
     return promise.forget();
   }
 
   // 1. If mediaKeys and the mediaKeys attribute are the same object,
   // return a resolved promise.
   if (mMediaKeys == aMediaKeys) {
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   // Note: Our attaching code is synchronous, so we can skip the following steps.
 
   // 2. If this object's attaching media keys value is true, return a
   // promise rejected with a new DOMException whose name is InvalidStateError.
   // 3. Let this object's attaching media keys value be true.
@@ -5817,17 +5817,17 @@ HTMLMediaElement::SetMediaKeys(mozilla::
   }
 
   // 5.4 Set the mediaKeys attribute to mediaKeys.
   mMediaKeys = aMediaKeys;
 
   // 5.5 Let this object's attaching media keys value be false.
 
   // 5.6 Resolve promise.
-  promise->MaybeResolve(JS::UndefinedHandleValue);
+  promise->MaybeResolveWithUndefined();
 
   // 6. Return promise.
   return promise.forget();
 }
 
 EventHandlerNonNull*
 HTMLMediaElement::GetOnencrypted()
 {
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -656,127 +656,151 @@ HTMLTextAreaElement::GetTextLength(int32
 }
 
 NS_IMETHODIMP
 HTMLTextAreaElement::GetSelectionStart(int32_t *aSelectionStart)
 {
   NS_ENSURE_ARG_POINTER(aSelectionStart);
 
   ErrorResult error;
-  *aSelectionStart = GetSelectionStart(error);
+  Nullable<uint32_t> selStart(GetSelectionStart(error));
+  if (error.Failed()) {
+    return error.StealNSResult();
+  }
+
+  *aSelectionStart = int32_t(selStart.Value());
   return error.StealNSResult();
 }
 
-uint32_t
+Nullable<uint32_t>
 HTMLTextAreaElement::GetSelectionStart(ErrorResult& aError)
 {
   int32_t selStart, selEnd;
   nsresult rv = GetSelectionRange(&selStart, &selEnd);
 
   if (NS_FAILED(rv) && mState.IsSelectionCached()) {
-    return mState.GetSelectionProperties().GetStart();
+    return Nullable<uint32_t>(mState.GetSelectionProperties().GetStart());
   }
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
-  return selStart;
+  return Nullable<uint32_t>(selStart);
 }
 
 NS_IMETHODIMP
 HTMLTextAreaElement::SetSelectionStart(int32_t aSelectionStart)
 {
   ErrorResult error;
-  SetSelectionStart(aSelectionStart, error);
+  Nullable<uint32_t> selStart(aSelectionStart);
+  SetSelectionStart(selStart, error);
   return error.StealNSResult();
 }
 
 void
-HTMLTextAreaElement::SetSelectionStart(uint32_t aSelectionStart, ErrorResult& aError)
+HTMLTextAreaElement::SetSelectionStart(const Nullable<uint32_t>& aSelectionStart,
+                                       ErrorResult& aError)
 {
+  int32_t selStart = 0;
+  if (!aSelectionStart.IsNull()) {
+    selStart = aSelectionStart.Value();
+  }
+
   if (mState.IsSelectionCached()) {
-    mState.GetSelectionProperties().SetStart(aSelectionStart);
+    mState.GetSelectionProperties().SetStart(selStart);
     return;
   }
 
   nsAutoString direction;
   nsresult rv = GetSelectionDirection(direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
   }
   int32_t start, end;
   rv = GetSelectionRange(&start, &end);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
   }
-  start = aSelectionStart;
+  start = selStart;
   if (end < start) {
     end = start;
   }
   rv = SetSelectionRange(start, end, direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
 }
 
 NS_IMETHODIMP
 HTMLTextAreaElement::GetSelectionEnd(int32_t *aSelectionEnd)
 {
   NS_ENSURE_ARG_POINTER(aSelectionEnd);
 
   ErrorResult error;
-  *aSelectionEnd = GetSelectionEnd(error);
-  return error.StealNSResult();
+  Nullable<uint32_t> selEnd(GetSelectionEnd(error));
+  if (error.Failed()) {
+    return error.StealNSResult();
+  }
+
+  *aSelectionEnd = int32_t(selEnd.Value());
+  return NS_OK;
 }
 
-uint32_t
+Nullable<uint32_t>
 HTMLTextAreaElement::GetSelectionEnd(ErrorResult& aError)
 {
   int32_t selStart, selEnd;
   nsresult rv = GetSelectionRange(&selStart, &selEnd);
 
   if (NS_FAILED(rv) && mState.IsSelectionCached()) {
-    return mState.GetSelectionProperties().GetEnd();
+    return Nullable<uint32_t>(mState.GetSelectionProperties().GetEnd());
   }
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
-  return selEnd;
+  return Nullable<uint32_t>(selEnd);
 }
 
 NS_IMETHODIMP
 HTMLTextAreaElement::SetSelectionEnd(int32_t aSelectionEnd)
 {
   ErrorResult error;
-  SetSelectionEnd(aSelectionEnd, error);
+  Nullable<uint32_t> selEnd(aSelectionEnd);
+  SetSelectionEnd(selEnd, error);
   return error.StealNSResult();
 }
 
 void
-HTMLTextAreaElement::SetSelectionEnd(uint32_t aSelectionEnd, ErrorResult& aError)
+HTMLTextAreaElement::SetSelectionEnd(const Nullable<uint32_t>& aSelectionEnd,
+                                     ErrorResult& aError)
 {
+  int32_t selEnd = 0;
+  if (!aSelectionEnd.IsNull()) {
+    selEnd = aSelectionEnd.Value();
+  }
+
   if (mState.IsSelectionCached()) {
-    mState.GetSelectionProperties().SetEnd(aSelectionEnd);
+    mState.GetSelectionProperties().SetEnd(selEnd);
     return;
   }
 
   nsAutoString direction;
   nsresult rv = GetSelectionDirection(direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
   }
   int32_t start, end;
   rv = GetSelectionRange(&start, &end);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
   }
-  end = aSelectionEnd;
+  end = selEnd;
   if (start > end) {
     start = end;
   }
   rv = SetSelectionRange(start, end, direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
 }
@@ -843,17 +867,18 @@ NS_IMETHODIMP
 HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection)
 {
   ErrorResult error;
   SetSelectionDirection(aDirection, error);
   return error.StealNSResult();
 }
 
 void
-HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection, ErrorResult& aError)
+HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection,
+                                           ErrorResult& aError)
 {
   if (mState.IsSelectionCached()) {
     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
     if (aDirection.EqualsLiteral("forward")) {
       dir = nsITextControlFrame::eForward;
     } else if (aDirection.EqualsLiteral("backward")) {
       dir = nsITextControlFrame::eBackward;
     }
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -264,20 +264,20 @@ public:
   // nsIConstraintValidation::WillValidate is fine.
   // nsIConstraintValidation::Validity() is fine.
   // nsIConstraintValidation::GetValidationMessage() is fine.
   // nsIConstraintValidation::CheckValidity() is fine.
   using nsIConstraintValidation::CheckValidity;
   using nsIConstraintValidation::ReportValidity;
   // nsIConstraintValidation::SetCustomValidity() is fine.
   // XPCOM Select is fine
-  uint32_t GetSelectionStart(ErrorResult& aError);
-  void SetSelectionStart(uint32_t aSelectionStart, ErrorResult& aError);
-  uint32_t GetSelectionEnd(ErrorResult& aError);
-  void SetSelectionEnd(uint32_t aSelectionEnd, ErrorResult& aError);
+  Nullable<uint32_t> GetSelectionStart(ErrorResult& aError);
+  void SetSelectionStart(const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError);
+  Nullable<uint32_t> GetSelectionEnd(ErrorResult& aError);
+  void SetSelectionEnd(const Nullable<uint32_t>& aSelectionEnd, ErrorResult& aError);
   void GetSelectionDirection(nsAString& aDirection, ErrorResult& aError);
   void SetSelectionDirection(const nsAString& aDirection, ErrorResult& aError);
   void SetSelectionRange(uint32_t aSelectionStart, uint32_t aSelectionEnd, const Optional<nsAString>& aDirecton, ErrorResult& aError);
   nsIControllers* GetControllers(ErrorResult& aError);
   nsIEditor* GetEditor()
   {
     return mState.GetEditor();
   }
--- a/dom/html/test/forms/test_set_range_text.html
+++ b/dom/html/test/forms/test_set_range_text.html
@@ -56,33 +56,33 @@ https://bugzilla.mozilla.org/show_bug.cg
       msg = "input_" + NonSupportedTypes[i];
       elem = document.getElementById(msg);
       elem.focus();
       try {
         elem.setRangeText("abc");
       } catch (ex) {
        opThrows = true;
       }
-      ok(opThrows, msg + " should throw NotSupportedError");
+      ok(opThrows, msg + " should throw InvalidStateError");
     }
 
     var numOfSelectCalls = 0, expectedNumOfSelectCalls = 0;
     //Supported types should not throw
     for (i = 0; i < SupportedTypes.length; ++i) {
       opThrows = false;
       msg = "input_" + SupportedTypes[i];
       elem = document.getElementById(msg);
       elem.focus();
       try {
         elem.setRangeText("abc");
         expectedNumOfSelectCalls += 1;
       } catch (ex) {
         opThrows = true;
       }
-      is(opThrows, false, msg + " should not throw NotSupportedError");
+      is(opThrows, false, msg + " should not throw InvalidStateError");
 
       elem.addEventListener("select", function (aEvent) {
         ok(true, "select event should be fired for " + aEvent.target.id);
         if (++numOfSelectCalls == expectedNumOfSelectCalls) {
           SimpleTest.finish();
         } else if (numOfSelectCalls > expectedNumOfSelectCalls) {
           ok(false, "Too many select events were fired");
         }
--- a/dom/interfaces/storage/nsIDOMStorageManager.idl
+++ b/dom/interfaces/storage/nsIDOMStorageManager.idl
@@ -34,34 +34,32 @@ interface nsIDOMStorageManager : nsISupp
    *    Principal to bound storage to.
    * @param aDocumentURI
    *    URL of the demanding document, used for DOM storage event only.
    * @param aPrivate
    *    Whether the demanding document is running in Private Browsing mode or not.
    */
   nsIDOMStorage createStorage(in mozIDOMWindow aWindow,
                               in nsIPrincipal aPrincipal,
-                              in DOMString aDocumentURI,
-                              [optional] in bool aPrivate);
+                              in DOMString aDocumentURI);
   /**
    * Returns instance of DOM storage object for given principal.
    * If there is no storage managed for the scope, then null is returned and
    * no object is created.  Otherwise, an object (new) for the existing storage
    * scope is returned.
    *
    * @param aWindow
    *    The parent window.
    * @param aPrincipal
    *    Principal to bound storage to.
    * @param aPrivate
    *    Whether the demanding document is running in Private Browsing mode or not.
    */
   nsIDOMStorage getStorage(in mozIDOMWindow aWindow,
-                           in nsIPrincipal aPrincipal,
-                           [optional] in bool aPrivate);
+                           in nsIPrincipal aPrincipal);
 
   /**
    * Clones given storage into this storage manager.
    *
    * @param aStorageToCloneFrom
    *    The storage to copy all items from into this manager.  Manager will then
    *    return a new and independent object that contains snapshot of data from
    *    the moment this method was called.  Modification to this new object will
@@ -95,11 +93,10 @@ interface nsIDOMStorageManager : nsISupp
    *
    * Currently just forwards to the createStorage method of this
    * interface.
    *
    * Extension developers are strongly encouraged to use getStorage
    * or createStorage method instead.
    */
   nsIDOMStorage getLocalStorageForPrincipal(in nsIPrincipal aPrincipal,
-                                            in DOMString aDocumentURI,
-                                            [optional] in bool aPrivate);
+                                            in DOMString aDocumentURI);
 };
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -839,17 +839,17 @@ MediaDecoder::Seek(double aTime, SeekTar
 
 void
 MediaDecoder::AsyncResolveSeekDOMPromiseIfExists()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mSeekDOMPromise) {
     RefPtr<dom::Promise> promise = mSeekDOMPromise;
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-      promise->MaybeResolve(JS::UndefinedHandleValue);
+      promise->MaybeResolveWithUndefined();
     });
     AbstractThread::MainThread()->Dispatch(r.forget());
     mSeekDOMPromise = nullptr;
   }
 }
 
 void
 MediaDecoder::AsyncRejectSeekDOMPromiseIfExists()
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -34,16 +34,21 @@ using mozilla::CheckedUint32;
 // dependent on other changes which we don't want to wait for. We plan to
 // remove this file in the near future.
 
 
 // This belongs in xpcom/monitor/Monitor.h, once we've made
 // mozilla::Monitor non-reentrant.
 namespace mozilla {
 
+// EME Key System String.
+static const char* const kEMEKeySystemClearkey = "org.w3.clearkey";
+static const char* const kEMEKeySystemWidevine = "com.widevine.alpha";
+static const char* const kEMEKeySystemPrimetime = "com.adobe.primetime";
+
 /**
  * ReentrantMonitorConditionallyEnter
  *
  * Enters the supplied monitor only if the conditional value |aEnter| is true.
  * E.g. Used to allow unmonitored read access on the decode thread,
  * and monitored access on all other threads.
  */
 class MOZ_STACK_CLASS ReentrantMonitorConditionallyEnter
--- a/dom/media/eme/EMEUtils.h
+++ b/dom/media/eme/EMEUtils.h
@@ -2,26 +2,23 @@
 /* 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/. */
 
 #ifndef EME_LOG_H_
 #define EME_LOG_H_
 
+#include "VideoUtils.h"
 #include "mozilla/Logging.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
-static const char* const kEMEKeySystemClearkey = "org.w3.clearkey";
-static const char* const kEMEKeySystemWidevine = "com.widevine.alpha";
-static const char* const kEMEKeySystemPrimetime = "com.adobe.primetime";
-
 namespace dom {
 class ArrayBufferViewOrArrayBuffer;
 }
 
 #ifndef EME_LOG
   LogModule* GetEMELog();
   #define EME_LOG(...) MOZ_LOG(GetEMELog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
   #define EME_LOG_ENABLED() MOZ_LOG_TEST(GetEMELog(), mozilla::LogLevel::Debug)
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -333,17 +333,17 @@ MediaKeySession::Close(ErrorResult& aRv)
     EME_LOG("MediaKeySession[%p,''] Close() called before sessionId set by CDM", this);
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
       NS_LITERAL_CSTRING("MediaKeySession.Close() called before sessionId set by CDM"));
     return promise.forget();
   }
   if (IsClosed() || !mKeys->GetCDMProxy()) {
     EME_LOG("MediaKeySession[%p,'%s'] Close() already closed",
             this, NS_ConvertUTF16toUTF8(mSessionId).get());
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
   PromiseId pid = mKeys->StorePromise(promise);
   mKeys->GetCDMProxy()->CloseSession(mSessionId, pid);
 
   EME_LOG("MediaKeySession[%p,'%s'] Close() sent to CDM, promiseId=%d",
           this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid);
 
@@ -356,17 +356,17 @@ MediaKeySession::OnClosed()
   if (IsClosed()) {
     return;
   }
   EME_LOG("MediaKeySession[%p,'%s'] session close operation complete.",
           this, NS_ConvertUTF16toUTF8(mSessionId).get());
   mIsClosed = true;
   mKeys->OnSessionClosed(this);
   mKeys = nullptr;
-  mClosed->MaybeResolve(JS::UndefinedHandleValue);
+  mClosed->MaybeResolveWithUndefined();
 }
 
 bool
 MediaKeySession::IsClosed() const
 {
   return mIsClosed;
 }
 
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -278,17 +278,17 @@ MediaKeys::ResolvePromise(PromiseId aId)
                            NS_LITERAL_CSTRING("CDM LoadSession() returned a different session ID than requested"));
       mPendingSessions.Remove(aId);
       return;
     }
     mPendingSessions.Remove(aId);
     mKeySessions.Put(session->GetSessionId(), session);
     promise->MaybeResolve(session);
   } else {
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
   }
   MOZ_ASSERT(!mPromises.Contains(aId));
 }
 
 class MediaKeysGMPCrashHelper : public GMPCrashHelper
 {
 public:
   explicit MediaKeysGMPCrashHelper(MediaKeys* aMediaKeys)
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -18,16 +18,17 @@
 #include "nsIObserverService.h"
 #include "GMPTimerParent.h"
 #include "runnable_utils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
 #include "GMPContentParent.h"
 #include "MediaPrefs.h"
+#include "VideoUtils.h"
 
 #include "mozilla/dom/CrashReporterParent.h"
 using mozilla::dom::CrashReporterParent;
 using mozilla::ipc::GeckoChildProcessHost;
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsPrintfCString.h"
 using CrashReporter::AnnotationTable;
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -30,18 +30,16 @@ EXPORTS += [
     'gmp-api/gmp-video-frame.h',
     'gmp-api/gmp-video-host.h',
     'gmp-api/gmp-video-plane.h',
     'GMPAudioDecoderChild.h',
     'GMPAudioDecoderParent.h',
     'GMPAudioDecoderProxy.h',
     'GMPAudioHost.h',
     'GMPCallbackBase.h',
-    'GMPCDMCallbackProxy.h',
-    'GMPCDMProxy.h',
     'GMPChild.h',
     'GMPContentChild.h',
     'GMPContentParent.h',
     'GMPCrashHelperHolder.h',
     'GMPDecryptorChild.h',
     'GMPDecryptorParent.h',
     'GMPDecryptorProxy.h',
     'GMPEncryptedBufferDataImpl.h',
@@ -68,32 +66,36 @@ EXPORTS += [
     'GMPVideoEncoderChild.h',
     'GMPVideoEncoderParent.h',
     'GMPVideoEncoderProxy.h',
     'GMPVideoHost.h',
     'GMPVideoi420FrameImpl.h',
     'GMPVideoPlaneImpl.h',
 ]
 
+if CONFIG['MOZ_EME']:
+    EXPORTS += [
+        'GMPCDMCallbackProxy.h',
+        'GMPCDMProxy.h',
+    ]
+
 # We link GMPLoader into xul on B2G/Fennec as its code does not need to be
 # covered by a DRM vendor's voucher.
 if CONFIG['OS_TARGET'] == 'Android':
     SOURCES += [
       'GMPLoader.cpp',
     ]
     USE_LIBS += [
         'rlz',
     ]
 
 UNIFIED_SOURCES += [
     'GMPAudioDecoderChild.cpp',
     'GMPAudioDecoderParent.cpp',
     'GMPAudioHost.cpp',
-    'GMPCDMCallbackProxy.cpp',
-    'GMPCDMProxy.cpp',
     'GMPChild.cpp',
     'GMPContentChild.cpp',
     'GMPContentParent.cpp',
     'GMPDecryptorChild.cpp',
     'GMPDecryptorParent.cpp',
     'GMPDiskStorage.cpp',
     'GMPEncryptedBufferDataImpl.cpp',
     'GMPMemoryStorage.cpp',
@@ -115,16 +117,22 @@ UNIFIED_SOURCES += [
     'GMPVideoEncodedFrameImpl.cpp',
     'GMPVideoEncoderChild.cpp',
     'GMPVideoEncoderParent.cpp',
     'GMPVideoHost.cpp',
     'GMPVideoi420FrameImpl.cpp',
     'GMPVideoPlaneImpl.cpp',
 ]
 
+if CONFIG['MOZ_EME']:
+    UNIFIED_SOURCES += [
+        'GMPCDMCallbackProxy.cpp',
+        'GMPCDMProxy.cpp',
+    ]
+
 DIRS += [
     'rlz',
     'widevine-adapter',
 ]
 
 IPDL_SOURCES += [
   'GMPTypes.ipdlh',
   'PGMP.ipdl',
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
@@ -1,23 +1,23 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WidevineAdapter.h"
 #include "content_decryption_module.h"
+#include "VideoUtils.h"
 #include "WidevineDecryptor.h"
 #include "WidevineUtils.h"
 #include "WidevineVideoDecoder.h"
 #include "gmp-api/gmp-entrypoints.h"
 #include "gmp-api/gmp-decryption.h"
 #include "gmp-api/gmp-video-codec.h"
 #include "gmp-api/gmp-platform.h"
-#include "mozilla/EMEUtils.h"
 #include "mozilla/StaticPtr.h"
 
 static const GMPPlatformAPI* sPlatform = nullptr;
 
 namespace mozilla {
 
 StaticRefPtr<CDMWrapper> sCDMWrapper;
 
--- a/dom/media/ogg/OggDemuxer.cpp
+++ b/dom/media/ogg/OggDemuxer.cpp
@@ -7,16 +7,17 @@
 #include "nsError.h"
 #include "MediaDecoderStateMachine.h"
 #include "AbstractMediaDecoder.h"
 #include "OggDemuxer.h"
 #include "OggCodecState.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/SharedThreadPool.h"
+#include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "MediaDataDemuxer.h"
 #include "nsAutoRef.h"
 #include "XiphExtradata.h"
 
 #include <algorithm>
 
 extern mozilla::LazyLogModule gMediaDemuxerLog;
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
@@ -5,19 +5,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPDecoderModule.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "GMPAudioDecoder.h"
 #include "GMPVideoDecoder.h"
 #include "MediaDataDecoderProxy.h"
 #include "MediaPrefs.h"
+#include "VideoUtils.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "nsServiceManagerUtils.h"
-#include "mozilla/EMEUtils.h"
 #include "mozilla/StaticMutex.h"
 #include "gmp-audio-decode.h"
 #include "gmp-video-decode.h"
 #include "MP4Decoder.h"
 #include "VPXDecoder.h"
 #ifdef XP_WIN
 #include "WMFDecoderModule.h"
 #endif
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -866,17 +866,17 @@ AudioContext::OnStateChanged(void* aProm
 
   MOZ_ASSERT(
     mIsOffline || aPromise || aNewState == AudioContextState::Running,
     "We should have a promise here if this is a real-time AudioContext."
     "Or this is the first time we switch to \"running\".");
 
   if (aPromise) {
     Promise* promise = reinterpret_cast<Promise*>(aPromise);
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     DebugOnly<bool> rv = mPromiseGripArray.RemoveElement(promise);
     MOZ_ASSERT(rv, "Promise wasn't in the grip array?");
   }
 
   if (mAudioContextState != aNewState) {
     RefPtr<OnStateChangeTask> onStateChangeTask =
       new OnStateChangeTask(this);
     NS_DispatchToMainThread(onStateChangeTask);
--- a/dom/mobilemessage/MobileMessageCallback.cpp
+++ b/dom/mobilemessage/MobileMessageCallback.cpp
@@ -359,17 +359,17 @@ MobileMessageCallback::NotifyGetSmscAddr
   const nsAString& errorStr = ConvertErrorCodeToErrorString(aError);
   mPromise->MaybeRejectBrokenly(errorStr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileMessageCallback::NotifySetSmscAddress()
 {
-  mPromise->MaybeResolve(JS::UndefinedHandleValue);
+  mPromise->MaybeResolveWithUndefined();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileMessageCallback::NotifySetSmscAddressFailed(int32_t aError)
 {
   const nsAString& errorStr = ConvertErrorCodeToErrorString(aError);
   mPromise->MaybeRejectBrokenly(errorStr);
--- a/dom/network/UDPSocket.cpp
+++ b/dom/network/UDPSocket.cpp
@@ -193,17 +193,17 @@ UDPSocket::CloseWithReason(nsresult aRea
 
   if (mSocketChild) {
     mSocketChild->Close();
     mSocketChild = nullptr;
   }
 
   if (mClosed) {
     if (NS_SUCCEEDED(aReason)) {
-      mClosed->MaybeResolve(JS::UndefinedHandleValue);
+      mClosed->MaybeResolveWithUndefined();
     } else {
       mClosed->MaybeReject(aReason);
     }
   }
 
   mPendingMcastCommands.Clear();
 }
 
@@ -464,17 +464,17 @@ UDPSocket::InitLocal(const nsAString& aL
   }
 
   mReadyState = SocketReadyState::Open;
   rv = DoPendingMcastCommand();
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  mOpened->MaybeResolve(JS::UndefinedHandleValue);
+  mOpened->MaybeResolveWithUndefined();
 
   return NS_OK;
 }
 
 nsresult
 UDPSocket::InitRemote(const nsAString& aLocalAddress,
                       const uint16_t& aLocalPort)
 {
@@ -731,17 +731,17 @@ UDPSocket::CallListenerOpened()
   mReadyState = SocketReadyState::Open;
   nsresult rv = DoPendingMcastCommand();
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     CloseWithReason(rv);
     return NS_OK;
   }
 
-  mOpened->MaybeResolve(JS::UndefinedHandleValue);
+  mOpened->MaybeResolveWithUndefined();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 UDPSocket::CallListenerConnected()
 {
   // This shouldn't be called here.
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -2705,17 +2705,17 @@ Notification::ShowPersistentNotification
     result.ThrowTypeError<MSG_NOTIFICATION_PERMISSION_DENIED>();
     p->MaybeReject(result);
     return p.forget();
   }
 
   // "Otherwise, resolve promise with undefined."
   // The Notification may still not be shown due to other errors, but the spec
   // is not concerned with those.
-  p->MaybeResolve(JS::UndefinedHandleValue);
+  p->MaybeResolveWithUndefined();
 
   RefPtr<Notification> notification =
     CreateAndShow(aCx, aGlobal, aTitle, aOptions, aScope, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   return p.forget();
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -168,19 +168,19 @@ PresentationDeviceRequest::CreateSession
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationDeviceRequest::Cancel()
+PresentationDeviceRequest::Cancel(nsresult aReason)
 {
-  return mCallback->NotifyError(NS_ERROR_DOM_ABORT_ERR);
+  return mCallback->NotifyError(aReason);
 }
 
 /*
  * Implementation of PresentationService
  */
 
 NS_IMPL_ISUPPORTS_INHERITED(PresentationService,
                             PresentationServiceBase,
--- a/dom/presentation/interfaces/nsIPresentationDevicePrompt.idl
+++ b/dom/presentation/interfaces/nsIPresentationDevicePrompt.idl
@@ -24,19 +24,20 @@ interface nsIPresentationDeviceRequest :
 
   /*
    * Callback after selecting a device
    * @param device The selected device.
    */
   void select(in nsIPresentationDevice device);
 
   /*
-    Callback after selection failed or canceled by user.
+   * Callback after selection failed or canceled by user.
+   * @param reason The error cause for canceling this request.
    */
-  void cancel();
+  void cancel(in nsresult reason);
 };
 
 /*
  * UI prompt for device selection.
  */
 [scriptable, uuid(ac1a7e44-de86-454f-a9f1-276de2539831)]
 interface nsIPresentationDevicePrompt : nsISupports
 {
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -204,18 +204,18 @@ const mockedDevicePrompt = {
   },
   promptDeviceSelection: function(request) {
     this._request = request;
     sendAsyncMessage('device-prompt');
   },
   simulateSelect: function() {
     this._request.select(mockedDevice);
   },
-  simulateCancel: function() {
-    this._request.cancel();
+  simulateCancel: function(result) {
+    this._request.cancel(result);
   }
 };
 
 const mockedSessionTransport = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport,
                                          Ci.nsIPresentationTCPSessionTransportBuilder,
                                          Ci.nsIPresentationDataChannelSessionTransportBuilder,
                                          Ci.nsIPresentationControlChannelListener,
@@ -388,18 +388,18 @@ addMessageListener('trigger-device-add',
                       .getService(Ci.nsIPresentationDeviceManager);
   deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener).addDevice(mockedDevice);
 });
 
 addMessageListener('trigger-device-prompt-select', function() {
   mockedDevicePrompt.simulateSelect();
 });
 
-addMessageListener('trigger-device-prompt-cancel', function() {
-  mockedDevicePrompt.simulateCancel();
+addMessageListener('trigger-device-prompt-cancel', function(result) {
+  mockedDevicePrompt.simulateCancel(result);
 });
 
 addMessageListener('trigger-incoming-session-request', function(url) {
   var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
                       .getService(Ci.nsIPresentationDeviceManager);
   deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
 	       .onSessionRequest(mockedDevice, url, sessionId, mockedControlChannel);
 });
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender_establish_connection_error.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender_establish_connection_error.html
@@ -51,26 +51,47 @@ function testCreateRequestWithEmptyURL()
   });
 }
 
 function testStartConnectionCancelPrompt() {
   return new Promise(function(aResolve, aReject) {
     gScript.addMessageListener('device-prompt', function devicePromptHandler() {
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
-      gScript.sendAsyncMessage('trigger-device-prompt-cancel');
+      gScript.sendAsyncMessage('trigger-device-prompt-cancel', SpecialPowers.Cr.NS_ERROR_DOM_NOT_ALLOWED_ERR);
     });
 
     request.start().then(
       function(aConnection) {
         ok(false, "|start| shouldn't succeed in this case.");
         aReject();
       },
       function(aError) {
-        is(aError.name, "AbortError", "AbortError is expected when the prompt is canceled.");
+        is(aError.name, "NotAllowedError", "NotAllowedError is expected when the prompt is canceled.");
+        aResolve();
+      }
+    );
+  });
+}
+
+function testStartConnectionNoDevice() {
+  return new Promise(function(aResolve, aReject) {
+    gScript.addMessageListener('device-prompt', function devicePromptHandler() {
+      gScript.removeMessageListener('device-prompt', devicePromptHandler);
+      info("Device prompt is triggered.");
+      gScript.sendAsyncMessage('trigger-device-prompt-cancel', SpecialPowers.Cr.NS_ERROR_DOM_NOT_FOUND_ERR);
+    });
+
+    request.start().then(
+      function(aConnection) {
+        ok(false, "|start| shouldn't succeed in this case.");
+        aReject();
+      },
+      function(aError) {
+        is(aError.name, "NotFoundError", "NotFoundError is expected when no available device.");
         aResolve();
       }
     );
   });
 }
 
 function testStartConnectionUnexpectedControlChannelCloseBeforeDataTransportInit() {
   return new Promise(function(aResolve, aReject) {
@@ -356,16 +377,17 @@ function teardown() {
 }
 
 function runTests() {
   ok(window.PresentationRequest, "PresentationRequest should be available.");
 
   testCreateRequestWithEmptyURL().
   then(setup).
   then(testStartConnectionCancelPrompt).
+  then(testStartConnectionNoDevice).
   then(testStartConnectionUnexpectedControlChannelCloseBeforeDataTransportInit).
   then(testStartConnectionUnexpectedControlChannelCloseNoReasonBeforeDataTransportInit).
   then(testStartConnectionUnexpectedControlChannelCloseBeforeDataTransportReady).
   then(testStartConnectionUnexpectedControlChannelCloseNoReasonBeforeDataTransportReady).
   then(testStartConnectionUnexpectedDataTransportClose).
   then(teardown);
 }
 
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -921,16 +921,24 @@ Promise::MaybeReject(JSContext* aCx,
   NS_ASSERT_OWNINGTHREAD(Promise);
 
   MaybeRejectInternal(aCx, aValue);
 }
 
 #endif // SPIDERMONKEY_PROMISE
 
 void
+Promise::MaybeResolveWithUndefined()
+{
+  NS_ASSERT_OWNINGTHREAD(Promise);
+
+  MaybeResolve(JS::UndefinedHandleValue);
+}
+
+void
 Promise::MaybeReject(const RefPtr<MediaStreamError>& aArg) {
   NS_ASSERT_OWNINGTHREAD(Promise);
 
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 
 void
 Promise::MaybeRejectWithNull()
@@ -943,17 +951,16 @@ Promise::MaybeRejectWithNull()
 void
 Promise::MaybeRejectWithUndefined()
 {
   NS_ASSERT_OWNINGTHREAD(Promise);
 
   MaybeSomething(JS::UndefinedHandleValue, &Promise::MaybeReject);
 }
 
-
 #ifdef SPIDERMONKEY_PROMISE
 void
 Promise::ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise)
 {
   MOZ_ASSERT(!js::IsWrapper(aPromise));
 
   MOZ_ASSERT(JS::GetPromiseState(aPromise) == JS::PromiseState::Rejected);
 
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -135,16 +135,18 @@ public:
   // Most DOM objects are handled already.  To add a new type T, add a
   // ToJSValue overload in ToJSValue.h.
   // aArg is a const reference so we can pass rvalues like integer constants
   template <typename T>
   void MaybeResolve(const T& aArg) {
     MaybeSomething(aArg, &Promise::MaybeResolve);
   }
 
+  void MaybeResolveWithUndefined();
+
   inline void MaybeReject(nsresult aArg) {
     MOZ_ASSERT(NS_FAILED(aArg));
     MaybeSomething(aArg, &Promise::MaybeReject);
   }
 
   inline void MaybeReject(ErrorResult& aArg) {
     MOZ_ASSERT(aArg.Failed());
     MaybeSomething(aArg, &Promise::MaybeReject);
--- a/dom/storage/DOMStorage.cpp
+++ b/dom/storage/DOMStorage.cpp
@@ -39,24 +39,22 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorage)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 DOMStorage::DOMStorage(nsPIDOMWindowInner* aWindow,
                        DOMStorageManager* aManager,
                        DOMStorageCache* aCache,
                        const nsAString& aDocumentURI,
-                       nsIPrincipal* aPrincipal,
-                       bool aIsPrivate)
+                       nsIPrincipal* aPrincipal)
 : mWindow(aWindow)
 , mManager(aManager)
 , mCache(aCache)
 , mDocumentURI(aDocumentURI)
 , mPrincipal(aPrincipal)
-, mIsPrivate(aIsPrivate)
 , mIsSessionOnly(false)
 {
   mCache->Preload();
 }
 
 DOMStorage::~DOMStorage()
 {
   mCache->KeepAlive();
@@ -226,18 +224,16 @@ DOMStorage::BroadcastChangeNotification(
 static const char kPermissionType[] = "cookie";
 static const char kStorageEnabled[] = "dom.storage.enabled";
 
 // static, public
 bool
 DOMStorage::CanUseStorage(nsPIDOMWindowInner* aWindow, DOMStorage* aStorage)
 {
   // This method is responsible for correct setting of mIsSessionOnly.
-  // It doesn't work with mIsPrivate flag at all, since it is checked
-  // regardless mIsSessionOnly flag in DOMStorageCache code.
 
   if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
     return false;
   }
 
   nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess::eDeny;
   if (aWindow) {
     access = nsContentUtils::StorageAllowedForWindow(aWindow);
@@ -278,16 +274,27 @@ PrincipalsEqual(nsIPrincipal* aObjectPri
 
 bool
 DOMStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
 {
   return PrincipalsEqual(mPrincipal, aPrincipal);
 }
 
 bool
+DOMStorage::IsPrivate() const
+{
+  uint32_t privateBrowsingId = 0;
+  nsresult rv = mPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  return privateBrowsingId > 0;
+}
+
+bool
 DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
 {
   return !aPrincipal || aPrincipal->Subsumes(mPrincipal);
 }
 
 void
 DOMStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
 {
--- a/dom/storage/DOMStorage.h
+++ b/dom/storage/DOMStorage.h
@@ -49,27 +49,22 @@ public:
   DOMStorageCache const* GetCache() const
   {
     return mCache;
   }
 
   nsIPrincipal* GetPrincipal();
   bool PrincipalEquals(nsIPrincipal* aPrincipal);
   bool CanAccess(nsIPrincipal* aPrincipal);
-  bool IsPrivate()
-  {
-    return mIsPrivate;
-  }
 
   DOMStorage(nsPIDOMWindowInner* aWindow,
              DOMStorageManager* aManager,
              DOMStorageCache* aCache,
              const nsAString& aDocumentURI,
-             nsIPrincipal* aPrincipal,
-             bool aIsPrivate);
+             nsIPrincipal* aPrincipal);
 
   // WebIDL
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsPIDOMWindowInner* GetParentObject() const
   {
     return mWindow;
   }
@@ -114,17 +109,17 @@ public:
   // on a storage is about to happen and ensures that the storage's
   // session-only flag is properly set according the current settings.
   // It is an optimization since the privileges check and session only
   // state determination are complex and share the code (comes hand in
   // hand together).
   static bool CanUseStorage(nsPIDOMWindowInner* aWindow,
                             DOMStorage* aStorage = nullptr);
 
-  bool IsPrivate() const { return mIsPrivate; }
+  bool IsPrivate() const;
   bool IsSessionOnly() const { return mIsSessionOnly; }
 
   bool IsForkOf(const DOMStorage* aOther) const
   {
     MOZ_ASSERT(aOther);
     return mCache == aOther->mCache;
   }
 
@@ -138,19 +133,16 @@ private:
   RefPtr<DOMStorageManager> mManager;
   RefPtr<DOMStorageCache> mCache;
   nsString mDocumentURI;
 
   // Principal this DOMStorage (i.e. localStorage or sessionStorage) has
   // been created for
   nsCOMPtr<nsIPrincipal> mPrincipal;
 
-  // Whether this storage is running in private-browsing window.
-  bool mIsPrivate : 1;
-
   // Whether storage is set to persist data only per session, may change
   // dynamically and is set by CanUseStorage function that is called
   // before any operation on the storage.
   bool mIsSessionOnly : 1;
 
   void BroadcastChangeNotification(const nsSubstring& aKey,
                                    const nsSubstring& aOldValue,
                                    const nsSubstring& aNewValue);
--- a/dom/storage/DOMStorageCache.h
+++ b/dom/storage/DOMStorageCache.h
@@ -96,17 +96,17 @@ public:
   // Starts async preload of this cache if it persistent and not loaded.
   void Preload();
 
   // Keeps the cache alive (i.e. present in the manager's hash table) for a time.
   void KeepAlive();
 
   // The set of methods that are invoked by DOM storage web API.
   // We are passing the DOMStorage object just to let the cache
-  // read properties like mPrivate and mSessionOnly.
+  // read properties like mPrincipal and mSessionOnly.
   // Get* methods return error when load from the database has failed.
   nsresult GetLength(const DOMStorage* aStorage, uint32_t* aRetval);
   nsresult GetKey(const DOMStorage* aStorage, uint32_t index, nsAString& aRetval);
   nsresult GetItem(const DOMStorage* aStorage, const nsAString& aKey, nsAString& aRetval);
   nsresult SetItem(const DOMStorage* aStorage, const nsAString& aKey, const nsString& aValue, nsString& aOld);
   nsresult RemoveItem(const DOMStorage* aStorage, const nsAString& aKey, nsString& aOld);
   nsresult Clear(const DOMStorage* aStorage);
 
--- a/dom/storage/DOMStorageManager.cpp
+++ b/dom/storage/DOMStorageManager.cpp
@@ -305,17 +305,16 @@ DOMStorageManager::DropCache(DOMStorageC
   table->RemoveEntry(aCache->OriginNoSuffix());
 }
 
 nsresult
 DOMStorageManager::GetStorageInternal(bool aCreate,
                                       mozIDOMWindow* aWindow,
                                       nsIPrincipal* aPrincipal,
                                       const nsAString& aDocumentURI,
-                                      bool aPrivate,
                                       nsIDOMStorage** aRetval)
 {
   nsresult rv;
 
   nsAutoCString originAttrSuffix;
   BasePrincipal::Cast(aPrincipal)->OriginAttributesRef().CreateSuffix(originAttrSuffix);
 
   nsAutoCString originKey;
@@ -356,49 +355,44 @@ DOMStorageManager::GetStorageInternal(bo
       return NS_ERROR_DOM_SECURITY_ERR;
     }
   }
 
   if (aRetval) {
     nsCOMPtr<nsPIDOMWindowInner> inner = nsPIDOMWindowInner::From(aWindow);
 
     nsCOMPtr<nsIDOMStorage> storage = new DOMStorage(
-      inner, this, cache, aDocumentURI, aPrincipal, aPrivate);
+      inner, this, cache, aDocumentURI, aPrincipal);
     storage.forget(aRetval);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DOMStorageManager::PrecacheStorage(nsIPrincipal* aPrincipal)
 {
-  return GetStorageInternal(true, nullptr, aPrincipal, EmptyString(), false,
-                            nullptr);
+  return GetStorageInternal(true, nullptr, aPrincipal, EmptyString(), nullptr);
 }
 
 NS_IMETHODIMP
 DOMStorageManager::CreateStorage(mozIDOMWindow* aWindow,
                                  nsIPrincipal* aPrincipal,
                                  const nsAString& aDocumentURI,
-                                 bool aPrivate,
                                  nsIDOMStorage** aRetval)
 {
-  return GetStorageInternal(true, aWindow, aPrincipal, aDocumentURI, aPrivate,
-                            aRetval);
+  return GetStorageInternal(true, aWindow, aPrincipal, aDocumentURI, aRetval);
 }
 
 NS_IMETHODIMP
 DOMStorageManager::GetStorage(mozIDOMWindow* aWindow,
                               nsIPrincipal* aPrincipal,
-                              bool aPrivate,
                               nsIDOMStorage** aRetval)
 {
-  return GetStorageInternal(false, aWindow, aPrincipal, EmptyString(), aPrivate,
-                            aRetval);
+  return GetStorageInternal(false, aWindow, aPrincipal, EmptyString(), aRetval);
 }
 
 NS_IMETHODIMP
 DOMStorageManager::CloneStorage(nsIDOMStorage* aStorage)
 {
   if (mType != SessionStorage) {
     // Cloning is supported only for sessionStorage
     return NS_ERROR_NOT_IMPLEMENTED;
@@ -468,24 +462,23 @@ DOMStorageManager::CheckStorage(nsIPrinc
   return NS_OK;
 }
 
 // Obsolete nsIDOMStorageManager methods
 
 NS_IMETHODIMP
 DOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal* aPrincipal,
                                                const nsAString& aDocumentURI,
-                                               bool aPrivate,
                                                nsIDOMStorage** aRetval)
 {
   if (mType != LocalStorage) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  return CreateStorage(nullptr, aPrincipal, aDocumentURI, aPrivate, aRetval);
+  return CreateStorage(nullptr, aPrincipal, aDocumentURI, aRetval);
 }
 
 void
 DOMStorageManager::ClearCaches(uint32_t aUnloadFlags,
                                const OriginAttributesPattern& aPattern,
                                const nsACString& aOriginScope)
 {
   for (auto iter1 = mCaches.Iter(); !iter1.Done(); iter1.Next()) {
--- a/dom/storage/DOMStorageManager.h
+++ b/dom/storage/DOMStorageManager.h
@@ -88,17 +88,16 @@ private:
                                              const nsACString& aOriginNoSuffix,
                                              nsIPrincipal* aPrincipal);
 
   // Helper for creation of DOM storage objects
   nsresult GetStorageInternal(bool aCreate,
                               mozIDOMWindow* aWindow,
                               nsIPrincipal* aPrincipal,
                               const nsAString& aDocumentURI,
-                              bool aPrivate,
                               nsIDOMStorage** aRetval);
 
   // Suffix->origin->cache map
   typedef nsTHashtable<DOMStorageCacheHashKey> CacheOriginHashtable;
   nsClassHashtable<nsCStringHashKey, CacheOriginHashtable> mCaches;
 
   const DOMStorage::StorageType mType;
 
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -768,17 +768,17 @@ Telephony::EnumerateCallState(nsITelepho
 NS_IMETHODIMP
 Telephony::EnumerateCallStateComplete()
 {
   // Set conference state.
   mGroup->ChangeState();
 
   HandleAudioAgentState();
   if (mReadyPromise) {
-    mReadyPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mReadyPromise->MaybeResolveWithUndefined();
   }
 
   if (NS_FAILED(mService->RegisterListener(mListener))) {
     NS_WARNING("Failed to register listener!");
   }
   return NS_OK;
 }
 
--- a/dom/telephony/TelephonyCallback.cpp
+++ b/dom/telephony/TelephonyCallback.cpp
@@ -19,17 +19,17 @@ TelephonyCallback::TelephonyCallback(Pro
 {
 }
 
 // nsITelephonyCallback
 
 NS_IMETHODIMP
 TelephonyCallback::NotifySuccess()
 {
-  mPromise->MaybeResolve(JS::UndefinedHandleValue);
+  mPromise->MaybeResolveWithUndefined();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyCallback::NotifyError(const nsAString& aError)
 {
   mPromise->MaybeRejectBrokenly(aError);
   return NS_OK;
new file mode 100644
index 0000000000000000000000000000000000000000..db812bd7d5367647d68fa2c2dbfa5bef3cdb084b
GIT binary patch
literal 91
zc%17D@N?(olHy`uVBq!ia0vp^DIm<q3?#jD*u{YqbAV5X>wg9Y$w!>#K(4T-i(^Oy
mWAXxR3D(64B0Wuk3=FIl42*JTHO>O189ZJ6T-G@yGywq3R1$9h
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -1,23 +1,25 @@
 [DEFAULT]
 support-files =
   497633.html
+  fail.png
   file_bug628069.html
   file_clonewrapper.html
   file_domWindowUtils_scrollbarSize.html
   file_frameElementWrapping.html
   file_interfaces.xml
   file_moving_nodeList.html
   file_moving_xhr.html
   file_showModalDialog.html
   historyframes.html
   image_50.png
   image_100.png
   image_200.png
+  pass.apng
   performance_timeline_main_test.html
   resource_timing_iframe.html
   resource_timing_main_test.html
   resource_timing_cross_origin.html
   res0.resource
   res1.resource
   res1.resource^headers^
   res2.resource
@@ -134,8 +136,9 @@ skip-if = buildapp == 'b2g' # Bug 118442
 [test_storagePermissionsLimitForeign.html]
 skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g
 [test_selectevents.html]
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Mouse doesn't select in the same way
 # Disabled on Android, see bug 1230232
 [test_WebKitCSSMatrix.html]
 [test_resource_timing_frameset.html]
 [test_bug1208217.html]
+[test_picture_apng.html]
new file mode 100644
index 0000000000000000000000000000000000000000..6e78a9eef4dae888be61ed4f8872b0743810b791
GIT binary patch
literal 188
zc%17D@N?(olHy`uVBq!ia0vp^DIm<j3?$ucQqzDGTYyi9D<dPL?|%k{#^Z575yp}r
zzhDN3XE#97ww^AIAsP4Ho@L}@VBle1u(tl?RtuRe4KEu#RD?QRlqTY)KG{n?Gg23P
z(BJwHXpnS?YeY$Kep*R+Vo@rCBhY0Ej>W~Pxk)*xMG8iGmTJ-e`hm(AJYD@<);T3K
F0RXuSHVFU#
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_picture_apng.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  <title>Image srcset mutations</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<script type="application/javascript">
+"use strict";
+window.onload = function() {
+  // Smoke test, check picture working as expected
+  const t0 = document.querySelector("#test0 img");
+  ok(t0.currentSrc.endsWith("apng"), `t0: expected pass.apng, got '${t0.currentSrc}'`);
+
+  // Test that the apng is selected over bogus types.
+  const t1 = document.querySelector("#test1 img");
+  ok(t1.currentSrc.endsWith("apng"), `t1: expected pass.apng, got '${t1.currentSrc}'`);
+
+  // Test that tree order precedence applies
+  const t2 = document.querySelector("#test2 img");
+  ok(t2.currentSrc.endsWith("apng"), `t2: expected pass.apng, got '${t2.currentSrc}'`);
+
+  // Test that apng doesn't alway win
+  const t3 = document.querySelector("#test3 img");
+  ok(t3.currentSrc.endsWith("apng"), `t3: expected pass.apng, got '${t3.currentSrc}'`);
+
+  // Test dynamically constructed picture, where apng is selected over a bogus
+  // source or the img src attribute
+  const pic = document.createElement("picture");
+  pic.id = "test4";
+  const t4 = document.createElement("img");
+  const bogusSource = document.createElement("source");
+  bogusSource.type = "bogus/bogus";
+  bogusSource.srcset = "fail.png";
+  const legitSource = document.createElement("source");
+  legitSource.type = "image/apng";
+  legitSource.srcset = "pass.apng";
+  pic.appendChild(bogusSource);
+  pic.appendChild(legitSource);
+  pic.appendChild(t4);
+  t4.src = "fail.png";
+  document.body.appendChild(pic);
+  t4.onload = ()=>{
+    ok(t4.currentSrc.endsWith("apng"), `t4: Expected pass.apng, got '${t4.currentSrc}'`);
+    SimpleTest.finish();
+  }
+};
+SimpleTest.waitForExplicitFinish();
+</script>
+
+<body>
+  <picture id="test0">
+    <srouce>
+    <img src="pass.apng">
+  </picture>
+  <picture id="test1">
+    <source type="bogus/type" srcset="fail.png">
+    <source type="image/apng" srcset="pass.apng">
+    <source type="image/jpeg" srcset="fail.png">
+    <img src="fail-fallback">
+  </picture>
+  <picture id="test2">
+    <source type="image/png" srcset="pass.apng">
+    <source srcset="fail.png">
+    <source type="bogus/type" srcset="fail.png">
+    <img src="fail-fallback">
+  </picture>
+  <picture id="test3">
+    <source type="image/jpeg" srcset="pass.apng">
+    <source type="image/apng" srcset="fail.png">
+    <img src="fail-fallback">
+  </picture>
+</body>
+
+</html>
--- a/dom/tv/TVServiceCallbacks.cpp
+++ b/dom/tv/TVServiceCallbacks.cpp
@@ -54,17 +54,17 @@ TVServiceSourceSetterCallback::NotifySuc
   }
 
   nsresult rv = mTuner->SetCurrentSource(mSourceType);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mPromise->MaybeReject(rv);
     return rv;
   }
 
-  mPromise->MaybeResolve(JS::UndefinedHandleValue);
+  mPromise->MaybeResolveWithUndefined();
   return NS_OK;
 }
 
 /* virtual */ NS_IMETHODIMP
 TVServiceSourceSetterCallback::NotifyError(uint16_t aErrorCode)
 {
   switch (aErrorCode) {
   case nsITVServiceCallback::TV_ERROR_FAILURE:
@@ -119,17 +119,17 @@ TVServiceChannelScanCallback::NotifySucc
   // |aDataList| is expected to be null for setter callbacks.
   if (aDataList) {
     mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     return NS_ERROR_INVALID_ARG;
   }
 
   mSource->SetIsScanning(mIsScanning);
 
-  mPromise->MaybeResolve(JS::UndefinedHandleValue);
+  mPromise->MaybeResolveWithUndefined();
   return NS_OK;
 }
 
 /* virtual */ NS_IMETHODIMP
 TVServiceChannelScanCallback::NotifyError(uint16_t aErrorCode)
 {
   switch (aErrorCode) {
   case nsITVServiceCallback::TV_ERROR_FAILURE:
@@ -206,17 +206,17 @@ TVServiceChannelSetterCallback::NotifySu
   }
 
   rv = mSource->SetCurrentChannel(channelData);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     return rv;
   }
 
-  mPromise->MaybeResolve(JS::UndefinedHandleValue);
+  mPromise->MaybeResolveWithUndefined();
   return NS_OK;
 }
 
 /* virtual */ NS_IMETHODIMP
 TVServiceChannelSetterCallback::NotifyError(uint16_t aErrorCode)
 {
   switch (aErrorCode) {
   case nsITVServiceCallback::TV_ERROR_FAILURE:
@@ -429,17 +429,17 @@ TVServiceProgramGetterCallback::NotifySu
   uint32_t length;
   nsresult rv = aDataList->GetLength(&length);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     return rv;
   }
 
   if (mIsSingular && length == 0) {
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
     return NS_OK;
   }
 
   if (mIsSingular) {
     nsCOMPtr<nsITVProgramData> programData = do_QueryElementAt(aDataList, 0);
     if (NS_WARN_IF(!programData)) {
       mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
       return NS_ERROR_DOM_ABORT_ERR;
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -148,18 +148,16 @@ interface CanvasRenderingContext2D {
 
   // Mozilla-specific stuff
   // FIXME Bug 768048 mozCurrentTransform/mozCurrentTransformInverse should return a WebIDL array.
   [Throws]
   attribute object mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
   [Throws]
   attribute object mozCurrentTransformInverse;
 
-  attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
-
   [Throws]
   attribute any mozDash; /* default |null| */
 
   [LenientFloat]
   attribute double mozDashOffset; /* default 0.0 */
 
   [SetterThrows]
   attribute DOMString mozTextStyle;
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -110,21 +110,21 @@ interface HTMLInputElement : HTMLElement
   void setCustomValidity(DOMString error);
 
   // Bug 850365 readonly attribute NodeList labels;
 
   void select();
 
   [Throws]
            // TODO: unsigned vs signed
-           attribute long selectionStart;
+           attribute long? selectionStart;
   [Throws]
-           attribute long selectionEnd;
+           attribute long? selectionEnd;
   [Throws]
-           attribute DOMString selectionDirection;
+           attribute DOMString? selectionDirection;
   [Throws]
   void setRangeText(DOMString replacement);
   [Throws]
   void setRangeText(DOMString replacement, unsigned long start,
     unsigned long end, optional SelectionMode selectionMode = "preserve");
 
   // also has obsolete members
 };
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -54,21 +54,21 @@ interface HTMLTextAreaElement : HTMLElem
   boolean checkValidity();
   boolean reportValidity();
   void setCustomValidity(DOMString error);
 
   // readonly attribute NodeList labels;
 
   void select();
   [Throws]
-           attribute unsigned long selectionStart;
+           attribute unsigned long? selectionStart;
   [Throws]
-           attribute unsigned long selectionEnd;
+           attribute unsigned long? selectionEnd;
   [Throws]
-           attribute DOMString selectionDirection;
+           attribute DOMString? selectionDirection;
   [Throws]
   void setRangeText(DOMString replacement);
   [Throws]
   void setRangeText(DOMString replacement, unsigned long start,
     unsigned long end, optional SelectionMode selectionMode = "preserve");
   [Throws]
   void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
 };
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -92,17 +92,17 @@ class GetRunnable final : public Runnabl
 
       if (NS_FAILED(mRv)) {
         promise->MaybeReject(mRv);
       } else if (mValue) {
         RefPtr<ServiceWorkerWindowClient> windowClient =
           new ServiceWorkerWindowClient(promise->GetParentObject(), *mValue);
         promise->MaybeResolve(windowClient.get());
       } else {
-        promise->MaybeResolve(JS::UndefinedHandleValue);
+        promise->MaybeResolveWithUndefined();
       }
       mPromiseProxy->CleanUp();
       return true;
     }
   };
 
   RefPtr<PromiseWorkerProxy> mPromiseProxy;
   nsString mClientId;
@@ -241,17 +241,17 @@ public:
   {
     MOZ_ASSERT(aWorkerPrivate);
     aWorkerPrivate->AssertIsOnWorkerThread();
 
     RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
     MOZ_ASSERT(promise);
 
     if (NS_SUCCEEDED(mResult)) {
-      promise->MaybeResolve(JS::UndefinedHandleValue);
+      promise->MaybeResolveWithUndefined();
     } else {
       promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     }
 
     mPromiseProxy->CleanUp();
     return true;
   }
 };
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -808,17 +808,17 @@ public:
       mPromise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
       return NS_OK;
     }
 
     RefPtr<ServiceWorkerRegistrationInfo> registration =
       swm->GetServiceWorkerRegistrationInfo(principal, uri);
 
     if (!registration) {
-      mPromise->MaybeResolve(JS::UndefinedHandleValue);
+      mPromise->MaybeResolveWithUndefined();
       return NS_OK;
     }
 
     NS_ConvertUTF8toUTF16 scope(registration->mScope);
     RefPtr<ServiceWorkerRegistration> swr =
       mWindow->GetServiceWorkerRegistration(scope);
     mPromise->MaybeResolve(swr);
 
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -371,17 +371,17 @@ public:
     : mPromise(aPromise)
   {
     AssertIsOnMainThread();
   }
 
   void
   UpdateSucceeded(ServiceWorkerRegistrationInfo* aRegistration) override
   {
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    mPromise->MaybeResolveWithUndefined();
   }
 
   void
   UpdateFailed(ErrorResult& aStatus) override
   {
     mPromise->MaybeReject(aStatus);
   }
 };
@@ -413,17 +413,17 @@ public:
     ErrorResult status;
     PickleIterator iter = PickleIterator(mSerializedErrorResult);
     Unused << IPC::ReadParam(&mSerializedErrorResult, &iter, &status);
 
     Promise* promise = mPromiseProxy->WorkerPromise();
     if (status.Failed()) {
       promise->MaybeReject(status);
     } else {
-      promise->MaybeResolve(JS::UndefinedHandleValue);
+      promise->MaybeResolveWithUndefined();
     }
     status.SuppressException();
     mPromiseProxy->CleanUp();
     return true;
   }
 };
 
 class WorkerThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
@@ -1114,17 +1114,17 @@ ServiceWorkerRegistrationWorkerThread::U
   if (aRv.Failed()) {
     return nullptr;
   }
 
   // Avoid infinite update loops by ignoring update() calls during top
   // level script evaluation.  See:
   // https://github.com/slightlyoff/ServiceWorker/issues/800
   if (worker->LoadScriptAsPartOfLoadingServiceWorkerScript()) {
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, promise);
   if (!proxy) {
     aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
     return nullptr;
   }
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -593,17 +593,17 @@ public:
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     MOZ_ASSERT(aWorkerPrivate);
     aWorkerPrivate->AssertIsOnWorkerThread();
 
     RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
 
     // Release the reference on the worker thread.
     mPromiseProxy->CleanUp();
 
     return true;
   }
 };
 
@@ -658,17 +658,17 @@ ServiceWorkerGlobalScope::SkipWaiting(Er
   RefPtr<Promise> promise = Promise::Create(this, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   RefPtr<PromiseWorkerProxy> promiseProxy =
     PromiseWorkerProxy::Create(mWorkerPrivate, promise);
   if (!promiseProxy) {
-    promise->MaybeResolve(JS::UndefinedHandleValue);
+    promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   RefPtr<WorkerScopeSkipWaitingRunnable> runnable =
     new WorkerScopeSkipWaitingRunnable(promiseProxy,
                                        NS_ConvertUTF16toUTF8(mScope));
 
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -1239,17 +1239,16 @@ nsWindowWatcher::OpenWindowInternal(mozI
     nsCOMPtr<nsIDOMStorageManager> newStorageManager =
       do_QueryInterface(newDocShell);
 
     if (parentStorageManager && newStorageManager) {
       nsCOMPtr<nsIDOMStorage> storage;
       nsCOMPtr<nsPIDOMWindowInner> pInnerWin = parentWindow->GetCurrentInnerWindow();
 
       parentStorageManager->GetStorage(pInnerWin, subjectPrincipal,
-                                       isPrivateBrowsingWindow,
                                        getter_AddRefs(storage));
       if (storage) {
         newStorageManager->CloneStorage(storage);
       }
     }
   }
 
   if (isNewToplevelWindow) {
--- a/extensions/cookie/test/unit/test_bug526789.js
+++ b/extensions/cookie/test/unit/test_bug526789.js
@@ -171,17 +171,16 @@ function run_test() {
   // aliases such as 'localhost', and eTLD's such as 'co.uk'; but that the
   // resulting cookie is for the exact host only.
   testDomainCookie("http://192.168.0.1/", "192.168.0.1");
   testDomainCookie("http://localhost/", "localhost");
   testDomainCookie("http://co.uk/", "co.uk");
 
   // Test that trailing dots are treated differently for purposes of the
   // 'domain' attribute when using setCookieString.
-  testTrailingDotCookie("http://192.168.0.1", "192.168.0.1");
   testTrailingDotCookie("http://localhost", "localhost");
   testTrailingDotCookie("http://foo.com", "foo.com");
 
   cm.removeAll();
 }
 
 function getCookieCount() {
   var count = 0;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -439,16 +439,19 @@ TextureClient::IsReadLocked() const
   return mReadLock && mReadLock->GetReadCount() > 1;
 }
 
 bool
 TextureClient::Lock(OpenMode aMode)
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(!mIsLocked);
+  if (!IsValid()) {
+    return false;
+  }
   if (mIsLocked) {
     return mOpenMode == aMode;
   }
 
   if (!!mFenceHandleWaiter && (aMode & OpenMode::OPEN_WRITE)) {
     mFenceHandleWaiter->WaitComplete();
   }
 
@@ -488,17 +491,17 @@ TextureClient::Lock(OpenMode aMode)
   return mIsLocked;
 }
 
 void
 TextureClient::Unlock()
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mIsLocked);
-  if (!mIsLocked) {
+  if (!IsValid() || !mIsLocked) {
     return;
   }
 
   if (mBorrowedDrawTarget) {
     if (mOpenMode & OpenMode::OPEN_WRITE) {
       mBorrowedDrawTarget->Flush();
       if (mReadbackSink && !mData->ReadBack(mReadbackSink)) {
         // Fallback implementation for reading back, because mData does not
@@ -617,17 +620,17 @@ TextureClient::BorrowDrawTarget()
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mIsLocked);
   // TODO- We can't really assert that at the moment because there is code that Borrows
   // the DrawTarget, just to get a snapshot, which is legit in term of OpenMode
   // but we should have a way to get a SourceSurface directly instead.
   //MOZ_ASSERT(mOpenMode & OpenMode::OPEN_WRITE);
 
-  if (!mIsLocked) {
+  if (!IsValid() || !mIsLocked) {
     return nullptr;
   }
 
   if (!NS_IsMainThread()) {
     return nullptr;
   }
 
   if (!mBorrowedDrawTarget) {
--- a/image/DecodedSurfaceProvider.cpp
+++ b/image/DecodedSurfaceProvider.cpp
@@ -15,16 +15,17 @@ using namespace mozilla::gfx;
 namespace mozilla {
 namespace image {
 
 DecodedSurfaceProvider::DecodedSurfaceProvider(NotNull<RasterImage*> aImage,
                                                NotNull<Decoder*> aDecoder,
                                                const SurfaceKey& aSurfaceKey)
   : ISurfaceProvider(AvailabilityState::StartAsPlaceholder())
   , mImage(aImage.get())
+  , mMutex("mozilla::image::DecodedSurfaceProvider")
   , mDecoder(aDecoder.get())
   , mSurfaceKey(aSurfaceKey)
 {
   MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
              "Use MetadataDecodingTask for metadata decodes");
   MOZ_ASSERT(mDecoder->IsFirstFrameDecode(),
              "Use AnimationDecodingTask for animation decodes");
 }
@@ -119,16 +120,18 @@ DecodedSurfaceProvider::LogicalSizeInByt
   // Single frame images are always 32bpp.
   IntSize size = mSurfaceKey.Size();
   return size.width * size.height * sizeof(uint32_t);
 }
 
 void
 DecodedSurfaceProvider::Run()
 {
+  MutexAutoLock lock(mMutex);
+
   if (!mDecoder || !mImage) {
     MOZ_ASSERT_UNREACHABLE("Running after decoding finished?");
     return;
   }
 
   // Run the decoder.
   LexerResult result = mDecoder->Decode(WrapNotNull(this));
 
@@ -157,16 +160,19 @@ DecodedSurfaceProvider::Run()
   MOZ_ASSERT_UNREACHABLE("Unexpected yield for single-frame image");
   mDecoder->TerminateFailure();
   FinishDecoding();
 }
 
 void
 DecodedSurfaceProvider::CheckForNewSurface()
 {
+  mMutex.AssertCurrentThreadOwns();
+  MOZ_ASSERT(mDecoder);
+
   if (mSurface) {
     // Single-frame images should produce no more than one surface, so if we
     // have one, it should be the same one the decoder is working on.
     MOZ_ASSERT(mSurface.get() == mDecoder->GetCurrentFrameRef().get(),
                "DecodedSurfaceProvider and Decoder have different surfaces?");
     return;
   }
 
@@ -181,16 +187,17 @@ DecodedSurfaceProvider::CheckForNewSurfa
   SurfaceCache::SurfaceAvailable(WrapNotNull(this),
                                  ImageKey(mImage.get()),
                                  mSurfaceKey);
 }
 
 void
 DecodedSurfaceProvider::FinishDecoding()
 {
+  mMutex.AssertCurrentThreadOwns();
   MOZ_ASSERT(mImage);
   MOZ_ASSERT(mDecoder);
 
   // Send notifications.
   NotifyDecodeComplete(WrapNotNull(mImage), WrapNotNull(mDecoder));
 
   // Destroy our decoder; we don't need it anymore. (And if we don't destroy it,
   // our surface can never be optimized, because the decoder has a
--- a/image/DecodedSurfaceProvider.h
+++ b/image/DecodedSurfaceProvider.h
@@ -65,16 +65,19 @@ private:
 
   void DropImageReference();
   void CheckForNewSurface();
   void FinishDecoding();
 
   /// The image associated with our decoder. Dropped after decoding.
   RefPtr<RasterImage> mImage;
 
+  /// Mutex protecting access to mDecoder.
+  Mutex mMutex;
+
   /// The decoder that will generate our surface. Dropped after decoding.
   RefPtr<Decoder> mDecoder;
 
   /// Our surface. Initially null until it's generated by the decoder.
   RefPtr<imgFrame> mSurface;
 
   /// A drawable reference to our service; used for locking.
   DrawableFrameRef mLockRef;
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -29,16 +29,18 @@ DecoderFactory::GetDecoderType(const cha
   // By default we don't know.
   DecoderType type = DecoderType::UNKNOWN;
 
   // PNG
   if (!strcmp(aMimeType, IMAGE_PNG)) {
     type = DecoderType::PNG;
   } else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
     type = DecoderType::PNG;
+  } else if (!strcmp(aMimeType, IMAGE_APNG)) {
+    type = DecoderType::PNG;
 
   // GIF
   } else if (!strcmp(aMimeType, IMAGE_GIF)) {
     type = DecoderType::GIF;
 
   // JPEG
   } else if (!strcmp(aMimeType, IMAGE_JPEG)) {
     type = DecoderType::JPEG;
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -100,27 +100,30 @@ IDecodingTask::Resume()
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // AnimationDecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
 AnimationDecodingTask::AnimationDecodingTask(NotNull<Decoder*> aDecoder)
-  : mDecoder(aDecoder)
+  : mMutex("mozilla::image::AnimationDecodingTask")
+  , mDecoder(aDecoder)
 {
   MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
              "Use MetadataDecodingTask for metadata decodes");
   MOZ_ASSERT(!mDecoder->IsFirstFrameDecode(),
              "Use DecodingTask for single-frame image decodes");
 }
 
 void
 AnimationDecodingTask::Run()
 {
+  MutexAutoLock lock(mMutex);
+
   while (true) {
     LexerResult result = mDecoder->Decode(WrapNotNull(this));
 
     if (result.is<TerminalState>()) {
       NotifyDecodeComplete(mDecoder->GetImage(), mDecoder);
       return;  // We're done.
     }
 
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -77,16 +77,19 @@ public:
 
   // Full decodes are low priority compared to metadata decodes because they
   // don't block layout or page load.
   TaskPriority Priority() const override { return TaskPriority::eLow; }
 
 private:
   virtual ~AnimationDecodingTask() { }
 
+  /// Mutex protecting access to mDecoder.
+  Mutex mMutex;
+
   NotNull<RefPtr<Decoder>> mDecoder;
 };
 
 
 /**
  * An IDecodingTask implementation for metadata decodes of images.
  */
 class MetadataDecodingTask final : public IDecodingTask
--- a/image/build/nsImageModule.cpp
+++ b/image/build/nsImageModule.cpp
@@ -75,16 +75,17 @@ static const mozilla::Module::CategoryEn
   { "Gecko-Content-Viewers", IMAGE_PJPEG, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_JPG, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_ICO, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_ICO_MS, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_BMP, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_BMP_MS, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_ICON_MS, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_PNG, "@mozilla.org/content/document-loader-factory;1" },
+  { "Gecko-Content-Viewers", IMAGE_APNG, "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", IMAGE_X_PNG, "@mozilla.org/content/document-loader-factory;1" },
   { "content-sniffing-services", "@mozilla.org/image/loader;1", "@mozilla.org/image/loader;1" },
   { nullptr }
 };
 
 static bool sInitialized = false;
 nsresult
 mozilla::image::EnsureModuleInitialized()
--- a/image/imgRequestProxy.cpp
+++ b/image/imgRequestProxy.cpp
@@ -663,17 +663,18 @@ imgRequestProxy::PerformClone(imgINotifi
 
 NS_IMETHODIMP
 imgRequestProxy::GetImagePrincipal(nsIPrincipal** aPrincipal)
 {
   if (!GetOwner()) {
     return NS_ERROR_FAILURE;
   }
 
-  NS_ADDREF(*aPrincipal = GetOwner()->GetPrincipal());
+  nsCOMPtr<nsIPrincipal> principal = GetOwner()->GetPrincipal();
+  principal.forget(aPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 imgRequestProxy::GetMultipart(bool* aMultipart)
 {
   if (!GetOwner()) {
     return NS_ERROR_FAILURE;
--- a/js/public/Initialization.h
+++ b/js/public/Initialization.h
@@ -81,16 +81,32 @@ JS_InitWithFailureDiagnostic(void)
 {
 #ifdef DEBUG
     return JS::detail::InitWithFailureDiagnostic(true);
 #else
     return JS::detail::InitWithFailureDiagnostic(false);
 #endif
 }
 
+/*
+ * Returns true if SpiderMonkey has been initialized successfully, even if it has
+ * possibly been shut down.
+ *
+ * Note that it is the responsibility of the embedder to call JS_Init() and
+ * JS_ShutDown() at the correct times, and therefore this API should ideally not
+ * be necessary to use.  This is only intended to be used in cases where the
+ * embedder isn't in full control of deciding whether to initialize SpiderMonkey
+ * or hand off the task to another consumer.
+ */
+inline bool
+JS_IsInitialized(void)
+{
+  return JS::detail::libraryInitState != JS::detail::InitState::Uninitialized;
+}
+
 /**
  * Destroy free-standing resources allocated by SpiderMonkey, not associated
  * with any runtime, context, or other structure.
  *
  * This method should be called after all other JSAPI data has been properly
  * cleaned up: every new runtime must have been destroyed, every new context
  * must have been destroyed, and so on.  Calling this method before all other
  * resources have been destroyed has undefined behavior.
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -452,16 +452,22 @@ BytecodeEmitter::emitDupAt(unsigned slot
     if (!emitN(JSOP_DUPAT, 3, &off))
         return false;
 
     jsbytecode* pc = code(off);
     SET_UINT24(pc, slotFromTop);
     return true;
 }
 
+bool
+BytecodeEmitter::emitCheckIsObj(CheckIsObjectKind kind)
+{
+    return emit2(JSOP_CHECKISOBJ, uint8_t(kind));
+}
+
 static const char*
 StatementName(StmtInfoBCE* stmt)
 {
     if (!stmt)
         return js_script_str;
 
     /* XXX too many "... statement" L10N gaffes -- fix via js.msg! */
     static const char* const statementName[] = {
@@ -4142,16 +4148,18 @@ BytecodeEmitter::emitIteratorNext(ParseN
     if (!emit1(JSOP_DUP))                                 // ... ITER ITER
         return false;
     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))     // ... ITER NEXT
         return false;
     if (!emit1(JSOP_SWAP))                                // ... NEXT ITER
         return false;
     if (!emitCall(JSOP_CALL, 0, pn))                      // ... RESULT
         return false;
+    if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
+        return false;
     checkTypeSet(JSOP_CALL);
     return true;
 }
 
 bool
 BytecodeEmitter::emitDefault(ParseNode* defaultExpr)
 {
     if (!emit1(JSOP_DUP))                                 // VALUE VALUE
@@ -7166,16 +7174,18 @@ BytecodeEmitter::emitYieldStar(ParseNode
     if (!emitAtomOp(cx->names().next, JSOP_CALLPROP))            // RECEIVED ITER ITER NEXT
         return false;
     if (!emit1(JSOP_SWAP))                                       // RECEIVED ITER NEXT ITER
         return false;
     if (!emit2(JSOP_PICK, 3))                                    // ITER NEXT ITER RECEIVED
         return false;
     if (!emitCall(JSOP_CALL, 1, iter))                           // ITER RESULT
         return false;
+    if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext))        // ITER RESULT
+        return false;
     checkTypeSet(JSOP_CALL);
     MOZ_ASSERT(this->stackDepth == depth);
 
     if (!emitJumpTargetAndPatch(checkResult))                    // checkResult:
         return false;
 
     // if (!result.done) goto tryStart;                          // ITER RESULT
     if (!emit1(JSOP_DUP))                                        // ITER RESULT RESULT
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -14,16 +14,17 @@
 #include "jscntxt.h"
 #include "jsopcode.h"
 #include "jsscript.h"
 
 #include "frontend/ParseMaps.h"
 #include "frontend/Parser.h"
 #include "frontend/SharedContext.h"
 #include "frontend/SourceNotes.h"
+#include "vm/Interpreter.h"
 
 namespace js {
 
 class ScopeObject;
 
 namespace frontend {
 
 class FullParseHandler;
@@ -499,16 +500,19 @@ struct BytecodeEmitter
 
     // Emit three bytecodes, an opcode with two bytes of immediate operands.
     MOZ_MUST_USE bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
 
     // Helper to emit JSOP_DUPAT. The argument is the value's depth on the
     // JS stack, as measured from the top.
     MOZ_MUST_USE bool emitDupAt(unsigned slotFromTop);
 
+    // Helper to emit JSOP_CHECKISOBJ.
+    MOZ_MUST_USE bool emitCheckIsObj(CheckIsObjectKind kind);
+
     // Emit a bytecode followed by an uint16 immediate operand stored in
     // big-endian order.
     MOZ_MUST_USE bool emitUint16Operand(JSOp op, uint32_t operand);
 
     // Emit a bytecode followed by an uint32 immediate operand.
     MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
 
     // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -18,16 +18,17 @@
 #include "asmjs/WasmJS.h"
 #include "builtin/ModuleObject.h"
 #include "gc/GCInternals.h"
 #include "gc/Policy.h"
 #include "jit/IonCode.h"
 #include "js/SliceBudget.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ArrayObject.h"
+#include "vm/Debugger.h"
 #include "vm/ScopeObject.h"
 #include "vm/Shape.h"
 #include "vm/Symbol.h"
 #include "vm/TypedArrayObject.h"
 #include "vm/UnboxedObject.h"
 
 #include "jscompartmentinlines.h"
 #include "jsgcinlines.h"
--- a/js/src/gc/Policy.h
+++ b/js/src/gc/Policy.h
@@ -25,16 +25,17 @@ class AccessorShape;
 class ArgumentsObject;
 class ArrayBufferObject;
 class ArrayBufferObjectMaybeShared;
 class ArrayBufferViewObject;
 class ArrayObject;
 class BaseShape;
 class ClonedBlockObject;
 class DebugScopeObject;
+class DebuggerFrame;
 class ExportEntryObject;
 class GlobalObject;
 class ImportEntryObject;
 class LazyScript;
 class ModuleEnvironmentObject;
 class ModuleNamespaceObject;
 class ModuleObject;
 class NativeObject;
@@ -81,16 +82,17 @@ class JitCode;
     D(js::ArgumentsObject*) \
     D(js::ArrayBufferObject*) \
     D(js::ArrayBufferObjectMaybeShared*) \
     D(js::ArrayBufferViewObject*) \
     D(js::ArrayObject*) \
     D(js::BaseShape*) \
     D(js::ClonedBlockObject*) \
     D(js::DebugScopeObject*) \
+    D(js::DebuggerFrame*) \
     D(js::ExportEntryObject*) \
     D(js::GlobalObject*) \
     D(js::ImportEntryObject*) \
     D(js::LazyScript*) \
     D(js::ModuleEnvironmentObject*) \
     D(js::ModuleNamespaceObject*) \
     D(js::ModuleObject*) \
     D(js::NativeObject*) \
--- a/js/src/gc/Rooting.h
+++ b/js/src/gc/Rooting.h
@@ -19,47 +19,59 @@ class PropertyName;
 class NativeObject;
 class ArrayObject;
 class GlobalObject;
 class PlainObject;
 class ScriptSourceObject;
 class SavedFrame;
 class Shape;
 class ObjectGroup;
+class DebuggerEnvironment;
+class DebuggerFrame;
+class DebuggerObject;
 
 // These are internal counterparts to the public types such as HandleObject.
 
-typedef JS::Handle<NativeObject*>      HandleNativeObject;
-typedef JS::Handle<Shape*>             HandleShape;
-typedef JS::Handle<ObjectGroup*>       HandleObjectGroup;
-typedef JS::Handle<JSAtom*>            HandleAtom;
-typedef JS::Handle<JSLinearString*>    HandleLinearString;
-typedef JS::Handle<PropertyName*>      HandlePropertyName;
-typedef JS::Handle<ArrayObject*>       HandleArrayObject;
-typedef JS::Handle<PlainObject*>       HandlePlainObject;
-typedef JS::Handle<SavedFrame*>        HandleSavedFrame;
-typedef JS::Handle<ScriptSourceObject*> HandleScriptSource;
+typedef JS::Handle<NativeObject*>           HandleNativeObject;
+typedef JS::Handle<Shape*>                  HandleShape;
+typedef JS::Handle<ObjectGroup*>            HandleObjectGroup;
+typedef JS::Handle<JSAtom*>                 HandleAtom;
+typedef JS::Handle<JSLinearString*>         HandleLinearString;
+typedef JS::Handle<PropertyName*>           HandlePropertyName;
+typedef JS::Handle<ArrayObject*>            HandleArrayObject;
+typedef JS::Handle<PlainObject*>            HandlePlainObject;
+typedef JS::Handle<SavedFrame*>             HandleSavedFrame;
+typedef JS::Handle<ScriptSourceObject*>     HandleScriptSource;
+typedef JS::Handle<DebuggerEnvironment*>    HandleDebuggerEnvironment;
+typedef JS::Handle<DebuggerFrame*>          HandleDebuggerFrame;
+typedef JS::Handle<DebuggerObject*>         HandleDebuggerObject;
 
-typedef JS::MutableHandle<Shape*>      MutableHandleShape;
-typedef JS::MutableHandle<JSAtom*>     MutableHandleAtom;
-typedef JS::MutableHandle<NativeObject*> MutableHandleNativeObject;
-typedef JS::MutableHandle<PlainObject*> MutableHandlePlainObject;
-typedef JS::MutableHandle<SavedFrame*> MutableHandleSavedFrame;
+typedef JS::MutableHandle<Shape*>               MutableHandleShape;
+typedef JS::MutableHandle<JSAtom*>              MutableHandleAtom;
+typedef JS::MutableHandle<NativeObject*>        MutableHandleNativeObject;
+typedef JS::MutableHandle<PlainObject*>         MutableHandlePlainObject;
+typedef JS::MutableHandle<SavedFrame*>          MutableHandleSavedFrame;
+typedef JS::MutableHandle<DebuggerEnvironment*> MutableHandleDebuggerEnvironment;
+typedef JS::MutableHandle<DebuggerFrame*>       MutableHandleDebuggerFrame;
+typedef JS::MutableHandle<DebuggerObject*>      MutableHandleDebuggerObject;
 
-typedef JS::Rooted<NativeObject*>      RootedNativeObject;
-typedef JS::Rooted<Shape*>             RootedShape;
-typedef JS::Rooted<ObjectGroup*>       RootedObjectGroup;
-typedef JS::Rooted<JSAtom*>            RootedAtom;
-typedef JS::Rooted<JSLinearString*>    RootedLinearString;
-typedef JS::Rooted<PropertyName*>      RootedPropertyName;
-typedef JS::Rooted<ArrayObject*>       RootedArrayObject;
-typedef JS::Rooted<GlobalObject*>      RootedGlobalObject;
-typedef JS::Rooted<PlainObject*>       RootedPlainObject;
-typedef JS::Rooted<SavedFrame*>        RootedSavedFrame;
-typedef JS::Rooted<ScriptSourceObject*> RootedScriptSource;
+typedef JS::Rooted<NativeObject*>           RootedNativeObject;
+typedef JS::Rooted<Shape*>                  RootedShape;
+typedef JS::Rooted<ObjectGroup*>            RootedObjectGroup;
+typedef JS::Rooted<JSAtom*>                 RootedAtom;
+typedef JS::Rooted<JSLinearString*>         RootedLinearString;
+typedef JS::Rooted<PropertyName*>           RootedPropertyName;
+typedef JS::Rooted<ArrayObject*>            RootedArrayObject;
+typedef JS::Rooted<GlobalObject*>           RootedGlobalObject;
+typedef JS::Rooted<PlainObject*>            RootedPlainObject;
+typedef JS::Rooted<SavedFrame*>             RootedSavedFrame;
+typedef JS::Rooted<ScriptSourceObject*>     RootedScriptSource;
+typedef JS::Rooted<DebuggerEnvironment*>    RootedDebuggerEnvironment;
+typedef JS::Rooted<DebuggerFrame*>          RootedDebuggerFrame;
+typedef JS::Rooted<DebuggerObject*>         RootedDebuggerObject;
 
 typedef JS::GCVector<JSFunction*>   FunctionVector;
 typedef JS::GCVector<PropertyName*> PropertyNameVector;
 typedef JS::GCVector<Shape*>        ShapeVector;
 typedef JS::GCVector<JSString*>     StringVector;
 
 } /* namespace js */
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1292858.js
@@ -0,0 +1,47 @@
+var caughtInvalidArguments = false;
+var a = -1
+try {
+    var buf = new Uint8ClampedArray(a);
+    throw new Error("didn't throw");
+} catch (e) {
+    assertEq(e instanceof TypeError, true,
+             "expected TypeError, instead threw: " + e);
+    caughtInvalidArguments = true;
+}
+assertEq(caughtInvalidArguments, true);
+
+var caughtInvalidArguments = false;
+var i = 0;
+while (true) {
+    i = (i + 1) | 0;
+    var a = inIon() ? -1 : 300;
+    try {
+        var buf = new Uint8ClampedArray(a);
+        assertEq(buf.length, 300);
+    } catch (e) {
+        assertEq(a, -1);
+        assertEq(e instanceof TypeError, true,
+                "expected TypeError, instead threw: " + e);
+        caughtInvalidArguments = true;
+        break;
+    }
+}
+assertEq(caughtInvalidArguments, true);
+
+var caughtInvalidArguments = false;
+var i = 0;
+while (true) {
+    i = (i + 1) | 0;
+    var a = inIon() ? -1 : 0;
+    try {
+        var buf = new Uint8ClampedArray(a);
+        assertEq(buf.length, 0);
+    } catch (e) {
+        assertEq(a, -1);
+        assertEq(e instanceof TypeError, true,
+                "expected TypeError, instead threw: " + e);
+        caughtInvalidArguments = true;
+        break;
+    }
+}
+assertEq(caughtInvalidArguments, true);
--- a/js/src/jit-test/tests/generators/bug931414.js
+++ b/js/src/jit-test/tests/generators/bug931414.js
@@ -1,9 +1,9 @@
-// |jit-test| error: is undefined
+// |jit-test| error: TypeError
 
 load(libdir + "iteration.js");
 
 function iterable() {
   var iterable = {};
   iterable[Symbol.iterator] = () => ({next: () => void 0});
   return iterable;
 }
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1291,16 +1291,39 @@ BaselineCompiler::emit_JSOP_HOLE()
 
 bool
 BaselineCompiler::emit_JSOP_NULL()
 {
     frame.push(NullValue());
     return true;
 }
 
+typedef bool (*ThrowCheckIsObjectFn)(JSContext*, CheckIsObjectKind);
+static const VMFunction ThrowCheckIsObjectInfo =
+    FunctionInfo<ThrowCheckIsObjectFn>(ThrowCheckIsObject);
+
+bool
+BaselineCompiler::emit_JSOP_CHECKISOBJ()
+{
+    frame.syncStack(0);
+    masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
+
+    Label ok;
+    masm.branchTestObject(Assembler::Equal, R0, &ok);
+
+    prepareVMCall();
+
+    pushArg(Imm32(GET_UINT8(pc)));
+    if (!callVM(ThrowCheckIsObjectInfo))
+        return false;
+
+    masm.bind(&ok);
+    return true;
+}
+
 typedef bool (*ThrowUninitializedThisFn)(JSContext*, BaselineFrame* frame);
 static const VMFunction ThrowUninitializedThisInfo =
     FunctionInfo<ThrowUninitializedThisFn>(BaselineThrowUninitializedThis);
 
 bool
 BaselineCompiler::emit_JSOP_CHECKTHIS()
 {
     frame.syncStack(0);
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -205,16 +205,17 @@ namespace jit {
     _(JSOP_RESUME)             \
     _(JSOP_CALLEE)             \
     _(JSOP_GETRVAL)            \
     _(JSOP_SETRVAL)            \
     _(JSOP_RETRVAL)            \
     _(JSOP_RETURN)             \
     _(JSOP_FUNCTIONTHIS)       \
     _(JSOP_GLOBALTHIS)         \
+    _(JSOP_CHECKISOBJ)         \
     _(JSOP_CHECKTHIS)          \
     _(JSOP_CHECKRETURN)        \
     _(JSOP_NEWTARGET)          \
     _(JSOP_SUPERCALL)          \
     _(JSOP_SPREADSUPERCALL)    \
     _(JSOP_THROWSETCONST)      \
     _(JSOP_THROWSETALIASEDCONST) \
     _(JSOP_INITHIDDENPROP_GETTER) \
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -394,22 +394,27 @@ jit::CanEnterBaselineMethod(JSContext* c
         }
     }
 
     RootedScript script(cx, state.script());
     return CanEnterBaselineJIT(cx, script, /* osrFrame = */ nullptr);
 };
 
 BaselineScript*
-BaselineScript::New(JSScript* jsscript, uint32_t prologueOffset, uint32_t epilogueOffset,
-                    uint32_t profilerEnterToggleOffset, uint32_t profilerExitToggleOffset,
-                    uint32_t traceLoggerEnterToggleOffset, uint32_t traceLoggerExitToggleOffset,
+BaselineScript::New(JSScript* jsscript,
+                    uint32_t prologueOffset, uint32_t epilogueOffset,
+                    uint32_t profilerEnterToggleOffset,
+                    uint32_t profilerExitToggleOffset,
+                    uint32_t traceLoggerEnterToggleOffset,
+                    uint32_t traceLoggerExitToggleOffset,
                     uint32_t postDebugPrologueOffset,
-                    size_t icEntries, size_t pcMappingIndexEntries, size_t pcMappingSize,
-                    size_t bytecodeTypeMapEntries, size_t yieldEntries)
+                    size_t icEntries,
+                    size_t pcMappingIndexEntries, size_t pcMappingSize,
+                    size_t bytecodeTypeMapEntries,
+                    size_t yieldEntries)
 {
     static const unsigned DataAlignment = sizeof(uintptr_t);
 
     size_t icEntriesSize = icEntries * sizeof(ICEntry);
     size_t pcMappingIndexEntriesSize = pcMappingIndexEntries * sizeof(PCMappingIndexEntry);
     size_t bytecodeTypeMapSize = bytecodeTypeMapEntries * sizeof(uint32_t);
     size_t yieldEntriesSize = yieldEntries * sizeof(uintptr_t);
 
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -246,25 +246,27 @@ struct BaselineScript
                    uint32_t postDebugPrologueOffset);
 
     ~BaselineScript() {
         // The contents of the fallback stub space are removed and freed
         // separately after the next minor GC. See BaselineScript::Destroy.
         MOZ_ASSERT(fallbackStubSpace_.isEmpty());
     }
 
-    static BaselineScript* New(JSScript* jsscript, uint32_t prologueOffset,
-                               uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
+    static BaselineScript* New(JSScript* jsscript,
+                               uint32_t prologueOffset, uint32_t epilogueOffset,
                                uint32_t profilerEnterToggleOffset,
                                uint32_t profilerExitToggleOffset,
                                uint32_t traceLoggerEnterToggleOffset,
                                uint32_t traceLoggerExitToggleOffset,
-                               size_t icEntries, size_t pcMappingIndexEntries,
-                               size_t pcMappingSize,
-                               size_t bytecodeTypeMapEntries, size_t yieldEntries);
+                               uint32_t postDebugPrologueOffset,
+                               size_t icEntries,
+                               size_t pcMappingIndexEntries, size_t pcMappingSize,
+                               size_t bytecodeTypeMapEntries,
+                               size_t yieldEntries);
 
     static void Trace(JSTracer* trc, BaselineScript* script);
     static void Destroy(FreeOp* fop, BaselineScript* script);
 
     void purgeOptimizedStubs(Zone* zone);
 
     static inline size_t offsetOfMethod() {
         return offsetof(BaselineScript, method_);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -11621,16 +11621,32 @@ CodeGenerator::visitCheckReturn(LCheckRe
     Label bail, noChecks;
     masm.branchTestObject(Assembler::Equal, returnValue, &noChecks);
     masm.branchTestUndefined(Assembler::NotEqual, returnValue, &bail);
     masm.branchTestMagicValue(Assembler::Equal, thisValue, JS_UNINITIALIZED_LEXICAL, &bail);
     bailoutFrom(&bail, ins->snapshot());
     masm.bind(&noChecks);
 }
 
+typedef bool (*ThrowCheckIsObjectFn)(JSContext*, CheckIsObjectKind);
+static const VMFunction ThrowCheckIsObjectInfo =
+    FunctionInfo<ThrowCheckIsObjectFn>(ThrowCheckIsObject, "ThrowCheckIsObject");
+
+void
+CodeGenerator::visitCheckIsObj(LCheckIsObj* ins)
+{
+    ValueOperand checkValue = ToValue(ins, LCheckIsObj::CheckValue);
+
+    OutOfLineCode* ool = oolCallVM(ThrowCheckIsObjectInfo, ins,
+                                   ArgList(Imm32(ins->mir()->checkKind())),
+                                   StoreNothing());
+    masm.branchTestObject(Assembler::NotEqual, checkValue, ool->entry());
+    masm.bind(ool->rejoin());
+}
+
 typedef bool (*ThrowObjCoercibleFn)(JSContext*, HandleValue);
 static const VMFunction ThrowObjectCoercibleInfo =
     FunctionInfo<ThrowObjCoercibleFn>(ThrowObjectCoercible, "ThrowObjectCoercible");
 
 void
 CodeGenerator::visitCheckObjCoercible(LCheckObjCoercible* ins)
 {
     ValueOperand checkValue = ToValue(ins, LCheckObjCoercible::CheckValue);
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -368,16 +368,17 @@ class CodeGenerator final : public CodeG
     void visitAsmJSVoidReturn(LAsmJSVoidReturn* ret);
     void visitLexicalCheck(LLexicalCheck* ins);
     void visitThrowRuntimeLexicalError(LThrowRuntimeLexicalError* ins);
     void visitGlobalNameConflictsCheck(LGlobalNameConflictsCheck* ins);
     void visitDebugger(LDebugger* ins);
     void visitNewTarget(LNewTarget* ins);
     void visitArrowNewTarget(LArrowNewTarget* ins);
     void visitCheckReturn(LCheckReturn* ins);
+    void visitCheckIsObj(LCheckIsObj* ins);
     void visitCheckObjCoercible(LCheckObjCoercible* ins);
     void visitDebugCheckSelfHosted(LDebugCheckSelfHosted* ins);
 
     void visitCheckOverRecursed(LCheckOverRecursed* lir);
     void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);
 
     void visitUnboxFloatingPoint(LUnboxFloatingPoint* lir);
     void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint* ool);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -2140,16 +2140,19 @@ IonBuilder::inspectOpcode(JSOp op)
         }
 
         // Just fall through to the unsupported bytecode case.
         break;
 
       case JSOP_NEWTARGET:
         return jsop_newtarget();
 
+      case JSOP_CHECKISOBJ:
+        return jsop_checkisobj(GET_UINT8(pc));
+
       case JSOP_CHECKOBJCOERCIBLE:
         return jsop_checkobjcoercible();
 
       case JSOP_DEBUGCHECKSELFHOSTED:
       {
 #ifdef DEBUG
         MDebugCheckSelfHosted* check = MDebugCheckSelfHosted::New(alloc(), current->pop());
         current->add(check);
@@ -10790,16 +10793,32 @@ IonBuilder::jsop_rest()
     // elements added.
     MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, index);
     current->add(initLength);
 
     return true;
 }
 
 bool
+IonBuilder::jsop_checkisobj(uint8_t kind)
+{
+    MDefinition* toCheck = current->peek(-1);
+
+    if (toCheck->type() == MIRType::Object) {
+        toCheck->setImplicitlyUsedUnchecked();
+        return true;
+    }
+
+    MCheckIsObj* check = MCheckIsObj::New(alloc(), current->pop(), kind);
+    current->add(check);
+    current->push(check);
+    return true;
+}
+
+bool
 IonBuilder::jsop_checkobjcoercible()
 {
     MDefinition* toCheck = current->peek(-1);
 
     if (!toCheck->mightBeType(MIRType::Undefined) &&
         !toCheck->mightBeType(MIRType::Null))
     {
         toCheck->setImplicitlyUsedUnchecked();
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -775,16 +775,17 @@ class IonBuilder
     MOZ_MUST_USE bool jsop_isnoiter();
     MOZ_MUST_USE bool jsop_iterend();
     MOZ_MUST_USE bool jsop_in();
     MOZ_MUST_USE bool jsop_instanceof();
     MOZ_MUST_USE bool jsop_getaliasedvar(ScopeCoordinate sc);
     MOZ_MUST_USE bool jsop_setaliasedvar(ScopeCoordinate sc);
     MOZ_MUST_USE bool jsop_debugger();
     MOZ_MUST_USE bool jsop_newtarget();
+    MOZ_MUST_USE bool jsop_checkisobj(uint8_t kind);
     MOZ_MUST_USE bool jsop_checkobjcoercible();
 
     /* Inlining. */
 
     enum InliningStatus
     {
         InliningStatus_Error,
         InliningStatus_NotInlined,
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -112,16 +112,19 @@ DefaultJitOptions::DefaultJitOptions()
     SET_DEFAULT(disableRangeAnalysis, false);
 
     // Toggles wheter Recover instructions is globally disabled.
     SET_DEFAULT(disableRecoverIns, false);
 
     // Toggle whether eager scalar replacement is globally disabled.
     SET_DEFAULT(disableScalarReplacement, false);
 
+    // Toggles whether CacheIR stubs are used.
+    SET_DEFAULT(disableCacheIR, false);
+
     // Toggles whether shared stubs are used in Ionmonkey.
     SET_DEFAULT(disableSharedStubs, false);
 
     // Toggles whether sincos optimization is globally disabled.
     // See bug984018: The MacOS is the only one that has the sincos fast.
     #if defined(XP_MACOSX)
         SET_DEFAULT(disableSincos, false);
     #else
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -56,16 +56,17 @@ struct DefaultJitOptions
     bool disableInlining;
     bool disableLicm;
     bool disableLoopUnrolling;
     bool disablePgo;
     bool disableInstructionReordering;
     bool disableRangeAnalysis;
     bool disableRecoverIns;
     bool disableScalarReplacement;
+    bool disableCacheIR;
     bool disableSharedStubs;
     bool disableSincos;
     bool disableSink;
     bool eagerCompilation;
     bool forceInlineCaches;
     bool limitScriptSize;
     bool osr;
     bool wasmTestMode;
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -4564,16 +4564,28 @@ LIRGenerator::visitCheckReturn(MCheckRet
 
     LCheckReturn* lir = new(alloc()) LCheckReturn(useBoxAtStart(retVal), useBoxAtStart(thisVal));
     assignSnapshot(lir, Bailout_BadDerivedConstructorReturn);
     add(lir, ins);
     redefine(ins, retVal);
 }
 
 void
+LIRGenerator::visitCheckIsObj(MCheckIsObj* ins)
+{
+    MDefinition* checkVal = ins->checkValue();
+    MOZ_ASSERT(checkVal->type() == MIRType::Value);
+
+    LCheckIsObj* lir = new(alloc()) LCheckIsObj(useBoxAtStart(checkVal));
+    redefine(ins, checkVal);
+    add(lir, ins);
+    assignSafepoint(lir, ins);
+}
+
+void
 LIRGenerator::visitCheckObjCoercible(MCheckObjCoercible* ins)
 {
     MDefinition* checkVal = ins->checkValue();
     MOZ_ASSERT(checkVal->type() == MIRType::Value);
 
     LCheckObjCoercible* lir = new(alloc()) LCheckObjCoercible(useBoxAtStart(checkVal));
     redefine(ins, checkVal);
     add(lir, ins);
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -312,16 +312,17 @@ class LIRGenerator : public LIRGenerator
     void visitThrowRuntimeLexicalError(MThrowRuntimeLexicalError* ins);
     void visitGlobalNameConflictsCheck(MGlobalNameConflictsCheck* ins);
     void visitDebugger(MDebugger* ins);
     void visitNewTarget(MNewTarget* ins);
     void visitArrowNewTarget(MArrowNewTarget* ins);
     void visitAtomicIsLockFree(MAtomicIsLockFree* ins);
     void visitGuardSharedTypedArray(MGuardSharedTypedArray* ins);
     void visitCheckReturn(MCheckReturn* ins);
+    void visitCheckIsObj(MCheckIsObj* ins);
     void visitCheckObjCoercible(MCheckObjCoercible* ins);
     void visitDebugCheckSelfHosted(MDebugCheckSelfHosted* ins);
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_Lowering_h */
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -13045,33 +13045,58 @@ class MAtomicTypedArrayElementBinop
 
 class MDebugger : public MNullaryInstruction
 {
   public:
     INSTRUCTION_HEADER(Debugger)
     TRIVIAL_NEW_WRAPPERS
 };
 
+class MCheckIsObj
+  : public MUnaryInstruction,
+    public BoxInputsPolicy::Data
+{
+    uint8_t checkKind_;
+
+    explicit MCheckIsObj(MDefinition* toCheck, uint8_t checkKind)
+      : MUnaryInstruction(toCheck), checkKind_(checkKind)
+    {
+        setResultType(MIRType::Value);
+        setResultTypeSet(toCheck->resultTypeSet());
+        setGuard();
+    }
+
+  public:
+    INSTRUCTION_HEADER(CheckIsObj)
+    TRIVIAL_NEW_WRAPPERS
+    NAMED_OPERANDS((0, checkValue))
+
+    uint8_t checkKind() const { return checkKind_; }
+
+    AliasSet getAliasSet() const override {
+        return AliasSet::None();
+    }
+};
+
 class MCheckObjCoercible
   : public MUnaryInstruction,
     public BoxInputsPolicy::Data
 {
     explicit MCheckObjCoercible(MDefinition* toCheck)
       : MUnaryInstruction(toCheck)
     {
         setGuard();
         setResultType(MIRType::Value);
         setResultTypeSet(toCheck->resultTypeSet());
     }
 
   public:
     INSTRUCTION_HEADER(CheckObjCoercible)
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, checkValue))
-
 };
 
 class MDebugCheckSelfHosted
   : public MUnaryInstruction,
     public BoxInputsPolicy::Data
 {
     explicit MDebugCheckSelfHosted(MDefinition* toCheck)
       : MUnaryInstruction(toCheck)
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -297,16 +297,17 @@ namespace jit {
     _(UnknownValue)                                                         \
     _(LexicalCheck)                                                         \
     _(ThrowRuntimeLexicalError)                                             \
     _(GlobalNameConflictsCheck)                                             \
     _(Debugger)                                                             \
     _(NewTarget)                                                            \
     _(ArrowNewTarget)                                                       \
     _(CheckReturn)                                                          \
+    _(CheckIsObj)                                                             \
     _(CheckObjCoercible)                                                    \
     _(DebugCheckSelfHosted)
 
 // Forward declarations of MIR types.
 #define FORWARD_DECLARE(op) class M##op;
  MIR_OPCODE_LIST(FORWARD_DECLARE)
 #undef FORWARD_DECLARE
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1019,31 +1019,35 @@ FindStartOfUndefinedAndUninitializedSlot
             *startOfUndefined = first;
             return;
         }
     }
     *startOfUndefined = 0;
 }
 
 static void
-AllocateObjectBufferWithInit(JSContext* cx, TypedArrayObject* obj, uint32_t count)
+AllocateObjectBufferWithInit(JSContext* cx, TypedArrayObject* obj, int32_t count)
 {
     JS::AutoCheckCannotGC nogc(cx);
 
     obj->initPrivate(nullptr);
-    obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(count));
 
     // Typed arrays with a non-compile-time known size that have a count of zero
     // eventually are essentially typed arrays with inline elements. The bounds
     // check will make sure that no elements are read or written to that memory.
-    if (count == 0) {
-        obj->setInlineElements();
+    // Negative numbers will bail out to the slow path, which in turn will raise
+    // an invalid argument exception.
+    if (count <= 0) {
+        if (count == 0)
+            obj->setInlineElements();
+        obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(0));
         return;
     }
 
+    obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(count));
     size_t nbytes;
 
     switch (obj->type()) {
 #define CREATE_TYPED_ARRAY(T, N) \
       case Scalar::N: \
         if (!js::CalculateAllocSize<T>(count, &nbytes)) \
             return; \
         break;
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -2711,17 +2711,17 @@ DoGetPropFallback(JSContext* cx, void* p
                                              stub->fallbackMonitorStub()->firstMonitorStub());
         ICStub* newStub = compiler.getStub(compiler.getStubSpace(info.outerScript(cx)));
         if (!newStub)
             return false;
         stub->addNewStub(newStub);
         attached = true;
     }
 
-    if (!attached) {
+    if (!attached && !JitOptions.disableCacheIR) {
         mozilla::Maybe<CacheIRWriter> writer;
         GetPropIRGenerator gen(cx, pc, val, name, res);
         if (!gen.tryAttachStub(writer))
             return false;
         if (gen.emitted()) {
             ICStub* newStub = AttachBaselineCacheIRStub(cx, writer.ref(), CacheKind::GetProp, stub);
             if (newStub) {
                 JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -8691,16 +8691,32 @@ class LCheckReturn : public LCallInstruc
         setBoxOperand(ReturnValue, retVal);
         setBoxOperand(ThisValue, thisVal);
     }
 
     static const size_t ReturnValue = 0;
     static const size_t ThisValue = BOX_PIECES;
 };
 
+class LCheckIsObj : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
+{
+  public:
+    LIR_HEADER(CheckIsObj)
+
+    static const size_t CheckValue = 0;
+
+    explicit LCheckIsObj(const LBoxAllocation& value) {
+        setBoxOperand(CheckValue, value);
+    }
+
+    MCheckIsObj* mir() const {
+        return mir_->toCheckIsObj();
+    }
+};
+
 class LCheckObjCoercible : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CheckObjCoercible)
 
     static const size_t CheckValue = 0;
 
     explicit LCheckObjCoercible(const LBoxAllocation& value) {
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -422,12 +422,13 @@
     _(AssertResultT)                \
     _(LexicalCheck)                 \
     _(ThrowRuntimeLexicalError)     \
     _(GlobalNameConflictsCheck)     \
     _(Debugger)                     \
     _(NewTarget)                    \
     _(ArrowNewTarget)               \
     _(CheckReturn)                  \
+    _(CheckIsObj)                   \
     _(CheckObjCoercible)            \
     _(DebugCheckSelfHosted)
 
 #endif /* jit_shared_LOpcodes_shared_h */
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4755,16 +4755,36 @@ JS::GetPromiseAllocationSite(JS::HandleO
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::GetPromiseResolutionSite(JS::HandleObject promise)
 {
     return promise->as<PromiseObject>().resolutionSite();
 }
 
+#ifdef DEBUG
+JS_PUBLIC_API(void)
+JS::DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise)
+{
+    RootedObject stack(cx, promise->as<PromiseObject>().allocationSite());
+    UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
+    if (stackStr.get())
+        fputs(stackStr.get(), stderr);
+}
+
+JS_PUBLIC_API(void)
+JS::DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise)
+{
+    RootedObject stack(cx, promise->as<PromiseObject>().resolutionSite());
+    UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
+    if (stackStr.get())
+        fputs(stackStr.get(), stderr);
+}
+#endif
+
 JS_PUBLIC_API(JSObject*)
 JS::CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue)
 {
     RootedObject promiseCtor(cx, GetPromiseConstructor(cx));
     if (!promiseCtor)
         return nullptr;
 
     JSObject* obj;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4431,16 +4431,24 @@ GetPromiseResult(JS::HandleObject promis
  * Promise's allocation.
  */
 extern JS_PUBLIC_API(JSObject*)
 GetPromiseAllocationSite(JS::HandleObject promise);
 
 extern JS_PUBLIC_API(JSObject*)
 GetPromiseResolutionSite(JS::HandleObject promise);
 
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise);
+
+extern JS_PUBLIC_API(void)
+DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise);
+#endif
+
 /**
  * Calls the current compartment's original Promise.resolve on the original
  * Promise constructor, with `resolutionValue` passed as an argument.
  */
 extern JS_PUBLIC_API(JSObject*)
 CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue);
 
 /**
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3437,16 +3437,18 @@ void
 JSObject::dump(FILE* fp) const
 {
     const JSObject* obj = this;
     JSObject* globalObj = &global();
     fprintf(fp, "object %p from global %p [%s]\n", (void*) obj,
             (void*) globalObj, globalObj->getClass()->name);
     const Class* clasp = obj->getClass();
     fprintf(fp, "class %p %s\n", (const void*)clasp, clasp->name);
+    const ObjectGroup* group = obj->group();
+    fprintf(fp, "group %p\n", (const void*)group);
 
     fprintf(fp, "flags:");
     if (obj->isDelegate()) fprintf(fp, " delegate");
     if (!obj->is<ProxyObject>() && !obj->nonProxyIsExtensible()) fprintf(fp, " not_extensible");
     if (obj->isIndexed()) fprintf(fp, " indexed");
     if (obj->isBoundFunction()) fprintf(fp, " bound_function");
     if (obj->isQualifiedVarObj()) fprintf(fp, " varobj");
     if (obj->isUnqualifiedVarObj()) fprintf(fp, " unqualified_varobj");
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1223,16 +1223,18 @@ ExpressionDecompiler::decompilePC(jsbyte
       case JSOP_NEWARRAY_COPYONWRITE: {
         JSObject* obj = script->getObject(GET_UINT32_INDEX(pc));
         RootedValue objv(cx, ObjectValue(*obj));
         JSString* str = ValueToSource(cx, objv);
         if (!str)
             return false;
         return write(str);
       }
+      case JSOP_CHECKISOBJ:
+        return decompilePCForStackOperand(pc, -1);
       case JSOP_VOID:
         return write("void ") && decompilePCForStackOperand(pc, -1);
       default:
         break;
     }
     return write("(intermediate value)");
 }
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3107,16 +3107,29 @@ ShapeOf(JSContext* cx, unsigned argc, JS
         return false;
     }
     JSObject* obj = &args[0].toObject();
     args.rval().set(JS_NumberValue(double(uintptr_t(obj->maybeShape()) >> 3)));
     return true;
 }
 
 static bool
+GroupOf(JSContext* cx, unsigned argc, JS::Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!args.get(0).isObject()) {
+        JS_ReportError(cx, "groupOf: object expected");
+        return false;
+    }
+    JSObject* obj = &args[0].toObject();
+    args.rval().set(JS_NumberValue(double(uintptr_t(obj->group()) >> 3)));
+    return true;
+}
+
+static bool
 Sleep_fn(JSContext* cx, unsigned argc, Value* vp)
 {
     ShellContext* sc = GetShellContext(cx);
     CallArgs args = CallArgsFromVp(argc, vp);
 
     TimeDuration duration = TimeDuration::FromSeconds(0.0);
     if (args.length() > 0) {
         double t_secs;
@@ -5449,16 +5462,20 @@ static const JSFunctionSpecWithHelp shel
 "setSharedArrayBuffer()",
 "  Install the SharedArrayBuffer object in the cross-worker mailbox.\n"
 "  setSharedArrayBuffer performs an ordering memory barrier.\n"),
 
     JS_FN_HELP("shapeOf", ShapeOf, 1, 0,
 "shapeOf(obj)",
 "  Get the shape of obj (an implementation detail)."),
 
+    JS_FN_HELP("groupOf", GroupOf, 1, 0,
+"groupOf(obj)",
+"  Get the group of obj (an implementation detail)."),
+
 #ifdef DEBUG
     JS_FN_HELP("arrayInfo", ArrayInfo, 1, 0,
 "arrayInfo(a1, a2, ...)",
 "  Report statistics about arrays."),
 #endif
 
     JS_FN_HELP("sleep", Sleep_fn, 1, 0,
 "sleep(dt)",
@@ -6819,16 +6836,25 @@ SetContextOptions(JSContext* cx, const O
                              .setWasm(true)
                              .setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
                              .setNativeRegExp(enableNativeRegExp)
                              .setUnboxedArrays(enableUnboxedArrays);
 
     if (op.getBoolOption("no-unboxed-objects"))
         jit::JitOptions.disableUnboxedObjects = true;
 
+    if (const char* str = op.getStringOption("cache-ir-stubs")) {
+        if (strcmp(str, "on") == 0)
+            jit::JitOptions.disableCacheIR = false;
+        else if (strcmp(str, "off") == 0)
+            jit::JitOptions.disableCacheIR = true;
+        else
+            return OptionFailure("cache-ir-stubs", str);
+    }
+
     if (const char* str = op.getStringOption("ion-scalar-replacement")) {
         if (strcmp(str, "on") == 0)
             jit::JitOptions.disableScalarReplacement = false;
         else if (strcmp(str, "off") == 0)
             jit::JitOptions.disableScalarReplacement = true;
         else
             return OptionFailure("ion-scalar-replacement", str);
     }
@@ -7271,18 +7297,20 @@ main(int argc, char** argv, char** envp)
                                "SharedArrayBuffer and Atomics "
 #  if SHARED_MEMORY_DEFAULT
                                "(default: on, off to disable)"
 #  else
                                "(default: off, on to enable)"
 #  endif
             )
 #endif
+        || !op.addStringOption('\0', "cache-ir-stubs", "on/off",
+                               "Use CacheIR stubs (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-shared-stubs", "on/off",
-                               "Use shared stubs (default: on, off to enable)")
+                               "Use shared stubs (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-scalar-replacement", "on/off",
                                "Scalar Replacement (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-gvn", "[mode]",
                                "Specify Ion global value numbering:\n"
                                "  off: disable GVN\n"
                                "  on:  enable GVN (default)\n")
         || !op.addStringOption('\0', "ion-licm", "on/off",
                                "Loop invariant code motion (default: on, off to disable)")
--- a/js/src/tests/ecma_6/Generators/delegating-yield-1.js
+++ b/js/src/tests/ecma_6/Generators/delegating-yield-1.js
@@ -27,16 +27,16 @@ function collect_results(iterable) {
     do {
         result = iter.next();
         ret.push(result);
     } while (!result.done);
     return ret;
 }
 
 // We have to put a full result for the end, because the return will re-box.
-var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
+var expected = [{value: 1}, {value: 34, done: true}];
 
 // Sanity check.
 assertDeepEq(expected, collect_results(results(expected)));
 assertDeepEq(expected, collect_results(yield_results(expected)));
 
 if (typeof reportCompare == "function")
     reportCompare(true, true);
--- a/js/src/tests/ecma_6/Generators/delegating-yield-3.js
+++ b/js/src/tests/ecma_6/Generators/delegating-yield-3.js
@@ -5,36 +5,36 @@ function* delegate(iter) { return yield*
 var GeneratorObjectPrototype = Object.getPrototypeOf(g).prototype;
 var GeneratorObjectPrototype_next = GeneratorObjectPrototype.next;
 
 // Monkeypatch next on an iterator.
 var inner = g(20);
 var outer = delegate(inner);
 assertIteratorNext(outer, 0);
 assertIteratorNext(outer, 1);
-inner.next = function() { return 0; };
+inner.next = function() { return { patched: true }; };
 // 42 yielded directly without re-boxing.
-assertEq(0, outer.next());
+assertEq(true, outer.next().patched);
 // Outer generator not terminated.
-assertEq(0, outer.next());
+assertEq(true, outer.next().patched);
 // Restore.
 inner.next = GeneratorObjectPrototype_next;
 assertIteratorNext(outer, 2);
 // Repatch.
 inner.next = function() { return { value: 42, done: true }; };
 assertIteratorDone(outer, 42);
 
 // Monkeypunch next on the prototype.
 var inner = g(20);
 var outer = delegate(inner);
 assertIteratorNext(outer, 0);
 assertIteratorNext(outer, 1);
-GeneratorObjectPrototype.next = function() { return 0; };
+GeneratorObjectPrototype.next = function() { return { patched: true }; };
 // 42 yielded directly without re-boxing.
-assertEq(0, GeneratorObjectPrototype_next.call(outer));
+assertEq(true, GeneratorObjectPrototype_next.call(outer).patched);
 // Outer generator not terminated.
-assertEq(0, GeneratorObjectPrototype_next.call(outer));
+assertEq(true, GeneratorObjectPrototype_next.call(outer).patched);
 // Restore.
 GeneratorObjectPrototype.next = GeneratorObjectPrototype_next;
 assertIteratorNext(outer, 2);
 
 if (typeof reportCompare == "function")
     reportCompare(true, true);
--- a/js/src/tests/ecma_6/Generators/delegating-yield-5.js
+++ b/js/src/tests/ecma_6/Generators/delegating-yield-5.js
@@ -23,15 +23,15 @@ function collect_results(iterable) {
     do {
         result = iter.next();
         ret.push(result);
     } while (!result.done);
     return ret;
 }
 
 // We have to put a full result for the end, because the return will re-box.
-var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
+var expected = [{value: 1}, {value: 34, done: true}];
 
 assertDeepEq(expected, collect_results(results(expected)));
 assertDeepEq(expected, collect_results(yield_results(expected, 20)));
 
 if (typeof reportCompare == "function")
     reportCompare(true, true);
--- a/js/src/tests/ecma_6/Generators/delegating-yield-7.js
+++ b/js/src/tests/ecma_6/Generators/delegating-yield-7.js
@@ -23,16 +23,16 @@ function collect_results(iter) {
     do {
         result = iter.next();
         ret.push(result);
     } while (!result.done);
     return ret;
 }
 
 // We have to put a full result for the end, because the return will re-box.
-var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
+var expected = [{value: 1}, {value: 34, done: true}];
 
 // Sanity check.
 assertDeepEq(expected, collect_results(results(expected)));
 assertDeepEq(expected, collect_results(yield_results(expected)));
 
 if (typeof reportCompare == "function")
     reportCompare(true, true);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Generators/iterator-next-non-object.js
@@ -0,0 +1,64 @@
+var BUGNUMBER = 1016936;
+var summary = "IteratorNext should throw if the value returned by iterator.next() is not an object.";
+
+print(BUGNUMBER + ": " + summary);
+
+var nonobjs = [
+    null,
+    undefined,
+    1,
+    true,
+    "a",
+    Symbol.iterator,
+];
+
+function createIterable(v) {
+    var iterable = {};
+    iterable[Symbol.iterator] = function () {
+        return {
+            next: function () {
+                return v;
+            }
+        };
+    };
+    return iterable;
+}
+
+function f() {
+}
+
+for (var nonobj of nonobjs) {
+    var iterable = createIterable(nonobj);
+
+    assertThrowsInstanceOf(() => [...iterable], TypeError);
+    assertThrowsInstanceOf(() => f(...iterable), TypeError);
+
+    assertThrowsInstanceOf(() => { for (var x of iterable) {} }, TypeError);
+
+    assertThrowsInstanceOf(() => {
+        var [a] = iterable;
+    }, TypeError);
+    assertThrowsInstanceOf(() => {
+        var [...a] = iterable;
+    }, TypeError);
+
+    assertThrowsInstanceOf(() => Array.from(iterable), TypeError);
+    assertThrowsInstanceOf(() => new Map(iterable), TypeError);
+    assertThrowsInstanceOf(() => new Set(iterable), TypeError);
+    assertThrowsInstanceOf(() => new WeakMap(iterable), TypeError);
+    assertThrowsInstanceOf(() => new WeakSet(iterable), TypeError);
+    // FIXME: bug 1232266
+    // assertThrowsInstanceOf(() => new Int8Array(iterable), TypeError);
+    assertThrowsInstanceOf(() => Int8Array.from(iterable), TypeError);
+
+    assertThrowsInstanceOf(() => {
+        var g = function*() {
+            yield* iterable;
+        };
+        var v = g();
+        v.next();
+    }, TypeError);
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -717,42 +717,42 @@ Debugger::memory() const
     MOZ_ASSERT(hasMemory());
     return object->getReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE).toObject().as<DebuggerMemory>();
 }
 
 bool
 Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr referent,
                                  const ScriptFrameIter* maybeIter, MutableHandleValue vp)
 {
-    Rooted<DebuggerFrame*> result(cx);
+    RootedDebuggerFrame result(cx);
     if (!Debugger::getScriptFrameWithIter(cx, referent, maybeIter, &result))
         return false;
 
     vp.setObject(*result);
     return true;
 }
 
 bool
 Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr referent,
                                  const ScriptFrameIter* maybeIter,
-                                 MutableHandle<DebuggerFrame*> result)
+                                 MutableHandleDebuggerFrame result)
 {
     MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == referent);
     MOZ_ASSERT(!referent.script()->selfHosted());
 
     if (!referent.script()->ensureHasAnalyzedArgsUsage(cx))
         return false;
 
     FrameMap::AddPtr p = frames.lookupForAdd(referent);
     if (!p) {
         /* Create and populate the Debugger.Frame object. */
         RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject());
         RootedNativeObject debugger(cx, object);
 
-        Rooted<DebuggerFrame*> frame(cx, DebuggerFrame::create(cx, proto, referent, maybeIter,
+        RootedDebuggerFrame frame(cx, DebuggerFrame::create(cx, proto, referent, maybeIter,
                                                                debugger));
         if (!frame)
             return false;
 
         if (!ensureExecutionObservabilityOfFrame(cx, referent))
             return false;
 
         if (!frames.add(p, referent, frame)) {
@@ -890,17 +890,17 @@ Debugger::slowPathOnLeaveFrame(JSContext
 
     // This path can be hit via unwinding the stack due to over-recursion or
     // OOM. In those cases, don't fire the frames' onPop handlers, because
     // invoking JS will only trigger the same condition. See
     // slowPathOnExceptionUnwind.
     if (!cx->isThrowingOverRecursed() && !cx->isThrowingOutOfMemory()) {
         /* For each Debugger.Frame, fire its onPop handler, if any. */
         for (size_t i = 0; i < frames.length(); i++) {
-            HandleNativeObject frameobj = frames[i];
+            HandleDebuggerFrame frameobj = frames[i];
             Debugger* dbg = Debugger::fromChildJSObject(frameobj);
             EnterDebuggeeNoExecute nx(cx, *dbg);
 
             if (dbg->enabled &&
                 !frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER).isUndefined())
             {
                 RootedValue handler(cx, frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER));
 
@@ -1035,28 +1035,28 @@ Debugger::slowPathOnExceptionUnwind(JSCo
 bool
 Debugger::wrapEnvironment(JSContext* cx, Handle<Env*> env, MutableHandleValue rval)
 {
     if (!env) {
         rval.setNull();
         return true;
     }
 
-    Rooted<DebuggerEnvironment*> envobj(cx);
+    RootedDebuggerEnvironment envobj(cx);
 
     if (!wrapEnvironment(cx, env, &envobj))
         return false;
 
     rval.setObject(*envobj);
     return true;
 }
 
 bool
 Debugger::wrapEnvironment(JSContext* cx, Handle<Env*> env,
-                          MutableHandle<DebuggerEnvironment*> result)
+                          MutableHandleDebuggerEnvironment result)
 {
     MOZ_ASSERT(env);
 
     /*
      * DebuggerEnv should only wrap a debug scope chain obtained (transitively)
      * from GetDebugScopeFor(Frame|Function).
      */
     MOZ_ASSERT(!IsSyntacticScope(env));
@@ -1064,17 +1064,17 @@ Debugger::wrapEnvironment(JSContext* cx,
     DependentAddPtr<ObjectWeakMap> p(cx, environments, env);
     if (p) {
         result.set(&p->value()->as<DebuggerEnvironment>());
     } else {
         /* Create a new Debugger.Environment for env. */
         RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject());
         RootedNativeObject debugger(cx, object);
 
-        Rooted<DebuggerEnvironment*> envobj(cx,
+        RootedDebuggerEnvironment envobj(cx,
             DebuggerEnvironment::create(cx, proto, env, debugger));
         if (!envobj)
             return false;
 
         if (!p.add(cx, environments, env, envobj)) {
             NukeDebuggerWrapper(envobj);
             return false;
         }
@@ -1094,17 +1094,17 @@ Debugger::wrapEnvironment(JSContext* cx,
 
 bool
 Debugger::wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp)
 {
     assertSameCompartment(cx, object.get());
 
     if (vp.isObject()) {
         RootedObject obj(cx, &vp.toObject());
-        Rooted<DebuggerObject*> dobj(cx);
+        RootedDebuggerObject dobj(cx);
 
         if (!wrapDebuggeeObject(cx, obj, &dobj))
             return false;
 
         vp.setObject(*dobj);
     } else if (vp.isMagic()) {
         RootedPlainObject optObj(cx, NewBuiltinClassInstance<PlainObject>(cx));
         if (!optObj)
@@ -1133,17 +1133,17 @@ Debugger::wrapDebuggeeValue(JSContext* c
         return false;
     }
 
     return true;
 }
 
 bool
 Debugger::wrapDebuggeeObject(JSContext* cx, HandleObject obj,
-                             MutableHandle<DebuggerObject*> result)
+                             MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(obj);
 
     if (obj->is<JSFunction>()) {
         MOZ_ASSERT(!IsInternalFunctionObject(*obj));
         RootedFunction fun(cx, &obj->as<JSFunction>());
         if (!EnsureFunctionHasScript(cx, fun))
             return false;
@@ -1151,17 +1151,17 @@ Debugger::wrapDebuggeeObject(JSContext* 
 
     DependentAddPtr<ObjectWeakMap> p(cx, objects, obj);
     if (p) {
         result.set(&p->value()->as<DebuggerObject>());
     } else {
         /* Create a new Debugger.Object for obj. */
         RootedNativeObject debugger(cx, object);
         RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject());
-        Rooted<DebuggerObject*> dobj(cx, DebuggerObject::create(cx, proto, obj, debugger));
+        RootedDebuggerObject dobj(cx, DebuggerObject::create(cx, proto, obj, debugger));
         if (!dobj)
             return false;
 
         if (!p.add(cx, objects, obj, dobj)) {
             NukeDebuggerWrapper(dobj);
             return false;
         }
 
@@ -1942,17 +1942,17 @@ Debugger::onSingleStep(JSContext* cx, Mu
             }
         }
         MOZ_ASSERT(stepperCount == trappingScript->stepModeCount());
     }
 #endif
 
     // Call onStep for frames that have the handler set.
     for (size_t i = 0; i < frames.length(); i++) {
-        HandleNativeObject frame = frames[i];
+        HandleDebuggerFrame frame = frames[i];
         if (frame->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER).isUndefined())
             continue;
 
         Debugger* dbg = Debugger::fromChildJSObject(frame);
         EnterDebuggeeNoExecute nx(cx, *dbg);
 
         Maybe<AutoCompartment> ac;
         ac.emplace(cx, dbg->object);
@@ -2502,17 +2502,17 @@ Debugger::forEachDebuggerFrame(AbstractF
         }
     }
 }
 
 /* static */ bool
 Debugger::getDebuggerFrames(AbstractFramePtr frame, MutableHandle<DebuggerFrameVector> frames)
 {
     bool hadOOM = false;
-    forEachDebuggerFrame(frame, [&](NativeObject* frameobj) {
+    forEachDebuggerFrame(frame, [&](DebuggerFrame* frameobj) {
         if (!hadOOM && !frames.append(frameobj))
             hadOOM = true;
     });
     return !hadOOM;
 }
 
 /* static */ bool
 Debugger::updateExecutionObservability(JSContext* cx, ExecutionObservableSet& obs,
@@ -2967,17 +2967,17 @@ Debugger::trace(JSTracer* trc)
      * Mark Debugger.Frame objects. These are all reachable from JS, because the
      * corresponding JS frames are still on the stack.
      *
      * (Once we support generator frames properly, we will need
      * weakly-referenced Debugger.Frame objects as well, for suspended generator
      * frames.)
      */
     for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) {
-        HeapPtr<NativeObject*>& frameobj = r.front().value();
+        HeapPtr<DebuggerFrame*>& frameobj = r.front().value();
         MOZ_ASSERT(MaybeForwarded(frameobj.get())->getPrivate());
         TraceEdge(trc, &frameobj, "live Debugger.Frame");
     }
 
     allocationsLog.trace(trc);
 
     /* Trace the weak map from JSScript instances to Debugger.Script objects. */
     scripts.trace(trc);
@@ -6149,17 +6149,17 @@ Debugger::replaceFrameGuts(JSContext* cx
     // the frames that were successfully replaced. For OSR frames, OOM here
     // means those frames will pop from the OSR trampoline, which does not
     // call Debugger::onLeaveFrame.
     auto removeToDebuggerFramesOnExit = MakeScopeExit([&] {
         removeFromFrameMapsAndClearBreakpointsIn(cx, to);
     });
 
     for (size_t i = 0; i < frames.length(); i++) {
-        HandleNativeObject frameobj = frames[i];
+        HandleDebuggerFrame frameobj = frames[i];
         Debugger* dbg = Debugger::fromChildJSObject(frameobj);
 
         // Update frame object's ScriptFrameIter::data pointer.
         DebuggerFrame_freeScriptFrameIterData(cx->runtime()->defaultFreeOp(), frameobj);
         ScriptFrameIter::Data* data = iter.copyData();
         if (!data)
             return false;
         frameobj->setPrivate(data);
@@ -7084,35 +7084,35 @@ DebuggerFrame::create(JSContext* cx, Han
   }
 
   frame.setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*debugger));
 
   return &frame;
 }
 
 /* static */ bool
-DebuggerFrame::getCallee(JSContext* cx, Handle<DebuggerFrame*> frame,
-                         MutableHandle<DebuggerObject*> result)
+DebuggerFrame::getCallee(JSContext* cx, HandleDebuggerFrame frame,
+                         MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(frame->isLive());
 
     AbstractFramePtr referent = DebuggerFrame::getReferent(frame);
     if (!referent.isFunctionFrame()) {
         result.set(nullptr);
         return true;
     }
 
     Debugger* dbg = frame->owner();
 
     RootedObject callee(cx, referent.callee());
     return dbg->wrapDebuggeeObject(cx, callee, result);
 }
 
 /* static */ bool
-DebuggerFrame::getIsConstructing(JSContext* cx, Handle<DebuggerFrame*> frame, bool& result)
+DebuggerFrame::getIsConstructing(JSContext* cx, HandleDebuggerFrame frame, bool& result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Maybe<ScriptFrameIter> maybeIter;
     if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
         return false;
     ScriptFrameIter& iter = *maybeIter;
 
@@ -7153,18 +7153,18 @@ UpdateFrameIterPc(FrameIter& iter)
 #endif
         return;
     }
 
     iter.updatePcQuadratic();
 }
 
 /* static */ bool
-DebuggerFrame::getEnvironment(JSContext* cx, Handle<DebuggerFrame*> frame,
-                              MutableHandle<DebuggerEnvironment*> result)
+DebuggerFrame::getEnvironment(JSContext* cx, HandleDebuggerFrame frame,
+                              MutableHandleDebuggerEnvironment result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Debugger* dbg = frame->owner();
 
     Maybe<ScriptFrameIter> maybeIter;
     if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
         return false;
@@ -7178,41 +7178,41 @@ DebuggerFrame::getEnvironment(JSContext*
         if (!env)
             return false;
     }
 
     return dbg->wrapEnvironment(cx, env, result);
 }
 
 /* static */ bool
-DebuggerFrame::getIsGenerator(Handle<DebuggerFrame*> frame)
+DebuggerFrame::getIsGenerator(HandleDebuggerFrame frame)
 {
     return DebuggerFrame::getReferent(frame).script()->isGenerator();
 }
 
 /* static */ bool
-DebuggerFrame::getOffset(JSContext* cx, Handle<DebuggerFrame*> frame, size_t& result)
+DebuggerFrame::getOffset(JSContext* cx, HandleDebuggerFrame frame, size_t& result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Maybe<ScriptFrameIter> maybeIter;
     if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
         return false;
     ScriptFrameIter& iter = *maybeIter;
 
     JSScript* script = iter.script();
     UpdateFrameIterPc(iter);
     jsbytecode* pc = iter.pc();
     result = script->pcToOffset(pc);
     return true;
 }
 
 /* static */ bool
-DebuggerFrame::getOlder(JSContext* cx, Handle<DebuggerFrame*> frame,
-                        MutableHandle<DebuggerFrame*> result)
+DebuggerFrame::getOlder(JSContext* cx, HandleDebuggerFrame frame,
+                        MutableHandleDebuggerFrame result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Debugger* dbg = frame->owner();
 
     Maybe<ScriptFrameIter> maybeIter;
     if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
         return false;
@@ -7226,17 +7226,17 @@ DebuggerFrame::getOlder(JSContext* cx, H
         }
     }
 
     result.set(nullptr);
     return true;
 }
 
 /* static */ bool
-DebuggerFrame::getThis(JSContext* cx, Handle<DebuggerFrame*> frame, MutableHandleValue result)
+DebuggerFrame::getThis(JSContext* cx, HandleDebuggerFrame frame, MutableHandleValue result)
 {
     MOZ_ASSERT(frame->isLive());
 
     Debugger* dbg = frame->owner();
 
     Maybe<ScriptFrameIter> maybeIter;
     if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
         return false;
@@ -7251,17 +7251,17 @@ DebuggerFrame::getThis(JSContext* cx, Ha
         if (!GetThisValueForDebuggerMaybeOptimizedOut(cx, frame, iter.pc(), result))
             return false;
     }
 
     return dbg->wrapDebuggeeValue(cx, result);
 }
 
 /* static */ DebuggerFrameType
-DebuggerFrame::getType(Handle<DebuggerFrame*> frame)
+DebuggerFrame::getType(HandleDebuggerFrame frame)
 {
     AbstractFramePtr referent = DebuggerFrame::getReferent(frame);
 
     /*
      * Indirect eval frames are both isGlobalFrame() and isEvalFrame(), so the
      * order of checks here is significant.
      */
     if (referent.isEvalFrame())
@@ -7271,17 +7271,17 @@ DebuggerFrame::getType(Handle<DebuggerFr
     else if (referent.isFunctionFrame())
         return DebuggerFrameType::Call;
     else if (referent.isModuleFrame())
         return DebuggerFrameType::Module;
     MOZ_CRASH("Unknown frame type");
 }
 
 /* static */ DebuggerFrameImplementation
-DebuggerFrame::getImplementation(Handle<DebuggerFrame*> frame)
+DebuggerFrame::getImplementation(HandleDebuggerFrame frame)
 {
     AbstractFramePtr referent = DebuggerFrame::getReferent(frame);
 
     if (referent.isBaselineFrame())
         return DebuggerFrameImplementation::Baseline;
     else if (referent.isRematerializedFrame())
         return DebuggerFrameImplementation::Ion;
     return DebuggerFrameImplementation::Interpreter;
@@ -7289,40 +7289,40 @@ DebuggerFrame::getImplementation(Handle<
 
 /* statuc */ bool
 DebuggerFrame::isLive() const
 {
     return !!getPrivate();
 }
 
 /* static */ bool
-DebuggerFrame::requireLive(JSContext* cx, Handle<DebuggerFrame*> frame)
+DebuggerFrame::requireLive(JSContext* cx, HandleDebuggerFrame frame)
 {
     if (!frame->isLive()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_LIVE,
                              "Debugger.Frame");
         return false;
     }
 
     return true;
 }
 
 /* static */ AbstractFramePtr
-DebuggerFrame::getReferent(Handle<DebuggerFrame*> frame)
+DebuggerFrame::getReferent(HandleDebuggerFrame frame)
 {
     AbstractFramePtr referent = AbstractFramePtr::FromRaw(frame->getPrivate());
     if (referent.isScriptFrameIterData()) {
         ScriptFrameIter iter(*(ScriptFrameIter::Data*)(referent.raw()));
         referent = iter.abstractFramePtr();
     }
     return referent;
 }
 
 /* static */ bool
-DebuggerFrame::getScriptFrameIter(JSContext* cx, Handle<DebuggerFrame*> frame,
+DebuggerFrame::getScriptFrameIter(JSContext* cx, HandleDebuggerFrame frame,
                                   Maybe<ScriptFrameIter>& result)
 {
     AbstractFramePtr referent = AbstractFramePtr::FromRaw(frame->getPrivate());
     if (referent.isScriptFrameIterData()) {
         result.emplace(*reinterpret_cast<ScriptFrameIter::Data*>(referent.raw()));
     } else {
         result.emplace(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK);
         ScriptFrameIter& iter = *result;
@@ -7367,17 +7367,17 @@ DebuggerFrame::checkThis(JSContext* cx, 
     if (!thisobj)
         return nullptr;
     if (thisobj->getClass() != &DebuggerFrame::class_) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
                              "Debugger.Frame", fnname, thisobj->getClass()->name);
         return nullptr;
     }
 
-    Rooted<DebuggerFrame*> frame(cx, &thisobj->as<DebuggerFrame>());
+    RootedDebuggerFrame frame(cx, &thisobj->as<DebuggerFrame>());
 
     /*
      * Forbid Debugger.Frame.prototype, which is of class DebuggerFrame::class_
      * but isn't really a working Debugger.Frame object. The prototype object
      * is distinguished by having a nullptr private value. Also, forbid popped
      * frames.
      */
     if (!frame->getPrivate() &&
@@ -7408,17 +7408,17 @@ DebuggerFrame::checkThis(JSContext* cx, 
  * always create a ScriptFrameIter from the cached Data.
  *
  * Methods that only need the AbstractFramePtr should use THIS_FRAME.
  * Methods that need a ScriptFrameIterator should use THIS_FRAME_ITER.
  */
 
 #define THIS_DEBUGGER_FRAME(cx, argc, vp, fnname, args, frame)                          \
     CallArgs args = CallArgsFromVp(argc, vp);                                           \
-    Rooted<DebuggerFrame*> frame(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
+    RootedDebuggerFrame frame(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
     if (!frame)                                                                         \
         return false;
 
 #define THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj)                       \
     CallArgs args = CallArgsFromVp(argc, vp);                                         \
     RootedNativeObject thisobj(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
     if (!thisobj)                                                                     \
         return false
@@ -7518,30 +7518,30 @@ DebuggerFrame::implementationGetter(JSCo
     return true;
 }
 
 /* static */ bool
 DebuggerFrame::environmentGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER_FRAME(cx, argc, vp, "get environment", args, frame);
 
-    Rooted<DebuggerEnvironment*> result(cx);
+    RootedDebuggerEnvironment result(cx);
     if (!DebuggerFrame::getEnvironment(cx, frame, &result))
         return false;
 
     args.rval().setObject(*result);
     return true;
 }
 
 /* static */ bool
 DebuggerFrame::calleeGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER_FRAME(cx, argc, vp, "get callee", args, frame);
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!DebuggerFrame::getCallee(cx, frame, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* static */ bool
@@ -7574,17 +7574,17 @@ DebuggerFrame::thisGetter(JSContext* cx,
     return DebuggerFrame::getThis(cx, frame, args.rval());
 }
 
 /* static */ bool
 DebuggerFrame::olderGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER_FRAME(cx, argc, vp, "get older", args, frame);
 
-    Rooted<DebuggerFrame*> result(cx);
+    RootedDebuggerFrame result(cx);
     if (!DebuggerFrame::getOlder(cx, frame, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* The getter used for each element of frame.arguments. See DebuggerFrame_getArguments. */
@@ -7745,17 +7745,17 @@ DebuggerFrame::offsetGetter(JSContext* c
     args.rval().setNumber(double(result));
     return true;
 }
 
 /* static */ bool
 DebuggerFrame::liveGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    Rooted<DebuggerFrame*> frame(cx, DebuggerFrame::checkThis(cx, args, "get live", false));
+    RootedDebuggerFrame frame(cx, DebuggerFrame::checkThis(cx, args, "get live", false));
     if (!frame)
         return false;
 
     args.rval().setBoolean(frame->isLive());
     return true;
 }
 
 static bool
@@ -8122,17 +8122,17 @@ DebuggerObject::checkThis(JSContext* cx,
                              "Debugger.Object", fnname, "prototype object");
         return nullptr;
     }
     return nthisobj;
 }
 
 #define THIS_DEBUGOBJECT(cx, argc, vp, fnname, args, object)                         \
     CallArgs args = CallArgsFromVp(argc, vp);                                        \
-    Rooted<DebuggerObject*> object(cx, DebuggerObject::checkThis(cx, args, fnname)); \
+    RootedDebuggerObject object(cx, DebuggerObject::checkThis(cx, args, fnname)); \
     if (!object)                                                                     \
         return false;                                                                \
 
 #define THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, fnname, args, obj)     \
     CallArgs args = CallArgsFromVp(argc, vp);                          \
     RootedObject obj(cx, DebuggerObject::checkThis(cx, args, fnname)); \
     if (!obj)                                                          \
         return false;                                                  \
@@ -8221,17 +8221,17 @@ DebuggerObject::isArrowFunctionGetter(JS
     return true;
 }
 
 /* static */ bool
 DebuggerObject::protoGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get proto", args, object)
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!DebuggerObject::getPrototypeOf(cx, object, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* static */ bool
@@ -8383,17 +8383,17 @@ DebuggerObject::boundTargetFunctionGette
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get boundTargetFunction", args, object)
 
     if (!object->isDebuggeeFunction() || !object->isBoundFunction()) {
         args.rval().setUndefined();
         return true;
     }
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!DebuggerObject::getBoundTargetFunction(cx, object, &result))
         return false;
 
     args.rval().setObject(*result);
     return true;
 }
 
 /* static */ bool
@@ -8431,17 +8431,17 @@ DebuggerObject::boundArgumentsGetter(JSC
     return true;
 }
 
 /* static */ bool
 DebuggerObject::globalGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get global", args, object)
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!DebuggerObject::getGlobal(cx, object, &result))
         return false;
 
     args.rval().setObject(*result);
     return true;
 }
 
 /* static */ bool
@@ -9060,17 +9060,17 @@ DebuggerObject::unsafeDereferenceMethod(
     return true;
 }
 
 /* static */ bool
 DebuggerObject::unwrapMethod(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "unwrap", args, object);
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!DebuggerObject::unwrap(cx, object, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 const JSPropertySpec DebuggerObject::properties_[] = {
@@ -9214,17 +9214,17 @@ DebuggerObject::isGlobal() const
 
 bool
 DebuggerObject::isScriptedProxy() const
 {
     return js::IsScriptedProxy(referent());
 }
 
 /* static */ bool
-DebuggerObject::isPromise(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::isPromise(JSContext* cx, HandleDebuggerObject object,
                           bool& result)
 {
     JSObject* referent = object->referent();
     if (IsCrossCompartmentWrapper(referent)) {
         referent = CheckedUnwrap(referent);
 
         if (!referent) {
             JS_ReportError(cx, "Permission denied to access object");
@@ -9232,17 +9232,17 @@ DebuggerObject::isPromise(JSContext* cx,
         }
       }
 
     result = referent->is<PromiseObject>();
     return true;
 }
 
 /* static */ bool
-DebuggerObject::getClassName(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getClassName(JSContext* cx, HandleDebuggerObject object,
                              MutableHandleString result)
 {
     RootedObject referent(cx, object->referent());
 
     const char* className;
     {
         AutoCompartment ac(cx, referent);
         className = GetObjectClassName(cx, referent);
@@ -9252,18 +9252,18 @@ DebuggerObject::getClassName(JSContext* 
     if (!str)
         return false;
 
     result.set(str);
     return true;
 }
 
 /* static */ bool
-DebuggerObject::getGlobal(JSContext* cx, Handle<DebuggerObject*> object,
-                          MutableHandle<DebuggerObject*> result)
+DebuggerObject::getGlobal(JSContext* cx, HandleDebuggerObject object,
+                          MutableHandleDebuggerObject result)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     RootedObject global(cx, &referent->global());
     return dbg->wrapDebuggeeObject(cx, global, result);
 }
 
@@ -9279,17 +9279,17 @@ JSAtom*
 DebuggerObject::displayName() const
 {
     MOZ_ASSERT(isFunction());
 
     return referent()->as<JSFunction>().displayAtom();
 }
 
 /* static */ bool
-DebuggerObject::getParameterNames(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getParameterNames(JSContext* cx, HandleDebuggerObject object,
                                   MutableHandle<StringVector> result)
 {
     MOZ_ASSERT(object->isDebuggeeFunction());
 
     RootedFunction referent(cx, &object->referent()->as<JSFunction>());
 
     if (!result.growBy(referent->nargs()))
         return false;
@@ -9314,43 +9314,43 @@ DebuggerObject::getParameterNames(JSCont
         for (size_t i = 0; i < referent->nargs(); i++)
             result[i].set(nullptr);
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::getBoundTargetFunction(JSContext* cx, Handle<DebuggerObject*> object,
-                                       MutableHandle<DebuggerObject*> result)
+DebuggerObject::getBoundTargetFunction(JSContext* cx, HandleDebuggerObject object,
+                                       MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(object->isBoundFunction());
 
     RootedFunction referent(cx, &object->referent()->as<JSFunction>());
     Debugger* dbg = object->owner();
 
     RootedObject target(cx, referent->getBoundFunctionTarget());
     return dbg->wrapDebuggeeObject(cx, target, result);
 }
 
 /* static */ bool
-DebuggerObject::getBoundThis(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getBoundThis(JSContext* cx, HandleDebuggerObject object,
                              MutableHandleValue result)
 {
     MOZ_ASSERT(object->isBoundFunction());
 
     RootedFunction referent(cx, &object->referent()->as<JSFunction>());
     Debugger* dbg = object->owner();
 
     result.set(referent->getBoundFunctionThis());
     return dbg->wrapDebuggeeValue(cx, result);
 }
 
 /* static */ bool
-DebuggerObject::getBoundArguments(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getBoundArguments(JSContext* cx, HandleDebuggerObject object,
                                   MutableHandle<ValueVector> result)
 {
     MOZ_ASSERT(object->isBoundFunction());
 
     RootedFunction referent(cx, &object->referent()->as<JSFunction>());
     Debugger* dbg = object->owner();
 
     size_t length = referent->getBoundFunctionArgumentCount();
@@ -9373,31 +9373,31 @@ Debugger::getObjectAllocationSite(JSObje
 
     MOZ_ASSERT(!metadata->is<WrapperObject>());
     return SavedFrame::isSavedFrameAndNotProto(*metadata)
         ? &metadata->as<SavedFrame>()
         : nullptr;
 }
 
 /* static */ bool
-DebuggerObject::getAllocationSite(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getAllocationSite(JSContext* cx, HandleDebuggerObject object,
                                   MutableHandleObject result)
 {
     RootedObject referent(cx, object->referent());
 
     RootedObject allocSite(cx, Debugger::getObjectAllocationSite(*referent));
     if (!cx->compartment()->wrap(cx, &allocSite))
         return false;
 
     result.set(allocSite);
     return true;
 }
 
 /* static */ bool
-DebuggerObject::getErrorMessageName(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getErrorMessageName(JSContext* cx, HandleDebuggerObject object,
                                     MutableHandleString result)
 {
     RootedObject referent(cx, object->referent());
 
     JSObject* obj = referent;
     if (IsCrossCompartmentWrapper(obj))
         obj = CheckedUnwrap(obj);
 
@@ -9421,53 +9421,53 @@ DebuggerObject::getErrorMessageName(JSCo
         }
     }
 
     result.set(nullptr);
     return true;
 }
 
 /* static */ bool
-DebuggerObject::isExtensible(JSContext* cx, Handle<DebuggerObject*> object, bool& result)
+DebuggerObject::isExtensible(JSContext* cx, HandleDebuggerObject object, bool& result)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
     ErrorCopier ec(ac);
     return IsExtensible(cx, referent, &result);
 }
 
 /* static */ bool
-DebuggerObject::isSealed(JSContext* cx, Handle<DebuggerObject*> object, bool& result)
+DebuggerObject::isSealed(JSContext* cx, HandleDebuggerObject object, bool& result)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return TestIntegrityLevel(cx, referent, IntegrityLevel::Sealed, &result);
 }
 
 /* static */ bool
-DebuggerObject::isFrozen(JSContext* cx, Handle<DebuggerObject*> object, bool& result)
+DebuggerObject::isFrozen(JSContext* cx, HandleDebuggerObject object, bool& result)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return TestIntegrityLevel(cx, referent, IntegrityLevel::Frozen, &result);
 }
 
 /* static */ bool
-DebuggerObject::getPrototypeOf(JSContext* cx, Handle<DebuggerObject*> object,
-                               MutableHandle<DebuggerObject*> result)
+DebuggerObject::getPrototypeOf(JSContext* cx, HandleDebuggerObject object,
+                               MutableHandleDebuggerObject result)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     RootedObject proto(cx);
     {
         AutoCompartment ac(cx, referent);
         if (!GetPrototype(cx, referent, &proto))
@@ -9478,17 +9478,17 @@ DebuggerObject::getPrototypeOf(JSContext
         result.set(nullptr);
         return true;
     }
 
     return dbg->wrapDebuggeeObject(cx, proto, result);
 }
 
 /* static */ bool
-DebuggerObject::getOwnPropertyNames(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getOwnPropertyNames(JSContext* cx, HandleDebuggerObject object,
                                     MutableHandle<IdVector> result)
 {
     RootedObject referent(cx, object->referent());
 
     AutoIdVector ids(cx);
     {
         Maybe<AutoCompartment> ac;
         ac.emplace(cx, referent);
@@ -9497,17 +9497,17 @@ DebuggerObject::getOwnPropertyNames(JSCo
         if (!GetPropertyKeys(cx, referent, JSITER_OWNONLY | JSITER_HIDDEN, &ids))
             return false;
     }
 
     return result.append(ids.begin(), ids.end());
 }
 
 /* static */ bool
-DebuggerObject::getOwnPropertySymbols(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getOwnPropertySymbols(JSContext* cx, HandleDebuggerObject object,
                                       MutableHandle<IdVector> result)
 {
     RootedObject referent(cx, object->referent());
 
     AutoIdVector ids(cx);
     {
         Maybe<AutoCompartment> ac;
         ac.emplace(cx, referent);
@@ -9518,17 +9518,17 @@ DebuggerObject::getOwnPropertySymbols(JS
                              &ids))
             return false;
     }
 
     return result.append(ids.begin(), ids.end());
 }
 
 /* static */ bool
-DebuggerObject::getOwnPropertyDescriptor(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::getOwnPropertyDescriptor(JSContext* cx, HandleDebuggerObject object,
                                          HandleId id, MutableHandle<PropertyDescriptor> desc)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     /* Bug: This can cause the debuggee to run! */
     {
         Maybe<AutoCompartment> ac;
@@ -9560,53 +9560,53 @@ DebuggerObject::getOwnPropertyDescriptor
         // Avoid tripping same-compartment assertions in JS::FromPropertyDescriptor().
         desc.object().set(object);
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::preventExtensions(JSContext* cx, Handle<DebuggerObject*> object)
+DebuggerObject::preventExtensions(JSContext* cx, HandleDebuggerObject object)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return PreventExtensions(cx, referent);
 }
 
 /* static */ bool
-DebuggerObject::seal(JSContext* cx, Handle<DebuggerObject*> object)
+DebuggerObject::seal(JSContext* cx, HandleDebuggerObject object)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return SetIntegrityLevel(cx, referent, IntegrityLevel::Sealed);
 }
 
 /* static */ bool
-DebuggerObject::freeze(JSContext* cx, Handle<DebuggerObject*> object)
+DebuggerObject::freeze(JSContext* cx, HandleDebuggerObject object)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return SetIntegrityLevel(cx, referent, IntegrityLevel::Frozen);
 }
 
 /* static */ bool
-DebuggerObject::defineProperty(JSContext* cx, Handle<DebuggerObject*> object, HandleId id,
+DebuggerObject::defineProperty(JSContext* cx, HandleDebuggerObject object, HandleId id,
                                Handle<PropertyDescriptor> desc_)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     Rooted<PropertyDescriptor> desc(cx, desc_);
     if (!dbg->unwrapPropertyDescriptor(cx, referent, &desc))
         return false;
@@ -9621,17 +9621,17 @@ DebuggerObject::defineProperty(JSContext
     ErrorCopier ec(ac);
     if (!DefineProperty(cx, referent, id, desc))
         return false;
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::defineProperties(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::defineProperties(JSContext* cx, HandleDebuggerObject object,
                                  Handle<IdVector> ids,
                                  Handle<PropertyDescriptorVector> descs_)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     Rooted<PropertyDescriptorVector> descs(cx, PropertyDescriptorVector(cx));
     if (!descs.append(descs_.begin(), descs_.end()))
@@ -9655,30 +9655,30 @@ DebuggerObject::defineProperties(JSConte
         if (!DefineProperty(cx, referent, ids[i], descs[i]))
             return false;
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::deleteProperty(JSContext* cx, Handle<DebuggerObject*> object, HandleId id,
+DebuggerObject::deleteProperty(JSContext* cx, HandleDebuggerObject object, HandleId id,
                                ObjectOpResult& result)
 {
     RootedObject referent(cx, object->referent());
 
     Maybe<AutoCompartment> ac;
     ac.emplace(cx, referent);
 
     ErrorCopier ec(ac);
     return DeleteProperty(cx, referent, id, result);
 }
 
 /* static */ bool
-DebuggerObject::call(JSContext* cx, Handle<DebuggerObject*> object, HandleValue thisv_,
+DebuggerObject::call(JSContext* cx, HandleDebuggerObject object, HandleValue thisv_,
                      Handle<ValueVector> args, MutableHandleValue result)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     if (!referent->isCallable()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
                              "Debugger.Object", "call", referent->getClass()->name);
@@ -9733,17 +9733,17 @@ DebuggerObject::call(JSContext* cx, Hand
             ok = js::Call(cx, calleev, thisv, invokeArgs, result);
         }
     }
 
     return dbg->receiveCompletionValue(ac, ok, result, result);
 }
 
 /* static */ bool
-DebuggerObject::forceLexicalInitializationByName(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::forceLexicalInitializationByName(JSContext* cx, HandleDebuggerObject object,
                                                  HandleId id, bool& result)
 {
     if (!JSID_IS_STRING(id)) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                              JSMSG_NOT_EXPECTED_TYPE, "Debugger.Object.prototype.forceLexicalInitializationByName",
                              "string", InformalValueTypeName(IdToValue(id)));
         return false;
     }
@@ -9766,32 +9766,32 @@ DebuggerObject::forceLexicalInitializati
             result = true;
         }
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::executeInGlobal(JSContext* cx, HandleDebuggerObject object,
                                 mozilla::Range<const char16_t> chars, HandleObject bindings,
                                 const EvalOptions& options, MutableHandleValue result)
 {
     MOZ_ASSERT(object->isGlobal());
 
     Rooted<GlobalObject*> referent(cx, &object->referent()->as<GlobalObject>());
     Debugger* dbg = object->owner();
 
     RootedObject globalLexical(cx, &referent->lexicalScope());
     return DebuggerGenericEval(cx, chars, bindings, options, result, dbg, globalLexical,
                                nullptr);
 }
 
 /* static */ bool
-DebuggerObject::makeDebuggeeValue(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::makeDebuggeeValue(JSContext* cx, HandleDebuggerObject object,
                                   HandleValue value_, MutableHandleValue result)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     RootedValue value(cx, value_);
 
     /* Non-objects are already debuggee values. */
@@ -9810,34 +9810,34 @@ DebuggerObject::makeDebuggeeValue(JSCont
             return false;
     }
 
     result.set(value);
     return true;
 }
 
 /* static */ bool
-DebuggerObject::unsafeDereference(JSContext* cx, Handle<DebuggerObject*> object,
+DebuggerObject::unsafeDereference(JSContext* cx, HandleDebuggerObject object,
                                   MutableHandleObject result)
 {
     RootedObject referent(cx, object->referent());
 
     if (!cx->compartment()->wrap(cx, &referent))
         return false;
 
     // Wrapping should return the WindowProxy.
     MOZ_ASSERT(!IsWindow(referent));
 
     result.set(referent);
     return true;
 }
 
 /* static */ bool
-DebuggerObject::unwrap(JSContext* cx, Handle<DebuggerObject*> object,
-                       MutableHandle<DebuggerObject*> result)
+DebuggerObject::unwrap(JSContext* cx, HandleDebuggerObject object,
+                       MutableHandleDebuggerObject result)
 {
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
 
     RootedObject unwrapped(cx, UnwrapOneChecked(referent));
     if (!unwrapped) {
         result.set(nullptr);
         return true;
@@ -9852,17 +9852,17 @@ DebuggerObject::unwrap(JSContext* cx, Ha
                              JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
         return false;
     }
 
     return dbg->wrapDebuggeeObject(cx, unwrapped, result);
 }
 
 /* static */ bool
-DebuggerObject::requireGlobal(JSContext* cx, Handle<DebuggerObject*> object)
+DebuggerObject::requireGlobal(JSContext* cx, HandleDebuggerObject object)
 {
     if (!object->isGlobal()) {
         RootedObject referent(cx, object->referent());
 
         const char* isWrapper = "";
         const char* isWindowProxy = "";
 
         /* Help the poor programmer by pointing out wrappers around globals... */
@@ -9889,29 +9889,29 @@ DebuggerObject::requireGlobal(JSContext*
         }
         return false;
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerObject::scriptedProxyTarget(JSContext* cx, Handle<DebuggerObject*> object,
-                                    MutableHandle<DebuggerObject*> result)
+DebuggerObject::scriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
+                                    MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(object->isScriptedProxy());
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
     RootedObject unwrapped(cx, js::GetProxyTargetObject(referent));
     return dbg->wrapDebuggeeObject(cx, unwrapped, result);
 }
 
 /* static */ bool
-DebuggerObject::scriptedProxyHandler(JSContext* cx, Handle<DebuggerObject*> object,
-                                     MutableHandle<DebuggerObject*> result)
+DebuggerObject::scriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
+                                     MutableHandleDebuggerObject result)
 {
     MOZ_ASSERT(object->isScriptedProxy());
     RootedObject referent(cx, object->referent());
     Debugger* dbg = object->owner();
     RootedObject unwrapped(cx, ScriptedProxyHandler::handlerObject(referent));
     return dbg->wrapDebuggeeObject(cx, unwrapped, result);
 }
 
@@ -10035,17 +10035,17 @@ DebuggerEnvironment::typeGetter(JSContex
 /* static */ bool
 DebuggerEnvironment::parentGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER_ENVIRONMENT(cx, argc, vp, "get type", args, environment);
 
     if (!environment->requireDebuggee(cx))
         return false;
 
-    Rooted<DebuggerEnvironment*> result(cx);
+    RootedDebuggerEnvironment result(cx);
     if (!environment->getParent(cx, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* static */ bool
@@ -10056,33 +10056,33 @@ DebuggerEnvironment::objectGetter(JSCont
     if (!environment->requireDebuggee(cx))
         return false;
 
     if (environment->type() == DebuggerEnvironmentType::Declarative) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_NO_SCOPE_OBJECT);
         return false;
     }
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!environment->getObject(cx, &result))
         return false;
 
     args.rval().setObject(*result);
     return true;
 }
 
 /* static */ bool
 DebuggerEnvironment::calleeGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER_ENVIRONMENT(cx, argc, vp, "get callee", args, environment);
 
     if (!environment->requireDebuggee(cx))
         return false;
 
-    Rooted<DebuggerObject*> result(cx);
+    RootedDebuggerObject result(cx);
     if (!environment->getCallee(cx, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* static */ bool
@@ -10132,17 +10132,17 @@ DebuggerEnvironment::findMethod(JSContex
 
     if (!environment->requireDebuggee(cx))
         return false;
 
     RootedId id(cx);
     if (!ValueToIdentifier(cx, args[0], &id))
         return false;
 
-    Rooted<DebuggerEnvironment*> result(cx);
+    RootedDebuggerEnvironment result(cx);
     if (!DebuggerEnvironment::find(cx, environment, id, &result))
         return false;
 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 /* static */ bool
@@ -10247,30 +10247,30 @@ DebuggerEnvironment::type() const
     if (IsDeclarative(referent()))
         return DebuggerEnvironmentType::Declarative;
     else if (IsDebugScopeWrapper<DynamicWithObject>(referent()))
         return DebuggerEnvironmentType::With;
     return DebuggerEnvironmentType::Object;
 }
 
 bool
-DebuggerEnvironment::getParent(JSContext* cx, MutableHandle<DebuggerEnvironment*> result) const
+DebuggerEnvironment::getParent(JSContext* cx, MutableHandleDebuggerEnvironment result) const
 {
     /* Don't bother switching compartments just to get env's parent. */
     Rooted<Env*> parent(cx, referent()->enclosingScope());
     if (!parent) {
         result.set(nullptr);
         return true;
     }
 
     return owner()->wrapEnvironment(cx, parent, result);
 }
 
 bool
-DebuggerEnvironment::getObject(JSContext* cx, MutableHandle<DebuggerObject*> result) const
+DebuggerEnvironment::getObject(JSContext* cx, MutableHandleDebuggerObject result) const
 {
     MOZ_ASSERT(type() != DebuggerEnvironmentType::Declarative);
 
     /* Don't bother switching compartments just to get env's object. */
     RootedObject object(cx);
     if (IsDebugScopeWrapper<DynamicWithObject>(referent())) {
         object.set(&referent()->as<DebugScopeObject>().scope().as<DynamicWithObject>().object());
     } else if (IsDebugScopeWrapper<NonSyntacticVariablesObject>(referent())) {
@@ -10279,17 +10279,17 @@ DebuggerEnvironment::getObject(JSContext
         object.set(referent());
         MOZ_ASSERT(!object->is<DebugScopeObject>());
     }
 
     return owner()->wrapDebuggeeObject(cx, object, result);
 }
 
 bool
-DebuggerEnvironment::getCallee(JSContext* cx, MutableHandle<DebuggerObject*> result) const
+DebuggerEnvironment::getCallee(JSContext* cx, MutableHandleDebuggerObject result) const
 {
     if (!referent()->is<DebugScopeObject>()) {
         result.set(nullptr);
         return true;
     }
 
     JSObject& scope = referent()->as<DebugScopeObject>().scope();
     if (!scope.is<CallObject>()) {
@@ -10323,17 +10323,17 @@ DebuggerEnvironment::isDebuggee() const
 
 bool
 DebuggerEnvironment::isOptimized() const
 {
     return referent()->is<DebugScopeObject>() && referent()->as<DebugScopeObject>().isOptimizedOut();
 }
 
 /* static */ bool
-DebuggerEnvironment::getNames(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+DebuggerEnvironment::getNames(JSContext* cx, HandleDebuggerEnvironment environment,
                               MutableHandle<IdVector> result)
 {
     MOZ_ASSERT(environment->isDebuggee());
 
     Rooted<Env*> referent(cx, environment->referent());
 
     AutoIdVector ids(cx);
     {
@@ -10352,18 +10352,18 @@ DebuggerEnvironment::getNames(JSContext*
                 return false;
         }
     }
 
     return true;
 }
 
 /* static */ bool
-DebuggerEnvironment::find(JSContext* cx, Handle<DebuggerEnvironment*> environment, HandleId id,
-                          MutableHandle<DebuggerEnvironment*> result)
+DebuggerEnvironment::find(JSContext* cx, HandleDebuggerEnvironment environment, HandleId id,
+                          MutableHandleDebuggerEnvironment result)
 {
     MOZ_ASSERT(environment->isDebuggee());
 
     Rooted<Env*> env(cx, environment->referent());
     Debugger* dbg = environment->owner();
 
     {
         Maybe<AutoCompartment> ac;
@@ -10384,17 +10384,17 @@ DebuggerEnvironment::find(JSContext* cx,
         result.set(nullptr);
         return true;
     }
 
     return dbg->wrapEnvironment(cx, env, result);
 }
 
 /* static */ bool
-DebuggerEnvironment::getVariable(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+DebuggerEnvironment::getVariable(JSContext* cx, HandleDebuggerEnvironment environment,
                                  HandleId id, MutableHandleValue result)
 {
     MOZ_ASSERT(environment->isDebuggee());
 
     Rooted<Env*> referent(cx, environment->referent());
     Debugger* dbg = environment->owner();
 
     {
@@ -10434,17 +10434,17 @@ DebuggerEnvironment::getVariable(JSConte
             IsInternalFunctionObject(obj->as<JSFunction>()))
             result.setMagic(JS_OPTIMIZED_OUT);
     }
 
     return dbg->wrapDebuggeeValue(cx, result);
 }
 
 /* static */ bool
-DebuggerEnvironment::setVariable(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+DebuggerEnvironment::setVariable(JSContext* cx, HandleDebuggerEnvironment environment,
                                  HandleId id, HandleValue value_)
 {
     MOZ_ASSERT(environment->isDebuggee());
 
     Rooted<Env*> referent(cx, environment->referent());
     Debugger* dbg = environment->owner();
 
     RootedValue value(cx, value_);
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -240,20 +240,16 @@ typedef JSObject Env;
 //   2. A wasm JSFunction, denoting a synthesized wasm function script.
 //      NYI!
 typedef mozilla::Variant<JSScript*, WasmInstanceObject*> DebuggerScriptReferent;
 
 // Either a ScriptSourceObject, for ordinary JS, or a WasmInstanceObject,
 // denoting the synthesized source of a wasm module.
 typedef mozilla::Variant<ScriptSourceObject*, WasmInstanceObject*> DebuggerSourceReferent;
 
-class DebuggerEnvironment;
-class DebuggerFrame;
-class DebuggerObject;
-
 class Debugger : private mozilla::LinkedListElement<Debugger>
 {
     friend class Breakpoint;
     friend class DebuggerMemory;
     friend class SavedStacks;
     friend class mozilla::LinkedListElement<Debugger>;
     friend class mozilla::LinkedList<Debugger>;
     friend bool (::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
@@ -453,17 +449,17 @@ class Debugger : private mozilla::Linked
      * removeDebuggee.
      *
      * We don't trace the keys of this map (the frames are on the stack and
      * thus necessarily live), but we do trace the values. It's like a WeakMap
      * that way, but since stack frames are not gc-things, the implementation
      * has to be different.
      */
     typedef HashMap<AbstractFramePtr,
-                    HeapPtr<NativeObject*>,
+                    HeapPtr<DebuggerFrame*>,
                     DefaultHasher<AbstractFramePtr>,
                     RuntimeAllocPolicy> FrameMap;
     FrameMap frames;
 
     /* An ephemeral map from JSScript* to Debugger.Script instances. */
     typedef DebuggerWeakMap<JSScript*> ScriptWeakMap;
     ScriptWeakMap scripts;
 
@@ -645,17 +641,17 @@ class Debugger : private mozilla::Linked
     template <typename FrameFn /* void (NativeObject*) */>
     static void forEachDebuggerFrame(AbstractFramePtr frame, FrameFn fn);
 
     /*
      * Return a vector containing all Debugger.Frame instances referring to
      * |frame|. |global| is |frame|'s global object; if nullptr or omitted, we
      * compute it ourselves from |frame|.
      */
-    using DebuggerFrameVector = GCVector<NativeObject*>;
+    using DebuggerFrameVector = GCVector<DebuggerFrame*>;
     static MOZ_MUST_USE bool getDebuggerFrames(AbstractFramePtr frame,
                                                MutableHandle<DebuggerFrameVector> frames);
 
   public:
     static MOZ_MUST_USE bool ensureExecutionObservabilityOfOsrFrame(JSContext* cx,
                                                                     InterpreterFrame* frame);
 
     // Public for DebuggerScript_setBreakpoint.
@@ -763,17 +759,17 @@ class Debugger : private mozilla::Linked
      * Gets a Debugger.Frame object. If maybeIter is non-null, we eagerly copy
      * its data if we need to make a new Debugger.Frame.
      */
     MOZ_MUST_USE bool getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
                                              const ScriptFrameIter* maybeIter,
                                              MutableHandleValue vp);
     MOZ_MUST_USE bool getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
                                              const ScriptFrameIter* maybeIter,
-                                             MutableHandle<DebuggerFrame*> result);
+                                             MutableHandleDebuggerFrame result);
 
     inline Breakpoint* firstBreakpoint() const;
 
     static inline Debugger* fromOnNewGlobalObjectWatchersLink(JSCList* link);
 
     static MOZ_MUST_USE bool replaceFrameGuts(JSContext* cx, AbstractFramePtr from,
                                               AbstractFramePtr to,
                                               ScriptFrameIter& iter);
@@ -909,17 +905,17 @@ class Debugger : private mozilla::Linked
 
     /*
      * If env is nullptr, call vp->setNull() and return true. Otherwise, find
      * or create a Debugger.Environment object for the given Env. On success,
      * store the Environment object in *vp and return true.
      */
     MOZ_MUST_USE bool wrapEnvironment(JSContext* cx, Handle<Env*> env, MutableHandleValue vp);
     MOZ_MUST_USE bool wrapEnvironment(JSContext* cx, Handle<Env*> env,
-                                      MutableHandle<DebuggerEnvironment*> result);
+                                      MutableHandleDebuggerEnvironment result);
 
     /*
      * Like cx->compartment()->wrap(cx, vp), but for the debugger compartment.
      *
      * Preconditions: *vp is a value from a debuggee compartment; cx is in the
      * debugger's compartment.
      *
      * If *vp is an object, this produces a (new or existing) Debugger.Object
@@ -933,17 +929,17 @@ class Debugger : private mozilla::Linked
      * true }.
      *
      * If *vp is a magic JS_UNINITIALIZED_LEXICAL value signifying an
      * unaccessible uninitialized binding, this produces a plain object of the
      * form { uninitialized: true }.
      */
     MOZ_MUST_USE bool wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
     MOZ_MUST_USE bool wrapDebuggeeObject(JSContext* cx, HandleObject obj,
-                                         MutableHandle<DebuggerObject*> result);
+                                         MutableHandleDebuggerObject result);
 
     /*
      * Unwrap a Debug.Object, without rewrapping it for any particular debuggee
      * compartment.
      *
      * Preconditions: cx is in the debugger compartment. *vp is a value in that
      * compartment. (*vp should be a "debuggee value", meaning it is the
      * debugger's reflection of a value in the debuggee.)
@@ -990,17 +986,17 @@ class Debugger : private mozilla::Linked
      * frame, in which case the cost of walking the stack has already been
      * paid.
      */
     MOZ_MUST_USE bool getScriptFrame(JSContext* cx, const ScriptFrameIter& iter,
                                      MutableHandleValue vp) {
         return getScriptFrameWithIter(cx, iter.abstractFramePtr(), &iter, vp);
     }
     MOZ_MUST_USE bool getScriptFrame(JSContext* cx, const ScriptFrameIter& iter,
-                                     MutableHandle<DebuggerFrame*> result);
+                                     MutableHandleDebuggerFrame result);
 
 
     /*
      * Set |*status| and |*value| to a (JSTrapStatus, Value) pair reflecting a
      * standard SpiderMonkey call state: a boolean success value |ok|, a return
      * value |rv|, and a context |cx| that may or may not have an exception set.
      * If an exception was pending on |cx|, it is cleared (and |ok| is asserted
      * to be false).
@@ -1084,29 +1080,29 @@ class DebuggerEnvironment : public Nativ
 
     static const Class class_;
 
     static NativeObject* initClass(JSContext* cx, HandleObject dbgCtor, HandleObject objProto);
     static DebuggerEnvironment* create(JSContext* cx, HandleObject proto, HandleObject referent,
                                        HandleNativeObject debugger);
 
     DebuggerEnvironmentType type() const;
-    MOZ_MUST_USE bool getParent(JSContext* cx, MutableHandle<DebuggerEnvironment*> result) const;
-    MOZ_MUST_USE bool getObject(JSContext* cx, MutableHandle<DebuggerObject*> result) const;
-    MOZ_MUST_USE bool getCallee(JSContext* cx, MutableHandle<DebuggerObject*> result) const;
+    MOZ_MUST_USE bool getParent(JSContext* cx, MutableHandleDebuggerEnvironment result) const;
+    MOZ_MUST_USE bool getObject(JSContext* cx, MutableHandleDebuggerObject result) const;
+    MOZ_MUST_USE bool getCallee(JSContext* cx, MutableHandleDebuggerObject result) const;
     bool isDebuggee() const;
     bool isOptimized() const;
 
-    static MOZ_MUST_USE bool getNames(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+    static MOZ_MUST_USE bool getNames(JSContext* cx, HandleDebuggerEnvironment environment,
                                       MutableHandle<IdVector> result);
-    static MOZ_MUST_USE bool find(JSContext* cx, Handle<DebuggerEnvironment*> environment,
-                                  HandleId id, MutableHandle<DebuggerEnvironment*> result);
-    static MOZ_MUST_USE bool getVariable(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+    static MOZ_MUST_USE bool find(JSContext* cx, HandleDebuggerEnvironment environment,
+                                  HandleId id, MutableHandleDebuggerEnvironment result);
+    static MOZ_MUST_USE bool getVariable(JSContext* cx, HandleDebuggerEnvironment environment,
                                          HandleId id, MutableHandleValue result);
-    static MOZ_MUST_USE bool setVariable(JSContext* cx, Handle<DebuggerEnvironment*> environment,
+    static MOZ_MUST_USE bool setVariable(JSContext* cx, HandleDebuggerEnvironment environment,
                                          HandleId id, HandleValue value);
 
   private:
     static const ClassOps classOps_;
 
     static const JSPropertySpec properties_[];
     static const JSFunctionSpec methods_[];
 
@@ -1162,43 +1158,42 @@ class DebuggerFrame : public NativeObjec
     static const Class class_;
 
     static NativeObject* initClass(JSContext* cx, HandleObject dbgCtor, HandleObject objProto);
     static DebuggerFrame* create(JSContext* cx, HandleObject proto, AbstractFramePtr referent,
                                  const ScriptFrameIter* maybeIter, HandleNativeObject debugger);
     static DebuggerFrame* checkThis(JSContext* cx, const CallArgs& args, const char* fnname,
                                     bool checkLive);
 
-    static MOZ_MUST_USE bool getCallee(JSContext* cx, Handle<DebuggerFrame*> frame,
-                                       MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool getIsConstructing(JSContext* cx, Handle<DebuggerFrame*> frame,
+    static MOZ_MUST_USE bool getCallee(JSContext* cx, HandleDebuggerFrame frame,
+                                       MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool getIsConstructing(JSContext* cx, HandleDebuggerFrame frame,
                                                bool& result);
-    static MOZ_MUST_USE bool getEnvironment(JSContext* cx, Handle<DebuggerFrame*> frame,
-                                            MutableHandle<DebuggerEnvironment*> result);
-    static bool getIsGenerator(Handle<DebuggerFrame*> frame);
-    static MOZ_MUST_USE bool getOffset(JSContext* cx, Handle<DebuggerFrame*> frame,
-                                       size_t& offset);
-    static MOZ_MUST_USE bool getOlder(JSContext* cx, Handle<DebuggerFrame*> frame,
-                                      MutableHandle<DebuggerFrame*> result);
-    static MOZ_MUST_USE bool getThis(JSContext* cx, Handle<DebuggerFrame*> frame,
+    static MOZ_MUST_USE bool getEnvironment(JSContext* cx, HandleDebuggerFrame frame,
+                                            MutableHandleDebuggerEnvironment result);
+    static bool getIsGenerator(HandleDebuggerFrame frame);
+    static MOZ_MUST_USE bool getOffset(JSContext* cx, HandleDebuggerFrame frame, size_t& result);
+    static MOZ_MUST_USE bool getOlder(JSContext* cx, HandleDebuggerFrame frame,
+                                      MutableHandleDebuggerFrame result);
+    static MOZ_MUST_USE bool getThis(JSContext* cx, HandleDebuggerFrame frame,
                                      MutableHandleValue result);
-    static DebuggerFrameType getType(Handle<DebuggerFrame*> frame);
-    static DebuggerFrameImplementation getImplementation(Handle<DebuggerFrame*> frame);
+    static DebuggerFrameType getType(HandleDebuggerFrame frame);
+    static DebuggerFrameImplementation getImplementation(HandleDebuggerFrame frame);
 
     bool isLive() const;
 
   private:
     static const ClassOps classOps_;
 
     static const JSPropertySpec properties_[];
     static const JSFunctionSpec methods_[];
 
-    static MOZ_MUST_USE bool requireLive(JSContext* cx, Handle<DebuggerFrame*> frame);
-    static AbstractFramePtr getReferent(Handle<DebuggerFrame*> frame);
-    static MOZ_MUST_USE bool getScriptFrameIter(JSContext* cx, Handle<DebuggerFrame*> frame,
+    static MOZ_MUST_USE bool requireLive(JSContext* cx, HandleDebuggerFrame frame);
+    static AbstractFramePtr getReferent(HandleDebuggerFrame frame);
+    static MOZ_MUST_USE bool getScriptFrameIter(JSContext* cx, HandleDebuggerFrame frame,
                                                 mozilla::Maybe<ScriptFrameIter>& result);
 
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     static MOZ_MUST_USE bool calleeGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool constructingGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool environmentGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool generatorGetter(JSContext* cx, unsigned argc, Value* vp);
@@ -1217,77 +1212,77 @@ class DebuggerObject : public NativeObje
   public:
     static const Class class_;
 
     static NativeObject* initClass(JSContext* cx, HandleObject obj, HandleObject debugCtor);
     static DebuggerObject* create(JSContext* cx, HandleObject proto, HandleObject obj,
                                   HandleNativeObject debugger);
 
     // Properties
-    static MOZ_MUST_USE bool getClassName(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getClassName(JSContext* cx, HandleDebuggerObject object,
                                           MutableHandleString result);
-    static MOZ_MUST_USE bool getGlobal(JSContext* cx, Handle<DebuggerObject*> object,
-                                       MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool getParameterNames(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getGlobal(JSContext* cx, HandleDebuggerObject object,
+                                       MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool getParameterNames(JSContext* cx, HandleDebuggerObject object,
                                                MutableHandle<StringVector> result);
-    static MOZ_MUST_USE bool getBoundTargetFunction(JSContext* cx, Handle<DebuggerObject*> object,
-                                                 MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool getBoundThis(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getBoundTargetFunction(JSContext* cx, HandleDebuggerObject object,
+                                                 MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool getBoundThis(JSContext* cx, HandleDebuggerObject object,
                                           MutableHandleValue result);
-    static MOZ_MUST_USE bool getBoundArguments(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getBoundArguments(JSContext* cx, HandleDebuggerObject object,
                                                MutableHandle<ValueVector> result);
-    static MOZ_MUST_USE bool getAllocationSite(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getAllocationSite(JSContext* cx, HandleDebuggerObject object,
                                             MutableHandleObject result);
-    static MOZ_MUST_USE bool getErrorMessageName(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getErrorMessageName(JSContext* cx, HandleDebuggerObject object,
                                                  MutableHandleString result);
-    static MOZ_MUST_USE bool scriptedProxyTarget(JSContext* cx, Handle<DebuggerObject*> object,
-                                                 MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool scriptedProxyHandler(JSContext* cx, Handle<DebuggerObject*> object,
-                                                  MutableHandle<DebuggerObject*> result);
+    static MOZ_MUST_USE bool scriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
+                                                 MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool scriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
+                                                  MutableHandleDebuggerObject result);
 
     // Methods
-    static MOZ_MUST_USE bool isExtensible(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
                                           bool& result);
-    static MOZ_MUST_USE bool isSealed(JSContext* cx, Handle<DebuggerObject*> object, bool& result);
-    static MOZ_MUST_USE bool isFrozen(JSContext* cx, Handle<DebuggerObject*> object, bool& result);
-    static MOZ_MUST_USE bool getPrototypeOf(JSContext* cx, Handle<DebuggerObject*> object,
-                                            MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool getOwnPropertyNames(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool isSealed(JSContext* cx, HandleDebuggerObject object, bool& result);
+    static MOZ_MUST_USE bool isFrozen(JSContext* cx, HandleDebuggerObject object, bool& result);
+    static MOZ_MUST_USE bool getPrototypeOf(JSContext* cx, HandleDebuggerObject object,
+                                            MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool getOwnPropertyNames(JSContext* cx, HandleDebuggerObject object,
                                                  MutableHandle<IdVector> result);
-    static MOZ_MUST_USE bool getOwnPropertySymbols(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getOwnPropertySymbols(JSContext* cx, HandleDebuggerObject object,
                                                    MutableHandle<IdVector> result);
-    static MOZ_MUST_USE bool getOwnPropertyDescriptor(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool getOwnPropertyDescriptor(JSContext* cx, HandleDebuggerObject object,
                                                       HandleId id,
                                                       MutableHandle<PropertyDescriptor> desc);
-    static MOZ_MUST_USE bool preventExtensions(JSContext* cx, Handle<DebuggerObject*> object);
-    static MOZ_MUST_USE bool seal(JSContext* cx, Handle<DebuggerObject*> object);
-    static MOZ_MUST_USE bool freeze(JSContext* cx, Handle<DebuggerObject*> object);
-    static MOZ_MUST_USE bool defineProperty(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool preventExtensions(JSContext* cx, HandleDebuggerObject object);
+    static MOZ_MUST_USE bool seal(JSContext* cx, HandleDebuggerObject object);
+    static MOZ_MUST_USE bool freeze(JSContext* cx, HandleDebuggerObject object);
+    static MOZ_MUST_USE bool defineProperty(JSContext* cx, HandleDebuggerObject object,
                                             HandleId id, Handle<PropertyDescriptor> desc);
-    static MOZ_MUST_USE bool defineProperties(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool defineProperties(JSContext* cx, HandleDebuggerObject object,
                                               Handle<IdVector> ids,
                                               Handle<PropertyDescriptorVector> descs);
-    static MOZ_MUST_USE bool deleteProperty(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool deleteProperty(JSContext* cx, HandleDebuggerObject object,
                                             HandleId id, ObjectOpResult& result);
-    static MOZ_MUST_USE bool call(JSContext* cx, Handle<DebuggerObject*> object, HandleValue thisv,
+    static MOZ_MUST_USE bool call(JSContext* cx, HandleDebuggerObject object, HandleValue thisv,
                                   Handle<ValueVector> args, MutableHandleValue result);
     static MOZ_MUST_USE bool forceLexicalInitializationByName(JSContext* cx,
-                                                              Handle<DebuggerObject*> object,
+                                                              HandleDebuggerObject object,
                                                               HandleId id, bool& result);
-    static MOZ_MUST_USE bool executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool executeInGlobal(JSContext* cx, HandleDebuggerObject object,
                                              mozilla::Range<const char16_t> chars,
                                              HandleObject bindings, const EvalOptions& options,
                                              MutableHandleValue result);
-    static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx, HandleDebuggerObject object,
                                                HandleValue value, MutableHandleValue result);
-    static MOZ_MUST_USE bool unsafeDereference(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool unsafeDereference(JSContext* cx, HandleDebuggerObject object,
                                                MutableHandleObject result);
-    static MOZ_MUST_USE bool unwrap(JSContext* cx, Handle<DebuggerObject*> object,
-                                    MutableHandle<DebuggerObject*> result);
-    static MOZ_MUST_USE bool isPromise(JSContext* cx, Handle<DebuggerObject*> object,
+    static MOZ_MUST_USE bool unwrap(JSContext* cx, HandleDebuggerObject object,
+                                    MutableHandleDebuggerObject result);
+    static MOZ_MUST_USE bool isPromise(JSContext* cx, HandleDebuggerObject object,
                                        bool& result);
 
     // Infallible properties
     bool isCallable() const;
     bool isFunction() const;
     bool isDebuggeeFunction() const;
     bool isBoundFunction() const;
     bool isArrowFunction() const;
@@ -1315,17 +1310,17 @@ class DebuggerObject : public NativeObje
         JSObject* obj = (JSObject*) getPrivate();
         MOZ_ASSERT(obj);
         return obj;
     }
 
     Debugger* owner() const;
 
     static DebuggerObject* checkThis(JSContext* cx, const CallArgs& args, const char* fnname);
-    static MOZ_MUST_USE bool requireGlobal(JSContext* cx, Handle<DebuggerObject*> object);
+    static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
 
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     // JSNative properties
     static MOZ_MUST_USE bool callableGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isBoundFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isArrowFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool protoGetter(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/vm/ForOfIterator.cpp
+++ b/js/src/vm/ForOfIterator.cpp
@@ -130,20 +130,20 @@ ForOfIterator::next(MutableHandleValue v
 
     RootedValue v(cx_);
     if (!GetProperty(cx_, iterator, iterator, cx_->names().next, &v))
         return false;
 
     if (!js::Call(cx_, v, iterator, &v))
         return false;
 
-    RootedObject resultObj(cx_, ToObject(cx_, v));
-    if (!resultObj)
-        return false;
+    if (!v.isObject())
+        return ThrowCheckIsObject(cx_, CheckIsObjectKind::IteratorNext);
 
+    RootedObject resultObj(cx_, &v.toObject());
     if (!GetProperty(cx_, resultObj, resultObj, cx_->names().done, &v))
         return false;
 
     *done = ToBoolean(v);
     if (*done) {
         vp.setUndefined();
         return true;
     }
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1820,17 +1820,16 @@ CASE(EnableInterruptsPseudoOpcode)
     /* Commence executing the actual opcode. */
     SANITY_CHECKS();
     DISPATCH_TO(op);
 }
 
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_NOP_DESTRUCTURING)
-CASE(JSOP_UNUSED14)
 CASE(JSOP_UNUSED149)
 CASE(JSOP_UNUSED179)
 CASE(JSOP_UNUSED180)
 CASE(JSOP_UNUSED181)
 CASE(JSOP_UNUSED182)
 CASE(JSOP_UNUSED183)
 CASE(JSOP_UNUSED187)
 CASE(JSOP_UNUSED192)
@@ -2551,16 +2550,25 @@ CASE(JSOP_GLOBALTHIS)
             goto error;
     } else {
         ClonedBlockObject* lexicalScope = &cx->global()->lexicalScope();
         PUSH_COPY(lexicalScope->thisValue());
     }
 }
 END_CASE(JSOP_GLOBALTHIS)
 
+CASE(JSOP_CHECKISOBJ)
+{
+    if (!REGS.sp[-1].isObject()) {
+        MOZ_ALWAYS_FALSE(ThrowCheckIsObject(cx, CheckIsObjectKind(GET_UINT8(REGS.pc))));
+        goto error;
+    }
+}
+END_CASE(JSOP_CHECKISOBJ)
+
 CASE(JSOP_CHECKTHIS)
 {
     if (REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)) {
         MOZ_ALWAYS_FALSE(ThrowUninitializedThis(cx, REGS.fp()));
         goto error;
     }
 }
 END_CASE(JSOP_CHECKTHIS)
@@ -4964,16 +4972,29 @@ js::ReportRuntimeRedeclaration(JSContext
         else
             kindStr = frontend::Definition::kindString(declKind);
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_REDECLARED_VAR,
                              kindStr, printable.ptr());
     }
 }
 
 bool
+js::ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind)
+{
+    switch (kind) {
+      case CheckIsObjectKind::IteratorNext:
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NEXT_RETURNED_PRIMITIVE);
+        break;
+      default:
+        MOZ_CRASH("Unknown kind");
+    }
+    return false;
+}
+
+bool
 js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame)
 {
     RootedFunction fun(cx);
     if (frame.isFunctionFrame()) {
         fun = frame.callee();
     } else {
         MOZ_ASSERT(frame.isEvalFrame());
         MOZ_ASSERT(frame.script()->isDirectEvalInFunction());
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -554,16 +554,23 @@ ReportRuntimeLexicalError(JSContext* cx,
 
 // The parser only reports redeclarations that occurs within a single
 // script. Due to the extensibility of the global lexical scope, we also check
 // for redeclarations during runtime in JSOP_DEF{VAR,LET,CONST}.
 void
 ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name,
                            frontend::Definition::Kind declKind);
 
+enum class CheckIsObjectKind : uint8_t {
+    IteratorNext
+};
+
+bool
+ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind);
+
 bool
 ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame);
 
 bool
 DefaultClassConstructor(JSContext* cx, unsigned argc, Value* vp);
 
 bool
 Debug_CheckSelfHosted(JSContext* cx, HandleValue v);
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -215,17 +215,26 @@ 1234567890123456789012345678901234567890
      * Duplicates the top two values on the stack.
      *   Category: Operators
      *   Type: Stack Operations
      *   Operands:
      *   Stack: v1, v2 => v1, v2, v1, v2
      */ \
     macro(JSOP_DUP2,      13, "dup2",       NULL,         1,  2,  4, JOF_BYTE) \
     \
-    macro(JSOP_UNUSED14,  14, "unused14",   NULL,         1,  0,  0, JOF_BYTE) \
+    /*
+     * Checks that the top value on the stack is an object, and throws a
+     * TypeError if not. The operand 'kind' is used only to generate an
+     * appropriate error message.
+     *   Category: Statements
+     *   Type: Generator
+     *   Operands: uint8_t kind
+     *   Stack: result => result
+     */ \
+    macro(JSOP_CHECKISOBJ,14, "checkisobj", NULL,         2,  1,  1, JOF_UINT8) \
     \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * the result of the operation applied to the two operands, converting
      * both to 32-bit signed integers if necessary.
      *   Category: Operators
      *   Type: Bitwise Logical Operators
      *   Operands:
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1586,16 +1586,27 @@ CompartmentChecker::check(SavedStacks* s
         MOZ_CRASH();
     }
 }
 #endif /* JS_CRASH_DIAGNOSTICS */
 
 /* static */ ReconstructedSavedFramePrincipals ReconstructedSavedFramePrincipals::IsSystem;
 /* static */ ReconstructedSavedFramePrincipals ReconstructedSavedFramePrincipals::IsNotSystem;
 
+UTF8CharsZ
+BuildUTF8StackString(JSContext* cx, HandleObject stack)
+{
+    RootedString stackStr(cx);
+    if (!JS::BuildStackString(cx, stack, &stackStr))
+        return UTF8CharsZ();
+
+    char* chars = JS_EncodeStringToUTF8(cx, stackStr);
+    return UTF8CharsZ(chars, strlen(chars));
+}
+
 } /* namespace js */
 
 namespace JS {
 namespace ubi {
 
 bool
 ConcreteStackFrame<SavedFrame>::isSystem() const
 {
--- a/js/src/vm/SavedStacks.h
+++ b/js/src/vm/SavedStacks.h
@@ -319,11 +319,14 @@ class RootedBase<SavedStacks::LocationVa
   : public SavedStacks::MutableLocationValueOperations<JS::Rooted<SavedStacks::LocationValue>>
 {};
 
 template <>
 class MutableHandleBase<SavedStacks::LocationValue>
   : public SavedStacks::MutableLocationValueOperations<JS::MutableHandle<SavedStacks::LocationValue>>
 {};
 
+UTF8CharsZ
+BuildUTF8StackString(JSContext* cx, HandleObject stack);
+
 } /* namespace js */
 
 #endif /* vm_SavedStacks_h */
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -545,27 +545,28 @@ class TypedArrayObjectTemplate : public 
     makeInstance(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer,
                  uint32_t byteOffset, uint32_t len)
     {
         RootedObject proto(cx, nullptr);
         return makeInstance(cx, buffer, byteOffset, len, proto);
     }
 
     static TypedArrayObject*
-    makeTemplateObject(JSContext* cx, uint32_t len)
+    makeTemplateObject(JSContext* cx, int32_t len)
     {
+        MOZ_ASSERT(len >= 0);
         size_t nbytes;
         MOZ_ALWAYS_TRUE(CalculateAllocSize<NativeType>(len, &nbytes));
         MOZ_ASSERT(nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH);
         NewObjectKind newKind = TenuredObject;
         bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
         const Class* clasp = instanceClass();
         gc::AllocKind allocKind = !fitsInline
                                   ? GetGCObjectKind(clasp)
-                                  : AllocKindForLazyBuffer(len * sizeof(NativeType));
+                                  : AllocKindForLazyBuffer(nbytes);
         MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
         allocKind = GetBackgroundAllocKind(allocKind);
 
         AutoSetNewObjectMetadata metadata(cx);
         jsbytecode* pc;
         RootedScript script(cx, cx->currentScript(&pc));
         if (script && ObjectGroup::useSingletonForAllocationSite(script, pc, clasp))
             newKind = SingletonObject;
@@ -584,19 +585,20 @@ class TypedArrayObjectTemplate : public 
         // inline data and avoid allocating memory that will never be used.
         void* buf = tarray->fixedData(FIXED_DATA_START);
         initTypedArraySlots(cx, tarray, len, buf, allocKind);
 
         return tarray;
     }
 
     static void
-    initTypedArraySlots(JSContext* cx, TypedArrayObject* tarray, uint32_t len,
+    initTypedArraySlots(JSContext* cx, TypedArrayObject* tarray, int32_t len,
                         void* buf, AllocKind allocKind)
     {
+        MOZ_ASSERT(len >= 0);
         tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, NullValue());
         tarray->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(AssertedCast<int32_t>(len)));
         tarray->setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
 
         // Verify that the private slot is at the expected place.
         MOZ_ASSERT(tarray->numFixedSlots() == TypedArrayObject::DATA_SLOT);
 
         if (buf) {
@@ -616,30 +618,32 @@ class TypedArrayObjectTemplate : public 
 
             void* data = tarray->fixedData(FIXED_DATA_START);
             tarray->initPrivate(data);
             memset(data, 0, nbytes);
         }
     }
 
     static TypedArrayObject*
-    makeTypedArrayWithTemplate(JSContext* cx, TypedArrayObject* templateObj, uint32_t len)
+    makeTypedArrayWithTemplate(JSContext* cx, TypedArrayObject* templateObj, int32_t len)
     {
         size_t nbytes;
-        if (!js::CalculateAllocSize<NativeType>(len, &nbytes))
+        if (len < 0 || !js::CalculateAllocSize<NativeType>(len, &nbytes)) {
+            JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
             return nullptr;
+        }
 
         bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
 
         AutoSetNewObjectMetadata metadata(cx);
 
         const Class* clasp = templateObj->group()->clasp();
         gc::AllocKind allocKind = !fitsInline
                                   ? GetGCObjectKind(clasp)
-                                  : AllocKindForLazyBuffer(len * sizeof(NativeType));
+                                  : AllocKindForLazyBuffer(nbytes);
         MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
         allocKind = GetBackgroundAllocKind(allocKind);
         RootedObjectGroup group(cx, templateObj->group());
 
         NewObjectKind newKind = TenuredObject;
 
         ScopedJSFreePtr<void> buf;
         if (!fitsInline && len > 0) {
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -217,8 +217,12 @@ XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_STARTPA
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY          , "Cannot print this document yet, it is still being loaded.")
 
 /* Codes related to content */
 XPC_MSG_DEF(NS_ERROR_CONTENT_CRASHED                  , "The process that hosted this content has crashed.")
 
 /* Codes for the JS-implemented Push DOM API. These can be removed as part of bug 1252660. */
 XPC_MSG_DEF(NS_ERROR_DOM_PUSH_INVALID_KEY_ERR         , "Invalid raw ECDSA P-256 public key.")
 XPC_MSG_DEF(NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR      , "A subscription with a different application server key already exists.")
+
+/* Codes defined in WebIDL https://heycam.github.io/webidl/#idl-DOMException-error-names */
+XPC_MSG_DEF(NS_ERROR_DOM_NOT_FOUND_ERR                , "The object can not be found here.")
+XPC_MSG_DEF(NS_ERROR_DOM_NOT_ALLOWED_ERR              , "The request is not allowed.")
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -5904,18 +5904,19 @@ nsDisplayTransform::ShouldPrerenderTrans
   }
 
   nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
   // Only prerender if the transformed frame's size is <= the
   // reference frame size (~viewport), allowing a 1/8th fuzz factor
   // for shadows, borders, etc.
   refSize += nsSize(refSize.width / 8, refSize.height / 8);
   gfxSize scale = nsLayoutUtils::GetTransformToAncestorScale(aFrame);
-  nsSize frameSize = aFrame->GetVisualOverflowRectRelativeToSelf().Size() *
-    nsSize(scale.width, scale.height);
+  nsSize frameSize = nsSize(
+    aFrame->GetVisualOverflowRectRelativeToSelf().Size().width * scale.width,
+    aFrame->GetVisualOverflowRectRelativeToSelf().Size().height * scale.height);
   nscoord maxInAppUnits = nscoord_MAX;
   if (frameSize <= refSize) {
     maxInAppUnits = aFrame->PresContext()->DevPixelsToAppUnits(4096);
     if (frameSize <= nsSize(maxInAppUnits, maxInAppUnits)) {
       return true;
     }
   }
 
new file mode 100644
index 0000000000000000000000000000000000000000..6e78a9eef4dae888be61ed4f8872b0743810b791
GIT binary patch
literal 188
zc%17D@N?(olHy`uVBq!ia0vp^DIm<j3?$ucQqzDGTYyi9D<dPL?|%k{#^Z575yp}r
zzhDN3XE#97ww^AIAsP4Ho@L}@VBle1u(tl?RtuRe4KEu#RD?QRlqTY)KG{n?Gg23P
z(BJwHXpnS?YeY$Kep*R+Vo@rCBhY0Ej>W~Pxk)*xMG8iGmTJ-e`hm(AJYD@<);T3K
F0RXuSHVFU#
new file mode 100644
--- /dev/null
+++ b/layout/reftests/apng-mime/expected.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>apng expected</title>
+<img src="animated.apng">
new file mode 100644
--- /dev/null
+++ b/layout/reftests/apng-mime/reftest.list
@@ -0,0 +1,1 @@
+== test.html expected.html
new file mode 100644
index 0000000000000000000000000000000000000000..6f76d4438724111983a11860f13568361b52d9bc
GIT binary patch
literal 100
zc%17D@N?(olHy`uVBq!ia0vp^CqS5y8Awi_W^)%vF$egBxTd6}EPfSw1jv=~ba4!k
rkbHZv5y)XUyx@1R|3ikWAU1;^qeuV)<1IPC3=q%L)z4*}Q$iB}r??p{
new file mode 100644
--- /dev/null
+++ b/layout/reftests/apng-mime/test.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>apng test</title>
+<picture>
+<source type="image/apng" srcset="animated.apng">
+<img src="static.png">
+</picture>
--- a/layout/reftests/canvas/evenodd-fill-1.html
+++ b/layout/reftests/canvas/evenodd-fill-1.html
@@ -1,16 +1,15 @@
 <html>
 <head>
   <script type="text/javascript">
 window.onload = function() {
     var ctx = document.getElementById("c1").getContext("2d");
-    ctx.mozFillRule = "evenodd";
     ctx.rect(50, 50, 200, 200);
     ctx.rect(100, 100, 100, 100);
-    ctx.fill();
+    ctx.fill("evenodd");
 }
   </script>
 </head>
 <body>
   <div><canvas id="c1" width="300" height="300"></canvas></div>
 </body>
 </html>
--- a/layout/reftests/canvas/evenodd-fill-3.html
+++ b/layout/reftests/canvas/evenodd-fill-3.html
@@ -1,27 +1,26 @@
 <html>
 <head>
   <script type="text/javascript">
 window.onload = function() {
     var ctx = document.getElementById("c1").getContext("2d");
-    ctx.mozFillRule = "evenodd";
 
     ctx.moveTo(50, 50);
     ctx.lineTo(250, 50);
     ctx.lineTo(250, 250);
     ctx.lineTo(50, 250);
     ctx.lineTo(50, 50);
 
     ctx.moveTo(100, 100);
     ctx.lineTo(100, 200);
     ctx.lineTo(200, 200);
     ctx.lineTo(200, 100);
     ctx.lineTo(100, 100);
 
-    ctx.fill();
+    ctx.fill("evenodd");
 }
   </script>
 </head>
 <body>
   <div><canvas id="c1" width="300" height="300"></canvas></div>
 </body>
 </html>
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -68,21 +68,18 @@ random-if(cocoaWidget&&azureSkia) random
 # test
 fails-if(azureSkia||azureSkiaGL||azureQuartz) == linear-gradient-1a.html linear-gradient-1-ref.html
 
 # this passes with cairo on 10.7 and 10.8 but not with azure for reasons unknown
 fails-if(!(Android)&&(OSX==1006||(azureQuartz&&OSX>=1007))||azureSkiaGL||azureSkia) == linear-gradient-1b.html linear-gradient-1-ref.html
 
 == zero-dimensions.html zero-dimensions-ref.html
 
-== evenodd-fill-sanity.html data:text/html,<body>Pass
 != evenodd-fill-1.html nonzero-fill-1.html
 == evenodd-fill-1.html evenodd-fill-ref.html
-random-if(azureSkiaGL) == evenodd-fill-2.html evenodd-fill-ref.html
-== evenodd-fill-3.html nonzero-fill-2.html
 
 == dash-sanity.html data:text/html,<body>Pass
 fuzzy-if(azureSkia||skiaContent,9,470) random-if(Android) == dash-1.html dash-1-ref.svg  # Bug 668412 (really is android-specific, not IPC-specific)
 
 == ctm-sanity.html data:text/html,<body>Pass
 == ctm-singular-sanity.html data:text/html,<body>Pass
 == ctm-1.html ctm-1-ref.html
 
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -14,16 +14,19 @@ include ../../image/test/reftest/reftest
 # CSSWG tests
 include w3c-css/submitted/reftest.list
 include w3c-css/received/reftest.list
 
 # relative and absolute positioning
 include abs-pos/reftest.list
 include position-relative/reftest.list
 
+# apng-mime
+include apng-mime/reftest.list
+
 include async-scrolling/reftest.list
 
 # backgrounds/
 include backgrounds/reftest.list
 
 # bidi/
 include bidi/reftest.list
 
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -12078,38 +12078,43 @@ CSSParserImpl::ParseImageLayersItem(
   // Fill in the values that the shorthand will set if we don't find
   // other values.
   aState.mImage->mValue.SetNoneValue();
   aState.mAttachment->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL,
                                          eCSSUnit_Enumerated);
   aState.mClip->mValue.SetIntValue(NS_STYLE_IMAGELAYER_CLIP_BORDER,
                                    eCSSUnit_Enumerated);
 
-
-
+  aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
+                                      eCSSUnit_Enumerated);
+  aState.mRepeat->mYValue.Reset();
+
+  RefPtr<nsCSSValue::Array> positionXArr = nsCSSValue::Array::Create(2);
+  RefPtr<nsCSSValue::Array> positionYArr = nsCSSValue::Array::Create(2);
+  aState.mPositionX->mValue.SetArrayValue(positionXArr, eCSSUnit_Array);
+  aState.mPositionY->mValue.SetArrayValue(positionYArr, eCSSUnit_Array);
 
   if (eCSSProperty_mask == aTable[nsStyleImageLayers::shorthand]) {
     aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_BORDER,
                                        eCSSUnit_Enumerated);
     aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT,
                                         eCSSUnit_Enumerated);
+
+    positionXArr->Item(1).SetPercentValue(0.5f);
+    positionYArr->Item(1).SetPercentValue(0.5f);
   } else {
     aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_PADDING,
                                        eCSSUnit_Enumerated);
     aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
                                         eCSSUnit_Enumerated);
-  }
-  aState.mRepeat->mYValue.Reset();
-
-  RefPtr<nsCSSValue::Array> positionXArr = nsCSSValue::Array::Create(2);
-  RefPtr<nsCSSValue::Array> positionYArr = nsCSSValue::Array::Create(2);
-  aState.mPositionX->mValue.SetArrayValue(positionXArr, eCSSUnit_Array);
-  aState.mPositionY->mValue.SetArrayValue(positionYArr, eCSSUnit_Array);
-  positionXArr->Item(1).SetPercentValue(0.0f);
-  positionYArr->Item(1).SetPercentValue(0.0f);
+
+    positionXArr->Item(1).SetPercentValue(0.0f);
+    positionYArr->Item(1).SetPercentValue(0.0f);
+  }
+
   aState.mSize->mXValue.SetAutoValue();
   aState.mSize->mYValue.SetAutoValue();
   aState.mComposite->mValue.SetIntValue(NS_STYLE_MASK_COMPOSITE_ADD,
                                         eCSSUnit_Enumerated);
   aState.mMode->mValue.SetIntValue(NS_STYLE_MASK_MODE_MATCH_SOURCE,
                                    eCSSUnit_Enumerated);
   bool haveColor = false,
        haveImage = false,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6143,17 +6143,17 @@ nsComputedDOMStyle::DoGetMask()
   // Mask is now a shorthand, but it used to be a longhand, so that we
   // need to support computed style for the cases where it used to be
   // a longhand.
   if (svg->mMask.mImageCount > 1 ||
       firstLayer.mClip != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
       firstLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_BORDER ||
       firstLayer.mComposite != NS_STYLE_MASK_COMPOSITE_ADD ||
       firstLayer.mMaskMode != NS_STYLE_MASK_MODE_MATCH_SOURCE ||
-      !firstLayer.mPosition.IsInitialValue() ||
+      !firstLayer.mPosition.IsInitialValue(nsStyleImageLayers::LayerType::Mask) ||
       !firstLayer.mRepeat.IsInitialValue(nsStyleImageLayers::LayerType::Mask) ||
       !firstLayer.mSize.IsInitialValue() ||
       !(firstLayer.mImage.GetType() == eStyleImageType_Null ||
         firstLayer.mImage.GetType() == eStyleImageType_Image)) {
     return nullptr;
   }
 
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9984,17 +9984,17 @@ nsRuleNode::ComputeSVGResetData(void* aS
                     &nsStyleImageLayers::Layer::mImage,
                     initialImage, parentSVGReset->mMask.mImageCount,
                     svgReset->mMask.mImageCount,
                     maxItemCount, rebuild, conditions);
   SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
                     svgReset->mMask.mLayers,
                     parentSVGReset->mMask.mLayers,
                     &nsStyleImageLayers::Layer::mSourceURI,
-                    nsCOMPtr<nsIURI>(), parentSVGReset->mMask.mImageCount,
+                    FragmentOrURL(), parentSVGReset->mMask.mImageCount,
                     svgReset->mMask.mImageCount,
                     maxItemCount, rebuild, conditions);
 
   // mask-repeat: enum, inherit, initial [pair list]
   nsStyleImageLayers::Repeat initialRepeat;
   initialRepeat.SetInitialValues(nsStyleImageLayers::LayerType::Mask);
   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
                         svgReset->mMask.mLayers,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2483,22 +2483,31 @@ nsStyleImageLayers::HasLayerWithImage() 
       return true;
     }
   }
 
   return false;
 }
 
 bool
-nsStyleImageLayers::Position::IsInitialValue() const
+nsStyleImageLayers::Position::IsInitialValue(LayerType aType) const
 {
-  if (mXPosition.mPercent == 0.0 && mXPosition.mLength == 0 &&
-      mXPosition.mHasPercent && mYPosition.mPercent == 0.0 &&
-      mYPosition.mLength == 0 && mYPosition.mHasPercent) {
-    return true;
+  if (aType == LayerType::Background) {
+    if (mXPosition.mPercent == 0.0 && mXPosition.mLength == 0 &&
+        mXPosition.mHasPercent && mYPosition.mPercent == 0.0 &&
+        mYPosition.mLength == 0 && mYPosition.mHasPercent) {
+      return true;
+    }
+  } else {
+    MOZ_ASSERT(aType == LayerType::Mask);
+    if (mXPosition.mPercent == 0.5f && mXPosition.mLength == 0 &&
+        mXPosition.mHasPercent && mYPosition.mPercent == 0.5f &&
+        mYPosition.mLength == 0 && mYPosition.mHasPercent) {
+      return true;
+    }
   }
 
   return false;
 }
 
 void
 nsStyleImageLayers::Position::SetInitialPercentValues(float aPercentVal)
 {
@@ -2653,35 +2662,36 @@ nsStyleImageLayers::Repeat::SetInitialVa
 
 nsStyleImageLayers::Layer::Layer()
   : mClip(NS_STYLE_IMAGELAYER_CLIP_BORDER)
   , mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL)
   , mBlendMode(NS_STYLE_BLEND_NORMAL)
   , mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
   , mMaskMode(NS_STYLE_MASK_MODE_MATCH_SOURCE)
 {
-  mPosition.SetInitialPercentValues(0.0f); // Initial value is "0% 0%"
   mImage.SetNull();
   mSize.SetInitialValues();
 }
 
 nsStyleImageLayers::Layer::~Layer()
 {
 }
 
 void
 nsStyleImageLayers::Layer::Initialize(nsStyleImageLayers::LayerType aType)
 {
   mRepeat.SetInitialValues(aType);
 
   if (aType == LayerType::Background) {
     mOrigin = NS_STYLE_IMAGELAYER_ORIGIN_PADDING;
+    mPosition.SetInitialPercentValues(0.0f); // Initial value is "0% 0%"
   } else {
     MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
     mOrigin = NS_STYLE_IMAGELAYER_ORIGIN_BORDER;
+    mPosition.SetInitialPercentValues(0.5f); // Initial value is "50% 50%"
   }
 }
 
 bool
 nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
 {
   // Do we even have an image?
   if (mImage.IsEmpty()) {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -561,17 +561,17 @@ struct nsStyleImageLayers {
   friend struct Position;
   struct Position {
     typedef nsStyleCoord::CalcValue PositionCoord;
     PositionCoord mXPosition, mYPosition;
 
     // Initialize nothing
     Position() {}
 
-    bool IsInitialValue() const;
+    bool IsInitialValue(LayerType aType) const;
 
     // Sets both mXPosition and mYPosition to the given percent value for the
     // initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
     void SetInitialPercentValues(float aPercentVal);
 
     // Sets both mXPosition and mYPosition to 0 (app units) for the
     // initial property-value as a length with no percentage component.
     void SetInitialZeroValues();
--- a/layout/style/test/bug453896_iframe.html
+++ b/layout/style/test/bug453896_iframe.html
@@ -28,18 +28,18 @@ function run(test_window)
     test_window.ok(!query_applies(q), q + " should not apply");
   }
 
   // in this test, assume the common underlying implementation is correct
   let width_val = 157; // pick two not-too-round numbers
   let height_val = 182;
   iframe_style.width = width_val + "px";
   iframe_style.height = height_val + "px";
-  for (let [feature, value] in
-         Iterator({ "width": width_val, "height": height_val })) {
+  for (let [feature, value] of
+         Object.entries({ "width": width_val, "height": height_val })) {
     should_apply("all and (" + feature + ": " + value + "px)");
     should_not_apply("all and (" + feature + ": " + (value + 1) + "px)");
     should_not_apply("all and (" + feature + ": " + (value - 1) + "px)");
   }
 
   iframe_style.width = "0";
   should_apply("all and (height)");
   should_not_apply("all and (width)");
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -6910,58 +6910,59 @@ function SupportsMaskShorthand() {
 
 if (SupportsMaskShorthand()) {
   gCSSProperties["mask"] = {
     domProp: "mask",
     inherited: false,
     type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
     /* FIXME: All mask-border-* should be added when we implement them. */
     subproperties: ["mask-clip", "mask-image", "mask-mode", "mask-origin", "mask-position-x", "mask-position-y", "mask-repeat", "mask-size" , "mask-composite"],
-    initial_values: [ "match-source", "none", "no-repeat", "add", "0% 0%", "top left", "left top", "0% 0% / auto", "top left / auto", "left top / auto", "0% 0% / auto auto",
-      "top left none", "left top none", "none left top", "none top left", "none 0% 0%", "left top / auto none", "left top / auto auto none",
-      "match-source none no-repeat add top left", "left top no-repeat none add", "none no-repeat add top left / auto", "left top / auto no-repeat none add match-source", "none no-repeat add 0% 0% / auto auto match-source",
+    initial_values: [ "match-source", "none", "no-repeat", "add", "50% 50%", "center center", "50% 50% / auto", "center / auto", "center center / auto", "50% 50% / auto auto",
+      "center none", "center center none", "none center", "none center center", "none 50% 50%", "center / auto none",
+      "center center / auto auto none",
+      "match-source none no-repeat add center center", "center centerp no-repeat none add", "none no-repeat add center center / auto", "center center / auto no-repeat none add match-source", "none no-repeat add 0% 0% / auto auto match-source",
       "border-box", "border-box border-box" ],
     other_values: [
-      "none alpha no-repeat add left top",
+      "none alpha no-repeat add center",
       "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
-      "no-repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') alpha left top add",
+      "no-repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==') alpha center add",
       "repeat-x",
       "repeat-y",
       "repeat",
-      "none repeat-y alpha add 0% 0%",
+      "none repeat-y alpha add 50% 50%",
       "subtract",
-      "0% top subtract alpha no-repeat none",
+      "50% center subtract alpha no-repeat none",
       "top",
       "left",
-      "50% 50%",
-      "center",
-      "top / 100px",
-      "left / contain",
-      "left / cover",
+      "0% 0%",
+      "top left",
+      "center / 100px",
+      "center / contain",
+      "center / cover",
       "10px / 10%",
       "10em / calc(20px)",
-      "top left / 100px 100px",
-      "top left / 100px auto",
-      "top left / 100px 10%",
-      "top left / 100px calc(20px)",
+      "center center / 100px 100px",
+      "center center / 100px auto",
+      "center center / 100px 10%",
+      "center center / 100px calc(20px)",
       "bottom right add none alpha no-repeat",
-      "50% alpha",
-      "alpha 50%",
-      "50%",
+      "0% alpha",
+      "alpha 0%",
+      "0%",
       "url(#mymask)",
       "-moz-radial-gradient(10% bottom, #ffffff, black) add repeat",
       "-moz-linear-gradient(10px 10px -45deg, red, blue) no-repeat",
       "-moz-linear-gradient(10px 10px -0.125turn, red, blue) no-repeat",
       "-moz-repeating-radial-gradient(10% bottom, #ffffff, black) add repeat",
       "-moz-repeating-linear-gradient(10px 10px -45deg, red, blue) no-repeat",
       "-moz-element(#test) alpha",
       /* multiple mask-image */
       "url(404.png), url(404.png)",
       "repeat-x, subtract, none",
-      "0% top url(404.png), url(404.png) 0% top",
+      "50% top url(404.png), url(404.png) 50% top",
       "subtract repeat-y top left url(404.png), repeat-x alpha",
       "url(404.png), -moz-linear-gradient(20px 20px -45deg, blue, green), -moz-element(#a) alpha",
       "top left / contain, bottom right / cover",
       /* test cases with clip+origin in the shorthand */
       "url(404.png) alpha padding-box",
       "url(404.png) border-box alpha",
       "content-box url(404.png)",
       "url(404.png) alpha padding-box padding-box",
@@ -7035,18 +7036,19 @@ if (SupportsMaskShorthand()) {
     initial_values: [ "border-box" ],
     other_values: [ "padding-box", "content-box", "border-box, padding-box", "padding-box, padding-box, padding-box", "border-box, border-box" ],
     invalid_values: [ "margin-box", "padding-box padding-box" ]
   };
   gCSSProperties["mask-position"] = {
     domProp: "maskPosition",
     inherited: false,
     type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
-    initial_values: [ "top 0% left 0%", "top 0% left", "top left", "left top", "0% 0%", "0% top", "left 0%" ],
-    other_values: [ "top", "left", "right", "bottom", "center", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "50%", "top left, top left", "top left, top right", "top right, top left", "left top, 0% 0%", "10% 20%, 30%, 40%", "top left, bottom right", "right bottom, left top", "0%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
+    initial_values: [ "left 50% top 50%", "left 50% center", "center", "center center", "50% 50%", "50% center", "center 50%" ],
+    other_values: [ "top", "left", "right", "bottom", "center bottom", "bottom center", "center right", "right center", "center top", "top center", "center left", "left center", "right bottom", "bottom right", "0%", "top left, top left", "top left, top right", "top right, top left", "left top, 0% 0%", "10% 20%, 30%, 40%", "top left, bottom right", "right bottom, left top", "0%", "0px", "30px", "0%, 10%, 20%, 30%", "top, top, top, top, top",
+      "top 0% left 0%", "top 0% left", "top left", "left top", "0% 0%", "0% top", "left 0%",
       "calc(20px)",
       "calc(20px) 10px",
       "10px calc(20px)",
       "calc(20px) 25%",
       "25% calc(20px)",
       "calc(20px) calc(20px)",
       "calc(20px + 1em) calc(20px / 2)",
       "calc(20px + 50%) calc(50% - 10px)",
--- a/media/libpng/CHANGES
+++ b/media/libpng/CHANGES
@@ -5591,16 +5591,95 @@ Version 1.6.23rc01 [June 2, 2016]
 
 Version 1.6.23rc02 [June 4, 2016]
   Fixed undefined behavior in png_push_save_buffer(). Do not call
     memcpy() with a null source, even if count is zero (Leon Scroggins III).
 
 Version 1.6.23 [June 9, 2016]
   Fixed bad link to RFC2083 in png.5 (Nikola Forro).
 
+Version 1.6.24beta01 [June 11, 2016]
+  Avoid potential overflow of the PNG_IMAGE_SIZE macro.  This macro
+    is not used within libpng, but is used in some of the examples.
+
+Version 1.6.24beta02 [June 23, 2016]
+  Correct filter heuristic overflow handling. This was broken when the
+    write filter code was moved out-of-line; if there is a single filter and
+    the heuristic sum overflows the calculation of the filtered line is not
+    completed.  In versions prior to 1.6 the code was duplicated in-line
+    and the check not performed, so the filter operation completed; however,
+    in the multi-filter case where the sum is performed the 'none' filter would
+    be selected if all the sums overflowed, even if it wasn't in the filter
+    list.  The fix to the first problem is simply to provide PNG_SIZE_MAX as
+    the current lmins sum value; this means the sum can never exceed it and
+    overflows silently.  A reasonable compiler that does choose to inline
+    the code will simply eliminate the sum check.
+  The fix to the second problem is to use high precision arithmetic (this is
+    implemented in 1.7), however a simple safe fix here is to chose the lowest
+    numbered filter in the list from png_set_filter (this only works if the
+    first problem is also fixed) (John Bowler).
+  Use a more efficient absolute value calculation on SSE2 (Matthieu Darbois).
+  Fixed the case where PNG_IMAGE_BUFFER_SIZE can overflow in the application
+    as a result of the application using an increased 'row_stride'; previously
+    png_image_finish_read only checked for overflow on the base calculation of
+    components.  (I.e. it checked for overflow of a 32-bit number on the total
+    number of pixel components in the output format, not the possibly padded row
+    length and not the number of bytes, which for linear formats is twice the
+    number of components.)
+  MSVC does not like '-(unsigned)', so replaced it with 0U-(unsigned)
+  MSVC does not like (uInt) = -(unsigned) (i.e. as an initializer), unless
+    the conversion is explicitly invoked by a cast.
+  Put the SKIP definition in the correct place. It needs to come after the
+    png.h include (see all the other .c files in contrib/libtests) because it
+    depends on PNG_LIBPNG_VER.
+  Removed the three compile warning options from the individual project
+    files into the zlib.props globals.  It increases the warning level from 4
+    to All and adds a list of the warnings that need to be turned off.  This is
+    semi-documentary; the intent is to tell libpng users which warnings have
+    been examined and judged non-fixable at present.  The warning about
+    structure padding is fixable, but it would be a signficant change (moving
+    structure members around).
+
+Version 1.6.24beta03 [July 4, 2016]
+  Optimized absolute value calculation in filter selection, similar to
+    code in the PAETH decoder in pngrutil.c. Build with PNG_USE_ABS to
+    use this.
+  Added pngcp to the build together with a pngcp.dfa configuration test.
+  Added high resolution timing to pngcp.
+  Added "Common linking failures" section to INSTALL.
+  Relocated misplaced #endif in png.c sRGB profile checking.
+  Fixed two Coverity issues in pngcp.c.
+
+Version 1.6.24beta04 [July 8, 2016]
+  Avoid filter-selection heuristic sum calculations in cases where only one
+    filter is a candidate for selection. This trades off code size (added
+    private png_setup_*_row_only() functions) for speed.
+
+Version 1.6.24beta05 [July 13, 2016]
+  Fixed some indentation to comply with our coding style.
+  Added contrib/tools/reindent.
+
+Version 1.6.24beta06 [July 18, 2016]
+  Fixed more indentation to comply with our coding style.
+  Eliminated unnecessary tests of boolean png_isaligned() vs 0.
+
+Version 1.6.24rc01 [July 25, 2016]
+  No changes.
+
+Version 1.6.24rc02 [August 1, 2016]
+  Conditionally compile SSE2 headers in contrib/intel/intel_sse.patch
+  Conditionally compile png_decompress_chunk().
+
+Version 1.6.24rc03 [August 2, 2016]
+  Conditionally compile ARM_NEON headers in pngpriv.h
+  Updated contrib/intel/intel_sse.patch
+
+Version 1.6.24[August 4, 2016]
+  No changes.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
 to subscribe)
 or to glennrp at users.sourceforge.net
 
 Glenn R-P
 #endif
--- a/media/libpng/LICENSE
+++ b/media/libpng/LICENSE
@@ -3,29 +3,25 @@ This copy of the libpng notices is provi
 any discrepancy between this copy and the notices in the file png.h that is
 included in the libpng distribution, the latter shall prevail.
 
 COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
 
 If you modify libpng you may insert additional notices immediately following
 this sentence.
 
-pnglibconf.h and moz.build are distributed under the Mozilla Public License,
-v. 2.0. If a copy of the MPL was not distributed with this file, You can
-obtain one at http://mozilla.org/MPL/2.0/.
-
 This modified version of libpng code adds animated PNG support and is
 released under the libpng license described below. The modifications are
 Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 surrounding them in the modified libpng source files.
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
+libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are
 Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
 derived from libpng-1.0.6, and are distributed according to the same
 disclaimer and license as libpng-1.0.6 with the following individuals
 added to the list of Contributing Authors:
 
    Simon-Pierre Cadieux
    Eric S. Raymond
    Mans Rullgard
@@ -132,9 +128,9 @@ The Copyright owner believes that the Ex
 Number (ECCN) for libpng is EAR99, which means not subject to export
 controls or International Traffic in Arms Regulations (ITAR) because
 it is open source, publicly available software, that does not contain
 any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
 734.7(b).
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-June 9, 2016
+August 4, 2016
--- a/media/libpng/MOZCHANGES
+++ b/media/libpng/MOZCHANGES
@@ -1,11 +1,13 @@
 
 Changes made to pristine libpng source by mozilla.org developers.
 
+2016/08/06  -- Synced with libpng-1.6.24 (bug #1291986).
+
 2016/06/09  -- Synced with libpng-1.6.23 (bug #1275901).
 
 2016/01/16  -- Synced with libpng-1.6.21 (bug #1230757).
 
 2015/11/12  -- Synced with libpng-1.6.19 (bug #1224244).
 
 2015/07/30  -- Synced with libpng-1.6.18 (bug #1186977).
 
--- a/media/libpng/README
+++ b/media/libpng/README
@@ -1,9 +1,9 @@
-README for libpng version 1.6.23 - June 9, 2016 (shared library 16.0)
+README for libpng version 1.6.24 - August 4, 2016 (shared library 16.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
 
 Libpng comes in several distribution formats.  Get libpng-*.tar.gz or
 libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
 or lpng*.7z or lpng*.zip if you want DOS-style line endings.
 
--- a/media/libpng/apng.patch
+++ b/media/libpng/apng.patch
@@ -9,17 +9,17 @@ Index: LICENSE
 +This modified version of libpng code adds animated PNG support and is
 +released under the libpng license described below. The modifications are
 +Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 +and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 +surrounding them in the modified libpng source files.
 +
  This code is released under the libpng license.
  
- libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
+ libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are
 Index: pngread.c
 ===================================================================
 --- pngread.c
 +++ pngread.c
 @@ -161,6 +161,9 @@
  
        else if (chunk_name == png_IDAT)
        {
@@ -41,17 +41,17 @@ Index: pngread.c
 +         png_handle_fcTL(png_ptr, info_ptr, length);
 +
 +      else if (chunk_name == png_fdAT)
 +         png_handle_fdAT(png_ptr, info_ptr, length);
 +#endif
 +
        else
           png_handle_unknown(png_ptr, info_ptr, length,
-             PNG_HANDLE_CHUNK_AS_DEFAULT);
+              PNG_HANDLE_CHUNK_AS_DEFAULT);
 @@ -257,6 +271,72 @@
  }
  #endif /* SEQUENTIAL_READ */
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +void PNGAPI
 +png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
 +{
@@ -294,29 +294,29 @@ Index: pngget.c
 Index: png.c
 ===================================================================
 --- png.c
 +++ png.c
 @@ -775,17 +775,21 @@
  #else
  #  ifdef __STDC__
     return PNG_STRING_NEWLINE \
--      "libpng version 1.6.23 - June 9, 2016" PNG_STRING_NEWLINE \
-+      "libpng version 1.6.23+apng - June 9, 2016" PNG_STRING_NEWLINE \
+-      "libpng version 1.6.24 - August 4, 2016" PNG_STRING_NEWLINE \
++      "libpng version 1.6.24+apng - August 4, 2016" PNG_STRING_NEWLINE \
        "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
        PNG_STRING_NEWLINE \
        "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
        "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
 -      PNG_STRING_NEWLINE;
 +      PNG_STRING_NEWLINE \
 +      "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \
 +      "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ;
  #  else
--   return "libpng version 1.6.23 - June 9, 2016\
-+   return "libpng version 1.6.23+apng - June 9, 2016\
+-   return "libpng version 1.6.24 - August 4, 2016\
++   return "libpng version 1.6.24+apng - August 4, 2016\
        Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
        Copyright (c) 1996-1997 Andreas Dilger\
 -      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
 +      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\
 +      Portions Copyright (c) 2006-2007 Andrew Smith\
 +      Portions Copyright (c) 2008-2016 Max Stepin";
  #  endif
  #endif
@@ -333,40 +333,40 @@ Index: png.h
 + * released under the libpng license described below. The modifications are
 + * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 + * and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 + * surrounding them in the modified libpng source files.
 + *
   * This code is released under the libpng license.
   *
   * Some files in the "contrib" directory and some configure-generated
-@@ -313,9 +319,9 @@
+@@ -313,8 +319,9 @@
   */
  
  /* Version information for png.h - this should match the version in png.c */
--#define PNG_LIBPNG_VER_STRING "1.6.23"
-+#define PNG_LIBPNG_VER_STRING "1.6.23+apng"
- #define PNG_HEADER_VERSION_STRING \
--     " libpng version 1.6.23 - June 9, 2016\n"
-+     " libpng version 1.6.23+apng - June 9, 2016\n"
+-#define PNG_LIBPNG_VER_STRING "1.6.24"
+-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.24 - August 4, 2016\n"
++#define PNG_LIBPNG_VER_STRING "1.6.24+apng"
++#define PNG_HEADER_VERSION_STRING \
++     " libpng version 1.6.24+apng - August 4, 2016\n"
  
  #define PNG_LIBPNG_VER_SONUM   16
  #define PNG_LIBPNG_VER_DLLNUM  16
-@@ -366,6 +372,10 @@
+@@ -365,6 +372,10 @@
  #   include "pnglibconf.h"
  #endif
  
 +#define PNG_APNG_SUPPORTED
 +#define PNG_READ_APNG_SUPPORTED
 +#define PNG_WRITE_APNG_SUPPORTED
 +
  #ifndef PNG_VERSION_INFO_ONLY
-    /* Machine specific configuration. */
+ /* Machine specific configuration. */
  #  include "pngconf.h"
-@@ -461,6 +471,17 @@
+@@ -460,6 +471,17 @@
   * See pngconf.h for base types that vary by machine/system
   */
  
 +#ifdef PNG_APNG_SUPPORTED
 +/* dispose_op flags from inside fcTL */
 +#define PNG_DISPOSE_OP_NONE        0x00
 +#define PNG_DISPOSE_OP_BACKGROUND  0x01
 +#define PNG_DISPOSE_OP_PREVIOUS    0x02
@@ -374,115 +374,115 @@ Index: png.h
 +/* blend_op flags from inside fcTL */
 +#define PNG_BLEND_OP_SOURCE        0x00
 +#define PNG_BLEND_OP_OVER          0x01
 +#endif /* APNG */
 +
  /* This triggers a compiler error in png.c, if png.c and png.h
   * do not agree upon the version number.
   */
-@@ -781,6 +802,10 @@
+@@ -780,6 +802,10 @@
  #define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
  #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
  #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
 +#ifdef PNG_APNG_SUPPORTED
-+#define PNG_INFO_acTL 0x10000
-+#define PNG_INFO_fcTL 0x20000
++#define PNG_INFO_acTL 0x10000U
++#define PNG_INFO_fcTL 0x20000U
 +#endif
  
  /* This is used for the transformation routines, as some of them
   * change these values for the row.  It also should enable using
-@@ -818,6 +843,10 @@
+@@ -817,6 +843,10 @@
  #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
  typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
 +#ifdef PNG_APNG_SUPPORTED
 +typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
 +    png_uint_32));
 +#endif
  
  /* The following callback receives png_uint_32 row_number, int pass for the
   * png_bytep data of the row.  When transforming an interlaced image the
-@@ -3237,6 +3266,75 @@
+@@ -3242,6 +3272,75 @@
   *  END OF HARDWARE AND SOFTWARE OPTIONS
   ******************************************************************************/
  
 +#ifdef PNG_APNG_SUPPORTED
-+PNG_EXPORT(245, png_uint_32, png_get_acTL, (png_structp png_ptr,
++PNG_EXPORT(246, png_uint_32, png_get_acTL, (png_structp png_ptr,
 +   png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
 +
-+PNG_EXPORT(246, png_uint_32, png_set_acTL, (png_structp png_ptr,
++PNG_EXPORT(247, png_uint_32, png_set_acTL, (png_structp png_ptr,
 +   png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
 +
-+PNG_EXPORT(247, png_uint_32, png_get_num_frames, (png_structp png_ptr,
++PNG_EXPORT(248, png_uint_32, png_get_num_frames, (png_structp png_ptr,
 +   png_infop info_ptr));
 +
-+PNG_EXPORT(248, png_uint_32, png_get_num_plays, (png_structp png_ptr,
++PNG_EXPORT(249, png_uint_32, png_get_num_plays, (png_structp png_ptr,
 +   png_infop info_ptr));
 +
-+PNG_EXPORT(249, png_uint_32, png_get_next_frame_fcTL,
++PNG_EXPORT(250, png_uint_32, png_get_next_frame_fcTL,
 +   (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
 +   png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
 +   png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
 +   png_byte *blend_op));
 +
-+PNG_EXPORT(250, png_uint_32, png_set_next_frame_fcTL,
++PNG_EXPORT(251, png_uint_32, png_set_next_frame_fcTL,
 +   (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
 +   png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
 +   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 +   png_byte blend_op));
 +
-+PNG_EXPORT(251, png_uint_32, png_get_next_frame_width,
++PNG_EXPORT(252, png_uint_32, png_get_next_frame_width,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(252, png_uint_32, png_get_next_frame_height,
++PNG_EXPORT(253, png_uint_32, png_get_next_frame_height,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(253, png_uint_32, png_get_next_frame_x_offset,
++PNG_EXPORT(254, png_uint_32, png_get_next_frame_x_offset,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(254, png_uint_32, png_get_next_frame_y_offset,
++PNG_EXPORT(255, png_uint_32, png_get_next_frame_y_offset,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(255, png_uint_16, png_get_next_frame_delay_num,
++PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_num,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_den,
++PNG_EXPORT(257, png_uint_16, png_get_next_frame_delay_den,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(257, png_byte, png_get_next_frame_dispose_op,
++PNG_EXPORT(258, png_byte, png_get_next_frame_dispose_op,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(258, png_byte, png_get_next_frame_blend_op,
++PNG_EXPORT(259, png_byte, png_get_next_frame_blend_op,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(259, png_byte, png_get_first_frame_is_hidden,
++PNG_EXPORT(260, png_byte, png_get_first_frame_is_hidden,
 +   (png_structp png_ptr, png_infop info_ptr));
-+PNG_EXPORT(260, png_uint_32, png_set_first_frame_is_hidden,
++PNG_EXPORT(261, png_uint_32, png_set_first_frame_is_hidden,
 +   (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
 +
 +#ifdef PNG_READ_APNG_SUPPORTED
-+PNG_EXPORT(261, void, png_read_frame_head, (png_structp png_ptr,
++PNG_EXPORT(262, void, png_read_frame_head, (png_structp png_ptr,
 +   png_infop info_ptr));
 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-+PNG_EXPORT(262, void, png_set_progressive_frame_fn, (png_structp png_ptr,
++PNG_EXPORT(263, void, png_set_progressive_frame_fn, (png_structp png_ptr,
 +   png_progressive_frame_ptr frame_info_fn,
 +   png_progressive_frame_ptr frame_end_fn));
 +#endif /* PROGRESSIVE_READ */
 +#endif /* READ_APNG */
 +
 +#ifdef PNG_WRITE_APNG_SUPPORTED
-+PNG_EXPORT(263, void, png_write_frame_head, (png_structp png_ptr,
++PNG_EXPORT(264, void, png_write_frame_head, (png_structp png_ptr,
 +   png_infop info_ptr, png_bytepp row_pointers,
 +   png_uint_32 width, png_uint_32 height,
 +   png_uint_32 x_offset, png_uint_32 y_offset,
 +   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 +   png_byte blend_op));
 +
-+PNG_EXPORT(264, void, png_write_frame_tail, (png_structp png_ptr,
++PNG_EXPORT(265, void, png_write_frame_tail, (png_structp png_ptr,
 +   png_infop info_ptr));
 +#endif /* WRITE_APNG */
 +#endif /* APNG */
 +
  /* Maintainer: Put new public prototypes here ^, in libpng.3, in project
   * defs, and in scripts/symbols.def.
   */
-@@ -3245,7 +3343,11 @@
+@@ -3250,7 +3349,11 @@
   * one to use is one more than this.)
   */
  #ifdef PNG_EXPORT_LAST_ORDINAL
 +#ifdef PNG_APNG_SUPPORTED
 +  PNG_EXPORT_LAST_ORDINAL(265);
 +#else
    PNG_EXPORT_LAST_ORDINAL(245);
 +#endif /* APNG */
@@ -516,17 +516,17 @@ Index: pngpriv.h
 +/* For png_struct.apng_flags: */
 +#define PNG_FIRST_FRAME_HIDDEN       0x0001
 +#define PNG_APNG_APP                 0x0002
 +#endif
 +
  /* The following will work on (signed char*) strings, whereas the get_uint_32
   * macro will fail on top-bit-set values because of the sign extension.
   */
-@@ -1441,6 +1455,49 @@
+@@ -1443,6 +1457,49 @@
  
  #endif /* PROGRESSIVE_READ */
  
 +#ifdef PNG_APNG_SUPPORTED
 +PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
 +   png_uint_32 width, png_uint_32 height,
 +   png_uint_32 x_offset, png_uint_32 y_offset,
 +   png_uint_16 delay_num, png_uint_16 delay_den,
@@ -1039,19 +1039,19 @@ Index: pngset.c
 +
 +void /* PRIVATE */
 +png_ensure_fcTL_is_valid(png_structp png_ptr,
 +    png_uint_32 width, png_uint_32 height,
 +    png_uint_32 x_offset, png_uint_32 y_offset,
 +    png_uint_16 delay_num, png_uint_16 delay_den,
 +    png_byte dispose_op, png_byte blend_op)
 +{
-+    if (width > PNG_UINT_31_MAX)
++    if (width == 0 || width > PNG_UINT_31_MAX)
 +        png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
-+    if (height > PNG_UINT_31_MAX)
++    if (height == 0 || height > PNG_UINT_31_MAX)
 +        png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
 +    if (x_offset > PNG_UINT_31_MAX)
 +        png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
 +    if (y_offset > PNG_UINT_31_MAX)
 +        png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
 +    if (width + x_offset > png_ptr->first_frame_width ||
 +        height + y_offset > png_ptr->first_frame_height)
 +        png_error(png_ptr, "dimensions of a frame are greater than "
@@ -1092,29 +1092,29 @@ Index: pngset.c
 +
  #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
  static png_byte
  check_location(png_const_structrp png_ptr, int location)
 Index: pngrutil.c
 ===================================================================
 --- pngrutil.c
 +++ pngrutil.c
-@@ -855,6 +855,11 @@
+@@ -857,6 +857,11 @@
     filter_type = buf[11];
     interlace_type = buf[12];
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +   png_ptr->first_frame_width = width;
 +   png_ptr->first_frame_height = height;
 +#endif
 +
     /* Set internal variables */
     png_ptr->width = width;
     png_ptr->height = height;
-@@ -2755,6 +2760,180 @@
+@@ -2757,6 +2762,180 @@
  }
  #endif
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +void /* PRIVATE */
 +png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 +{
 +    png_byte data[8];
@@ -1285,17 +1285,17 @@ Index: pngrutil.c
 +
 +    png_ptr->next_seq_num++;
 +}
 +#endif /* READ_APNG */
 +
  #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
  /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
  static int
-@@ -4014,6 +4193,38 @@
+@@ -4016,6 +4195,38 @@
           uInt avail_in;
           png_bytep buffer;
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +         png_uint_32 bytes_to_skip = 0;
 +
 +         while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
 +         {
@@ -1324,35 +1324,35 @@ Index: pngrutil.c
 +
 +               png_ptr->idat_size -= 4;
 +            }
 +         }
 +#else
           while (png_ptr->idat_size == 0)
           {
              png_crc_finish(png_ptr, 0);
-@@ -4025,6 +4236,7 @@
+@@ -4027,6 +4238,7 @@
              if (png_ptr->chunk_name != png_IDAT)
                 png_error(png_ptr, "Not enough image data");
           }
 +#endif /* READ_APNG */
  
           avail_in = png_ptr->IDAT_read_size;
  
-@@ -4088,6 +4300,9 @@
+@@ -4090,6 +4302,9 @@
  
           png_ptr->mode |= PNG_AFTER_IDAT;
           png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
 +#ifdef PNG_READ_APNG_SUPPORTED
 +         png_ptr->num_frames_read++;
 +#endif
  
           if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
              png_chunk_benign_error(png_ptr, "Extra compressed data");
-@@ -4526,4 +4741,80 @@
+@@ -4528,4 +4743,80 @@
  
     png_ptr->flags |= PNG_FLAG_ROW_INIT;
  }
 +
 +#ifdef PNG_READ_APNG_SUPPORTED
 +/* This function is to be called after the main IDAT set has been read and
 + * before a new IDAT is read. It resets some parts of png_ptr
 + * to make them usable by the read functions again */
@@ -1471,17 +1471,17 @@ Index: pngwutil.c
 +#ifdef PNG_WRITE_APNG_SUPPORTED
 +         else
 +            png_write_fdAT(png_ptr, data, size);
 +#endif /* WRITE_APNG */
 +
           png_ptr->zstream.avail_out = 0;
           png_ptr->zstream.next_out = NULL;
           png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
-@@ -1857,6 +1878,82 @@
+@@ -1858,6 +1879,82 @@
  }
  #endif
  
 +#ifdef PNG_WRITE_APNG_SUPPORTED
 +void /* PRIVATE */
 +png_write_acTL(png_structp png_ptr,
 +    png_uint_32 num_frames, png_uint_32 num_plays)
 +{
@@ -1554,17 +1554,17 @@ Index: pngwutil.c
 +
 +    png_ptr->next_seq_num++;
 +}
 +#endif /* WRITE_APNG */
 +
  /* Initializes the row writing capability of libpng */
  void /* PRIVATE */
  png_write_start_row(png_structrp png_ptr)
-@@ -2622,4 +2719,39 @@
+@@ -2752,4 +2849,39 @@
     }
  #endif /* WRITE_FLUSH */
  }
 +
 +#ifdef PNG_WRITE_APNG_SUPPORTED
 +void /* PRIVATE */
 +png_write_reset(png_structp png_ptr)
 +{
--- a/media/libpng/arm/arm_init.c
+++ b/media/libpng/arm/arm_init.c
@@ -1,14 +1,14 @@
 
 /* arm_init.c - NEON optimised filter functions
  *
  * Copyright (c) 2014,2016 Glenn Randers-Pehrson
  * Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.22 [May 24, 2016]
+ * Last changed in libpng 1.6.22 [May 26, 2016]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
  * called.
  */
--- a/media/libpng/arm/filter_neon.S
+++ b/media/libpng/arm/filter_neon.S
@@ -5,22 +5,16 @@
  * Written by Mans Rullgard, 2011.
  * Last changed in libpng 1.6.16 [December 22, 2014]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
-/* These are required because Mozilla's moz.build system doesn't pass
- * -DDefined macros to the assembler.
- */
-#define PNG_READ_SUPPORTED
-#define MOZ_PNG_HAVE_ARM_NEON
-
 /* This is required to get the symbol renames, which are #defines, and the
  * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
  */
 #define PNG_VERSION_INFO_ONLY
 #include "../pngpriv.h"
 
 #if defined(__linux__) && defined(__ELF__)
 .section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
--- a/media/libpng/arm/filter_neon_intrinsics.c
+++ b/media/libpng/arm/filter_neon_intrinsics.c
@@ -1,16 +1,16 @@
 
 /* filter_neon_intrinsics.c - NEON optimised filter functions
  *
  * Copyright (c) 2014,2016 Glenn Randers-Pehrson
  * Written by James Yu <james.yu at linaro.org>, October 2013.
  * Based on filter_neon.S, written by Mans Rullgard, 2011.
  *
- * Last changed in libpng 1.6.22 [May 24, 2016]
+ * Last changed in libpng 1.6.22 [May 26, 2016]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "../pngpriv.h"
 
--- a/media/libpng/libpng-manual.txt
+++ b/media/libpng/libpng-manual.txt
@@ -1,22 +1,22 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.23 - June 9, 2016
+ libpng version 1.6.24 - August 4, 2016
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  This document is released under the libpng license.
  For conditions of distribution and use, see the disclaimer
  and license in png.h
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.23 - June 9, 2016
+ libpng versions 0.97, January 1998, through 1.6.24 - August 4, 2016
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  libpng 1.0 beta 6 - version 0.96 - May 28, 1997
  Updated and distributed by Andreas Dilger
  Copyright (c) 1996, 1997 Andreas Dilger
 
  libpng 1.0 beta 2 - version 0.88 - January 26, 1996
@@ -554,17 +554,17 @@ To inform libpng about your function, us
     png_set_read_status_fn(png_ptr, read_row_callback);
 
 When this function is called the row has already been completely processed and
 the 'row' and 'pass' refer to the next row to be handled.  For the
 non-interlaced case the row that was just handled is simply one less than the
 passed in row number, and pass will always be 0.  For the interlaced case the
 same applies unless the row value is 0, in which case the row just handled was
 the last one from one of the preceding passes.  Because interlacing may skip a
-pass you cannot be sure that the preceding pass is just 'pass-1', if you really
+pass you cannot be sure that the preceding pass is just 'pass-1'; if you really
 need to know what the last pass is record (row,pass) from the callback and use
 the last recorded value each time.
 
 As with the user transform you can find the output row using the
 PNG_ROW_FROM_PASS_ROW macro.
 
 Unknown-chunk handling
 
@@ -2225,32 +2225,37 @@ each pass.
 
 If you are not going to display the image after each pass, but are
 going to wait until the entire image is read in, use the sparkle
 effect.  This effect is faster and the end result of either method
 is exactly the same.  If you are planning on displaying the image
 after each pass, the "rectangle" effect is generally considered the
 better looking one.
 
-If you only want the "sparkle" effect, just call png_read_rows() as
+If you only want the "sparkle" effect, just call png_read_row() or
+png_read_rows() as
 normal, with the third parameter NULL.  Make sure you make pass over
 the image number_of_passes times, and you don't change the data in the
 rows between calls.  You can change the locations of the data, just
 not the data.  Each pass only writes the pixels appropriate for that
 pass, and assumes the data from previous passes is still valid.
 
     png_read_rows(png_ptr, row_pointers, NULL,
         number_of_rows);
+    or
+    png_read_row(png_ptr, row_pointers, NULL);
 
 If you only want the first effect (the rectangles), do the same as
 before except pass the row buffer in the third parameter, and leave
 the second parameter NULL.
 
     png_read_rows(png_ptr, NULL, row_pointers,
         number_of_rows);
+    or
+    png_read_row(png_ptr, NULL, row_pointers);
 
 If you don't want libpng to handle the interlacing details, just call
 png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images.
 Each of the images is a valid image by itself; however, you will almost
 certainly need to distribute the pixels from each sub-image to the
 correct place.  This is where everything gets very tricky.
 
 If you want to retrieve the separate images you must pass the correct
@@ -5340,17 +5345,17 @@ Lines do not exceed 80 characters.
 Other rules can be inferred by inspecting the libpng source.
 
 XVI. Y2K Compliance in libpng
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.23 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.24 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
 that will hold years up to 65535.  The other, which is deprecated,
 holds the date in text format, and will hold years up to 9999.
 
 The integer is
     "png_uint_16 year" in png_time_struct.
--- a/media/libpng/png.c
+++ b/media/libpng/png.c
@@ -1,25 +1,25 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Last changed in libpng 1.6.24 [August 4, 2016]
  * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_23 Your_png_h_is_not_version_1_6_23;
+typedef png_libpng_version_1_6_24 Your_png_h_is_not_version_1_6_24;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
  * stream we can set num_bytes = 8 so that libpng will not attempt to read
  * or write any of the magic bytes before it starts on the IHDR.
  */
 
 #ifdef PNG_READ_SUPPORTED
@@ -80,17 +80,17 @@ png_zalloc,(voidpf png_ptr, uInt items, 
    png_alloc_size_t num_bytes = size;
 
    if (png_ptr == NULL)
       return NULL;
 
    if (items >= (~(png_alloc_size_t)0)/size)
    {
       png_warning (png_voidcast(png_structrp, png_ptr),
-         "Potential overflow in png_zalloc()");
+          "Potential overflow in png_zalloc()");
       return NULL;
    }
 
    num_bytes *= items;
    return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
 }
 
 /* Function to free memory for zlib */
@@ -167,20 +167,20 @@ png_calculate_crc(png_structrp png_ptr, 
 }
 
 /* Check a user supplied version number, called from both read and write
  * functions that create a png_struct.
  */
 int
 png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
 {
-     /* Libpng versions 1.0.0 and later are binary compatible if the version
-      * string matches through the second '.'; we must recompile any
-      * applications that use any older library version.
-      */
+   /* Libpng versions 1.0.0 and later are binary compatible if the version
+    * string matches through the second '.'; we must recompile any
+    * applications that use any older library version.
+    */
 
    if (user_png_ver != NULL)
    {
       int i = -1;
       int found_dots = 0;
 
       do
       {
@@ -292,17 +292,17 @@ png_create_png_struct,(png_const_charp u
          create_struct.jmp_buf_size = 0; /*stack allocation*/
          create_struct.longjmp_fn = longjmp;
 #  endif
          /* Call the general version checker (shared with read and write code):
           */
          if (png_user_version_check(&create_struct, user_png_ver) != 0)
          {
             png_structrp png_ptr = png_voidcast(png_structrp,
-               png_malloc_warn(&create_struct, (sizeof *png_ptr)));
+                png_malloc_warn(&create_struct, (sizeof *png_ptr)));
 
             if (png_ptr != NULL)
             {
                /* png_ptr->zstream holds a back-pointer to the png_struct, so
                 * this can only be done now:
                 */
                create_struct.zstream.zalloc = png_zalloc;
                create_struct.zstream.zfree = png_zfree;
@@ -341,17 +341,17 @@ png_create_info_struct,(png_const_struct
       return NULL;
 
    /* Use the internal API that does not (or at least should not) error out, so
     * that this call always returns ok.  The application typically sets up the
     * error handling *after* creating the info_struct because this is the way it
     * has always been done in 'example.c'.
     */
    info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
-      (sizeof *info_ptr)));
+       (sizeof *info_ptr)));
 
    if (info_ptr != NULL)
       memset(info_ptr, 0, (sizeof *info_ptr));
 
    return info_ptr;
 }
 
 /* This function frees the memory associated with a single info struct.
@@ -397,45 +397,45 @@ png_destroy_info_struct(png_const_struct
  * is just a memset).
  *
  * NOTE: it is almost inconceivable that this API is used because it bypasses
  * the user-memory mechanism and the user error handling/warning mechanisms in
  * those cases where it does anything other than a memset.
  */
 PNG_FUNCTION(void,PNGAPI
 png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
-   PNG_DEPRECATED)
+    PNG_DEPRECATED)
 {
    png_inforp info_ptr = *ptr_ptr;
 
    png_debug(1, "in png_info_init_3");
 
    if (info_ptr == NULL)
       return;
 
    if ((sizeof (png_info)) > png_info_struct_size)
    {
       *ptr_ptr = NULL;
       /* The following line is why this API should not be used: */
       free(info_ptr);
       info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
-         (sizeof *info_ptr)));
+          (sizeof *info_ptr)));
       if (info_ptr == NULL)
          return;
       *ptr_ptr = info_ptr;
    }
 
    /* Set everything to 0 */
    memset(info_ptr, 0, (sizeof *info_ptr));
 }
 
 /* The following API is not called internally */
 void PNGAPI
 png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
-   int freer, png_uint_32 mask)
+    int freer, png_uint_32 mask)
 {
    png_debug(1, "in png_data_freer");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    if (freer == PNG_DESTROY_WILL_FREE_DATA)
       info_ptr->free_me |= mask;
@@ -444,17 +444,17 @@ png_data_freer(png_const_structrp png_pt
       info_ptr->free_me &= ~mask;
 
    else
       png_error(png_ptr, "Unknown freer parameter in png_data_freer");
 }
 
 void PNGAPI
 png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
-   int num)
+    int num)
 {
    png_debug(1, "in png_free_data");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
 #ifdef PNG_TEXT_SUPPORTED
    /* Free text item num or (if num == -1) all text items */
@@ -770,26 +770,26 @@ png_const_charp PNGAPI
 png_get_copyright(png_const_structrp png_ptr)
 {
    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
 #ifdef PNG_STRING_COPYRIGHT
    return PNG_STRING_COPYRIGHT
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.23+apng - June 9, 2016" PNG_STRING_NEWLINE \
+      "libpng version 1.6.24+apng - August 4, 2016" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
       "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
       PNG_STRING_NEWLINE \
       "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \
       "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ;
 #  else
-   return "libpng version 1.6.23+apng - June 9, 2016\
+   return "libpng version 1.6.24+apng - August 4, 2016\
       Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\
       Portions Copyright (c) 2006-2007 Andrew Smith\
       Portions Copyright (c) 2008-2016 Max Stepin";
 #  endif
 #endif
 }
@@ -1032,61 +1032,61 @@ png_zstream_error(png_structrp png_ptr, 
 /* png_convert_size: a PNGAPI but no longer in png.h, so deleted
  * at libpng 1.5.5!
  */
 
 /* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
 #ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
 static int
 png_colorspace_check_gamma(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_fixed_point gAMA, int from)
+    png_colorspacerp colorspace, png_fixed_point gAMA, int from)
    /* This is called to check a new gamma value against an existing one.  The
     * routine returns false if the new gamma value should not be written.
     *
     * 'from' says where the new gamma value comes from:
     *
     *    0: the new gamma value is the libpng estimate for an ICC profile
     *    1: the new gamma value comes from a gAMA chunk
     *    2: the new gamma value comes from an sRGB chunk
     */
 {
    png_fixed_point gtest;
 
    if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-      (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
+       (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
       png_gamma_significant(gtest) != 0))
    {
       /* Either this is an sRGB image, in which case the calculated gamma
        * approximation should match, or this is an image with a profile and the
        * value libpng calculates for the gamma of the profile does not match the
        * value recorded in the file.  The former, sRGB, case is an error, the
        * latter is just a warning.
        */
       if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
       {
          png_chunk_report(png_ptr, "gamma value does not match sRGB",
-            PNG_CHUNK_ERROR);
+             PNG_CHUNK_ERROR);
          /* Do not overwrite an sRGB value */
          return from == 2;
       }
 
       else /* sRGB tag not involved */
       {
          png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
-            PNG_CHUNK_WARNING);
+             PNG_CHUNK_WARNING);
          return from == 1;
       }
    }
 
    return 1;
 }
 
 void /* PRIVATE */
 png_colorspace_set_gamma(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_fixed_point gAMA)
+    png_colorspacerp colorspace, png_fixed_point gAMA)
 {
    /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
     * occur.  Since the fixed point representation is asymetrical it is
     * possible for 1/gamma to overflow the limit of 21474 and this means the
     * gamma value must be at least 5/100000 and hence at most 20000.0.  For
     * safety the limits here are a little narrower.  The values are 0.00016 to
     * 6250.0, which are truly ridiculous gamma values (and will produce
     * displays that are all black or all white.)
@@ -1634,18 +1634,18 @@ static const png_xy sRGB_xy = /* From IT
    /* red   */ 64000, 33000,
    /* green */ 30000, 60000,
    /* blue  */ 15000,  6000,
    /* white */ 31270, 32900
 };
 
 static int
 png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
-   int preferred)
+    png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
+    int preferred)
 {
    if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
       return 0;
 
    /* The consistency check is performed on the chromaticities; this factors out
     * variations because of the normalization (or not) of the end point Y
     * values.
     */
@@ -1682,31 +1682,31 @@ png_colorspace_set_xy_and_XYZ(png_const_
       colorspace->flags &= PNG_COLORSPACE_CANCEL(
          PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
 
    return 2; /* ok and changed */
 }
 
 int /* PRIVATE */
 png_colorspace_set_chromaticities(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, const png_xy *xy, int preferred)
+    png_colorspacerp colorspace, const png_xy *xy, int preferred)
 {
    /* We must check the end points to ensure they are reasonable - in the past
     * color management systems have crashed as a result of getting bogus
     * colorant values, while this isn't the fault of libpng it is the
     * responsibility of libpng because PNG carries the bomb and libpng is in a
     * position to protect against it.
     */
    png_XYZ XYZ;
 
    switch (png_colorspace_check_xy(&XYZ, xy))
    {
       case 0: /* success */
          return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
-            preferred);
+             preferred);
 
       case 1:
          /* We can't invert the chromaticities so we can't produce value XYZ
           * values.  Likely as not a color management system will fail too.
           */
          colorspace->flags |= PNG_COLORSPACE_INVALID;
          png_benign_error(png_ptr, "invalid chromaticities");
          break;
@@ -1719,26 +1719,26 @@ png_colorspace_set_chromaticities(png_co
          png_error(png_ptr, "internal error checking chromaticities");
    }
 
    return 0; /* failed */
 }
 
 int /* PRIVATE */
 png_colorspace_set_endpoints(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
+    png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
 {
    png_XYZ XYZ = *XYZ_in;
    png_xy xy;
 
    switch (png_colorspace_check_XYZ(&xy, &XYZ))
    {
       case 0:
          return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
-            preferred);
+             preferred);
 
       case 1:
          /* End points are invalid. */
          colorspace->flags |= PNG_COLORSPACE_INVALID;
          png_benign_error(png_ptr, "invalid end points");
          break;
 
       default:
@@ -1785,17 +1785,17 @@ is_ICC_signature(png_alloc_size_t it)
    return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
       is_ICC_signature_char((it >> 16) & 0xff) &&
       is_ICC_signature_char((it >> 8) & 0xff) &&
       is_ICC_signature_char(it & 0xff);
 }
 
 static int
 png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_charp name, png_alloc_size_t value, png_const_charp reason)
+    png_const_charp name, png_alloc_size_t value, png_const_charp reason)
 {
    size_t pos;
    char message[196]; /* see below for calculation */
 
    if (colorspace != NULL)
       colorspace->flags |= PNG_COLORSPACE_INVALID;
 
    pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
@@ -1810,41 +1810,41 @@ png_icc_profile_error(png_const_structrp
       message[pos++] = ' ';
    }
 #  ifdef PNG_WARNINGS_SUPPORTED
    else
       {
          char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
 
          pos = png_safecat(message, (sizeof message), pos,
-            png_format_number(number, number+(sizeof number),
-               PNG_NUMBER_FORMAT_x, value));
+             png_format_number(number, number+(sizeof number),
+             PNG_NUMBER_FORMAT_x, value));
          pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
       }
 #  endif
    /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
    pos = png_safecat(message, (sizeof message), pos, reason);
    PNG_UNUSED(pos)
 
    /* This is recoverable, but make it unconditionally an app_error on write to
     * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
     * on read, with a warning, but on write unless the app turns off
     * application errors the PNG won't be written.)
     */
    png_chunk_report(png_ptr, message,
-      (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
+       (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
 
    return 0;
 }
 #endif /* sRGB || iCCP */
 
 #ifdef PNG_sRGB_SUPPORTED
 int /* PRIVATE */
 png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   int intent)
+    int intent)
 {
    /* sRGB sets known gamma, end points and (from the chunk) intent. */
    /* IMPORTANT: these are not necessarily the values found in an ICC profile
     * because ICC profiles store values adapted to a D50 environment; it is
     * expected that the ICC profile mediaWhitePointTag will be D50; see the
     * checks and code elsewhere to understand this better.
     *
     * These XYZ values, which are accurate to 5dp, produce rgb to gray
@@ -1871,43 +1871,43 @@ png_colorspace_set_sRGB(png_const_struct
     * called below because an iCCP chunk matches sRGB then it is quite
     * conceivable that an older app recorded incorrect gAMA and cHRM because of
     * an incorrect calculation based on the values in the profile - this does
     * *not* invalidate the profile (though it still produces an error, which can
     * be ignored.)
     */
    if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
       return png_icc_profile_error(png_ptr, colorspace, "sRGB",
-         (unsigned)intent, "invalid sRGB rendering intent");
+          (unsigned)intent, "invalid sRGB rendering intent");
 
    if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
-      colorspace->rendering_intent != intent)
+       colorspace->rendering_intent != intent)
       return png_icc_profile_error(png_ptr, colorspace, "sRGB",
          (unsigned)intent, "inconsistent rendering intents");
 
    if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
    {
       png_benign_error(png_ptr, "duplicate sRGB information ignored");
       return 0;
    }
 
    /* If the standard sRGB cHRM chunk does not match the one from the PNG file
     * warn but overwrite the value with the correct one.
     */
    if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
-      !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
-         100))
+       !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
+       100))
       png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
          PNG_CHUNK_ERROR);
 
    /* This check is just done for the error reporting - the routine always
     * returns true when the 'from' argument corresponds to sRGB (2).
     */
    (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
-      2/*from sRGB*/);
+       2/*from sRGB*/);
 
    /* intent: bugs in GCC force 'int' to be used as the parameter type. */
    colorspace->rendering_intent = (png_uint_16)intent;
    colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
 
    /* endpoints */
    colorspace->end_points_xy = sRGB_xy;
    colorspace->end_points_XYZ = sRGB_XYZ;
@@ -1932,95 +1932,95 @@ png_colorspace_set_sRGB(png_const_struct
  *
  *    (63189.8112, 65536, 54060.6464)
  */
 static const png_byte D50_nCIEXYZ[12] =
    { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
 
 int /* PRIVATE */
 png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_charp name, png_uint_32 profile_length)
+    png_const_charp name, png_uint_32 profile_length)
 {
    if (profile_length < 132)
       return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-         "too short");
+          "too short");
 
    return 1;
 }
 
 int /* PRIVATE */
 png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_charp name, png_uint_32 profile_length,
-   png_const_bytep profile/* first 132 bytes only */, int color_type)
+    png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile/* first 132 bytes only */, int color_type)
 {
    png_uint_32 temp;
 
    /* Length check; this cannot be ignored in this code because profile_length
     * is used later to check the tag table, so even if the profile seems over
     * long profile_length from the caller must be correct.  The caller can fix
     * this up on read or write by just passing in the profile header length.
     */
    temp = png_get_uint_32(profile);
    if (temp != profile_length)
       return png_icc_profile_error(png_ptr, colorspace, name, temp,
-         "length does not match profile");
+          "length does not match profile");
 
    temp = (png_uint_32) (*(profile+8));
    if (temp > 3 && (profile_length & 3))
       return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-         "invalid length");
+          "invalid length");
 
    temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
    if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
       profile_length < 132+12*temp) /* truncated tag table */
       return png_icc_profile_error(png_ptr, colorspace, name, temp,
-         "tag count too large");
+          "tag count too large");
 
    /* The 'intent' must be valid or we can't store it, ICC limits the intent to
     * 16 bits.
     */
    temp = png_get_uint_32(profile+64);
    if (temp >= 0xffff) /* The ICC limit */
       return png_icc_profile_error(png_ptr, colorspace, name, temp,
-         "invalid rendering intent");
+          "invalid rendering intent");
 
    /* This is just a warning because the profile may be valid in future
     * versions.
     */
    if (temp >= PNG_sRGB_INTENT_LAST)
       (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-         "intent outside defined range");
+          "intent outside defined range");
 
    /* At this point the tag table can't be checked because it hasn't necessarily
     * been loaded; however, various header fields can be checked.  These checks
     * are for values permitted by the PNG spec in an ICC profile; the PNG spec
     * restricts the profiles that can be passed in an iCCP chunk (they must be
     * appropriate to processing PNG data!)
     */
 
    /* Data checks (could be skipped).  These checks must be independent of the
     * version number; however, the version number doesn't accomodate changes in
     * the header fields (just the known tags and the interpretation of the
     * data.)
     */
    temp = png_get_uint_32(profile+36); /* signature 'ascp' */
    if (temp != 0x61637370)
       return png_icc_profile_error(png_ptr, colorspace, name, temp,
-         "invalid signature");
+          "invalid signature");
 
    /* Currently the PCS illuminant/adopted white point (the computational
     * white point) are required to be D50,
     * however the profile contains a record of the illuminant so perhaps ICC
     * expects to be able to change this in the future (despite the rationale in
     * the introduction for using a fixed PCS adopted white.)  Consequently the
     * following is just a warning.
     */
    if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
       (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
-         "PCS illuminant is not D50");
+          "PCS illuminant is not D50");
 
    /* The PNG spec requires this:
     * "If the iCCP chunk is present, the image samples conform to the colour
     * space represented by the embedded ICC profile as defined by the
     * International Color Consortium [ICC]. The colour space of the ICC profile
     * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
     * 6), or a greyscale colour space for greyscale images (PNG colour types 0
     * and 4)."
@@ -2038,28 +2038,28 @@ png_icc_check_header(png_const_structrp 
     * almost certainly more correct to ignore the profile.
     */
    temp = png_get_uint_32(profile+16); /* data colour space field */
    switch (temp)
    {
       case 0x52474220: /* 'RGB ' */
          if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
             return png_icc_profile_error(png_ptr, colorspace, name, temp,
-               "RGB color space not permitted on grayscale PNG");
+                "RGB color space not permitted on grayscale PNG");
          break;
 
       case 0x47524159: /* 'GRAY' */
          if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
             return png_icc_profile_error(png_ptr, colorspace, name, temp,
-               "Gray color space not permitted on RGB PNG");
+                "Gray color space not permitted on RGB PNG");
          break;
 
       default:
          return png_icc_profile_error(png_ptr, colorspace, name, temp,
-            "invalid ICC profile color space");
+             "invalid ICC profile color space");
    }
 
    /* It is up to the application to check that the profile class matches the
     * application requirements; the spec provides no guidance, but it's pretty
     * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
     * ('prtr') or 'spac' (for generic color spaces).  Issue a warning in these
     * cases.  Issue an error for device link or abstract profiles - these don't
     * contain the records necessary to transform the color-space to anything
@@ -2074,70 +2074,70 @@ png_icc_check_header(png_const_structrp 
       case 0x70727472: /* 'prtr' */
       case 0x73706163: /* 'spac' */
          /* All supported */
          break;
 
       case 0x61627374: /* 'abst' */
          /* May not be embedded in an image */
          return png_icc_profile_error(png_ptr, colorspace, name, temp,
-            "invalid embedded Abstract ICC profile");
+             "invalid embedded Abstract ICC profile");
 
       case 0x6c696e6b: /* 'link' */
          /* DeviceLink profiles cannot be interpreted in a non-device specific
           * fashion, if an app uses the AToB0Tag in the profile the results are
           * undefined unless the result is sent to the intended device,
           * therefore a DeviceLink profile should not be found embedded in a
           * PNG.
           */
          return png_icc_profile_error(png_ptr, colorspace, name, temp,
-            "unexpected DeviceLink ICC profile class");
+             "unexpected DeviceLink ICC profile class");
 
       case 0x6e6d636c: /* 'nmcl' */
          /* A NamedColor profile is also device specific, however it doesn't
           * contain an AToB0 tag that is open to misinterpretation.  Almost
           * certainly it will fail the tests below.
           */
          (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-            "unexpected NamedColor ICC profile class");
+             "unexpected NamedColor ICC profile class");
          break;
 
       default:
          /* To allow for future enhancements to the profile accept unrecognized
           * profile classes with a warning, these then hit the test below on the
           * tag content to ensure they are backward compatible with one of the
           * understood profiles.
           */
          (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-            "unrecognized ICC profile class");
+             "unrecognized ICC profile class");
          break;
    }
 
    /* For any profile other than a device link one the PCS must be encoded
     * either in XYZ or Lab.
     */
    temp = png_get_uint_32(profile+20);
    switch (temp)
    {
       case 0x58595a20: /* 'XYZ ' */
       case 0x4c616220: /* 'Lab ' */
          break;
 
       default:
          return png_icc_profile_error(png_ptr, colorspace, name, temp,
-            "unexpected ICC PCS encoding");
+             "unexpected ICC PCS encoding");
    }
 
    return 1;
 }
 
 int /* PRIVATE */
 png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_charp name, png_uint_32 profile_length,
-   png_const_bytep profile /* header plus whole tag table */)
+    png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile /* header plus whole tag table */)
 {
    png_uint_32 tag_count = png_get_uint_32(profile+128);
    png_uint_32 itag;
    png_const_bytep tag = profile+132; /* The first tag */
 
    /* First scan all the tags in the table and add bits to the icc_info value
     * (temporarily in 'tags').
     */
@@ -2155,25 +2155,25 @@ png_icc_check_tag_table(png_const_struct
        */
       if ((tag_start & 3) != 0)
       {
          /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
           * only a warning here because libpng does not care about the
           * alignment.
           */
          (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
-            "ICC profile tag start not a multiple of 4");
+             "ICC profile tag start not a multiple of 4");
       }
 
       /* This is a hard error; potentially it can cause read outside the
        * profile.
        */
       if (tag_start > profile_length || tag_length > profile_length - tag_start)
          return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
-            "ICC profile tag outside profile");
+             "ICC profile tag outside profile");
    }
 
    return 1; /* success, maybe with warnings */
 }
 
 #ifdef PNG_sRGB_SUPPORTED
 #if PNG_sRGB_PROFILE_CHECKS >= 0
 /* Information about the known ICC sRGB profiles */
@@ -2191,61 +2191,61 @@ static const struct
 
 } png_sRGB_checks[] =
 {
    /* This data comes from contrib/tools/checksum-icc run on downloads of
     * all four ICC sRGB profiles from www.color.org.
     */
    /* adler32, crc32, MD5[4], intent, date, length, file-name */
    PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
-      PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
-      "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
+       PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
+       "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
 
    /* ICC sRGB v2 perceptual no black-compensation: */
    PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
-      PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
-      "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
+       PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
+       "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
 
    PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
-      PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
-      "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
+       PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
+       "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
 
    /* ICC sRGB v4 perceptual */
    PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
-      PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
-      "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
+       PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
+       "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
 
    /* The following profiles have no known MD5 checksum. If there is a match
     * on the (empty) MD5 the other fields are used to attempt a match and
     * a warning is produced.  The first two of these profiles have a 'cprt' tag
     * which suggests that they were also made by Hewlett Packard.
     */
    PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
-      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
-      "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
+       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
+       "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
 
    /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
     * match the D50 PCS illuminant in the header (it is in fact the D65 values,
     * so the white point is recorded as the un-adapted value.)  The profiles
     * below only differ in one byte - the intent - and are basically the same as
     * the previous profile except for the mediaWhitePointTag error and a missing
     * chromaticAdaptationTag.
     */
    PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
-      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
-      "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
+       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
+       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
 
    PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
-      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
-      "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
+       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
+       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
 };
 
 static int
 png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
-   png_const_bytep profile, uLong adler)
+    png_const_bytep profile, uLong adler)
 {
    /* The quick check is to verify just the MD5 signature and trust the
     * rest of the data.  Because the profile has already been verified for
     * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'
     * field too, so if the profile has been edited with an intent not defined
     * by sRGB (but maybe defined by a later ICC specification) the read of
     * the profile will fail at that point.
     */
@@ -2319,28 +2319,28 @@ png_compare_ICC_profile_with_sRGB(png_co
                   if (png_sRGB_checks[i].is_broken != 0)
                   {
                      /* These profiles are known to have bad data that may cause
                       * problems if they are used, therefore attempt to
                       * discourage their use, skip the 'have_md5' warning below,
                       * which is made irrelevant by this error.
                       */
                      png_chunk_report(png_ptr, "known incorrect sRGB profile",
-                        PNG_CHUNK_ERROR);
+                         PNG_CHUNK_ERROR);
                   }
 
                   /* Warn that this being done; this isn't even an error since
                    * the profile is perfectly valid, but it would be nice if
                    * people used the up-to-date ones.
                    */
                   else if (png_sRGB_checks[i].have_md5 == 0)
                   {
                      png_chunk_report(png_ptr,
-                        "out-of-date sRGB profile with no signature",
-                        PNG_CHUNK_WARNING);
+                         "out-of-date sRGB profile with no signature",
+                         PNG_CHUNK_WARNING);
                   }
 
                   return 1+png_sRGB_checks[i].is_broken;
                }
             }
 
 # if PNG_sRGB_PROFILE_CHECKS > 0
          /* The signature matched, but the profile had been changed in some
@@ -2353,48 +2353,46 @@ png_compare_ICC_profile_with_sRGB(png_co
          break;
 # endif
          }
       }
    }
 
    return 0; /* no match */
 }
-#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
 
 void /* PRIVATE */
 png_icc_set_sRGB(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
+    png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
 {
    /* Is this profile one of the known ICC sRGB profiles?  If it is, just set
     * the sRGB information.
     */
-#if PNG_sRGB_PROFILE_CHECKS >= 0
    if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
-#endif
       (void)png_colorspace_set_sRGB(png_ptr, colorspace,
          (int)/*already checked*/png_get_uint_32(profile+64));
 }
+#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
 #endif /* sRGB */
 
 int /* PRIVATE */
 png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
-   int color_type)
+    png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
+    int color_type)
 {
    if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
       return 0;
 
    if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
        png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
-          color_type) != 0 &&
+           color_type) != 0 &&
        png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
-          profile) != 0)
+           profile) != 0)
    {
-#     ifdef PNG_sRGB_SUPPORTED
+#     if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
          /* If no sRGB support, don't try storing sRGB information */
          png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
 #     endif
       return 1;
    }
 
    /* Failure case */
    return 0;
@@ -2443,17 +2441,17 @@ png_colorspace_set_rgb_coefficients(png_
                r += add;
             else
                b += add;
          }
 
          /* Check for an internal error. */
          if (r+g+b != 32768)
             png_error(png_ptr,
-               "internal error handling cHRM coefficients");
+                "internal error handling cHRM coefficients");
 
          else
          {
             png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
             png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
          }
       }
 
@@ -2469,27 +2467,27 @@ png_colorspace_set_rgb_coefficients(png_
 
 #endif /* COLORSPACE */
 
 #ifdef __GNUC__
 /* This exists solely to work round a warning from GNU C. */
 static int /* PRIVATE */
 png_gt(size_t a, size_t b)
 {
-    return a > b;
+   return a > b;
 }
 #else
 #   define png_gt(a,b) ((a) > (b))
 #endif
 
 void /* PRIVATE */
 png_check_IHDR(png_const_structrp png_ptr,
-   png_uint_32 width, png_uint_32 height, int bit_depth,
-   int color_type, int interlace_type, int compression_type,
-   int filter_type)
+    png_uint_32 width, png_uint_32 height, int bit_depth,
+    int color_type, int interlace_type, int compression_type,
+    int filter_type)
 {
    int error = 0;
 
    /* Check for width and height valid values */
    if (width == 0)
    {
       png_warning(png_ptr, "Image width is zero in IHDR");
       error = 1;
@@ -2642,17 +2640,17 @@ png_check_IHDR(png_const_structrp png_pt
  * comments in pngpriv.h
  */
 /* The following is used internally to preserve the sticky flags */
 #define png_fp_add(state, flags) ((state) |= (flags))
 #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
 
 int /* PRIVATE */
 png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
-   png_size_tp whereami)
+    png_size_tp whereami)
 {
    int state = *statep;
    png_size_t i = *whereami;
 
    while (i < size)
    {
       int type;
       /* First find the type of the next character */
@@ -3805,35 +3803,35 @@ png_gamma_8bit_correct(unsigned int valu
 }
 
 #ifdef PNG_16BIT_SUPPORTED
 png_uint_16
 png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
 {
    if (value > 0 && value < 65535)
    {
-#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-         /* The same (unsigned int)->(double) constraints apply here as above,
-          * however in this case the (unsigned int) to (int) conversion can
-          * overflow on an ANSI-C90 compliant system so the cast needs to ensure
-          * that this is not possible.
-          */
-         double r = floor(65535*pow((png_int_32)value/65535.,
-                     gamma_val*.00001)+.5);
-         return (png_uint_16)r;
-#     else
-         png_int_32 lg2 = png_log16bit(value);
-         png_fixed_point res;
-
-         if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
-            return png_exp16bit(res);
-
-         /* Overflow. */
-         value = 0;
-#     endif
+# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+      /* The same (unsigned int)->(double) constraints apply here as above,
+       * however in this case the (unsigned int) to (int) conversion can
+       * overflow on an ANSI-C90 compliant system so the cast needs to ensure
+       * that this is not possible.
+       */
+      double r = floor(65535*pow((png_int_32)value/65535.,
+          gamma_val*.00001)+.5);
+      return (png_uint_16)r;
+# else
+      png_int_32 lg2 = png_log16bit(value);
+      png_fixed_point res;
+
+      if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
+         return png_exp16bit(res);
+
+      /* Overflow. */
+      value = 0;
+# endif
    }
 
    return (png_uint_16)value;
 }
 #endif /* 16BIT */
 
 /* This does the right thing based on the bit_depth field of the
  * png_struct, interpreting values as 8-bit or 16-bit.  While the result
@@ -3862,17 +3860,17 @@ png_gamma_correct(png_structrp png_ptr, 
  * to shift the input values right (or 16-number_of_signifiant_bits).
  *
  * The caller is responsible for ensuring that the table gets cleaned up on
  * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
  * should be somewhere that will be cleaned.
  */
 static void
 png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
-   PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+    PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
 {
    /* Various values derived from 'shift': */
    PNG_CONST unsigned int num = 1U << (8U - shift);
 #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
    /* CSE the division and work round wacky GCC warnings (see the comments
     * in png_gamma_8bit_correct for where these come from.)
     */
    PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
@@ -3939,17 +3937,17 @@ png_build_16bit_table(png_structrp png_p
    }
 }
 
 /* NOTE: this function expects the *inverse* of the overall gamma transformation
  * required.
  */
 static void
 png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
-   PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+    PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
 {
    PNG_CONST unsigned int num = 1U << (8U - shift);
    PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
    unsigned int i;
    png_uint_32 last;
 
    png_uint_16pp table = *ptable =
        (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
@@ -4007,17 +4005,17 @@ png_build_16to8_table(png_structrp png_p
 #endif /* 16BIT */
 
 /* Build a single 8-bit table: same as the 16-bit case but much simpler (and
  * typically much faster).  Note that libpng currently does no sBIT processing
  * (apparently contrary to the spec) so a 256-entry table is always generated.
  */
 static void
 png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
-   PNG_CONST png_fixed_point gamma_val)
+    PNG_CONST png_fixed_point gamma_val)
 {
    unsigned int i;
    png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
 
    if (png_gamma_significant(gamma_val) != 0)
       for (i=0; i<256; i++)
          table[i] = png_gamma_8bit_correct(i, gamma_val);
 
@@ -4087,141 +4085,143 @@ png_destroy_gamma_table(png_structrp png
 /* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
  * tables, we don't make a full table if we are reducing to 8-bit in
  * the future.  Note also how the gamma_16 tables are segmented so that
  * we don't need to allocate > 64K chunks for a full 16-bit table.
  */
 void /* PRIVATE */
 png_build_gamma_table(png_structrp png_ptr, int bit_depth)
 {
-  png_debug(1, "in png_build_gamma_table");
-
-  /* Remove any existing table; this copes with multiple calls to
-   * png_read_update_info.  The warning is because building the gamma tables
-   * multiple times is a performance hit - it's harmless but the ability to call
-   * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
-   * to warn if the app introduces such a hit.
-   */
-  if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
-  {
-    png_warning(png_ptr, "gamma table being rebuilt");
-    png_destroy_gamma_table(png_ptr);
-  }
-
-  if (bit_depth <= 8)
-  {
-     png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
-         png_ptr->screen_gamma > 0 ?  png_reciprocal2(png_ptr->colorspace.gamma,
-         png_ptr->screen_gamma) : PNG_FP_1);
+   png_debug(1, "in png_build_gamma_table");
+
+   /* Remove any existing table; this copes with multiple calls to
+    * png_read_update_info. The warning is because building the gamma tables
+    * multiple times is a performance hit - it's harmless but the ability to
+    * call png_read_update_info() multiple times is new in 1.5.6 so it seems
+    * sensible to warn if the app introduces such a hit.
+    */
+   if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
+   {
+      png_warning(png_ptr, "gamma table being rebuilt");
+      png_destroy_gamma_table(png_ptr);
+   }
+
+   if (bit_depth <= 8)
+   {
+      png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
+          png_ptr->screen_gamma > 0 ?
+          png_reciprocal2(png_ptr->colorspace.gamma,
+          png_ptr->screen_gamma) : PNG_FP_1);
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
    defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-     if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-     {
-        png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
-            png_reciprocal(png_ptr->colorspace.gamma));
-
-        png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
-            png_ptr->screen_gamma > 0 ?  png_reciprocal(png_ptr->screen_gamma) :
-            png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-     }
+      if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+      {
+         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
+             png_reciprocal(png_ptr->colorspace.gamma));
+
+         png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
+             png_ptr->screen_gamma > 0 ?
+             png_reciprocal(png_ptr->screen_gamma) :
+             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+      }
 #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-  }
+   }
 #ifdef PNG_16BIT_SUPPORTED
-  else
-  {
-     png_byte shift, sig_bit;
-
-     if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-     {
-        sig_bit = png_ptr->sig_bit.red;
-
-        if (png_ptr->sig_bit.green > sig_bit)
-           sig_bit = png_ptr->sig_bit.green;
-
-        if (png_ptr->sig_bit.blue > sig_bit)
-           sig_bit = png_ptr->sig_bit.blue;
-     }
-     else
-        sig_bit = png_ptr->sig_bit.gray;
-
-     /* 16-bit gamma code uses this equation:
-      *
-      *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
-      *
-      * Where 'iv' is the input color value and 'ov' is the output value -
-      * pow(iv, gamma).
-      *
-      * Thus the gamma table consists of up to 256 256-entry tables.  The table
-      * is selected by the (8-gamma_shift) most significant of the low 8 bits of
-      * the color value then indexed by the upper 8 bits:
-      *
-      *   table[low bits][high 8 bits]
-      *
-      * So the table 'n' corresponds to all those 'iv' of:
-      *
-      *   <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
-      *
-      */
-     if (sig_bit > 0 && sig_bit < 16U)
-        /* shift == insignificant bits */
-        shift = (png_byte)((16U - sig_bit) & 0xff);
-
-     else
-        shift = 0; /* keep all 16 bits */
-
-     if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-     {
-        /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
-         * the significant bits in the *input* when the output will
-         * eventually be 8 bits.  By default it is 11.
-         */
-        if (shift < (16U - PNG_MAX_GAMMA_8))
-           shift = (16U - PNG_MAX_GAMMA_8);
-     }
-
-     if (shift > 8U)
-        shift = 8U; /* Guarantees at least one table! */
-
-     png_ptr->gamma_shift = shift;
-
-     /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
-      * PNG_COMPOSE).  This effectively smashed the background calculation for
-      * 16-bit output because the 8-bit table assumes the result will be reduced
-      * to 8 bits.
-      */
-     if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-         png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
-         png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
-         png_ptr->screen_gamma) : PNG_FP_1);
-
-     else
-         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
-         png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
-         png_ptr->screen_gamma) : PNG_FP_1);
+   else
+   {
+      png_byte shift, sig_bit;
+
+      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+      {
+         sig_bit = png_ptr->sig_bit.red;
+
+         if (png_ptr->sig_bit.green > sig_bit)
+            sig_bit = png_ptr->sig_bit.green;
+
+         if (png_ptr->sig_bit.blue > sig_bit)
+            sig_bit = png_ptr->sig_bit.blue;
+      }
+      else
+         sig_bit = png_ptr->sig_bit.gray;
+
+      /* 16-bit gamma code uses this equation:
+       *
+       *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
+       *
+       * Where 'iv' is the input color value and 'ov' is the output value -
+       * pow(iv, gamma).
+       *
+       * Thus the gamma table consists of up to 256 256-entry tables.  The table
+       * is selected by the (8-gamma_shift) most significant of the low 8 bits
+       * of the color value then indexed by the upper 8 bits:
+       *
+       *   table[low bits][high 8 bits]
+       *
+       * So the table 'n' corresponds to all those 'iv' of:
+       *
+       *   <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
+       *
+       */
+      if (sig_bit > 0 && sig_bit < 16U)
+         /* shift == insignificant bits */
+         shift = (png_byte)((16U - sig_bit) & 0xff);
+
+      else
+         shift = 0; /* keep all 16 bits */
+
+      if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
+      {
+         /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
+          * the significant bits in the *input* when the output will
+          * eventually be 8 bits.  By default it is 11.
+          */
+         if (shift < (16U - PNG_MAX_GAMMA_8))
+            shift = (16U - PNG_MAX_GAMMA_8);
+      }
+
+      if (shift > 8U)
+         shift = 8U; /* Guarantees at least one table! */
+
+      png_ptr->gamma_shift = shift;
+
+      /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
+       * PNG_COMPOSE).  This effectively smashed the background calculation for
+       * 16-bit output because the 8-bit table assumes the result will be
+       * reduced to 8 bits.
+       */
+      if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
+          png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
+          png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
+          png_ptr->screen_gamma) : PNG_FP_1);
+
+      else
+          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
+          png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
+          png_ptr->screen_gamma) : PNG_FP_1);
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
    defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-     if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-     {
-        png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
-            png_reciprocal(png_ptr->colorspace.gamma));
-
-        /* Notice that the '16 from 1' table should be full precision, however
-         * the lookup on this table still uses gamma_shift, so it can't be.
-         * TODO: fix this.
-         */
-        png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
-            png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
-            png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-     }
+      if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+      {
+         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
+             png_reciprocal(png_ptr->colorspace.gamma));
+
+         /* Notice that the '16 from 1' table should be full precision, however
+          * the lookup on this table still uses gamma_shift, so it can't be.
+          * TODO: fix this.
+          */
+         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
+             png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
+             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+      }
 #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-  }
+   }
 #endif /* 16BIT */
 }
 #endif /* READ_GAMMA */
 
 /* HARDWARE OR SOFTWARE OPTION SUPPORT */
 #ifdef PNG_SET_OPTION_SUPPORTED
 int PNGAPI
 png_set_option(png_structrp png_ptr, int option, int onoff)
--- a/media/libpng/png.h
+++ b/media/libpng/png.h
@@ -1,23 +1,23 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.23, June 9, 2016
+ * libpng version 1.6.24, August 4, 2016
  *
  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license (See LICENSE, below)
  *
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.23, June 9, 2016:
+ *   libpng versions 0.97, January 1998, through 1.6.24, August 4, 2016:
  *     Glenn Randers-Pehrson.
  *   See also "Contributing Authors", below.
  */
 
 /*
  * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
  *
  * If you modify libpng you may insert additional notices immediately following
@@ -30,17 +30,17 @@
  * surrounding them in the modified libpng source files.
  *
  * This code is released under the libpng license.
  *
  * Some files in the "contrib" directory and some configure-generated
  * files that are distributed with libpng have other copyright owners and
  * are released under other open source licenses.
  *
- * libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
+ * libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are
  * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
  * derived from libpng-1.0.6, and are distributed according to the same
  * disclaimer and license as libpng-1.0.6 with the following individuals
  * added to the list of Contributing Authors:
  *
  *    Simon-Pierre Cadieux
  *    Eric S. Raymond
  *    Mans Rullgard
@@ -218,17 +218,17 @@
  *    1.0.7                    1    10007  (still compatible)
  *    ...
  *    1.0.19                  10    10019  10.so.0.19[.0]
  *    ...
  *    1.2.56                  13    10256  12.so.0.56[.0]
  *    ...
  *    1.5.27                  15    10527  15.so.15.27[.0]
  *    ...
- *    1.6.23                  16    10623  16.so.16.23[.0]
+ *    1.6.24                  16    10624  16.so.16.24[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
  *    used for changes in backward compatibility, as it is intended.  The
  *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
  *    for applications, is an unsigned integer of the form xyyzz corresponding
  *    to the source version x.y.z (leading zeros in y and z).  Beta versions
  *    were given the previous public release number plus a letter, until
@@ -246,23 +246,23 @@
  * is available as a W3C Recommendation and as an ISO Specification,
  * <http://www.w3.org/TR/2003/REC-PNG-20031110/
  */
 
 /*
  * Y2K compliance in libpng:
  * =========================
  *
- *    June 9, 2016
+ *    August 4, 2016
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.6.23 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.24 are Y2K compliant.  It is my belief that
  *    earlier versions were also Y2K compliant.
  *
  *    Libpng only has two year fields.  One is a 2-byte unsigned integer
  *    that will hold years up to 65535.  The other, which is deprecated,
  *    holds the date in text format, and will hold years up to 9999.
  *
  *    The integer is
  *        "png_uint_16 year" in png_time_struct.
@@ -314,27 +314,27 @@
  * file has been stripped from your copy of libpng, you can find it at
  * <http://www.libpng.org/pub/png/libpng-manual.txt>
  *
  * If you just need to read a PNG file and don't want to read the documentation
  * skip to the end of this file and read the section entitled 'simplified API'.
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.23+apng"
+#define PNG_LIBPNG_VER_STRING "1.6.24+apng"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.6.23+apng - June 9, 2016\n"
+     " libpng version 1.6.24+apng - August 4, 2016\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
 
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 23
+#define PNG_LIBPNG_VER_RELEASE 24
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
 
 #define PNG_LIBPNG_VER_BUILD  0
 
 /* Release Status */
@@ -355,34 +355,34 @@
 #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10623 /* 1.6.23 */
+#define PNG_LIBPNG_VER 10624 /* 1.6.24 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
  */
 #ifndef PNGLCONF_H
-    /* If pnglibconf.h is missing, you can
-     * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
-     */
+/* If pnglibconf.h is missing, you can
+ * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
+ */
 #   include "pnglibconf.h"
 #endif
 
 #define PNG_APNG_SUPPORTED
 #define PNG_READ_APNG_SUPPORTED
 #define PNG_WRITE_APNG_SUPPORTED
 
 #ifndef PNG_VERSION_INFO_ONLY
-   /* Machine specific configuration. */
+/* Machine specific configuration. */
 #  include "pngconf.h"
 #endif
 
 /*
  * Added at libpng-1.2.8
  *
  * Ref MSDN: Private as priority over Special
  * VS_FF_PRIVATEBUILD File *was not* built using standard release
@@ -480,17 +480,17 @@ extern "C" {
 /* blend_op flags from inside fcTL */
 #define PNG_BLEND_OP_SOURCE        0x00
 #define PNG_BLEND_OP_OVER          0x01
 #endif /* APNG */
 
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_23;
+typedef char* png_libpng_version_1_6_24;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
  * png_struct is the cache of information used while reading or writing a single
  * PNG file.  One of these is always required, although the simplified API
  * (below) hides the creation and destruction of it.
  */
 typedef struct png_struct_def png_struct;
@@ -673,27 +673,27 @@ typedef png_time * * png_timepp;
  * no specific support.  The idea is that we can use this to queue
  * up private chunks for output even though the library doesn't actually
  * know about their semantics.
  *
  * The data in the structure is set by libpng on read and used on write.
  */
 typedef struct png_unknown_chunk_t
 {
-    png_byte name[5]; /* Textual chunk name with '\0' terminator */
-    png_byte *data;   /* Data, should not be modified on read! */
-    png_size_t size;
-
-    /* On write 'location' must be set using the flag values listed below.
-     * Notice that on read it is set by libpng however the values stored have
-     * more bits set than are listed below.  Always treat the value as a
-     * bitmask.  On write set only one bit - setting multiple bits may cause the
-     * chunk to be written in multiple places.
-     */
-    png_byte location; /* mode of operation at read time */
+   png_byte name[5]; /* Textual chunk name with '\0' terminator */
+   png_byte *data;   /* Data, should not be modified on read! */
+   png_size_t size;
+
+   /* On write 'location' must be set using the flag values listed below.
+    * Notice that on read it is set by libpng however the values stored have
+    * more bits set than are listed below.  Always treat the value as a
+    * bitmask.  On write set only one bit - setting multiple bits may cause the
+    * chunk to be written in multiple places.
+    */
+   png_byte location; /* mode of operation at read time */
 }
 png_unknown_chunk;
 
 typedef png_unknown_chunk * png_unknown_chunkp;
 typedef const png_unknown_chunk * png_const_unknown_chunkp;
 typedef png_unknown_chunk * * png_unknown_chunkpp;
 #endif
 
@@ -798,18 +798,18 @@ typedef png_unknown_chunk * * png_unknow
 #define PNG_INFO_tIME 0x0200U
 #define PNG_INFO_pCAL 0x0400U
 #define PNG_INFO_sRGB 0x0800U  /* GR-P, 0.96a */
 #define PNG_INFO_iCCP 0x1000U  /* ESR, 1.0.6 */
 #define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
 #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
 #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
 #ifdef PNG_APNG_SUPPORTED
-#define PNG_INFO_acTL 0x10000
-#define PNG_INFO_fcTL 0x20000
+#define PNG_INFO_acTL 0x10000U
+#define PNG_INFO_fcTL 0x20000U
 #endif
 
 /* This is used for the transformation routines, as some of them
  * change these values for the row.  It also should enable using
  * the routines for other purposes.
  */
 typedef struct png_row_info_struct
 {
@@ -2324,26 +2324,28 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (p
  *    If num_chunks is 0 the "keep" parameter specifies the default behavior for
  *    unknown chunks, as described above.
  *
  *    If num_chunks is negative, then the "keep" parameter specifies the manner
  *    for handling all unknown chunks plus all chunks recognized by libpng
  *    except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
  *    be processed by libpng.
  */
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
     int keep, png_const_bytep chunk_list, int num_chunks));
+#endif /* HANDLE_AS_UNKNOWN */
 
 /* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned;
  * the result is therefore true (non-zero) if special handling is required,
  * false for the default handling.
  */
 PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
     png_const_bytep chunk_name));
-#endif
+#endif /* SET_UNKNOWN_CHUNKS */
 
 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
 PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
     png_inforp info_ptr, png_const_unknown_chunkp unknowns,
     int num_unknowns));
    /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added
     * unknowns to the location currently stored in the png_struct.  This is
     * invariably the wrong value on write.  To fix this call the following API
@@ -2554,43 +2556,47 @@ PNG_EXPORT(216, png_uint_32, png_get_io_
  * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
  * standard method.
  *
  * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
  */
 
  /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
 
-#  define png_composite(composite, fg, alpha, bg)         \
-     { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \
-           * (png_uint_16)(alpha)                         \
-           + (png_uint_16)(bg)*(png_uint_16)(255          \
-           - (png_uint_16)(alpha)) + 128);                \
-       (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); }
-
-#  define png_composite_16(composite, fg, alpha, bg)       \
-     { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg)  \
-           * (png_uint_32)(alpha)                          \
-           + (png_uint_32)(bg)*(65535                      \
-           - (png_uint_32)(alpha)) + 32768);               \
-       (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); }
+#  define png_composite(composite, fg, alpha, bg)        \
+   {                                                     \
+      png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \
+          * (png_uint_16)(alpha)                         \
+          + (png_uint_16)(bg)*(png_uint_16)(255          \
+          - (png_uint_16)(alpha)) + 128);                \
+      (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \
+   }
+
+#  define png_composite_16(composite, fg, alpha, bg)     \
+   {                                                     \
+      png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
+          * (png_uint_32)(alpha)                         \
+          + (png_uint_32)(bg)*(65535                     \
+          - (png_uint_32)(alpha)) + 32768);              \
+      (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \
+   }
 
 #else  /* Standard method using integer division */
 
-#  define png_composite(composite, fg, alpha, bg)                        \
-     (composite) =                                                       \
-         (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) +  \
-         (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
-         127) / 255))
-
-#  define png_composite_16(composite, fg, alpha, bg)                         \
-     (composite) =                                                           \
-         (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \
-         (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) +     \
-         32767) / 65535))
+#  define png_composite(composite, fg, alpha, bg)                      \
+   (composite) =                                                       \
+       (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) +  \
+       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
+       127) / 255))
+
+#  define png_composite_16(composite, fg, alpha, bg)                       \
+   (composite) =                                                           \
+       (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+       (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) +     \
+       32767) / 65535))
 #endif /* READ_COMPOSITE_NODIV */
 
 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
 PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf));
 PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf));
 PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf));
 #endif
 
@@ -2616,48 +2622,48 @@ PNG_EXPORT(207, void, png_save_uint_16, 
 #endif
 
 #ifdef PNG_USE_READ_MACROS
 /* Inline macros to do direct reads of bytes from the input buffer.
  * The png_get_int_32() routine assumes we are using two's complement
  * format for negative values, which is almost certainly true.
  */
 #  define PNG_get_uint_32(buf) \
-     (((png_uint_32)(*(buf)) << 24) + \
-      ((png_uint_32)(*((buf) + 1)) << 16) + \
-      ((png_uint_32)(*((buf) + 2)) << 8) + \
-      ((png_uint_32)(*((buf) + 3))))
+   (((png_uint_32)(*(buf)) << 24) + \
+    ((png_uint_32)(*((buf) + 1)) << 16) + \
+    ((png_uint_32)(*((buf) + 2)) << 8) + \
+    ((png_uint_32)(*((buf) + 3))))
 
    /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
     * function) incorrectly returned a value of type png_uint_32.
     */
 #  define PNG_get_uint_16(buf) \
-     ((png_uint_16) \
-      (((unsigned int)(*(buf)) << 8) + \
-       ((unsigned int)(*((buf) + 1)))))
+   ((png_uint_16) \
+    (((unsigned int)(*(buf)) << 8) + \
+    ((unsigned int)(*((buf) + 1)))))
 
 #  define PNG_get_int_32(buf) \
-     ((png_int_32)((*(buf) & 0x80) \
-      ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
-      : (png_int_32)png_get_uint_32(buf)))
-
-   /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
-    * but defining a macro name prefixed with PNG_PREFIX.
-    */
+   ((png_int_32)((*(buf) & 0x80) \
+    ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
+    : (png_int_32)png_get_uint_32(buf)))
+
+/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
+ * but defining a macro name prefixed with PNG_PREFIX.
+ */
 #  ifndef PNG_PREFIX
-#     define png_get_uint_32(buf) PNG_get_uint_32(buf)
-#     define png_get_uint_16(buf) PNG_get_uint_16(buf)
-#     define png_get_int_32(buf)  PNG_get_int_32(buf)
+#    define png_get_uint_32(buf) PNG_get_uint_32(buf)
+#    define png_get_uint_16(buf) PNG_get_uint_16(buf)
+#    define png_get_int_32(buf)  PNG_get_int_32(buf)
 #  endif
 #else
 #  ifdef PNG_PREFIX
-      /* No macros; revert to the (redefined) function */
-#     define PNG_get_uint_32 (png_get_uint_32)
-#     define PNG_get_uint_16 (png_get_uint_16)
-#     define PNG_get_int_32  (png_get_int_32)
+   /* No macros; revert to the (redefined) function */
+#    define PNG_get_uint_32 (png_get_uint_32)
+#    define PNG_get_uint_16 (png_get_uint_16)
+#    define PNG_get_int_32  (png_get_int_32)
 #  endif
 #endif
 
 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
 PNG_EXPORT(242, void, png_set_check_for_invalid_index,
     (png_structrp png_ptr, int allowed));
 #  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
 PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
@@ -3195,19 +3201,19 @@ PNG_EXPORT(245, int, png_image_write_to_
 
 #define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
    PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
    /* An upper bound on the size of the data in the PNG IDAT chunks. */
 
 #define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
    ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
     (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
-     12U+3U*(image).colormap_entries/*PLTE data*/+\
-     (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
-      12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
+    12U+3U*(image).colormap_entries/*PLTE data*/+\
+    (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
+    12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
     12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
    /* A helper for the following macro; if your compiler cannot handle the
     * following macro use this one with the result of
     * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
     * compilers should handle this just fine.)
     */
 
 #define PNG_IMAGE_PNG_SIZE_MAX(image)\
@@ -3262,80 +3268,80 @@ PNG_EXPORT(244, int, png_set_option, (pn
    int onoff));
 #endif /* SET_OPTION */
 
 /*******************************************************************************
  *  END OF HARDWARE AND SOFTWARE OPTIONS
  ******************************************************************************/
 
 #ifdef PNG_APNG_SUPPORTED
-PNG_EXPORT(245, png_uint_32, png_get_acTL, (png_structp png_ptr,
+PNG_EXPORT(246, png_uint_32, png_get_acTL, (png_structp png_ptr,
    png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
 
-PNG_EXPORT(246, png_uint_32, png_set_acTL, (png_structp png_ptr,
+PNG_EXPORT(247, png_uint_32, png_set_acTL, (png_structp png_ptr,
    png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
 
-PNG_EXPORT(247, png_uint_32, png_get_num_frames, (png_structp png_ptr,
+PNG_EXPORT(248, png_uint_32, png_get_num_frames, (png_structp png_ptr,
    png_infop info_ptr));
 
-PNG_EXPORT(248, png_uint_32, png_get_num_plays, (png_structp png_ptr,
+PNG_EXPORT(249, png_uint_32, png_get_num_plays, (png_structp png_ptr,
    png_infop info_ptr));
 
-PNG_EXPORT(249, png_uint_32, png_get_next_frame_fcTL,
+PNG_EXPORT(250, png_uint_32, png_get_next_frame_fcTL,
    (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
    png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
    png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
    png_byte *blend_op));
 
-PNG_EXPORT(250, png_uint_32, png_set_next_frame_fcTL,
+PNG_EXPORT(251, png_uint_32, png_set_next_frame_fcTL,
    (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
    png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
    png_byte blend_op));
 
-PNG_EXPORT(251, png_uint_32, png_get_next_frame_width,
+PNG_EXPORT(252, png_uint_32, png_get_next_frame_width,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(252, png_uint_32, png_get_next_frame_height,
+PNG_EXPORT(253, png_uint_32, png_get_next_frame_height,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(253, png_uint_32, png_get_next_frame_x_offset,
+PNG_EXPORT(254, png_uint_32, png_get_next_frame_x_offset,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(254, png_uint_32, png_get_next_frame_y_offset,
+PNG_EXPORT(255, png_uint_32, png_get_next_frame_y_offset,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(255, png_uint_16, png_get_next_frame_delay_num,
+PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_num,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_den,
+PNG_EXPORT(257, png_uint_16, png_get_next_frame_delay_den,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(257, png_byte, png_get_next_frame_dispose_op,
+PNG_EXPORT(258, png_byte, png_get_next_frame_dispose_op,
    (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(258, png_byte, png_get_next_frame_blend_op,</