Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 01 Aug 2017 13:17:21 -0700
changeset 423326 a3e675a3b10a0ea289c301bedc31866f3daf7875
parent 423301 65d1f1440a9fd3006e2c94a811986d3df84b257d (current diff)
parent 423325 13750b02d0219aec45da8bbe24aaa235593d5696 (diff)
child 423341 555fc75ee236bbad1c6fb87334e278f99dbd36c3
child 424237 3914cf7ba9a4d229b095c1a404c3981922e232cb
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to central, a=merge MozReview-Commit-ID: 6SriUFkS6u7
browser/components/sessionstore/FrameTree.jsm
new file mode 100644
--- /dev/null
+++ b/docshell/test/file_bug675587.html
@@ -0,0 +1,1 @@
+<script>location.hash='';</script>
--- a/docshell/test/mochitest.ini
+++ b/docshell/test/mochitest.ini
@@ -84,16 +84,17 @@ skip-if = toolkit == 'android'
 [test_bug653741.html]
 [test_bug660404.html]
 [test_bug662170.html]
 [test_bug668513.html]
 skip-if = toolkit == 'android'
 support-files = file_bug668513.html
 [test_bug669671.html]
 [test_bug675587.html]
+support-files = file_bug675587.html
 [test_bug680257.html]
 [test_bug691547.html]
 [test_bug694612.html]
 [test_bug703855.html]
 [test_bug713825.html]
 [test_bug728939.html]
 [test_bug797909.html]
 [test_bug1045096.html]
--- a/docshell/test/navigation/file_fragment_handling_during_load.html
+++ b/docshell/test/navigation/file_fragment_handling_during_load.html
@@ -1,24 +1,25 @@
 <html>
   <head>
     <script>
       var timerID = 0;
       function testDone() {
         clearTimeout(timerID);
         var l = document.body.firstChild.contentWindow.location.href;
-        opener.is(l, "data:text/html,bar", "Should have loaded a new document");
+        opener.ok(l.endsWith("file_fragment_handling_during_load_frame2.html"),
+                 "Should have loaded a new document");
         opener.nextTest();
         window.close();
       }
       function test() {
         var ifr = document.getElementsByTagName("iframe")[0];
         ifr.onload = testDone;
         ifr.contentWindow.location.hash = "b";
-        ifr.contentWindow.location.href = "data:text/html,bar";
+        ifr.contentWindow.location.href = "file_fragment_handling_during_load_frame2.html";
         history.back();
         timerID = setTimeout(testDone, 2000);
       }
     </script>
   </head>
-  <body onload="setTimeout(test, 0)"><iframe src="data:text/html,foo#a"></iframe>
+  <body onload="setTimeout(test, 0)"><iframe src="file_fragment_handling_during_load_frame1.html#a"></iframe>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/file_fragment_handling_during_load_frame1.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+foo
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/file_fragment_handling_during_load_frame2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+bar
+</body>
+</html>
--- a/docshell/test/navigation/file_nested_frames.html
+++ b/docshell/test/navigation/file_nested_frames.html
@@ -16,13 +16,13 @@
         d.close();
         opener.is(window.history.length, 1, "Unexpected history length");
         opener.nextTest();
         window.close();
       }
     </script>
   </head>
   <body>
-  <iframe id="testframe" src="data:text/html,<iframe onload='parent.nestedIframeLoaded();'></iframe>" onload="frameLoaded()"></iframe>
+  <iframe id="testframe" src="file_nested_frames_innerframe.html" onload="frameLoaded()"></iframe>
   <script>
   </script>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/navigation/file_nested_frames_innerframe.html
@@ -0,0 +1,1 @@
+<iframe onload='parent.nestedIframeLoaded();'></iframe>
--- a/docshell/test/navigation/file_scrollRestoration.html
+++ b/docshell/test/navigation/file_scrollRestoration.html
@@ -34,34 +34,34 @@
             break;
           }
           case 3: {
             opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
             opener.is(window.scrollY, 0, "Should not have restored scrolling.");
             opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
             document.getElementById("bottom").scrollIntoView();
             window.onunload = null; // Should get bfcache behavior.
-            opener.setTimeout("testWindow.history.back();", 250);
+            opener.setTimeout("SpecialPowers.wrap(testWindow).history.back();", 250);
             window.location.href = 'data:text/html,';
             break;
           }
           case 4: {
             opener.is(event.persisted, true, "Should have persisted session history entry.");
             opener.isnot(Math.round(window.scrollY), 0, "Should have kept the old scroll position.");
             opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
             window.scrollTo(0, 0);
             window.location.hash = "hash";
             requestAnimationFrame(test);
             break;
           }
           case 5: {
             opener.isnot(Math.round(window.scrollY), 0, "Should have scrolled to #hash.");
             opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
             window.onunload = function() {} // Disable bfcache.
-            opener.setTimeout("is(testWindow.history.scrollRestoration, 'auto'); testWindow.history.back();", 250);
+            opener.setTimeout("is(SpecialPowers.wrap(testWindow).history.scrollRestoration, 'auto'); SpecialPowers.wrap(testWindow).history.back();", 250);
             window.location.href = 'data:text/html,';
             break;
           }
           case 6: {
             opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
             opener.is(window.scrollY, 0, "Shouldn't have kept the old scroll position.");
             opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
             history.scrollRestoration = "auto";
@@ -93,17 +93,17 @@
 
             var ifr = document.createElement("iframe");
             ifr.src = "data:text/html,";
             document.body.appendChild(ifr);
             ifr.onload = test;
             break;
           }
           case 7: {
-            oldHistoryObject = event.target.contentWindow.history;
+            oldHistoryObject = SpecialPowers.wrap(event.target).contentWindow.history;
             event.target.src = "about:blank";
             break;
           }
           case 8: {
             try {
               var sr = oldHistoryObject.scrollRestoration;
               opener.ok(false, "Should have thrown an exception.");
             } catch(ex) {
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -8,17 +8,20 @@ support-files =
   bluebox_bug430723.html
   file_bug462076_1.html
   file_bug462076_2.html
   file_bug462076_3.html
   file_bug508537_1.html
   file_bug534178.html
   file_document_write_1.html
   file_fragment_handling_during_load.html
+  file_fragment_handling_during_load_frame1.html
+  file_fragment_handling_during_load_frame2.html
   file_nested_frames.html
+  file_nested_frames_innerframe.html
   file_scrollRestoration.html
   file_shiftReload_and_pushState.html
   file_static_and_dynamic_1.html
   frame0.html
   frame1.html
   frame2.html
   frame3.html
   goback.html
--- a/docshell/test/test_bug675587.html
+++ b/docshell/test/test_bug675587.html
@@ -6,29 +6,28 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>Test for Bug 675587</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <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=675587">Mozilla Bug 675587</a>
 <p id="display">
-  <iframe src="data:text/html,<script>location.hash='';</script>#hash"></iframe>
+  <iframe src="file_bug675587.html#hash"></iframe>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 675587 **/
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
-  is(window.frames[0].location.href,
-     "data:text/html,<script>location.hash='';</" + "script>#",
+  ok(window.frames[0].location.href.endsWith("file_bug675587.html#"),
      "Should have the right href");
   SimpleTest.finish();
 });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -193,17 +193,17 @@ public:
   }
 
 private:
   TypedArray_base(const TypedArray_base&) = delete;
 };
 
 template<typename T,
          JSObject* UnwrapArray(JSObject*),
-         T* GetData(JSObject*, bool* isShared, const JS::AutoRequireNoGC&),
+         T* GetData(JSObject*, bool* isShared, const JS::AutoCheckCannotGC&),
          void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**),
          JSObject* CreateNew(JSContext*, uint32_t)>
 struct TypedArray
   : public TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness>
 {
 private:
   typedef TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness> Base;
 
--- a/dom/tests/mochitest/chrome/chrome.ini
+++ b/dom/tests/mochitest/chrome/chrome.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 skip-if = os == 'android'
 support-files =
   489127.html
   DOMWindowCreated_chrome.xul
   DOMWindowCreated_content.html
   MozDomFullscreen_chrome.xul
   child_focus_frame.html
+  file_clipboard_events_chrome.html
   file_DOM_element_instanceof.xul
   file_MozDomFullscreen.html
   file_bug799299.xul
   file_bug800817.xul
   file_bug830858.xul
   file_bug1224790-1_modal.xul
   file_bug1224790-1_nonmodal.xul
   file_bug1224790-2_modal.xul
@@ -23,16 +24,17 @@ support-files =
   queryCaretRectWin.html
   selectAtPoint.html
   selectAtPoint-innerframe.html
   sizemode_attribute.xul
   window_activation.xul
   window_callback_wrapping.xul
   window_docshell_swap.xul
   window_focus.xul
+  window_focus_inner.xul
   window_focus_docnav.xul
   !/dom/tests/mochitest/general/file_clonewrapper.html
   !/dom/tests/mochitest/general/file_moving_nodeList.html
   !/dom/tests/mochitest/general/file_moving_xhr.html
   !/dom/tests/mochitest/geolocation/network_geolocation.sjs
 
 [test_DOMWindowCreated.xul]
 [test_DOM_element_instanceof.xul]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_clipboard_events_chrome.html
@@ -0,0 +1,1 @@
+<body onload='window.opener.doChecks(this)'><input id='i' value='Sample Text'></body>
--- a/dom/tests/mochitest/chrome/test_clipboard_events_chrome.html
+++ b/dom/tests/mochitest/chrome/test_clipboard_events_chrome.html
@@ -8,18 +8,17 @@
 
 <script>
 // This test checks that the dom.event.clipboardevents.enabled does not apply to chrome shells.
 
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
   SpecialPowers.pushPrefEnv({"set": [['dom.event.clipboardevents.enabled', false]]}, function() {
-    window.open("data:text/html,<body onload='window.opener.doChecks(this)'><input id='i' value='Sample Text'></body>",
-                "_blank", "chrome,width=200,height=200");
+    window.open("file_clipboard_events_chrome.html", "_blank", "chrome,width=200,height=200");
   });
 }
 
 var event_fired = false;
 
 function doChecks(win)
 {
   var windowFocused = function() {
--- a/dom/tests/mochitest/chrome/window_focus.xul
+++ b/dom/tests/mochitest/chrome/window_focus.xul
@@ -1374,25 +1374,18 @@ function switchWindowTest(otherWindow, f
   otherTextbox.addEventListener("focus", textboxFocused, true);
   otherTextbox.focus();
 }
 
 // open a window with no root element
 var noRootWindow = null;
 function doWindowNoRootTest()
 {
-  var data = "data:application/vnd.mozilla.xul+xml," + unescape(
-             "<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
-             "        style='-moz-user-focus: normal;'>" +
-             "<script>function dostuff() { setTimeout(function() { " +
-             "document.documentElement.focus(); document.removeChild(document.documentElement);" +
-             "window.opener.focus(); }, 100); }</script></window>");
-
   addEventListener("focus", doFrameSwitchingTests, true);
-  noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100");
+  noRootWindow = window.open("window_focus_inner.xul", "_blank", "chrome,width=100,height=100");
 }
 
 // these tests check when focus is moved between a tree of frames to ensure
 // that the focus is in the right place at each event step.
 function doFrameSwitchingTests()
 {
   removeEventListener("focus", doFrameSwitchingTests, true);
   noRootWindow.close();
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_focus_inner.xul
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' style='-moz-user-focus: normal;'>
+<script>
+  function dostuff() {
+    setTimeout(function() {
+      document.documentElement.focus();
+      document.removeChild(document.documentElement);
+      window.opener.focus();
+     }, 100);
+    }
+</script>
+</window>
--- a/image/ImageFactory.cpp
+++ b/image/ImageFactory.cpp
@@ -119,32 +119,57 @@ ImageFactory::CreateImage(nsIRequest* aR
 template <typename T>
 static already_AddRefed<Image>
 BadImage(const char* aMessage, RefPtr<T>& aImage)
 {
   aImage->SetHasError();
   return aImage.forget();
 }
 
+static void
+SetSourceSizeHint(RasterImage* aImage, uint32_t aSize)
+{
+  // Pass anything usable on so that the RasterImage can preallocate
+  // its source buffer.
+  if (aSize == 0) {
+    return;
+  }
+
+  // Bound by something reasonable
+  uint32_t sizeHint = std::min<uint32_t>(aSize, 20000000);
+  nsresult rv = aImage->SetSourceSizeHint(sizeHint);
+  if (NS_FAILED(rv)) {
+    // Flush memory, try to get some back, and try again.
+    rv = nsMemory::HeapMinimize(true);
+    nsresult rv2 = aImage->SetSourceSizeHint(sizeHint);
+    // If we've still failed at this point, things are going downhill.
+    if (NS_FAILED(rv) || NS_FAILED(rv2)) {
+      NS_WARNING("About to hit OOM in imagelib!");
+    }
+  }
+}
+
 /* static */ already_AddRefed<Image>
-ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
+ImageFactory::CreateAnonymousImage(const nsCString& aMimeType,
+                                   uint32_t aSizeHint /* = 0 */)
 {
   nsresult rv;
 
   RefPtr<RasterImage> newImage = new RasterImage();
 
   RefPtr<ProgressTracker> newTracker = new ProgressTracker();
   newTracker->SetImage(newImage);
   newImage->SetProgressTracker(newTracker);
 
   rv = newImage->Init(aMimeType.get(), Image::INIT_FLAG_SYNC_LOAD);
   if (NS_FAILED(rv)) {
     return BadImage("RasterImage::Init failed", newImage);
   }
 
+  SetSourceSizeHint(newImage, aSizeHint);
   return newImage.forget();
 }
 
 /* static */ already_AddRefed<MultipartImage>
 ImageFactory::CreateMultipartImage(Image* aFirstPart,
                                    ProgressTracker* aProgressTracker)
 {
   MOZ_ASSERT(aFirstPart);
@@ -220,35 +245,17 @@ ImageFactory::CreateRasterImage(nsIReque
 
   rv = newImage->Init(aMimeType.get(), aImageFlags);
   if (NS_FAILED(rv)) {
     return BadImage("RasterImage::Init failed", newImage);
   }
 
   newImage->SetInnerWindowID(aInnerWindowId);
 
-  uint32_t len = GetContentSize(aRequest);
-
-  // Pass anything usable on so that the RasterImage can preallocate
-  // its source buffer.
-  if (len > 0) {
-    // Bound by something reasonable
-    uint32_t sizeHint = std::min<uint32_t>(len, 20000000);
-    rv = newImage->SetSourceSizeHint(sizeHint);
-    if (NS_FAILED(rv)) {
-      // Flush memory, try to get some back, and try again.
-      rv = nsMemory::HeapMinimize(true);
-      nsresult rv2 = newImage->SetSourceSizeHint(sizeHint);
-      // If we've still failed at this point, things are going downhill.
-      if (NS_FAILED(rv) || NS_FAILED(rv2)) {
-        NS_WARNING("About to hit OOM in imagelib!");
-      }
-    }
-  }
-
+  SetSourceSizeHint(newImage, GetContentSize(aRequest));
   return newImage.forget();
 }
 
 /* static */ already_AddRefed<Image>
 ImageFactory::CreateVectorImage(nsIRequest* aRequest,
                                 ProgressTracker* aProgressTracker,
                                 const nsCString& aMimeType,
                                 ImageURL* aURI,
--- a/image/ImageFactory.h
+++ b/image/ImageFactory.h
@@ -46,19 +46,20 @@ public:
                                              ImageURL* aURI,
                                              bool aIsMultiPart,
                                              uint32_t aInnerWindowId);
   /**
    * Creates a new image which isn't associated with a URI or loaded through
    * the usual image loading mechanism.
    *
    * @param aMimeType      The mimetype of the image.
+   * @param aSizeHint      The length of the source data for the image.
    */
   static already_AddRefed<Image>
-  CreateAnonymousImage(const nsCString& aMimeType);
+  CreateAnonymousImage(const nsCString& aMimeType, uint32_t aSizeHint = 0);
 
   /**
    * Creates a new multipart/x-mixed-replace image wrapper, and initializes it
    * with the first part. Subsequent parts should be passed to the existing
    * MultipartImage via MultipartImage::BeginTransitionToPart().
    *
    * @param aFirstPart       An image containing the first part of the multipart
    *                         stream.
--- a/image/SourceBuffer.cpp
+++ b/image/SourceBuffer.cpp
@@ -219,40 +219,37 @@ SourceBuffer::Compact()
 
   // If our total length is zero (which means ExpectLength() got called, but no
   // data ever actually got written) then just empty our chunk list.
   if (MOZ_UNLIKELY(length == 0)) {
     mChunks.Clear();
     return NS_OK;
   }
 
-  Maybe<Chunk> newChunk = CreateChunk(length, /* aRoundUp = */ false);
-  if (MOZ_UNLIKELY(!newChunk || newChunk->AllocationFailed())) {
-    NS_WARNING("Failed to allocate chunk for SourceBuffer compacting - OOM?");
+  Chunk& mergeChunk = mChunks[0];
+  if (MOZ_UNLIKELY(!mergeChunk.SetCapacity(length))) {
+    NS_WARNING("Failed to reallocate chunk for SourceBuffer compacting - OOM?");
     return NS_OK;
   }
 
-  // Copy our old chunks into the new chunk.
-  for (uint32_t i = 0 ; i < mChunks.Length() ; ++i) {
-    size_t offset = newChunk->Length();
-    MOZ_ASSERT(offset < newChunk->Capacity());
-    MOZ_ASSERT(offset + mChunks[i].Length() <= newChunk->Capacity());
+  // Copy our old chunks into the newly reallocated first chunk.
+  for (uint32_t i = 1 ; i < mChunks.Length() ; ++i) {
+    size_t offset = mergeChunk.Length();
+    MOZ_ASSERT(offset < mergeChunk.Capacity());
+    MOZ_ASSERT(offset + mChunks[i].Length() <= mergeChunk.Capacity());
 
-    memcpy(newChunk->Data() + offset, mChunks[i].Data(), mChunks[i].Length());
-    newChunk->AddLength(mChunks[i].Length());
+    memcpy(mergeChunk.Data() + offset, mChunks[i].Data(), mChunks[i].Length());
+    mergeChunk.AddLength(mChunks[i].Length());
   }
 
-  MOZ_ASSERT(newChunk->Length() == newChunk->Capacity(),
+  MOZ_ASSERT(mergeChunk.Length() == mergeChunk.Capacity(),
              "Compacted chunk has slack space");
 
-  // Replace the old chunks with the new, compact chunk.
-  mChunks.Clear();
-  if (MOZ_UNLIKELY(NS_FAILED(AppendChunk(Move(newChunk))))) {
-    return HandleError(NS_ERROR_OUT_OF_MEMORY);
-  }
+  // Remove the redundant chunks.
+  mChunks.RemoveElementsAt(1, mChunks.Length() - 1);
   mChunks.Compact();
 
   return NS_OK;
 }
 
 /* static */ size_t
 SourceBuffer::RoundedUpCapacity(size_t aCapacity)
 {
@@ -332,17 +329,17 @@ SourceBuffer::ExpectLength(size_t aExpec
     return NS_OK;
   }
 
   if (MOZ_UNLIKELY(mChunks.Length() > 0)) {
     MOZ_ASSERT_UNREACHABLE("Duplicate or post-Append call to ExpectLength");
     return NS_OK;
   }
 
-  if (MOZ_UNLIKELY(NS_FAILED(AppendChunk(CreateChunk(aExpectedLength))))) {
+  if (MOZ_UNLIKELY(NS_FAILED(AppendChunk(CreateChunk(aExpectedLength, /* aRoundUp */ false))))) {
     return HandleError(NS_ERROR_OUT_OF_MEMORY);
   }
 
   return NS_OK;
 }
 
 nsresult
 SourceBuffer::Append(const char* aData, size_t aLength)
--- a/image/SourceBuffer.h
+++ b/image/SourceBuffer.h
@@ -374,69 +374,88 @@ private:
   friend class SourceBufferIterator;
 
   ~SourceBuffer();
 
   //////////////////////////////////////////////////////////////////////////////
   // Chunk type and chunk-related methods.
   //////////////////////////////////////////////////////////////////////////////
 
-  class Chunk
+  class Chunk final
   {
   public:
     explicit Chunk(size_t aCapacity)
       : mCapacity(aCapacity)
       , mLength(0)
     {
       MOZ_ASSERT(aCapacity > 0, "Creating zero-capacity chunk");
-      mData.reset(new (fallible) char[mCapacity]);
+      mData = static_cast<char*>(malloc(mCapacity));
+    }
+
+    ~Chunk()
+    {
+      free(mData);
     }
 
     Chunk(Chunk&& aOther)
       : mCapacity(aOther.mCapacity)
       , mLength(aOther.mLength)
-      , mData(Move(aOther.mData))
+      , mData(aOther.mData)
     {
       aOther.mCapacity = aOther.mLength = 0;
       aOther.mData = nullptr;
     }
 
     Chunk& operator=(Chunk&& aOther)
     {
+      free(mData);
       mCapacity = aOther.mCapacity;
       mLength = aOther.mLength;
-      mData = Move(aOther.mData);
+      mData = aOther.mData;
       aOther.mCapacity = aOther.mLength = 0;
       aOther.mData = nullptr;
       return *this;
     }
 
     bool AllocationFailed() const { return !mData; }
     size_t Capacity() const { return mCapacity; }
     size_t Length() const { return mLength; }
 
     char* Data() const
     {
       MOZ_ASSERT(mData, "Allocation failed but nobody checked for it");
-      return mData.get();
+      return mData;
     }
 
     void AddLength(size_t aAdditionalLength)
     {
       MOZ_ASSERT(mLength + aAdditionalLength <= mCapacity);
       mLength += aAdditionalLength;
     }
 
+    bool SetCapacity(size_t aCapacity)
+    {
+      MOZ_ASSERT(mData, "Allocation failed but nobody checked for it");
+      char* data = static_cast<char*>(realloc(mData, aCapacity));
+      if (!data) {
+        return false;
+      }
+
+      mData = data;
+      mCapacity = aCapacity;
+      return true;
+    }
+
   private:
     Chunk(const Chunk&) = delete;
     Chunk& operator=(const Chunk&) = delete;
 
     size_t mCapacity;
     size_t mLength;
-    UniquePtr<char[]> mData;
+    char* mData;
   };
 
   nsresult AppendChunk(Maybe<Chunk>&& aChunk);
   Maybe<Chunk> CreateChunk(size_t aCapacity, bool aRoundUp = true);
   nsresult Compact();
   static size_t RoundedUpCapacity(size_t aCapacity);
   size_t FibonacciCapacityWithMinimum(size_t aMinCapacity);
 
@@ -470,17 +489,17 @@ private:
   //////////////////////////////////////////////////////////////////////////////
   // Member variables.
   //////////////////////////////////////////////////////////////////////////////
 
   /// All private members are protected by mMutex.
   mutable Mutex mMutex;
 
   /// The data in this SourceBuffer, stored as a series of Chunks.
-  FallibleTArray<Chunk> mChunks;
+  AutoTArray<Chunk, 1> mChunks;
 
   /// Consumers which are waiting to be notified when new data is available.
   nsTArray<RefPtr<IResumable>> mWaitingConsumers;
 
   /// If present, marks this SourceBuffer complete with the given final status.
   Maybe<nsresult> mStatus;
 
   /// Count of active consumers.
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -158,20 +158,25 @@ nsICODecoder::ReadDirEntry(const char* a
     e.mHeight      = aData[1];
     e.mColorCount  = aData[2];
     e.mReserved    = aData[3];
     e.mPlanes      = LittleEndian::readUint16(aData + 4);
     e.mBitCount    = LittleEndian::readUint16(aData + 6);
     e.mBytesInRes  = LittleEndian::readUint32(aData + 8);
     e.mImageOffset = offset;
     e.mSize        = IntSize(e.mWidth, e.mHeight);
-    if (e.mWidth == 0 || e.mHeight == 0) {
-      mUnsizedDirEntries.AppendElement(e);
-    } else {
-      mDirEntries.AppendElement(e);
+
+    // Only accept entries with sufficient resource data to actually contain
+    // some image data.
+    if (e.mBytesInRes > BITMAPINFOSIZE) {
+      if (e.mWidth == 0 || e.mHeight == 0) {
+        mUnsizedDirEntries.AppendElement(e);
+      } else {
+        mDirEntries.AppendElement(e);
+      }
     }
   }
 
   if (mCurrIcon == mNumIcons) {
     if (mUnsizedDirEntries.IsEmpty()) {
       return Transition::To(ICOState::FINISHED_DIR_ENTRY, 0);
     }
     return Transition::To(ICOState::ITERATE_UNSIZED_DIR_ENTRY, 0);
--- a/image/imgTools.cpp
+++ b/image/imgTools.cpp
@@ -63,41 +63,42 @@ imgTools::DecodeImage(nsIInputStream* aI
                       imgIContainer** aContainer)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
 
   NS_ENSURE_ARG_POINTER(aInStr);
 
-  // Create a new image container to hold the decoded data.
-  nsAutoCString mimeType(aMimeType);
-  RefPtr<image::Image> image = ImageFactory::CreateAnonymousImage(mimeType);
-  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
-
-  if (image->HasError()) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Prepare the input stream.
   nsCOMPtr<nsIInputStream> inStream = aInStr;
   if (!NS_InputStreamIsBuffered(aInStr)) {
     nsCOMPtr<nsIInputStream> bufStream;
     rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024);
     if (NS_SUCCEEDED(rv)) {
       inStream = bufStream;
     }
   }
 
   // Figure out how much data we've been passed.
   uint64_t length;
   rv = inStream->Available(&length);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(length <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
 
+  // Create a new image container to hold the decoded data.
+  nsAutoCString mimeType(aMimeType);
+  RefPtr<image::Image> image =
+    ImageFactory::CreateAnonymousImage(mimeType, uint32_t(length));
+  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
+
+  if (image->HasError()) {
+    return NS_ERROR_FAILURE;
+  }
+
   // Send the source data to the Image.
   rv = image->OnImageDataAvailable(nullptr, nullptr, inStream, 0,
                                    uint32_t(length));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Let the Image know we've sent all the data.
   rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
   tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
--- a/image/test/gtest/TestSourceBuffer.cpp
+++ b/image/test/gtest/TestSourceBuffer.cpp
@@ -368,32 +368,35 @@ TEST_F(ImageSourceBuffer, MinChunkCapaci
   CheckedCompleteBuffer(iterator, 1);
 
   // Verify that the iterator sees the new byte and a new chunk has been
   // allocated.
   CheckedAdvanceIterator(iterator, 1, 2, SourceBuffer::MIN_CHUNK_CAPACITY + 1);
   CheckIteratorIsComplete(iterator, 2, SourceBuffer::MIN_CHUNK_CAPACITY + 1);
 }
 
-TEST_F(ImageSourceBuffer, ExpectLengthDoesNotShrinkBelowMinCapacity)
+TEST_F(ImageSourceBuffer, ExpectLengthAllocatesRequestedCapacity)
 {
   SourceBufferIterator iterator = mSourceBuffer->Iterator();
 
   // Write SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the buffer,
   // but call ExpectLength() first to make SourceBuffer expect only a single
-  // byte. We expect this to still result in only one chunk, because
-  // regardless of ExpectLength() we won't allocate a chunk smaller than
-  // MIN_CHUNK_CAPACITY bytes.
+  // byte. We expect this to still result in two chunks, because we trust the
+  // initial guess of ExpectLength() but after that it will only allocate chunks
+  // of at least MIN_CHUNK_CAPACITY bytes.
   EXPECT_TRUE(NS_SUCCEEDED(mSourceBuffer->ExpectLength(1)));
   CheckedAppendToBufferInChunks(10, SourceBuffer::MIN_CHUNK_CAPACITY);
   CheckedCompleteBuffer(iterator, SourceBuffer::MIN_CHUNK_CAPACITY);
 
-  // Verify that the iterator sees a single chunk.
-  CheckedAdvanceIterator(iterator, SourceBuffer::MIN_CHUNK_CAPACITY);
-  CheckIteratorIsComplete(iterator, 1, SourceBuffer::MIN_CHUNK_CAPACITY);
+  // Verify that the iterator sees a first chunk with 1 byte, and a second chunk
+  // with the remaining data.
+  CheckedAdvanceIterator(iterator, 1, 1, 1);
+  CheckedAdvanceIterator(iterator, SourceBuffer::MIN_CHUNK_CAPACITY - 1, 2,
+		                   SourceBuffer::MIN_CHUNK_CAPACITY);
+  CheckIteratorIsComplete(iterator, 2, SourceBuffer::MIN_CHUNK_CAPACITY);
 }
 
 TEST_F(ImageSourceBuffer, ExpectLengthGrowsAboveMinCapacity)
 {
   SourceBufferIterator iterator = mSourceBuffer->Iterator();
 
   // Write two times SourceBuffer::MIN_CHUNK_CAPACITY bytes of test data to the
   // buffer, calling ExpectLength() with the correct length first. We expect
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -527,34 +527,56 @@ class JS_PUBLIC_API(AutoAssertNoGC) : pu
     JSContext* cx_;
 
   public:
     explicit AutoAssertNoGC(JSContext* cx = nullptr);
     ~AutoAssertNoGC();
 };
 
 /**
+ * Assert if an allocation of a GC thing occurs while this class is live. This
+ * class does not disable the static rooting hazard analysis.
+ */
+class JS_PUBLIC_API(AutoAssertNoAlloc)
+{
+#ifdef JS_DEBUG
+    js::gc::GCRuntime* gc;
+
+  public:
+    AutoAssertNoAlloc() : gc(nullptr) {}
+    explicit AutoAssertNoAlloc(JSContext* cx);
+    void disallowAlloc(JSRuntime* rt);
+    ~AutoAssertNoAlloc();
+#else
+  public:
+    AutoAssertNoAlloc() {}
+    explicit AutoAssertNoAlloc(JSContext* cx) {}
+    void disallowAlloc(JSRuntime* rt) {}
+#endif
+};
+
+/**
  * Disable the static rooting hazard analysis in the live region and assert if
  * any allocation that could potentially trigger a GC occurs while this guard
  * object is live. This is most useful to help the exact rooting hazard analysis
  * in complex regions, since it cannot understand dataflow.
  *
  * Note: GC behavior is unpredictable even when deterministic and is generally
  *       non-deterministic in practice. The fact that this guard has not
  *       asserted is not a guarantee that a GC cannot happen in the guarded
  *       region. As a rule, anyone performing a GC unsafe action should
  *       understand the GC properties of all code in that region and ensure
  *       that the hazard analysis is correct for that code, rather than relying
  *       on this class.
  */
-class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoGC
+class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoAlloc
 {
   public:
-    AutoSuppressGCAnalysis() : AutoAssertNoGC() {}
-    explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoGC(cx) {}
+    AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
+    explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoAlloc(cx) {}
 } JS_HAZ_GC_SUPPRESSED;
 
 /**
  * Assert that code is only ever called from a GC callback, disable the static
  * rooting hazard analysis and assert if any allocation that could potentially
  * trigger a GC occurs while this guard object is live.
  *
  * This is useful to make the static analysis ignore code that runs in GC
--- a/js/public/UbiNodeBreadthFirst.h
+++ b/js/public/UbiNodeBreadthFirst.h
@@ -78,17 +78,17 @@ template<typename Handler>
 struct BreadthFirst {
 
     // Construct a breadth-first traversal object that reports the nodes it
     // reaches to |handler|. The traversal asserts that no GC happens in its
     // runtime during its lifetime.
     //
     // We do nothing with noGC, other than require it to exist, with a lifetime
     // that encloses our own.
-    BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoRequireNoGC& noGC)
+    BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
       : wantNames(true), cx(cx), visited(), handler(handler), pending(),
         traversalBegun(false), stopRequested(false), abandonRequested(false)
     { }
 
     // Initialize this traversal object. Return false on OOM.
     bool init() { return visited.init(); }
 
     // Add |node| as a starting point for the traversal. You may add
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -1008,17 +1008,17 @@ JS_GetDataViewByteOffset(JSObject* obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return 0;
     return obj->as<DataViewObject>().byteOffset();
 }
 
 JS_FRIEND_API(void*)
-JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     DataViewObject& dv = obj->as<DataViewObject>();
     *isSharedMemory = dv.isSharedMemory();
     return dv.dataPointerEither().unwrap(/*safe - caller sees isSharedMemory*/);
 }
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -3497,17 +3497,18 @@ ReadableByteStreamControllerPullSteps(JS
             void* underlyingSource = val.toPrivate();
 
             view = JS_NewUint8Array(cx, queueTotalSize);
             if (!view)
                 return nullptr;
 
             size_t bytesWritten;
             {
-                JS::AutoSuppressGCAnalysis noGC(cx);
+                JS::AutoSuppressGCAnalysis suppressGC(cx);
+                JS::AutoCheckCannotGC noGC;
                 bool dummy;
                 void* buffer = JS_GetArrayBufferViewData(view, &dummy, noGC);
                 auto cb = cx->runtime()->readableStreamWriteIntoReadRequestCallback;
                 MOZ_ASSERT(cb);
                 // TODO: use bytesWritten to correctly update the request's state.
                 cb(cx, stream, underlyingSource, stream->embeddingFlags(), buffer,
                    queueTotalSize, &bytesWritten);
             }
@@ -4239,17 +4240,18 @@ ReadableByteStreamControllerFillPullInto
         Value val = controller->getFixedSlot(ControllerSlot_UnderlyingSource);
         void* underlyingSource = val.toPrivate();
 
         RootedArrayBufferObject targetBuffer(cx, pullIntoDescriptor->buffer());
         Rooted<ReadableStream*> stream(cx, StreamFromController(controller));
 
         size_t bytesWritten;
         {
-            JS::AutoSuppressGCAnalysis noGC(cx);
+            JS::AutoSuppressGCAnalysis suppressGC(cx);
+            JS::AutoCheckCannotGC noGC;
             bool dummy;
             uint8_t* buffer = JS_GetArrayBufferData(targetBuffer, &dummy, noGC);
             buffer += bytesFilled;
             auto cb = cx->runtime()->readableStreamWriteIntoReadRequestCallback;
             MOZ_ASSERT(cb);
             cb(cx, stream, underlyingSource, stream->embeddingFlags(), buffer,
                totalBytesToCopyRemaining, &bytesWritten);
             pullIntoDescriptor->setBytesFilled(bytesFilled + bytesWritten);
@@ -5395,17 +5397,18 @@ ReadableStream::updateDataAvailableFromS
         if (!transferredView)
             return false;
 
         Value val = controller->getFixedSlot(ControllerSlot_UnderlyingSource);
         void* underlyingSource = val.toPrivate();
 
         size_t bytesWritten;
         {
-            JS::AutoSuppressGCAnalysis noGC(cx);
+            JS::AutoSuppressGCAnalysis suppressGC(cx);
+            JS::AutoCheckCannotGC noGC;
             bool dummy;
             void* buffer = JS_GetArrayBufferViewData(transferredView, &dummy, noGC);
             auto cb = cx->runtime()->readableStreamWriteIntoReadRequestCallback;
             MOZ_ASSERT(cb);
             // TODO: use bytesWritten to correctly update the request's state.
             cb(cx, stream, underlyingSource, stream->embeddingFlags(), buffer,
                availableData, &bytesWritten);
         }
--- a/js/src/gc/GenerateStatsPhases.py
+++ b/js/src/gc/GenerateStatsPhases.py
@@ -135,17 +135,16 @@ PhaseKindGraphRoots = [
             JoinParallelTasksPhaseKind
         ]),
         PhaseKind("SWEEP_OBJECT", "Sweep Object", 33),
         PhaseKind("SWEEP_STRING", "Sweep String", 34),
         PhaseKind("SWEEP_SCRIPT", "Sweep Script", 35),
         PhaseKind("SWEEP_SCOPE", "Sweep Scope", 59),
         PhaseKind("SWEEP_REGEXP_SHARED", "Sweep RegExpShared", 61),
         PhaseKind("SWEEP_SHAPE", "Sweep Shape", 36),
-        PhaseKind("SWEEP_JITCODE", "Sweep JIT code", 37),
         PhaseKind("FINALIZE_END", "Finalize End Callback", 38),
         PhaseKind("DESTROY", "Deallocate", 39),
         JoinParallelTasksPhaseKind
         ]),
     PhaseKind("COMPACT", "Compact", 40, [
         PhaseKind("COMPACT_MOVE", "Compact Move", 41),
         PhaseKind("COMPACT_UPDATE", "Compact Update", 42, [
             MarkRootsPhaseKind,
--- a/js/src/jsapi-tests/testTypedArrays.cpp
+++ b/js/src/jsapi-tests/testTypedArrays.cpp
@@ -68,17 +68,17 @@ BEGIN_TEST(testTypedArrays)
     return ok;
 }
 
 // Shared memory can only be mapped by a TypedArray by creating the
 // TypedArray with a SharedArrayBuffer explicitly, so no tests here.
 
 template<JSObject* Create(JSContext*, uint32_t),
          typename Element,
-         Element* GetData(JSObject*, bool* isShared, const JS::AutoRequireNoGC&)>
+         Element* GetData(JSObject*, bool* isShared, const JS::AutoCheckCannotGC&)>
 bool
 TestPlainTypedArray(JSContext* cx)
 {
     {
         RootedObject notArray(cx, Create(cx, UINT32_MAX));
         CHECK(!notArray);
     }
 
@@ -106,17 +106,17 @@ TestPlainTypedArray(JSContext* cx)
 
     return true;
 }
 
 template<JSObject* CreateWithBuffer(JSContext*, JS::HandleObject, uint32_t, int32_t),
          JSObject* CreateFromArray(JSContext*, JS::HandleObject),
          typename Element,
          bool Shared,
-         Element* GetData(JSObject*, bool*, const JS::AutoRequireNoGC&)>
+         Element* GetData(JSObject*, bool*, const JS::AutoCheckCannotGC&)>
 bool
 TestArrayFromBuffer(JSContext* cx)
 {
     if (Shared && !cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled())
         return true;
 
     size_t elts = 8;
     size_t nbytes = elts * sizeof(Element);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5815,32 +5815,32 @@ JS_StringIsFlat(JSString* str)
 
 JS_PUBLIC_API(bool)
 JS_StringHasLatin1Chars(JSString* str)
 {
     return str->hasLatin1Chars();
 }
 
 JS_PUBLIC_API(const JS::Latin1Char*)
-JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
+JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
                                  size_t* plength)
 {
     MOZ_ASSERT(plength);
     AssertHeapIsIdleOrStringIsFlat(str);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, str);
     JSLinearString* linear = str->ensureLinear(cx);
     if (!linear)
         return nullptr;
     *plength = linear->length();
     return linear->latin1Chars(nogc);
 }
 
 JS_PUBLIC_API(const char16_t*)
-JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
+JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
                                   size_t* plength)
 {
     MOZ_ASSERT(plength);
     AssertHeapIsIdleOrStringIsFlat(str);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, str);
     JSLinearString* linear = str->ensureLinear(cx);
     if (!linear)
@@ -5888,27 +5888,27 @@ JS_CopyStringChars(JSContext* cx, mozill
         return false;
 
     MOZ_ASSERT(linear->length() <= dest.length());
     CopyChars(dest.begin().get(), *linear);
     return true;
 }
 
 JS_PUBLIC_API(const Latin1Char*)
-JS_GetLatin1InternedStringChars(const JS::AutoRequireNoGC& nogc, JSString* str)
+JS_GetLatin1InternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str)
 {
     MOZ_ASSERT(str->isAtom());
     JSFlatString* flat = str->ensureFlat(nullptr);
     if (!flat)
         return nullptr;
     return flat->latin1Chars(nogc);
 }
 
 JS_PUBLIC_API(const char16_t*)
-JS_GetTwoByteInternedStringChars(const JS::AutoRequireNoGC& nogc, JSString* str)
+JS_GetTwoByteInternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str)
 {
     MOZ_ASSERT(str->isAtom());
     JSFlatString* flat = str->ensureFlat(nullptr);
     if (!flat)
         return nullptr;
     return flat->twoByteChars(nogc);
 }
 
@@ -5920,23 +5920,23 @@ JS_FlattenString(JSContext* cx, JSString
     assertSameCompartment(cx, str);
     JSFlatString* flat = str->ensureFlat(cx);
     if (!flat)
         return nullptr;
     return flat;
 }
 
 extern JS_PUBLIC_API(const Latin1Char*)
-JS_GetLatin1FlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str)
+JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str)
 {
     return str->latin1Chars(nogc);
 }
 
 extern JS_PUBLIC_API(const char16_t*)
-JS_GetTwoByteFlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str)
+JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str)
 {
     return str->twoByteChars(nogc);
 }
 
 JS_PUBLIC_API(bool)
 JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result)
 {
     AssertHeapIsIdle();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5015,21 +5015,21 @@ JS_GetStringLength(JSString* str);
 extern JS_PUBLIC_API(bool)
 JS_StringIsFlat(JSString* str);
 
 /** Returns true iff the string's characters are stored as Latin1. */
 extern JS_PUBLIC_API(bool)
 JS_StringHasLatin1Chars(JSString* str);
 
 extern JS_PUBLIC_API(const JS::Latin1Char*)
-JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
+JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
                                  size_t* length);
 
 extern JS_PUBLIC_API(const char16_t*)
-JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoRequireNoGC& nogc, JSString* str,
+JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
                                   size_t* length);
 
 extern JS_PUBLIC_API(bool)
 JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res);
 
 extern JS_PUBLIC_API(char16_t)
 JS_GetFlatStringCharAt(JSFlatString* str, size_t index);
 
@@ -5038,20 +5038,20 @@ JS_GetTwoByteExternalStringChars(JSStrin
 
 extern JS_PUBLIC_API(bool)
 JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str);
 
 extern JS_PUBLIC_API(JSFlatString*)
 JS_FlattenString(JSContext* cx, JSString* str);
 
 extern JS_PUBLIC_API(const JS::Latin1Char*)
-JS_GetLatin1FlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str);
+JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
 
 extern JS_PUBLIC_API(const char16_t*)
-JS_GetTwoByteFlatStringChars(const JS::AutoRequireNoGC& nogc, JSFlatString* str);
+JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
 
 static MOZ_ALWAYS_INLINE JSFlatString*
 JSID_TO_FLAT_STRING(jsid id)
 {
     MOZ_ASSERT(JSID_IS_STRING(id));
     return (JSFlatString*)(JSID_BITS(id));
 }
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -813,29 +813,29 @@ AtomHasLatin1Chars(JSAtom* atom)
 
 MOZ_ALWAYS_INLINE bool
 StringHasLatin1Chars(JSString* s)
 {
     return reinterpret_cast<shadow::String*>(s)->flags & shadow::String::LATIN1_CHARS_BIT;
 }
 
 MOZ_ALWAYS_INLINE const JS::Latin1Char*
-GetLatin1LinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
+GetLatin1LinearStringChars(const JS::AutoCheckCannotGC& nogc, JSLinearString* linear)
 {
     MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
 
     using shadow::String;
     String* s = reinterpret_cast<String*>(linear);
     if (s->flags & String::INLINE_CHARS_BIT)
         return s->inlineStorageLatin1;
     return s->nonInlineCharsLatin1;
 }
 
 MOZ_ALWAYS_INLINE const char16_t*
-GetTwoByteLinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
+GetTwoByteLinearStringChars(const JS::AutoCheckCannotGC& nogc, JSLinearString* linear)
 {
     MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
 
     using shadow::String;
     String* s = reinterpret_cast<String*>(linear);
     if (s->flags & String::INLINE_CHARS_BIT)
         return s->inlineStorageTwoByte;
     return s->nonInlineCharsTwoByte;
@@ -855,23 +855,23 @@ AtomToFlatString(JSAtom* atom)
 
 MOZ_ALWAYS_INLINE JSLinearString*
 FlatStringToLinearString(JSFlatString* s)
 {
     return reinterpret_cast<JSLinearString*>(s);
 }
 
 MOZ_ALWAYS_INLINE const JS::Latin1Char*
-GetLatin1AtomChars(const JS::AutoRequireNoGC& nogc, JSAtom* atom)
+GetLatin1AtomChars(const JS::AutoCheckCannotGC& nogc, JSAtom* atom)
 {
     return GetLatin1LinearStringChars(nogc, AtomToLinearString(atom));
 }
 
 MOZ_ALWAYS_INLINE const char16_t*
-GetTwoByteAtomChars(const JS::AutoRequireNoGC& nogc, JSAtom* atom)
+GetTwoByteAtomChars(const JS::AutoCheckCannotGC& nogc, JSAtom* atom)
 {
     return GetTwoByteLinearStringChars(nogc, AtomToLinearString(atom));
 }
 
 MOZ_ALWAYS_INLINE bool
 IsExternalString(JSString* str, const JSStringFinalizer** fin, const char16_t** chars)
 {
     using shadow::String;
@@ -1949,17 +1949,17 @@ GetArrayBufferLengthAndData(JSObject* ob
 // There is an isShared out argument for API consistency (eases use from DOM).
 // It will always be set to true.
 extern JS_FRIEND_API(void)
 GetSharedArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
 
 } // namespace js
 
 JS_FRIEND_API(uint8_t*)
-JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /*
  * Unwrap Typed arrays all at once. Return nullptr without throwing if the
  * object cannot be viewed as the correct typed array, or the typed array
  * object on success, filling both outparameters.
  */
 extern JS_FRIEND_API(JSObject*)
 JS_GetObjectAsInt8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int8_t** data);
@@ -2047,17 +2047,17 @@ JS_ArrayBufferHasData(JSObject* obj);
  * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  * ArrayBuffer, and the unwrapping will succeed.
  *
  * |*isSharedMemory| will be set to false, the argument is present to simplify
  * its use from code that also interacts with SharedArrayBuffer.
  */
 extern JS_FRIEND_API(uint8_t*)
-JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /**
  * Check whether the obj is ArrayBufferObject and memory mapped. Note that this
  * may return false if a security wrapper is encountered that denies the
  * unwrapping.
  */
 extern JS_FRIEND_API(bool)
 JS_IsMappedArrayBufferObject(JSObject* obj);
@@ -2124,40 +2124,40 @@ JS_GetArrayBufferViewByteOffset(JSObject
  * pass such a test: it is a typed array or a wrapper of a typed array, and the
  * unwrapping will succeed.
  *
  * |*isSharedMemory| will be set to true if the typed array maps a
  * SharedArrayBuffer, otherwise to false.
  */
 
 extern JS_FRIEND_API(int8_t*)
-JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint8_t*)
-JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint8_t*)
-JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(int16_t*)
-JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint16_t*)
-JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(int32_t*)
-JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(uint32_t*)
-JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(float*)
-JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 extern JS_FRIEND_API(double*)
-JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /**
  * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
  * versions when possible.
  */
 extern JS_FRIEND_API(void*)
-JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 /**
  * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
  * This may return a detached buffer.  |obj| must be an object that would
  * return true for JS_IsArrayBufferViewObject().
  */
 extern JS_FRIEND_API(JSObject*)
 JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
@@ -2224,17 +2224,17 @@ JS_GetDataViewByteLength(JSObject* obj);
  * it would pass such a test: it is a data view or a wrapper of a data view,
  * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
  * unable to assert when unwrapping should be disallowed.
  *
  * |*isSharedMemory| will be set to true if the DataView maps a SharedArrayBuffer,
  * otherwise to false.
  */
 JS_FRIEND_API(void*)
-JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
+JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
 
 namespace js {
 
 /**
  * Add a watchpoint -- in the Object.prototype.watch sense -- to |obj| for the
  * property |id|, using the callable object |callable| as the function to be
  * called for notifications.
  *
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -342,26 +342,20 @@ static const FinalizePhase ForegroundObj
         AllocKind::OBJECT12,
         AllocKind::OBJECT16
     }
 };
 
 /*
  * Finalization order for GC things swept incrementally on the active thread.
  */
-static const FinalizePhase IncrementalFinalizePhases[] = {
-    {
-        gcstats::PhaseKind::SWEEP_SCRIPT, {
-            AllocKind::SCRIPT
-        }
-    },
-    {
-        gcstats::PhaseKind::SWEEP_JITCODE, {
-            AllocKind::JITCODE
-        }
+static const FinalizePhase ForegroundNonObjectFinalizePhase = {
+    gcstats::PhaseKind::SWEEP_SCRIPT, {
+        AllocKind::SCRIPT,
+        AllocKind::JITCODE
     }
 };
 
 /*
  * Finalization order for GC things swept on the background thread.
  */
 static const FinalizePhase BackgroundFinalizePhases[] = {
     {
@@ -5352,19 +5346,17 @@ GCRuntime::beginSweepingSweepGroup()
         startSweepingAtomsTable();
 
     // Queue all GC things in all zones for sweeping, either on the foreground
     // or on the background thread.
 
     for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
 
         zone->arenas.queueForForegroundSweep(&fop, ForegroundObjectFinalizePhase);
-        for (unsigned i = 0; i < ArrayLength(IncrementalFinalizePhases); ++i)
-            zone->arenas.queueForForegroundSweep(&fop, IncrementalFinalizePhases[i]);
-
+        zone->arenas.queueForForegroundSweep(&fop, ForegroundNonObjectFinalizePhase);
         for (unsigned i = 0; i < ArrayLength(BackgroundFinalizePhases); ++i)
             zone->arenas.queueForBackgroundSweep(&fop, BackgroundFinalizePhases[i]);
 
         zone->arenas.queueForegroundThingsForSweep(&fop);
     }
 
     sweepCache = nullptr;
     sweepActions->assertFinished();
@@ -5861,36 +5853,38 @@ struct IncrementalIter
         return maybeIter.ref().get();
     }
 
     void next() {
         maybeIter.ref().next();
     }
 };
 
+namespace sweepaction {
+
 // Implementation of the SweepAction interface that calls a function.
 template <typename... Args>
-class SweepActionFunc : public SweepAction<Args...>
+class SweepActionFunc final : public SweepAction<Args...>
 {
     using Func = IncrementalProgress (*)(Args...);
 
     Func func;
 
   public:
     explicit SweepActionFunc(Func f) : func(f) {}
     IncrementalProgress run(Args... args) override {
         return func(args...);
     }
     void assertFinished() const override { }
 };
 
 // Implementation of the SweepAction interface that calls a list of actions in
 // sequence.
 template <typename... Args>
-class SweepActionSequence : public SweepAction<Args...>
+class SweepActionSequence final : public SweepAction<Args...>
 {
     using Action = SweepAction<Args...>;
     using ActionVector = Vector<UniquePtr<Action>, 0, SystemAllocPolicy>;
     using Iter = IncrementalIter<ContainerIter<ActionVector>>;
 
     ActionVector actions;
     typename Iter::State iterState;
 
@@ -5914,17 +5908,17 @@ class SweepActionSequence : public Sweep
     void assertFinished() const override {
         MOZ_ASSERT(iterState.isNothing());
         for (const auto& action : actions)
             action->assertFinished();
     }
 };
 
 template <typename Iter, typename Init, typename... Args>
-class SweepActionForEach : public SweepAction<Args...>
+class SweepActionForEach final : public SweepAction<Args...>
 {
     using Elem = decltype(mozilla::DeclVal<Iter>().get());
     using Action = SweepAction<Args..., Elem>;
     using IncrIter = IncrementalIter<Iter>;
 
     Init iterInit;
     UniquePtr<Action> action;
     typename IncrIter::State iterState;
@@ -5982,80 +5976,78 @@ class RemoveLastTemplateParameter<Target
     };
 
   public:
     using Type = typename Impl<List<>, Args...>::Type;
 };
 
 template <typename... Args>
 static UniquePtr<SweepAction<Args...>>
-SweepFunc(IncrementalProgress (*func)(Args...)) {
+Func(IncrementalProgress (*func)(Args...)) {
     return MakeUnique<SweepActionFunc<Args...>>(func);
 }
 
 template <typename... Args, typename... Rest>
 static UniquePtr<SweepAction<Args...>>
-SweepSequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
+Sequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
 {
     UniquePtr<SweepAction<Args...>> actions[] = { Move(first), Move(rest)... };
     auto seq = MakeUnique<SweepActionSequence<Args...>>();
     if (!seq || !seq->init(actions, ArrayLength(actions)))
         return nullptr;
 
     return UniquePtr<SweepAction<Args...>>(Move(seq));
 }
 
 template <typename... Args>
 static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
-SweepForEachZone(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
+ForEachZoneInSweepGroup(JSRuntime* rt, UniquePtr<SweepAction<Args...>> action)
 {
     if (!action)
         return nullptr;
 
     using Action = typename RemoveLastTemplateParameter<
         SweepActionForEach<GCSweepGroupIter, JSRuntime*, Args...>>::Type;
     return js::MakeUnique<Action>(rt, Move(action));
 }
 
 template <typename... Args>
 static UniquePtr<typename RemoveLastTemplateParameter<SweepAction<Args...>>::Type>
-SweepForEachAllocKind(AllocKinds kinds, UniquePtr<SweepAction<Args...>> action)
+ForEachAllocKind(AllocKinds kinds, UniquePtr<SweepAction<Args...>> action)
 {
     if (!action)
         return nullptr;
 
     using Action = typename RemoveLastTemplateParameter<
         SweepActionForEach<ContainerIter<AllocKinds>, AllocKinds, Args...>>::Type;
     return js::MakeUnique<Action>(kinds, Move(action));
 }
 
+} // namespace sweepaction
+
 bool
 GCRuntime::initSweepActions()
 {
-    sweepActions.ref() = SweepSequence(
-        SweepFunc(sweepAtomsTable),
-        SweepFunc(sweepWeakCaches),
-        SweepForEachZone(rt,
-            SweepForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
-                SweepFunc(finalizeAllocKind))),
-        SweepForEachZone(rt,
-            SweepSequence(
-                SweepFunc(sweepTypeInformation),
-                SweepFunc(mergeSweptObjectArenas))),
-        SweepForEachZone(rt,
-            SweepForEachAllocKind(IncrementalFinalizePhases[0].kinds,
-                SweepFunc(finalizeAllocKind))),
-        SweepForEachZone(rt,
-            SweepForEachAllocKind(IncrementalFinalizePhases[1].kinds,
-                SweepFunc(finalizeAllocKind))),
-        SweepForEachZone(rt,
-            SweepFunc(sweepShapeTree)));
-
-    static_assert(ArrayLength(IncrementalFinalizePhases) == 2,
-                  "We must have a phase for each element in IncrementalFinalizePhases");
+    using namespace sweepaction;
+
+    sweepActions.ref() = Sequence(
+        Func(sweepAtomsTable),
+        Func(sweepWeakCaches),
+        ForEachZoneInSweepGroup(rt,
+            ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
+                Func(finalizeAllocKind))),
+        ForEachZoneInSweepGroup(rt,
+            Sequence(
+                Func(sweepTypeInformation),
+                Func(mergeSweptObjectArenas))),
+        ForEachZoneInSweepGroup(rt,
+            ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
+                Func(finalizeAllocKind))),
+        ForEachZoneInSweepGroup(rt,
+            Func(sweepShapeTree)));
 
     return sweepActions != nullptr;
 }
 
 IncrementalProgress
 GCRuntime::performSweepActions(SliceBudget& budget, AutoLockForExclusiveAccess& lock)
 {
     AutoSetThreadIsSweeping threadIsSweeping;
@@ -7871,29 +7863,45 @@ js::gc::AssertGCThingHasType(js::gc::Cel
     else
         MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind);
 }
 #endif
 
 JS::AutoAssertNoGC::AutoAssertNoGC(JSContext* maybecx)
   : cx_(maybecx ? maybecx : TlsContext.get())
 {
-    if (cx_)
-        cx_->inUnsafeRegion++;
+    cx_->inUnsafeRegion++;
 }
 
 JS::AutoAssertNoGC::~AutoAssertNoGC()
 {
-    if (cx_) {
-        MOZ_ASSERT(cx_->inUnsafeRegion > 0);
-        cx_->inUnsafeRegion--;
-    }
+    MOZ_ASSERT(cx_->inUnsafeRegion > 0);
+    cx_->inUnsafeRegion--;
 }
 
 #ifdef DEBUG
+JS::AutoAssertNoAlloc::AutoAssertNoAlloc(JSContext* cx)
+  : gc(nullptr)
+{
+    disallowAlloc(cx->runtime());
+}
+
+void JS::AutoAssertNoAlloc::disallowAlloc(JSRuntime* rt)
+{
+    MOZ_ASSERT(!gc);
+    gc = &rt->gc;
+    TlsContext.get()->disallowAlloc();
+}
+
+JS::AutoAssertNoAlloc::~AutoAssertNoAlloc()
+{
+    if (gc)
+        TlsContext.get()->allowAlloc();
+}
+
 AutoAssertNoNurseryAlloc::AutoAssertNoNurseryAlloc()
 {
     TlsContext.get()->disallowNurseryAlloc();
 }
 
 AutoAssertNoNurseryAlloc::~AutoAssertNoNurseryAlloc()
 {
     TlsContext.get()->allowNurseryAlloc();
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1610,17 +1610,17 @@ js::UnwrapArrayBufferView(JSObject* obj)
 JS_FRIEND_API(uint32_t)
 JS_GetArrayBufferByteLength(JSObject* obj)
 {
     obj = CheckedUnwrap(obj);
     return obj ? AsArrayBuffer(obj).byteLength() : 0;
 }
 
 JS_FRIEND_API(uint8_t*)
-JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     if (!IsArrayBuffer(obj))
         return nullptr;
     *isSharedMemory = false;
     return AsArrayBuffer(obj).dataPointer();
@@ -1827,17 +1827,17 @@ JS_IsMappedArrayBufferObject(JSObject* o
     obj = CheckedUnwrap(obj);
     if (!obj)
         return false;
 
     return obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().isMapped();
 }
 
 JS_FRIEND_API(void*)
-JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     if (obj->is<DataViewObject>()) {
         DataViewObject& dv = obj->as<DataViewObject>();
         *isSharedMemory = dv.isSharedMemory();
         return dv.dataPointerEither().unwrap(/*safe - caller sees isSharedMemory flag*/);
--- a/js/src/vm/SharedArrayObject.cpp
+++ b/js/src/vm/SharedArrayObject.cpp
@@ -508,16 +508,16 @@ JS_NewSharedArrayBuffer(JSContext* cx, u
 JS_FRIEND_API(bool)
 JS_IsSharedArrayBufferObject(JSObject* obj)
 {
     obj = CheckedUnwrap(obj);
     return obj ? obj->is<SharedArrayBufferObject>() : false;
 }
 
 JS_FRIEND_API(uint8_t*)
-JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     *isSharedMemory = true;
     return obj->as<SharedArrayBufferObject>().dataPointerShared().unwrap(/*safe - caller knows*/);
 }
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -647,52 +647,52 @@ class JSLinearString : public JSString
     }
 
     MOZ_ALWAYS_INLINE const JS::Latin1Char* rawLatin1Chars() const;
     MOZ_ALWAYS_INLINE const char16_t* rawTwoByteChars() const;
 
   public:
     template<typename CharT>
     MOZ_ALWAYS_INLINE
-    const CharT* nonInlineChars(const JS::AutoRequireNoGC& nogc) const;
+    const CharT* nonInlineChars(const JS::AutoCheckCannotGC& nogc) const;
 
     MOZ_ALWAYS_INLINE
-    const JS::Latin1Char* nonInlineLatin1Chars(const JS::AutoRequireNoGC& nogc) const {
+    const JS::Latin1Char* nonInlineLatin1Chars(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(!isInline());
         MOZ_ASSERT(hasLatin1Chars());
         return d.s.u2.nonInlineCharsLatin1;
     }
 
     MOZ_ALWAYS_INLINE
-    const char16_t* nonInlineTwoByteChars(const JS::AutoRequireNoGC& nogc) const {
+    const char16_t* nonInlineTwoByteChars(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(!isInline());
         MOZ_ASSERT(hasTwoByteChars());
         return d.s.u2.nonInlineCharsTwoByte;
     }
 
     template<typename CharT>
     MOZ_ALWAYS_INLINE
-    const CharT* chars(const JS::AutoRequireNoGC& nogc) const;
+    const CharT* chars(const JS::AutoCheckCannotGC& nogc) const;
 
     MOZ_ALWAYS_INLINE
-    const JS::Latin1Char* latin1Chars(const JS::AutoRequireNoGC& nogc) const {
+    const JS::Latin1Char* latin1Chars(const JS::AutoCheckCannotGC& nogc) const {
         return rawLatin1Chars();
     }
 
     MOZ_ALWAYS_INLINE
-    const char16_t* twoByteChars(const JS::AutoRequireNoGC& nogc) const {
+    const char16_t* twoByteChars(const JS::AutoCheckCannotGC& nogc) const {
         return rawTwoByteChars();
     }
 
-    mozilla::Range<const JS::Latin1Char> latin1Range(const JS::AutoRequireNoGC& nogc) const {
+    mozilla::Range<const JS::Latin1Char> latin1Range(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(JSString::isLinear());
         return mozilla::Range<const JS::Latin1Char>(latin1Chars(nogc), length());
     }
 
-    mozilla::Range<const char16_t> twoByteRange(const JS::AutoRequireNoGC& nogc) const {
+    mozilla::Range<const char16_t> twoByteRange(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(JSString::isLinear());
         return mozilla::Range<const char16_t>(twoByteChars(nogc), length());
     }
 
     MOZ_ALWAYS_INLINE
     char16_t latin1OrTwoByteChar(size_t index) const {
         MOZ_ASSERT(JSString::isLinear());
         MOZ_ASSERT(index < length());
@@ -859,24 +859,24 @@ class JSExtensibleString : public JSFlat
 
 static_assert(sizeof(JSExtensibleString) == sizeof(JSString),
               "string subclasses must be binary-compatible with JSString");
 
 class JSInlineString : public JSFlatString
 {
   public:
     MOZ_ALWAYS_INLINE
-    const JS::Latin1Char* latin1Chars(const JS::AutoRequireNoGC& nogc) const {
+    const JS::Latin1Char* latin1Chars(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(JSString::isInline());
         MOZ_ASSERT(hasLatin1Chars());
         return d.inlineStorageLatin1;
     }
 
     MOZ_ALWAYS_INLINE
-    const char16_t* twoByteChars(const JS::AutoRequireNoGC& nogc) const {
+    const char16_t* twoByteChars(const JS::AutoCheckCannotGC& nogc) const {
         MOZ_ASSERT(JSString::isInline());
         MOZ_ASSERT(hasTwoByteChars());
         return d.inlineStorageTwoByte;
     }
 
     template<typename CharT>
     static bool lengthFits(size_t length);
 
@@ -1419,38 +1419,38 @@ JSString::base() const
 {
     MOZ_ASSERT(hasBase());
     MOZ_ASSERT(!d.s.u3.base->isInline());
     return d.s.u3.base;
 }
 
 template<>
 MOZ_ALWAYS_INLINE const char16_t*
-JSLinearString::nonInlineChars(const JS::AutoRequireNoGC& nogc) const
+JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC& nogc) const
 {
     return nonInlineTwoByteChars(nogc);
 }
 
 template<>
 MOZ_ALWAYS_INLINE const JS::Latin1Char*
-JSLinearString::nonInlineChars(const JS::AutoRequireNoGC& nogc) const
+JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC& nogc) const
 {
     return nonInlineLatin1Chars(nogc);
 }
 
 template<>
 MOZ_ALWAYS_INLINE const char16_t*
-JSLinearString::chars(const JS::AutoRequireNoGC& nogc) const
+JSLinearString::chars(const JS::AutoCheckCannotGC& nogc) const
 {
     return rawTwoByteChars();
 }
 
 template<>
 MOZ_ALWAYS_INLINE const JS::Latin1Char*
-JSLinearString::chars(const JS::AutoRequireNoGC& nogc) const
+JSLinearString::chars(const JS::AutoCheckCannotGC& nogc) const
 {
     return rawLatin1Chars();
 }
 
 template <>
 MOZ_ALWAYS_INLINE bool
 JSRope::copyChars<JS::Latin1Char>(JSContext* cx,
                                   js::ScopedJSFreePtr<JS::Latin1Char>& out) const
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -2344,113 +2344,113 @@ JS_GetArrayBufferViewType(JSObject* obj)
     if (obj->is<TypedArrayObject>())
         return obj->as<TypedArrayObject>().type();
     if (obj->is<DataViewObject>())
         return Scalar::MaxTypedArrayViewType;
     MOZ_CRASH("invalid ArrayBufferView type");
 }
 
 JS_FRIEND_API(int8_t*)
-JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int8);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<int8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isShared*/));
 }
 
 JS_FRIEND_API(uint8_t*)
-JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint8);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<uint8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(uint8_t*)
-JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint8Clamped);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<uint8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(int16_t*)
-JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int16);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<int16_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(uint16_t*)
-JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint16);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<uint16_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(int32_t*)
-JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int32);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<int32_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(uint32_t*)
-JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint32);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<uint32_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(float*)
-JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Float32);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<float*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
 }
 
 JS_FRIEND_API(double*)
-JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&)
+JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Float64);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<double*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
--- a/layout/base/tests/bug632215-1.html
+++ b/layout/base/tests/bug632215-1.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
   <head>
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body>
-    <iframe src="data:text/html,<body spellcheck=false></body>"></iframe>
+    <iframe srcdoc="<body spellcheck=false></body>"></iframe>
     <script>
       onload = function() {
         var i = document.querySelector("iframe");
         var d = i.contentDocument;
         var w = i.contentWindow;
         var s = w.getSelection();
         i.focus();
         d.body.contentEditable = true;
--- a/layout/base/tests/bug632215-2.html
+++ b/layout/base/tests/bug632215-2.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
   <head>
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body>
-    <iframe src="data:text/html,<body contenteditable spellcheck=false></body>"></iframe>
+    <iframe srcdoc="<body contenteditable spellcheck=false></body>"></iframe>
     <script>
       onload = function() {
         var i = document.querySelector("iframe");
         var d = i.contentDocument;
         var w = i.contentWindow;
         var s = w.getSelection();
         i.focus();
         d.body.contentEditable = false;
--- a/layout/base/tests/bug632215-ref.html
+++ b/layout/base/tests/bug632215-ref.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html>
   <body>
-    <iframe src="data:text/html,<body spellcheck=false>xx</body>"></iframe>
+    <iframe srcdoc="<body spellcheck=false>xx</body>"></iframe>
     <script>
       onload = function() {
         var i = document.querySelector("iframe");
         var d = i.contentDocument;
         var w = i.contentWindow;
         d.designMode = "on";
         i.focus();
         d.body.focus();
--- a/layout/base/tests/bug682712-1-ref.html
+++ b/layout/base/tests/bug682712-1-ref.html
@@ -1,14 +1,14 @@
 <html class="reftest-wait">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   </head>
   <body onload="start()">
-    <iframe src="data:text/html,<body contenteditable spellcheck=false>foo bar"></iframe>
+    <iframe srcdoc="<body contenteditable spellcheck=false>foo bar"></iframe>
     <script>
       function start() {
         var iframe = document.querySelector("iframe");
         var win = iframe.contentWindow;
         var doc = iframe.contentDocument;
 
         setTimeout(function() {
           doc.body.focus();
--- a/layout/base/tests/bug682712-1.html
+++ b/layout/base/tests/bug682712-1.html
@@ -1,15 +1,15 @@
 <html class="reftest-wait">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="start()">
-    <iframe src="data:text/html,<body contenteditable spellcheck=false>foo bar"></iframe>
+    <iframe srcdoc="<body contenteditable spellcheck=false>foo bar"></iframe>
     <script>
       function start() {
         var iframe = document.querySelector("iframe");
         var win = iframe.contentWindow;
         var doc = iframe.contentDocument;
 
         // Reframe the iframe
         iframe.style.display = "none";
--- a/layout/base/tests/bug746993-1-ref.html
+++ b/layout/base/tests/bug746993-1-ref.html
@@ -1,15 +1,15 @@
 <html class="reftest-wait">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="start()">
-    <iframe src="data:text/html,<body contenteditable spellcheck=false>Here's some text.<br /><br /><div></div></body>"></iframe>
+    <iframe srcdoc="<body contenteditable spellcheck=false>Here's some text.<br /><br /><div></div></body>"></iframe>
     <script>
       function start() {
         var iframe = document.querySelector("iframe");
         var win = iframe.contentWindow;
         var doc = iframe.contentDocument;
         iframe.focus();
         doc.body.focus();
         win.getSelection().collapse(doc.body, 3);
--- a/layout/base/tests/bug746993-1.html
+++ b/layout/base/tests/bug746993-1.html
@@ -1,15 +1,15 @@
 <html class="reftest-wait">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="start()">
-    <iframe src="data:text/html,<body contenteditable spellcheck=false><br /><div></div></body>"></iframe>
+    <iframe srcdoc="<body contenteditable spellcheck=false><br /><div></div></body>"></iframe>
     <script>
       function start() {
         var iframe = document.querySelector("iframe");
         var win = iframe.contentWindow;
         var doc = iframe.contentDocument;
         iframe.focus();
         doc.body.focus();
         win.getSelection().collapse(doc.body, 0);
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/file_bug842853-frame.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<a href="#anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/file_getBoxQuads_convertPointRectQuad_frame1.html
@@ -0,0 +1,3 @@
+<!DOCTYPE HTML>
+<html style='padding:25px'>
+<div id='f1d' style='position:absolute; left:14px; top:15px; width:16px; height:17px; background:pink'></div>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/file_getBoxQuads_convertPointRectQuad_frame2.html
@@ -0,0 +1,1 @@
+<div id='d'>
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -80,16 +80,18 @@ support-files =
 [test_bug696020.html]
 [test_bug718809.html]
 [test_bug725426.html]
 [test_bug731777.html]
 [test_bug749186.html]
 [test_bug761572.html]
 [test_bug770106.html]
 [test_bug842853.html]
+support-files =
+  file_bug842853-frame.html
 skip-if = toolkit == 'android' # Bug 1355821
 [test_bug842853-2.html]
 skip-if = toolkit == 'android' # Bug 1355821
 [test_bug849219.html]
 [test_bug851445.html]
 skip-if = toolkit == 'android' # Bug 1355821
 support-files = bug851445_helper.html
 [test_bug851485.html]
@@ -138,16 +140,19 @@ skip-if = e10s # bug 1020135, nested oop
 support-files = bug921928_event_target_iframe_apps_oop.html
 [test_event_target_radius.html]
 skip-if = toolkit == 'android' # Bug 1355836
 [test_flush_on_paint.html]
 skip-if = true # Bug 688128
 [test_frame_reconstruction_for_pseudo_elements.html]
 [test_frame_reconstruction_scroll_restore.html]
 [test_getBoxQuads_convertPointRectQuad.html]
+support-files =
+  file_getBoxQuads_convertPointRectQuad_frame1.html
+  file_getBoxQuads_convertPointRectQuad_frame2.html
 [test_getClientRects_emptytext.html]
 [test_mozPaintCount.html]
 skip-if = toolkit == 'android' # Requires plugin support
 [test_preserve3d_sorting_hit_testing.html]
 support-files = preserve3d_sorting_hit_testing_iframe.html
 [test_preserve3d_sorting_hit_testing2.html]
 support-files = preserve3d_sorting_hit_testing2_iframe.html
 [test_reftests_with_caret.html]
@@ -322,19 +327,23 @@ support-files =
   textarea-minlength-valid-change.html
   textarea-valid-ref.html
 [test_remote_frame.html]
 [test_resize_flush.html]
 support-files = resize_flush_iframe.html
 [test_scroll_event_ordering.html]
 [test_scroll_selection_into_view.html]
 skip-if = toolkit == 'android' # Bug 1355844
-support-files = scroll_selection_into_view_window.html
+support-files =
+  scroll_selection_into_view_window.html
+  scroll_selection_into_view_window_frame.html
 [test_scroll_snapping.html]
 skip-if = toolkit == 'android' || os == 'win' # Bug 1355851, win Bug 1379810
 [test_scroll_snapping_scrollbars.html]
 skip-if = toolkit == 'android' || (os == 'win' && !e10s) # Bug 1355851, bug 1381932
 [test_transformed_scrolling_repaints.html]
 [test_transformed_scrolling_repaints_2.html]
 [test_transformed_scrolling_repaints_3.html]
-support-files = transformed_scrolling_repaints_3_window.html
+support-files =
+  transformed_scrolling_repaints_3_window.html
+  transformed_scrolling_repaints_3_window_frame.html
 
 # *** Please maintain alphabetical ordering when adding new tests ***
--- a/layout/base/tests/scroll_selection_into_view_window.html
+++ b/layout/base/tests/scroll_selection_into_view_window.html
@@ -23,24 +23,17 @@
   <div style="height:400px;"></div>
   <div><span id="target3"
         style="display:inline-block; vertical-align:top; height:300px;"></span>
   </div>
   <div style="height:400px;"></div>
 </div>
 <div id="c4" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:200px; left:600px;">
   <iframe id="target4" style="border:none; width:100%; height:1100px; display:block;"
-          src="data:text/html,
-               <body style='margin:0; overflow:hidden;'>
-                 <div style='height:400px;'></div>
-                 <div><span id='target4'
-                            style='display:inline-block; vertical-align:top; height:300px;'></span>
-                 </div>
-                 <div style='height:400px;'></div>">
-  </iframe>
+          src="scroll_selection_into_view_window_frame.html"></iframe>
 </div>
 <div id="c5" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:0;">
   <div style="-moz-transform:translateY(400px); transform:translateY(400px)">
     <span id="target5" style="display:inline-block; vertical-align:top; height:20px;"></span>
   </div>
   <div style="height:800px;"></div>
 </div>
 <div id="c6" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:200px;">
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/scroll_selection_into_view_window_frame.html
@@ -0,0 +1,6 @@
+<body style='margin:0; overflow:hidden;'>
+<div style='height:400px;'></div>
+<div><span id='target4'
+           style='display:inline-block; vertical-align:top; height:300px;'></span>
+</div>
+<div style='height:400px;'></div>
--- a/layout/base/tests/test_bug842853.html
+++ b/layout/base/tests/test_bug842853.html
@@ -35,16 +35,16 @@ function runTest() {
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script>
 
 var e = document.createElement('iframe');
-var url = 'data:text/html,<a href="%23anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>'
+var url = 'file_bug842853-frame.html';
 e.setAttribute('src',url);
 e.setAttribute('onload','runTest()');
 document.body.appendChild(e);
 
 </script>
 </body>
 </html>
--- a/layout/base/tests/test_bug849219.html
+++ b/layout/base/tests/test_bug849219.html
@@ -35,16 +35,16 @@ function runTest() {
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script>
 
 var e = document.createElement('iframe');
-var url = 'data:text/html,<a href="%23anchor">Click to scroll to anchor</a><div style="height:5000px"></div><a name="anchor">FAIL</a>'
+var url = 'file_bug842853-frame.html';
 e.setAttribute('src',url);
 e.setAttribute('onload','runTest()');
 document.body.appendChild(e);
 
 </script>
 </body>
 </html>
--- a/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
+++ b/layout/base/tests/test_getBoxQuads_convertPointRectQuad.html
@@ -229,17 +229,17 @@ em {
               border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow;
               margin:9px 10px 11px 12px; background:blue;">
   </div>
 </div>
 
 <div id="dUnrelated" style="width:50px; height:50px;"></div>
 
 <iframe id="f1" style="width:50px; height:50px; border:0; background:lime;"
-        src="data:text/html,<!DOCTYPE HTML><html style='padding:25px'><div id='f1d' style='position:absolute; left:14px; top:15px; width:16px; height:17px; background:pink'></div>">
+        src="file_getBoxQuads_convertPointRectQuad_frame1.html">
 </iframe>
 <!--
 It matters that the first part of this span is on the same line as the above <iframe>!
 That ensures the first quad's X position is not equal to the anonymous block's X position.
 -->
 <span id="ibSplit"
   ><em id="ibSplitPart1" style="width:100px;"></em
   ><div style="width:110px; height:20px; background:black"></div
@@ -681,17 +681,17 @@ function runTest() {
   checkQuadIsRect("svg", {box:"content"},
                   svgContainerX + 11, svgContainerY + 11, 200, 200);
 
   // XXX Test SVG text (probably broken; unclear what the best way is to handle it)
 
   // Test that converting between nodes in different toplevel browsing contexts
   // throws an exception.
   try {
-    openedWindow = window.open("data:text/html,<div id='d'>","");
+    openedWindow = window.open("file_getBoxQuads_convertPointRectQuad_frame2.html","");
   } catch (ex) {
     // in some cases we can't open the window.
     openedWindow = null;
   }
   if (openedWindow) {
     openedWindow.addEventListener("load", function() {
       checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError");
       checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError");
--- a/layout/base/tests/transformed_scrolling_repaints_3_window.html
+++ b/layout/base/tests/transformed_scrolling_repaints_3_window.html
@@ -2,75 +2,18 @@
 <html>
 <head>
   <title>Test that scaled elements with scrolled contents don't repaint unnecessarily when we scroll inside them</title>
   <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
 </head>
 <!-- Need a timeout here to allow paint unsuppression before we start the test -->
 <body onload="setTimeout(startTest,0)" style="background:white;">
 <iframe id="t" style="-moz-transform: scale(0.48979); -moz-transform-origin:top left; width:500px; height:600px;"
-        src="data:text/html,
-<body style='background:yellow;'>
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p id='e'>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-<p>My graduate adviser was the most patient, understanding, and helpful
-person I've ever had the joy of dealing with. That doesn't change that 
-there are some real dicks out there, and some of them happen to be 
-scientists.
-</body>"></iframe>
+        src="transformed_scrolling_repaints_3_window_frame.html">
+</iframe>
 <pre id="test">
 <script type="application/javascript">
 var SimpleTest = window.opener.SimpleTest;
 var SpecialPowers = window.opener.SpecialPowers;
 var is = window.opener.is;
 var t, e, utils, iterations;
 var smoothScrollPref = "general.smoothScroll";
 
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/transformed_scrolling_repaints_3_window_frame.html
@@ -0,0 +1,58 @@
+<body style='background:yellow;'>
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p id='e'>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+<p>My graduate adviser was the most patient, understanding, and helpful
+person I've ever had the joy of dealing with. That doesn't change that 
+there are some real dicks out there, and some of them happen to be 
+scientists.
+</body>
--- a/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly
+++ b/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly
@@ -25,14 +25,15 @@ ac_add_options --disable-stdcxx-compat
 
 # Don't autoclobber l10n, as this can lead to missing binaries and broken builds
 # Bug 1283438
 mk_add_options AUTOCLOBBER=
 
 # Disable Keyfile Loading (and checks) since l10n doesn't need these keys
 # This overrides the settings in the common android mozconfig
 ac_add_options --without-mozilla-api-keyfile
+ac_add_options --without-google-api-keyfile
 ac_add_options --without-adjust-sdk-keyfile
 ac_add_options --without-leanplum-sdk-keyfile
 # Similarly explicitly disable install tracking for l10n, we'll inherit from en-US
 export MOZ_INSTALL_TRACKING=
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-api-15/l10n-nightly
+++ b/mobile/android/config/mozconfigs/android-api-15/l10n-nightly
@@ -25,14 +25,15 @@ ac_add_options --disable-stdcxx-compat
 
 # Don't autoclobber l10n, as this can lead to missing binaries and broken builds
 # Bug 1283438
 mk_add_options AUTOCLOBBER=
 
 # Disable Keyfile Loading (and checks) since l10n doesn't need these keys
 # This overrides the settings in the common android mozconfig
 ac_add_options --without-mozilla-api-keyfile
+ac_add_options --without-google-api-keyfile
 ac_add_options --without-adjust-sdk-keyfile
 ac_add_options --without-leanplum-sdk-keyfile
 # Similarly explicitly disable install tracking for l10n, we'll inherit from en-US
 export MOZ_INSTALL_TRACKING=
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/common
+++ b/mobile/android/config/mozconfigs/common
@@ -36,16 +36,17 @@ ac_add_options --with-android-sdk="$tops
 
 if [ -z "$NO_NDK" ]; then
     ac_add_options --with-android-ndk="$topsrcdir/android-ndk"
     ac_add_options --with-android-gnu-compiler-version=4.9
 fi
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 
+ac_add_options --with-google-api-keyfile=/builds/gapi.data
 ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-fennec-geoloc-api.key
 
 # MOZ_INSTALL_TRACKING does not guarantee MOZ_UPDATE_CHANNEL will be set so we
 # provide a default state. Currently, the default state provides a default
 # keyfile because an assertion will be thrown if MOZ_INSTALL_TRACKING is
 # specified but a keyfile is not. This assertion can catch if we misconfigure a
 # release or beta build and it does not have a valid keyfile.
 #
--- a/mozglue/misc/StackWalk.cpp
+++ b/mozglue/misc/StackWalk.cpp
@@ -146,16 +146,21 @@ StackWalkInitCriticalAddress()
   r = pthread_mutex_lock(&mutex);
   MOZ_ASSERT(r == 0);
   struct timespec abstime = { 0, 1 };
   r = pthread_cond_timedwait_relative_np(&cond, &mutex, &abstime);
 
   // restore the previous malloc logger
   malloc_logger = old_malloc_logger;
 
+  // XXX: the critical address machinery appears to have been unnecessary since
+  // Mac OS 10.7 (the minimum version we currently support is 10.9). See bug
+  // 1384814 for details.
+  MOZ_DIAGNOSTIC_ASSERT(!gCriticalAddress.mAddr);
+
   MOZ_ASSERT(r == ETIMEDOUT);
   r = pthread_mutex_unlock(&mutex);
   MOZ_ASSERT(r == 0);
   r = pthread_mutex_destroy(&mutex);
   MOZ_ASSERT(r == 0);
   r = pthread_cond_destroy(&cond);
   MOZ_ASSERT(r == 0);
 }
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -1426,33 +1426,33 @@ nsStandardURL::CheckIfHostIsAscii()
 {
     nsresult rv;
     if (mCheckedIfHostA) {
         return NS_OK;
     }
 
     mCheckedIfHostA = true;
 
-    // If the hostname doesn't begin with `xn--` we are sure it is ASCII.
-    if (!StringBeginsWith(Host(), NS_LITERAL_CSTRING("xn--"))) {
-        return NS_OK;
-    }
-
     if (!gIDN) {
         return NS_ERROR_NOT_INITIALIZED;
     }
 
+    nsAutoCString displayHost;
     bool isAscii;
-    rv = gIDN->ConvertToDisplayIDN(Host(), &isAscii, mDisplayHost);
+    rv = gIDN->ConvertToDisplayIDN(Host(), &isAscii, displayHost);
     if (NS_FAILED(rv)) {
         mDisplayHost.Truncate();
         mCheckedIfHostA = false;
         return rv;
     }
 
+    if (!isAscii) {
+        mDisplayHost = displayHost;
+    }
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::GetDisplaySpec(nsACString &aUnicodeSpec)
 {
     CheckIfHostIsAscii();
     aUnicodeSpec.Assign(mSpec);
--- a/netwerk/test/unit/test_standardurl.js
+++ b/netwerk/test/unit/test_standardurl.js
@@ -520,16 +520,20 @@ add_test(function test_idna_host() {
   equal(url.asciiHostPort, "xn--lt-uia.example.org:8080");
   equal(url.asciiSpec, "http://user:password@xn--lt-uia.example.org:8080/path?query#etc");
 
   url.ref = ""; // SetRef calls InvalidateCache()
   equal(url.spec, "http://user:password@ält.example.org:8080/path?query");
   equal(url.displaySpec, "http://user:password@ält.example.org:8080/path?query");
   equal(url.asciiSpec, "http://user:password@xn--lt-uia.example.org:8080/path?query");
 
+  url = stringToURL("http://user:password@www.ält.com:8080/path?query#etc");
+  url.ref = "";
+  equal(url.spec, "http://user:password@www.ält.com:8080/path?query");
+
   // We also check that the default behaviour changes once we filp the pref
   gPrefs.setBoolPref("network.standard-url.punycode-host", true);
 
   url = stringToURL("http://user:password@ält.example.org:8080/path?query#etc");
   equal(url.host, "xn--lt-uia.example.org");
   equal(url.hostPort, "xn--lt-uia.example.org:8080");
   equal(url.prePath, "http://user:password@xn--lt-uia.example.org:8080");
   equal(url.spec, "http://user:password@xn--lt-uia.example.org:8080/path?query#etc");
@@ -544,10 +548,14 @@ add_test(function test_idna_host() {
   equal(url.asciiHostPort, "xn--lt-uia.example.org:8080");
   equal(url.asciiSpec, "http://user:password@xn--lt-uia.example.org:8080/path?query#etc");
 
   url.ref = ""; // SetRef calls InvalidateCache()
   equal(url.spec, "http://user:password@xn--lt-uia.example.org:8080/path?query");
   equal(url.displaySpec, "http://user:password@ält.example.org:8080/path?query");
   equal(url.asciiSpec, "http://user:password@xn--lt-uia.example.org:8080/path?query");
 
+  url = stringToURL("http://user:password@www.ält.com:8080/path?query#etc");
+  url.ref = "";
+  equal(url.spec, "http://user:password@www.xn--lt-uia.com:8080/path?query");
+
   run_next_test();
 });
--- a/testing/mozharness/configs/builds/releng_base_android_64_builds.py
+++ b/testing/mozharness/configs/builds/releng_base_android_64_builds.py
@@ -25,24 +25,28 @@ config = {
     'enable_signing': True,
     # mock shtuff
     'mock_mozilla_dir':  '/builds/mock_mozilla',
     'mock_target': 'mozilla-centos6-x86_64-android',
     'mock_files': [
         ('/home/cltbld/.ssh', '/home/mock_mozilla/.ssh'),
         ('/home/cltbld/.hgrc', '/builds/.hgrc'),
         ('/home/cltbld/.boto', '/builds/.boto'),
+        ('/builds/gapi.data', '/builds/gapi.data'),
         ('/builds/relengapi.tok', '/builds/relengapi.tok'),
         ('/tools/tooltool.py', '/builds/tooltool.py'),
         ('/builds/mozilla-api.key', '/builds/mozilla-api.key'),
         ('/builds/mozilla-fennec-geoloc-api.key', '/builds/mozilla-fennec-geoloc-api.key'),
         ('/builds/crash-stats-api.token', '/builds/crash-stats-api.token'),
         ('/usr/local/lib/hgext', '/usr/local/lib/hgext'),
     ],
     'secret_files': [
+        {'filename': '/builds/gapi.data',
+         'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/gapi.data',
+         'min_scm_level': 1},
         {'filename': '/builds/mozilla-fennec-geoloc-api.key',
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/mozilla-fennec-geoloc-api.key',
          'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
         {'filename': '/builds/adjust-sdk.token',
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk.token',
          'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
         {'filename': '/builds/adjust-sdk-beta.token',
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk-beta.token',
--- a/toolkit/components/places/PageIconProtocolHandler.js
+++ b/toolkit/components/places/PageIconProtocolHandler.js
@@ -97,16 +97,17 @@ PageIconProtocolHandler.prototype = {
       let pageURI = NetUtil.newURI(uri.path.replace(/[&#]size=[^&]+$/, ""));
       let preferredSize = PlacesUtils.favicons.preferredSizeFromURI(uri);
       PlacesUtils.favicons.getFaviconDataForPage(pageURI, (iconURI, len, data, mimeType) => {
         if (len == 0) {
           streamDefaultFavicon(uri, loadInfo, pipe.outputStream, channel);
         } else {
           try {
             channel.contentType = mimeType;
+            channel.contentLength = len;
             serveIcon(pipe, data, len);
           } catch (ex) {
             streamDefaultFavicon(uri, loadInfo, pipe.outputStream, channel);
           }
         }
       }, preferredSize);
 
       return channel;