Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 09 Feb 2017 17:01:39 -0800
changeset 341710 25a94c1047e793ef096d8556fa3c26dd72bd37d7
parent 341678 00beaa76c5b155d249bc26ab6f2c9dcf6b5d7447 (current diff)
parent 341709 db62e3ac853f7c4d8f045629358264ebf822398c (diff)
child 341736 d362fcfd6f331119c081f2b22f77baee914b7a38
child 341777 e5fbb4e42df979dc3412e3eb6f574bfc7d9e0749
push id31341
push userkwierso@gmail.com
push dateFri, 10 Feb 2017 01:01:45 +0000
treeherdermozilla-central@25a94c1047e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
25a94c1047e7 / 54.0a1 / 20170210110240 / files
nightly linux64
25a94c1047e7 / 54.0a1 / 20170210110240 / files
nightly mac
25a94c1047e7 / 54.0a1 / 20170210030206 / files
nightly win32
25a94c1047e7 / 54.0a1 / 20170210030206 / files
nightly win64
25a94c1047e7 / 54.0a1 / 20170210030206 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to central, a=merge MozReview-Commit-ID: 9TTIrjfNKZm
dom/base/test/file_bug1263696_frame_fail.html
dom/base/test/file_bug1263696_frame_pass.html
dom/base/test/test_bug1263696.html
layout/reftests/forms/input/checkbox/checked-notref.html
layout/reftests/forms/input/checkbox/checked.html
layout/reftests/forms/input/radio/checked-notref.html
layout/reftests/forms/input/radio/checked.html
testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html
testing/web-platform/tests/html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html
testing/web-platform/tests/service-workers/service-worker/resources/get-host-info.sub.js
--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -1,14 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// This test checks that a <select> with an <optgroup> opens and can be navigated
-// in a child process. This is different than single-process as a <menulist> is used
-// to implement the dropdown list.
+// This test tests <select> in a child process. This is different than
+// single-process as a <menulist> is used to implement the dropdown list.
 
 requestLongerTimeout(2);
 
 const XHTML_DTD = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
 
 const PAGECONTENT =
   "<html xmlns='http://www.w3.org/1999/xhtml'>" +
   "<body onload='gChangeEvents = 0;gInputEvents = 0; gClickEvents = 0; document.body.firstChild.focus()'>" +
@@ -846,8 +845,40 @@ add_task(function* test_colors_applied_t
     testOptionColors(idx, child, menulist);
     idx++;
     child = child.nextSibling;
   }
 
   yield hideSelectPopup(selectPopup, "escape");
   yield BrowserTestUtils.removeTab(tab);
 });
+
+// This test checks that the popup is closed when the select element is blurred.
+add_task(function* test_blur_hides_popup() {
+  const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
+
+  yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+    content.addEventListener("blur", function(event) {
+      event.preventDefault();
+      event.stopPropagation();
+    }, true);
+
+    content.document.getElementById("one").focus();
+  });
+
+  let menulist = document.getElementById("ContentSelectDropdown");
+  let selectPopup = menulist.menupopup;
+
+  yield openSelectPopup(selectPopup);
+
+  let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
+
+  yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+    content.document.getElementById("one").blur();
+  });
+
+  yield popupHiddenPromise;
+
+  ok(true, "Blur closed popup");
+
+  yield BrowserTestUtils.removeTab(tab);
+});
--- a/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
@@ -28,19 +28,20 @@
 "algorithm": "sha512",
 "visibility": "public",
 "filename": "sccache2.tar.xz",
 "unpack": true,
 "digest": "b89c40dbf28c2bd54fadf017c15a8789f6e7611252a623cc3a1507e3dd6fc9e5a50d746e81776ba856e33fdc99b4a6413ba7c3ac0aed5f4835705da2b758ef22",
 "size": 1020700
 },
 {
-"size": 57060,
+"version": "https://github.com/andreas56/libdmg-hfsplus rev 81dd75fd1549b24bf8af9736ac25518b367e6b63",
+"size": 62032,
 "visibility": "public",
-"digest": "9649ca595f4cf088d118da26201f92cc94cda7af49c7c48112ee31cd13c83b2935b3e145de9dd78060cff2480b4c2e7ff5fb24235876956fed13c87852071998",
+"digest": "9073c41034784eb8823ec817aed42bbc65c8da63ad3fac572726fa48b36320ee302ca8f51b23576e7fdbeec6ab300610d0c58bbd9c52024577dfdb13d95aa2ec",
 "algorithm": "sha512",
 "unpack": true,
 "filename": "dmg.tar.xz"
 },
 {
 "version": "rustc 1.14.0 (e8a012324 2016-12-16) repack",
 "size": 152573516,
 "digest": "eef2f10bf57005d11c34b9b49eb76d0f09d026295055039fea89952a3be51580abdab29366278ed4bfa393b33c5cee4d51d3af4221e9e7d7d833d0fc1347597c",
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -83,32 +83,26 @@
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/PluginCrashedEvent.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLSharedObjectElement.h"
+#include "mozilla/dom/HTMLObjectElement.h"
 #include "nsChannelClassifier.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #ifdef CreateEvent
 #undef CreateEvent
 #endif
 #endif // XP_WIN
 
-#ifdef XP_MACOSX
-// HandlePluginCrashed() and HandlePluginInstantiated() needed from here to
-// fix bug 1147521.  Should later be replaced by proper interface methods,
-// maybe on nsIObjectLoadingContext.
-#include "mozilla/dom/HTMLObjectElement.h"
-#endif
-
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 static const char *kPrefJavaMIME = "plugin.java.mime";
 static const char *kPrefYoutubeRewrite = "plugins.rewrite_youtube_embeds";
 static const char *kPrefBlockURIs = "browser.safebrowsing.blockedURIs.enabled";
 static const char *kPrefFavorFallbackMode = "plugins.favorfallback.mode";
 static const char *kPrefFavorFallbackRules = "plugins.favorfallback.rules";
 
@@ -3013,50 +3007,53 @@ nsObjectLoadingContent::LoadFallback(Fal
 
   NS_ASSERTION(!mInstanceOwner && !mFrameLoader && !mChannel,
                "LoadFallback called with loaded content");
 
   //
   // Fixup mFallbackType
   //
   nsCOMPtr<nsIContent> thisContent =
-  do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
 
   if (!thisContent->IsHTMLElement() || mContentType.IsEmpty()) {
     // Don't let custom fallback handlers run outside HTML, tags without a
     // determined type should always just be alternate content
     aType = eFallbackAlternate;
   }
 
   // We'll set this to null no matter what now, doing it here means we'll load
   // child embeds as we find them in the upcoming loop.
   mType = eType_Null;
 
-  // Do a breadth-first traverse of node tree with the current element as root,
-  // looking for the first embed we can find.
+  bool thisIsObject = thisContent->IsHTMLElement(nsGkAtoms::object);
+
+  // Do a depth-first traverse of node tree with the current element as root,
+  // looking for <embed> or <object> elements that might now need to load.
   nsTArray<nsINodeList*> childNodes;
   if ((thisContent->IsHTMLElement(nsGkAtoms::object) ||
        thisContent->IsHTMLElement(nsGkAtoms::applet)) &&
       (aType == eFallbackUnsupported ||
        aType == eFallbackDisabled ||
        aType == eFallbackBlocklisted ||
        aType == eFallbackAlternate))
   {
     for (nsIContent* child = thisContent->GetFirstChild(); child;
          child = child->GetNextNode(thisContent)) {
       if (aType != eFallbackAlternate &&
           !child->IsHTMLElement(nsGkAtoms::param) &&
           nsStyleUtil::IsSignificantChild(child, true, false)) {
         aType = eFallbackAlternate;
       }
-      if (child->IsHTMLElement(nsGkAtoms::embed) &&
-          thisContent->IsHTMLElement(nsGkAtoms::object)) {
-        HTMLSharedObjectElement* object = static_cast<HTMLSharedObjectElement*>(child);
-        if (object) {
+      if (thisIsObject) {
+        if (child->IsHTMLElement(nsGkAtoms::embed)) {
+          HTMLSharedObjectElement* embed = static_cast<HTMLSharedObjectElement*>(child);
+          embed->StartObjectLoad(true, true);
+        } else if (auto object = HTMLObjectElement::FromContent(child)) {
           object->StartObjectLoad(true, true);
         }
       }
     }
   }
 
   mFallbackType = aType;
 
@@ -3812,16 +3809,48 @@ nsObjectLoadingContent::MaybeFireErrorEv
     RefPtr<AsyncEventDispatcher> loadBlockingAsyncDispatcher =
       new LoadBlockingAsyncEventDispatcher(thisContent,
                                            NS_LITERAL_STRING("error"),
                                            false, false);
     loadBlockingAsyncDispatcher->PostDOMEvent();
   }
 }
 
+bool
+nsObjectLoadingContent::BlockEmbedOrObjectContentLoading()
+{
+  nsCOMPtr<nsIContent> thisContent =
+    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  if (!thisContent->IsHTMLElement(nsGkAtoms::embed) &&
+      !thisContent->IsHTMLElement(nsGkAtoms::object)) {
+    // Doesn't apply to other elements (i.e. <applet>)
+    return false;
+  }
+
+  // Traverse up the node tree to see if we have any ancestors that may block us
+  // from loading
+  for (nsIContent* parent = thisContent->GetParent();
+       parent;
+       parent = parent->GetParent()) {
+    if (parent->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
+      return true;
+    }
+    // If we have an ancestor that is an object with a source, it'll have an
+    // associated displayed type. If that type is not null, don't load content
+    // for the embed.
+    if (HTMLObjectElement* object = HTMLObjectElement::FromContent(parent)) {
+      uint32_t type = object->DisplayedType();
+      if (type != eType_Null) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 // SetupProtoChainRunner implementation
 nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
     nsObjectLoadingContent* aContent)
   : mContent(aContent)
 {
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -329,16 +329,31 @@ class nsObjectLoadingContent : public ns
     void UnbindFromTree(bool aDeep = true,
                         bool aNullParent = true);
 
     /**
      * Return the content policy type used for loading the element.
      */
     virtual nsContentPolicyType GetContentPolicyType() const = 0;
 
+    /**
+     * Decides whether we should load <embed>/<object> node content.
+     *
+     * If this is an <embed> or <object> node there are cases in which we should
+     * not try to load the content:
+     *
+     * - If the node is the child of a media element
+     * - If the node is the child of an <object> node that already has
+     *   content being loaded.
+     *
+     * In these cases, this function will return false, which will cause
+     * us to skip calling LoadObject.
+     */
+    bool BlockEmbedOrObjectContentLoading();
+
   private:
 
     // Object parameter changes returned by UpdateObjectParameters
     enum ParameterUpdateFlags {
       eParamNoChange           = 0,
       // Parameters that potentially affect the channel changed
       // - mOriginalURI, mOriginalContentType
       eParamChannelChanged     = 1u << 0,
deleted file mode 100644
--- a/dom/base/test/file_bug1263696_frame_fail.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/REC-html401-19991224/strict.dtd">
-<html>
- <head>
-  <title>Bug 1263696 - iframe that should not be loaded</title>
- </head>
- <body>
-   <script>
-    parent.SimpleTest.ok(false, "this iframe should not load");
-   </script>
- </body>
-</html>
deleted file mode 100644
--- a/dom/base/test/file_bug1263696_frame_pass.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/REC-html401-19991224/strict.dtd">
-<html>
- <head>
-  <title>Bug 1263696 - iframe that should be loaded</title>
- </head>
- <body>
-   <script>
-    parent.index = parent.index + 1;
-    parent.SimpleTest.ok(true, "this iframe should load");
-   </script>
- </body>
-</html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -120,18 +120,16 @@ support-files =
   file_bug787778.sjs
   file_bug804395.jar
   file_bug869432.eventsource
   file_bug869432.eventsource^headers^
   file_bug902350.html
   file_bug902350_frame.html
   file_bug907892.html
   file_bug945152.jar
-  file_bug1263696_frame_pass.html
-  file_bug1263696_frame_fail.html
   file_bug1274806.html
   file_general_document.html
   file_htmlserializer_1.html
   file_htmlserializer_1_bodyonly.html
   file_htmlserializer_1_format.html
   file_htmlserializer_1_linebreak.html
   file_htmlserializer_1_links.html
   file_htmlserializer_1_nested_body.html
@@ -582,17 +580,16 @@ skip-if = toolkit == 'android'
 [test_bug1126851.html]
 [test_bug1163743.html]
 [test_bug1165501.html]
 [test_bug1187157.html]
 [test_bug1198095.html]
 [test_bug1238440.html]
 [test_bug1250148.html]
 [test_bug1259588.html]
-[test_bug1263696.html]
 [test_bug1268962.html]
 [test_bug1274806.html]
 [test_bug1281963.html]
 [test_bug1295852.html]
 [test_bug1307730.html]
 [test_bug1308069.html]
 [test_bug1314032.html]
 [test_bug1318303.html]
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -74,17 +74,17 @@ HTMLObjectElement::IsDoneAddingChildren(
 void
 HTMLObjectElement::DoneAddingChildren(bool aHaveNotified)
 {
   mIsDoneAddingChildren = true;
 
   // If we're already in a document, we need to trigger the load
   // Otherwise, BindToTree takes care of that.
   if (IsInComposedDoc()) {
-    StartObjectLoad(aHaveNotified);
+    StartObjectLoad(aHaveNotified, false);
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLObjectElement,
                                                   nsGenericHTMLFormElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
@@ -305,34 +305,36 @@ HTMLObjectElement::SetAttr(int32_t aName
   // if aNotify is false, we are coming from the parser or some such place;
   // we'll get bound after all the attributes have been set, so we'll do the
   // object load from BindToTree/DoneAddingChildren.
   // Skip the LoadObject call in that case.
   // We also don't want to start loading the object when we're not yet in
   // a document, just in case that the caller wants to set additional
   // attributes before inserting the node into the document.
   if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren &&
-      aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) {
+      aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data &&
+      !BlockEmbedOrObjectContentLoading()) {
     return LoadObject(aNotify, true);
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify)
 {
   nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID,
                                                     aAttribute, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // See comment in SetAttr
   if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren &&
-      aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) {
+      aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data &&
+      !BlockEmbedOrObjectContentLoading()) {
     return LoadObject(aNotify, true);
   }
 
   return NS_OK;
 }
 
 bool
 HTMLObjectElement::IsFocusableForTabIndex()
@@ -530,25 +532,26 @@ HTMLObjectElement::IsAttributeMapped(con
 
 nsMapRuleToAttributesFunc
 HTMLObjectElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 void
-HTMLObjectElement::StartObjectLoad(bool aNotify)
+HTMLObjectElement::StartObjectLoad(bool aNotify, bool aForce)
 {
   // BindToTree can call us asynchronously, and we may be removed from the tree
   // in the interim
-  if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) {
+  if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
+      BlockEmbedOrObjectContentLoading()) {
     return;
   }
 
-  LoadObject(aNotify);
+  LoadObject(aNotify, aForce);
   SetIsNetworkCreated(false);
 }
 
 EventStates
 HTMLObjectElement::IntrinsicState() const
 {
   return nsGenericHTMLFormElement::IntrinsicState() | ObjectState();
 }
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -93,17 +93,17 @@ public:
 
   // nsObjectLoadingContent
   virtual uint32_t GetCapabilities() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   nsresult CopyInnerTo(Element* aDest);
 
-  void StartObjectLoad() { StartObjectLoad(true); }
+  void StartObjectLoad() { StartObjectLoad(true, false); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLObjectElement,
                                            nsGenericHTMLFormElement)
 
   // Web IDL binding methods
   // XPCOM GetData is ok; note that it's a URI attribute with a weird base URI
   void SetData(const nsAString& aValue, ErrorResult& aRv)
   {
@@ -242,22 +242,22 @@ public:
   }
 
   nsIDocument*
   GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
   {
     return GetContentDocument(aSubjectPrincipal);
   }
 
-private:
   /**
    * Calls LoadObject with the correct arguments to start the plugin load.
    */
-  void StartObjectLoad(bool aNotify);
+  void StartObjectLoad(bool aNotify, bool aForceLoad);
 
+private:
   /**
    * Returns if the element is currently focusable regardless of it's tabindex
    * value. This is used to know the default tabindex value.
    */
   bool IsFocusableForTabIndex();
 
   nsContentPolicyType GetContentPolicyType() const override
   {
--- a/dom/html/HTMLSharedObjectElement.cpp
+++ b/dom/html/HTMLSharedObjectElement.cpp
@@ -175,17 +175,17 @@ HTMLSharedObjectElement::SetAttr(int32_t
   // we'll get bound after all the attributes have been set, so we'll do the
   // object load from BindToTree/DoneAddingChildren.
   // Skip the LoadObject call in that case.
   // We also don't want to start loading the object when we're not yet in
   // a document, just in case that the caller wants to set additional
   // attributes before inserting the node into the document.
   if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren &&
       aNameSpaceID == kNameSpaceID_None && aName == URIAttrName()
-      && !BlockEmbedContentLoading()) {
+      && !BlockEmbedOrObjectContentLoading()) {
     return LoadObject(aNotify, true);
   }
 
   return NS_OK;
 }
 
 bool
 HTMLSharedObjectElement::IsHTMLFocusable(bool aWithMouse,
@@ -308,17 +308,17 @@ HTMLSharedObjectElement::GetAttributeMap
 }
 
 void
 HTMLSharedObjectElement::StartObjectLoad(bool aNotify, bool aForceLoad)
 {
   // BindToTree can call us asynchronously, and we may be removed from the tree
   // in the interim
   if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
-      BlockEmbedContentLoading()) {
+      BlockEmbedOrObjectContentLoading()) {
     return;
   }
 
   LoadObject(aNotify, aForceLoad);
   SetIsNetworkCreated(false);
 }
 
 EventStates
@@ -384,36 +384,10 @@ HTMLSharedObjectElement::GetContentPolic
     // through RequestContext yet.
     return nsIContentPolicy::TYPE_INTERNAL_OBJECT;
   } else {
     MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed));
     return nsIContentPolicy::TYPE_INTERNAL_EMBED;
   }
 }
 
-bool
-HTMLSharedObjectElement::BlockEmbedContentLoading()
-{
-  // Only check on embed elements
-  if (!IsHTMLElement(nsGkAtoms::embed)) {
-    return false;
-  }
-  // Traverse up the node tree to see if we have any ancestors that may block us
-  // from loading
-  for (nsIContent* parent = GetParent(); parent; parent = parent->GetParent()) {
-    if (parent->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
-      return true;
-    }
-    // If we have an ancestor that is an object with a source, it'll have an
-    // associated displayed type. If that type is not null, don't load content
-    // for the embed.
-    if (HTMLObjectElement* object = HTMLObjectElement::FromContent(parent)) {
-      uint32_t type = object->DisplayedType();
-      if (type != eType_Null) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLSharedObjectElement.h
+++ b/dom/html/HTMLSharedObjectElement.h
@@ -215,29 +215,14 @@ private:
   // mIsDoneAddingChildren is only really used for <applet>.  This boolean is
   // always true for <embed>, per the documentation in nsIContent.h.
   bool mIsDoneAddingChildren;
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
-
-  /**
-   * Decides whether we should load embed node content.
-   *
-   * If this is an embed node there are cases in which we should not try to load
-   * the content:
-   *
-   * - If the embed node is the child of a media element
-   * - If the embed node is the child of an object node that already has
-   *   content being loaded.
-   *
-   * In these cases, this function will return false, which will cause
-   * us to skip calling LoadObject.
-   */
-  bool BlockEmbedContentLoading();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedObjectElement_h
--- a/dom/tests/mochitest/general/resource_timing_cross_origin.html
+++ b/dom/tests/mochitest/general/resource_timing_cross_origin.html
@@ -165,23 +165,23 @@ function finishTests() {
 <body>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=822480"
      title="Add resource timing API.">
     Bug #822480 -  Add in the Resource Timing API
   </a>
   <p id="display"></p>
   <div id="content">
-    <object data="http://mochi.test:8888/tests/dom/tests/mochitest/general/res0.resource"> <!-- same origin, no header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res0.resource"> <!-- cross origin, no header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res1.resource"> <!-- cross origin, Timing-Allow-Origin: * header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res2.resource"> <!-- cross origin redirect to test2.example.com, no header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res3.resource"> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8888 header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res4.resource"> <!-- cross origin redirect to mochi.test:8888/.../res1.resource, Timing-Allow-Origin: * -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res5.resource"> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8889 -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res6.resource"> <!-- cross origin, Timing-Allow-Origin: "" (empty string) -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res7.resource"> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8888 http://test1.com header -->
-    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res8.resource"> <!-- double cross origin redirect -->
+    <object data="http://mochi.test:8888/tests/dom/tests/mochitest/general/res0.resource"></object> <!-- same origin, no header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res0.resource"></object> <!-- cross origin, no header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res1.resource"></object> <!-- cross origin, Timing-Allow-Origin: * header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res2.resource"></object> <!-- cross origin redirect to test2.example.com, no header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res3.resource"></object> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8888 header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res4.resource"></object> <!-- cross origin redirect to mochi.test:8888/.../res1.resource, Timing-Allow-Origin: * -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res5.resource"></object> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8889 -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res6.resource"></object> <!-- cross origin, Timing-Allow-Origin: "" (empty string) -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res7.resource"></object> <!-- cross origin, Timing-Allow-Origin: http://mochi.test:8888 http://test1.com header -->
+    <object data="http://test1.example.com/tests/dom/tests/mochitest/general/res8.resource"></object> <!-- double cross origin redirect -->
     <script type="text/javascript" src="http://mochi.test:8888/tests/dom/tests/mochitest/general/resource_timing.js"></script> <!-- same origin script -->
   </div>
 </body>
 
 </html>
--- a/dom/tests/mochitest/general/test_focusrings.xul
+++ b/dom/tests/mochitest/general/test_focusrings.xul
@@ -163,13 +163,13 @@ SimpleTest.waitForFocus(runTest);
 
 <listbox id="l1" class="plain" height="20"/>
 <listbox id="l2" class="plain" height="20"/>
 <listbox id="l3" class="plain" height="20"/>
 <button id="b1" label="Button"/>
 <button id="b2" label="Button"/>
 <button id="b3" label="Button"/>
 
-<iframe id="child" src="data:text/html,&lt;html&gt;&lt;style&gt;* { outline: none; -moz-appearance: none; } %23elem:focus { outline: 2px solid red; } %23elem:-moz-focusring { outline: 1px solid blue; }&lt;/style&gt;&lt;div id='container'&gt;&lt;/html&gt;"/>
+<iframe id="child" src="data:text/html,&lt;html&gt;&lt;style&gt;* { outline: none; -moz-appearance: none; min-width:10px; min-height:10px; } %23elem:focus { outline: 2px solid red; } %23elem:-moz-focusring { outline: 1px solid blue; }&lt;/style&gt;&lt;div id='container'&gt;&lt;/html&gt;"/>
 
 <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
 
 </window>
--- a/dom/url/URL.h
+++ b/dom/url/URL.h
@@ -146,16 +146,22 @@ public:
   virtual void
   SetHash(const nsAString& aHash, ErrorResult& aRv) = 0;
 
   void Stringify(nsAString& aRetval, ErrorResult& aRv) const
   {
     GetHref(aRetval, aRv);
   }
 
+  void
+  ToJSON(nsAString& aResult, ErrorResult& aRv) const
+  {
+    GetHref(aResult, aRv);
+  }
+
   // URLSearchParamsObserver
   void
   URLSearchParamsUpdated(URLSearchParams* aSearchParams) override;
 
 protected:
   virtual ~URL()
   {}
 
--- a/dom/url/tests/test_url.html
+++ b/dom/url/tests/test_url.html
@@ -445,10 +445,16 @@
     url.search = "";
     is(url.href, "scheme:path#newhash");
 
     // we don't implement a spec-compliant parser yet.
     // make sure we are bug compatible with existing implementations.
     url = new URL("data:text/html,<a href=\"http://example.org/?q\">Link</a>");
     is(url.href, "data:text/html,<a%20href=\"http://example.org/?q\">Link</a>");
   </script>
+
+  <script>
+    var u = new URL('http://www.example.org');
+    ok(u.toJSON(), 'http://www.example.org', "URL.toJSON()");
+    is(JSON.stringify(u), "\"http://www.example.org/\"", "JSON.stringify(u) works");
+  </script>
 </body>
 </html>
--- a/dom/webidl/URL.webidl
+++ b/dom/webidl/URL.webidl
@@ -39,19 +39,22 @@ interface URL {
   [Throws]
            attribute USVString hostname;
   [Throws]
            attribute USVString port;
   [Throws]
            attribute USVString pathname;
   [Throws]
            attribute USVString search;
-  readonly attribute URLSearchParams searchParams;
+  [SameObject] readonly attribute URLSearchParams searchParams;
   [Throws]
            attribute USVString hash;
+
+  [Throws]
+  USVString toJSON();
 };
 
 partial interface URL {
   [Throws]
   static DOMString createObjectURL(Blob blob);
   [Throws]
   static DOMString createObjectURL(MediaStream stream);
   [Throws]
--- a/editor/reftests/reftest-stylo.list
+++ b/editor/reftests/reftest-stylo.list
@@ -83,17 +83,17 @@ fails needs-focus == spellcheck-non-lati
 fails needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean.html
 fails == unneeded_scroll.html unneeded_scroll.html
 # == caret_on_presshell_reinit.html caret_on_presshell_reinit.html
 # == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-2.html
 fails == 642800.html 642800.html
 fails == selection_visibility_after_reframe.html selection_visibility_after_reframe.html
 fails == selection_visibility_after_reframe-2.html selection_visibility_after_reframe-2.html
 fails == selection_visibility_after_reframe-3.html selection_visibility_after_reframe-3.html
-fails == 672709.html 672709.html
+== 672709.html 672709.html
 fails == 338427-1.html 338427-1.html
 fails == 674212-spellcheck.html 674212-spellcheck.html
 fails == 338427-2.html 338427-2.html
 fails == 338427-3.html 338427-3.html
 fails == 462758-grabbers-resizers.html 462758-grabbers-resizers.html
 fails == readwrite-non-editable.html readwrite-non-editable.html
 fails == readwrite-editable.html readwrite-editable.html
 fails == readonly-non-editable.html readonly-non-editable.html
--- a/gfx/tests/crashtests/crashtests.list
+++ b/gfx/tests/crashtests/crashtests.list
@@ -102,19 +102,19 @@ load 691581-1.html
 load 693143-1.html
 load 696936-1.html
 load 699563-1.html
 load 710149-1.html
 asserts-if(stylo,1) load 766452-1.html # bug 1324700
 load 766452-2.html
 load 768079-1.html
 asserts-if(stylo,2) load 783041-1.html # bug 1324661
-load 783041-2.html
-asserts-if(stylo,1) load 783041-3.html # bug 1324671
-load 783041-4.html
+asserts-if(stylo,2) load 783041-2.html # bug 1324661
+asserts-if(stylo,3) load 783041-3.html # bug 1324671
+asserts-if(stylo,2) load 783041-4.html # bug 1324661
 load 798853.html # bug 868792
 load 805760-1.html
 skip-if(Android) load 815489.html # bug 1216304
 load 836225-1.html
 load 839745-1.html
 load 856784-1.html
 load 893572-1.html
 load 893572-2.html
--- a/image/decoders/icon/mac/nsIconChannelCocoa.mm
+++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm
@@ -225,41 +225,52 @@ nsIconChannel::AsyncOpen(nsIStreamListen
              mLoadInfo->GetSecurityMode() == 0 ||
              mLoadInfo->GetInitialSecurityCheckDone() ||
              (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
               nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
              "security flags in loadInfo but asyncOpen2() not called");
 
   nsCOMPtr<nsIInputStream> inStream;
   nsresult rv = MakeInputStream(getter_AddRefs(inStream), true);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+      mCallbacks = nullptr;
+      return rv;
+  }
 
   // Init our stream pump
   rv = mPump->Init(inStream, int64_t(-1), int64_t(-1), 0, 0, false);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+      mCallbacks = nullptr;
+      return rv;
+  }
 
   rv = mPump->AsyncRead(this, ctxt);
   if (NS_SUCCEEDED(rv)) {
     // Store our real listener
     mListener = aListener;
     // Add ourself to the load group, if available
     if (mLoadGroup) {
       mLoadGroup->AddRequest(this, nullptr);
     }
+  } else {
+      mCallbacks = nullptr;
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+      mCallbacks = nullptr;
+      return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 nsresult
 nsIconChannel::MakeInputStream(nsIInputStream** _retval,
                                         bool aNonBlocking)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
--- a/image/decoders/icon/win/nsIconChannel.cpp
+++ b/image/decoders/icon/win/nsIconChannel.cpp
@@ -240,43 +240,51 @@ nsIconChannel::AsyncOpen(nsIStreamListen
              mLoadInfo->GetInitialSecurityCheckDone() ||
              (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
               nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
              "security flags in loadInfo but asyncOpen2() not called");
 
   nsCOMPtr<nsIInputStream> inStream;
   nsresult rv = MakeInputStream(getter_AddRefs(inStream), true);
   if (NS_FAILED(rv)) {
+    mCallbacks = nullptr;
     return rv;
   }
 
   // Init our streampump
   rv = mPump->Init(inStream, int64_t(-1), int64_t(-1), 0, 0, false);
   if (NS_FAILED(rv)) {
+    mCallbacks = nullptr;
     return rv;
   }
 
   rv = mPump->AsyncRead(this, ctxt);
   if (NS_SUCCEEDED(rv)) {
     // Store our real listener
     mListener = aListener;
     // Add ourself to the load group, if available
     if (mLoadGroup) {
       mLoadGroup->AddRequest(this, nullptr);
     }
+  } else {
+    mCallbacks = nullptr;
   }
+
   return rv;
 }
 
 NS_IMETHODIMP
 nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mCallbacks = nullptr;
+    return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 static DWORD
 GetSpecialFolderIcon(nsIFile* aFile, int aFolder,
                                   SHFILEINFOW* aSFI, UINT aInfoFlags)
 {
   DWORD shellResult = 0;
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2150,17 +2150,17 @@ SetJitCompilerOption(JSContext* cx, unsi
     if (number < 0)
         number = -1;
 
     // Throw if disabling the JITs and there's JIT code on the stack, to avoid
     // assertion failures.
     if ((opt == JSJITCOMPILER_BASELINE_ENABLE || opt == JSJITCOMPILER_ION_ENABLE) &&
         number == 0)
     {
-        js::jit::JitActivationIterator iter(cx->runtime());
+        js::jit::JitActivationIterator iter(cx);
         if (!iter.done()) {
             JS_ReportErrorASCII(cx, "Can't turn off JITs with JIT code on the stack.");
             return false;
         }
     }
 
     JS_SetGlobalJitCompilerOption(cx, opt, uint32_t(number));
 
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -42,16 +42,17 @@ class MOZ_RAII AutoTraceSession
     JSRuntime* runtime;
 
   private:
     AutoTraceSession(const AutoTraceSession&) = delete;
     void operator=(const AutoTraceSession&) = delete;
 
     JS::HeapState prevState;
     AutoGeckoProfilerEntry pseudoFrame;
+    JSRuntime::AutoProhibitActiveContextChange prohibitActiveContextChange;
 };
 
 class MOZ_RAII AutoPrepareForTracing
 {
     mozilla::Maybe<AutoTraceSession> session_;
 
   public:
     AutoPrepareForTracing(JSContext* cx, ZoneSelector selector);
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -980,17 +980,17 @@ class GCRuntime
 
   public:
     JSRuntime* const rt;
 
     /* Embedders can use this zone however they wish. */
     UnprotectedData<JS::Zone*> systemZone;
 
     // List of all zone groups (protected by the GC lock).
-    ActiveThreadData<ZoneGroupVector> groups;
+    ActiveThreadOrGCTaskData<ZoneGroupVector> groups;
 
     // The unique atoms zone, which has no zone group.
     WriteOnceData<Zone*> atomsZone;
 
   private:
     UnprotectedData<gcstats::Statistics> stats_;
   public:
     gcstats::Statistics& stats() { return stats_.ref(); }
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -541,17 +541,17 @@ js::Nursery::maybeEndProfile(ProfileKey 
     if (enableProfiling_)
         endProfile(key);
 }
 
 void
 js::Nursery::collect(JS::gcreason::Reason reason)
 {
     MOZ_ASSERT(!TlsContext.get()->suppressGC);
-    MOZ_RELEASE_ASSERT(TlsContext.get() == zoneGroup()->context);
+    MOZ_RELEASE_ASSERT(zoneGroup()->ownedByCurrentThread());
 
     if (!isEnabled() || isEmpty()) {
         // Our barriers are not always exact, and there may be entries in the
         // storebuffer even when the nursery is disabled or empty. It's not safe
         // to keep these entries as they may refer to tenured cells which may be
         // freed after this point.
         zoneGroup()->storeBuffer().clear();
     }
@@ -722,17 +722,17 @@ js::Nursery::doCollection(JS::gcreason::
     // Sweep compartments to update the array buffer object's view lists.
     maybeStartProfile(ProfileKey::SweepArrayBufferViewList);
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
         c->sweepAfterMinorGC(&mover);
     maybeEndProfile(ProfileKey::SweepArrayBufferViewList);
 
     // Update any slot or element pointers whose destination has been tenured.
     maybeStartProfile(ProfileKey::UpdateJitActivations);
-    js::jit::UpdateJitActivationsForMinorGC(rt, &mover);
+    js::jit::UpdateJitActivationsForMinorGC(zoneGroup(), &mover);
     forwardedBuffers.finish();
     maybeEndProfile(ProfileKey::UpdateJitActivations);
 
     maybeStartProfile(ProfileKey::ObjectsTenuredCallback);
     rt->gc.callObjectsTenuredCallback();
     maybeEndProfile(ProfileKey::ObjectsTenuredCallback);
 
     // Sweep.
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -320,19 +320,22 @@ void
 js::gc::GCRuntime::traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrMark,
                                       AutoLockForExclusiveAccess& lock)
 {
     MOZ_ASSERT(!TlsContext.get()->suppressGC);
 
     {
         gcstats::AutoPhase ap(stats(), gcstats::PHASE_MARK_STACK);
 
-        // Trace active interpreter and JIT stack roots.
-        TraceInterpreterActivations(rt, trc);
-        jit::TraceJitActivations(rt, trc);
+        JSContext* cx = TlsContext.get();
+        for (const CooperatingContext& target : rt->cooperatingContexts()) {
+            // Trace active interpreter and JIT stack roots.
+            TraceInterpreterActivations(cx, target, trc);
+            jit::TraceJitActivations(cx, target, trc);
+        }
 
         // Trace legacy C stack roots.
         AutoGCRooter::traceAll(trc);
 
         for (RootRange r = rootsHash.ref().all(); !r.empty(); r.popFront()) {
             const RootEntry& entry = r.front();
             TraceRoot(trc, entry.key(), entry.value());
         }
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -354,22 +354,16 @@ Zone::notifyObservingDebuggers()
 #endif
                 return;
             }
         }
     }
 }
 
 bool
-js::ZonesIter::atAtomsZone(JSRuntime* rt)
-{
-    return rt->isAtomsZone(*it);
-}
-
-bool
 Zone::isOnList() const
 {
     return listNext_ != NotOnList;
 }
 
 Zone*
 Zone::nextZone() const
 {
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -597,64 +597,136 @@ struct Zone : public JS::shadow::Zone,
     friend bool js::CurrentThreadCanAccessZone(Zone* zone);
     friend class js::gc::GCRuntime;
 };
 
 } // namespace JS
 
 namespace js {
 
+// Iterate over all zone groups except those which may be in use by parse
+// threads. Pretty soon this will exclude zone groups in use by parse threads
+// (as for ZonesIter), i.e. the zone groups in use by cooperating threads,
+// except that right now parse threads use zones in the same zone group as
+// cooperating threads (bug 1323066).
+class ZoneGroupsIter
+{
+    gc::AutoEnterIteration iterMarker;
+    ZoneGroup** it;
+    ZoneGroup** end;
+
+  public:
+    explicit ZoneGroupsIter(JSRuntime* rt) : iterMarker(&rt->gc) {
+        it = rt->gc.groups.ref().begin();
+        end = rt->gc.groups.ref().end();
+    }
+
+    bool done() const { return it == end; }
+
+    void next() {
+        MOZ_ASSERT(!done());
+        it++;
+    }
+
+    ZoneGroup* get() const {
+        MOZ_ASSERT(!done());
+        return *it;
+    }
+
+    operator ZoneGroup*() const { return get(); }
+    ZoneGroup* operator->() const { return get(); }
+};
+
 // Using the atoms zone without holding the exclusive access lock is dangerous
 // because worker threads may be using it simultaneously. Therefore, it's
 // better to skip the atoms zone when iterating over zones. If you need to
 // iterate over the atoms zone, consider taking the exclusive access lock first.
 enum ZoneSelector {
     WithAtoms,
     SkipAtoms
 };
 
-class ZonesIter
+// Iterate over all zones in one zone group.
+class ZonesInGroupIter
 {
     gc::AutoEnterIteration iterMarker;
-    JSRuntime* rt;
     JS::Zone** it;
     JS::Zone** end;
 
   public:
-    ZonesIter(JSRuntime* rt, ZoneSelector selector) : iterMarker(&rt->gc), rt(rt) {
-        if (selector == WithAtoms && rt->gc.atomsZone)
-            it = const_cast<JS::Zone**>(&rt->gc.atomsZone.ref());
-        else
-            it = rt->zoneGroupFromAnyThread()->zones().begin();
-        end = rt->zoneGroupFromAnyThread()->zones().end();
+    explicit ZonesInGroupIter(ZoneGroup* group) : iterMarker(&group->runtime->gc) {
+        it = group->zones().begin();
+        end = group->zones().end();
     }
 
-    bool atAtomsZone(JSRuntime* rt);
-
     bool done() const { return it == end; }
 
     void next() {
         MOZ_ASSERT(!done());
-        do {
-            if (it == &rt->gc.atomsZone.ref())
-                it = rt->zoneGroupFromAnyThread()->zones().begin();
-            else
-                it++;
-        } while (!done() && (*it)->usedByExclusiveThread);
+        it++;
     }
 
     JS::Zone* get() const {
         MOZ_ASSERT(!done());
         return *it;
     }
 
     operator JS::Zone*() const { return get(); }
     JS::Zone* operator->() const { return get(); }
 };
 
+// Iterate over all zones in the runtime, except those which may be in use by
+// parse threads.
+class ZonesIter
+{
+    ZoneGroupsIter group;
+    Maybe<ZonesInGroupIter> zone;
+    JS::Zone* atomsZone;
+
+  public:
+    ZonesIter(JSRuntime* rt, ZoneSelector selector)
+      : group(rt), atomsZone(selector == WithAtoms ? rt->gc.atomsZone.ref() : nullptr)
+    {
+        if (!atomsZone && !done())
+            next();
+    }
+
+    bool atAtomsZone(JSRuntime* rt) const {
+        return !!atomsZone;
+    }
+
+    bool done() const { return !atomsZone && group.done(); }
+
+    void next() {
+        MOZ_ASSERT(!done());
+        if (atomsZone)
+            atomsZone = nullptr;
+        while (!group.done()) {
+            if (zone.isSome())
+                zone.ref().next();
+            else
+                zone.emplace(group);
+            if (zone.ref().done()) {
+                zone.reset();
+                group.next();
+            } else if (!zone.ref().get()->usedByExclusiveThread) {
+                break;
+            }
+        }
+    }
+
+    JS::Zone* get() const {
+        MOZ_ASSERT(!done());
+        return atomsZone ? atomsZone : zone.ref().get();
+    }
+
+    operator JS::Zone*() const { return get(); }
+    JS::Zone* operator->() const { return get(); }
+};
+
 struct CompartmentsInZoneIter
 {
     explicit CompartmentsInZoneIter(JS::Zone* zone) : zone(zone) {
         it = zone->compartments().begin();
     }
 
     bool done() const {
         MOZ_ASSERT(it);
--- a/js/src/gc/ZoneGroup.cpp
+++ b/js/src/gc/ZoneGroup.cpp
@@ -9,30 +9,28 @@
 #include "jscntxt.h"
 
 #include "jit/JitCompartment.h"
 
 namespace js {
 
 ZoneGroup::ZoneGroup(JSRuntime* runtime)
   : runtime(runtime),
-    context(TlsContext.get()),
+    ownerContext_(TlsContext.get()),
     enterCount(this, 1),
     zones_(),
     nursery_(this, this),
     storeBuffer_(this, runtime, nursery()),
     blocksToFreeAfterMinorGC((size_t) JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     caches_(this),
 #ifdef DEBUG
     ionBailAfter_(this, 0),
 #endif
     jitZoneGroup(this, nullptr),
-    debuggerList_(this),
-    profilingScripts(this, false),
-    scriptAndCountsVector(this, nullptr)
+    debuggerList_(this)
 {}
 
 bool
 ZoneGroup::init(size_t maxNurseryBytes)
 {
     if (!caches().init())
         return false;
 
@@ -51,34 +49,35 @@ ZoneGroup::~ZoneGroup()
 {
     js_delete(jitZoneGroup.ref());
 }
 
 void
 ZoneGroup::enter()
 {
     JSContext* cx = TlsContext.get();
-    if (context == cx) {
+    if (ownerContext().context() == cx) {
         MOZ_ASSERT(enterCount);
     } else {
-        JSContext* old = context.exchange(cx);
-        MOZ_RELEASE_ASSERT(old == nullptr);
+        MOZ_ASSERT(ownerContext().context() == nullptr);
         MOZ_ASSERT(enterCount == 0);
+        ownerContext_ = CooperatingContext(cx);
     }
     enterCount++;
 }
 
 void
 ZoneGroup::leave()
 {
     MOZ_ASSERT(ownedByCurrentThread());
     MOZ_ASSERT(enterCount);
     if (--enterCount == 0)
-        context = nullptr;
+        ownerContext_ = CooperatingContext(nullptr);
 }
 
 bool
 ZoneGroup::ownedByCurrentThread()
 {
-    return context == TlsContext.get();
+    MOZ_ASSERT(TlsContext.get());
+    return ownerContext().context() == TlsContext.get();
 }
 
 } // namespace js
--- a/js/src/gc/ZoneGroup.h
+++ b/js/src/gc/ZoneGroup.h
@@ -6,27 +6,26 @@
 
 #ifndef gc_ZoneGroup_h
 #define gc_ZoneGroup_h
 
 #include "jsgc.h"
 
 #include "gc/Statistics.h"
 #include "vm/Caches.h"
+#include "vm/Stack.h"
 
 namespace js {
 
 namespace jit { class JitZoneGroup; }
 
 class AutoKeepAtoms;
 
 typedef Vector<JS::Zone*, 4, SystemAllocPolicy> ZoneVector;
 
-using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
-
 // Zone groups encapsulate data about a group of zones that are logically
 // related in some way. Currently, each runtime has a single zone group, and
 // all zones except the atoms zone (which has no group) are in that group.
 // This will change soon.
 //
 // When JSRuntimes become multithreaded (also happening soon; see bug 1323066),
 // zone groups will be the primary means by which threads ensure exclusive
 // access to the data they are using. Most data in a zone group, its zones,
@@ -37,22 +36,27 @@ using ScriptAndCountsVector = GCVector<S
 // are accessed by that thread even though it does not have exclusive access
 // to the entire zone group. This will also be changing soon.
 
 class ZoneGroup
 {
   public:
     JSRuntime* const runtime;
 
+  private:
     // The context with exclusive access to this zone group.
-    mozilla::Atomic<JSContext*, mozilla::ReleaseAcquire> context;
+    UnprotectedData<CooperatingContext> ownerContext_;
 
     // The number of times the context has entered this zone group.
     ZoneGroupData<size_t> enterCount;
 
+  public:
+    CooperatingContext& ownerContext() { return ownerContext_.ref(); }
+    void* addressOfOwnerContext() { return &ownerContext_.ref().cx; }
+
     void enter();
     void leave();
     bool ownedByCurrentThread();
 
     // All zones in the group.
   private:
     ActiveThreadOrGCTaskData<ZoneVector> zones_;
   public:
@@ -119,22 +123,16 @@ class ZoneGroup
 
     ZoneGroupData<jit::JitZoneGroup*> jitZoneGroup;
 
   private:
     /* Linked list of all Debugger objects in the group. */
     ZoneGroupData<mozilla::LinkedList<js::Debugger>> debuggerList_;
   public:
     mozilla::LinkedList<js::Debugger>& debuggerList() { return debuggerList_.ref(); }
-
-    /* If true, new scripts must be created with PC counter information. */
-    ZoneGroupOrIonCompileData<bool> profilingScripts;
-
-    /* Strong references on scripts held for PCCount profiling API. */
-    ZoneGroupData<JS::PersistentRooted<ScriptAndCountsVector>*> scriptAndCountsVector;
 };
 
 class MOZ_RAII AutoAccessZoneGroup
 {
     ZoneGroup* group;
 
   public:
     explicit AutoAccessZoneGroup(ZoneGroup* group)
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -152,17 +152,17 @@ NativeRegExpMacroAssembler::GenerateCode
     // Actually emit code to start a new stack frame.
     masm.reserveStack(frameSize);
     masm.checkStackAlignment();
 
     // Check if we have space on the stack. Use the *NoInterrupt stack limit to
     // avoid failing repeatedly when the regex code is called from Ion JIT code,
     // see bug 1208819.
     Label stack_ok;
-    void* context_addr = &cx->zone()->group()->context;
+    void* context_addr = cx->zone()->group()->addressOfOwnerContext();
     masm.loadPtr(AbsoluteAddress(context_addr), temp0);
     Address limit_addr(temp0, offsetof(JSContext, jitStackLimitNoInterrupt));
     masm.branchStackPtrRhs(Assembler::Below, limit_addr, &stack_ok);
 
     // Exit with an exception. There is not enough space on the stack
     // for our working registers.
     masm.movePtr(ImmWord(RegExpRunStatus_Error), temp0);
     masm.jump(&return_temp0);
@@ -461,17 +461,17 @@ NativeRegExpMacroAssembler::GenerateCode
         Label return_from_overflow_handler;
         masm.branchTest32(Assembler::Zero, temp0, temp0, &return_from_overflow_handler);
 
         // Otherwise, store the new backtrack stack base and recompute the new
         // top of the stack.
         Address backtrackStackBaseAddress(temp2, offsetof(FrameData, backtrackStackBase));
         masm.subPtr(backtrackStackBaseAddress, backtrack_stack_pointer);
 
-        void* context_addr = &cx->zone()->group()->context;
+        void* context_addr = cx->zone()->group()->addressOfOwnerContext();
         size_t baseOffset = offsetof(JSContext, regexpStack) + RegExpStack::offsetOfBase();
         masm.loadPtr(AbsoluteAddress(context_addr), temp1);
         masm.loadPtr(Address(temp1, baseOffset), temp1);
         masm.storePtr(temp1, backtrackStackBaseAddress);
         masm.addPtr(temp1, backtrack_stack_pointer);
 
         // Resume execution in calling code.
         masm.bind(&return_from_overflow_handler);
@@ -543,17 +543,17 @@ NativeRegExpMacroAssembler::AdvanceRegis
 
 void
 NativeRegExpMacroAssembler::Backtrack()
 {
     JitSpew(SPEW_PREFIX "Backtrack");
 
     // Check for an interrupt.
     Label noInterrupt;
-    void* contextAddr = &cx->zone()->group()->context;
+    void* contextAddr = cx->zone()->group()->addressOfOwnerContext();
     masm.loadPtr(AbsoluteAddress(contextAddr), temp0);
     masm.branch32(Assembler::Equal, Address(temp0, offsetof(JSContext, interrupt_)), Imm32(0),
                   &noInterrupt);
     masm.movePtr(ImmWord(RegExpRunStatus_Error), temp0);
     masm.jump(&exit_label_);
     masm.bind(&noInterrupt);
 
     // Pop code location from backtrack stack and jump to location.
@@ -1104,17 +1104,17 @@ NativeRegExpMacroAssembler::PopBacktrack
 }
 
 void
 NativeRegExpMacroAssembler::CheckBacktrackStackLimit()
 {
     JitSpew(SPEW_PREFIX "CheckBacktrackStackLimit");
 
     Label no_stack_overflow;
-    void* context_addr = &cx->zone()->group()->context;
+    void* context_addr = cx->zone()->group()->addressOfOwnerContext();
     size_t limitOffset = offsetof(JSContext, regexpStack) + RegExpStack::offsetOfLimit();
     masm.loadPtr(AbsoluteAddress(context_addr), temp1);
     masm.branchPtr(Assembler::AboveOrEqual, Address(temp1, limitOffset),
                    backtrack_stack_pointer, &no_stack_overflow);
 
     // Copy the stack pointer before the call() instruction modifies it.
     masm.moveStackPtrTo(temp2);
 
--- a/js/src/jit-test/tests/auto-regress/bug1334573.js
+++ b/js/src/jit-test/tests/auto-regress/bug1334573.js
@@ -1,6 +1,8 @@
 // |jit-test| error:Error
 
 if (this.Intl) {
     addIntlExtras(Intl);
     addIntlExtras(Intl);
+} else {
+    throw new Error();
 }
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -33,17 +33,17 @@ jit::Bailout(BailoutStack* sp, BaselineB
     MOZ_ASSERT(bailoutInfo);
 
     // We don't have an exit frame.
     MOZ_ASSERT(IsInRange(FAKE_JIT_TOP_FOR_BAILOUT, 0, 0x1000) &&
                IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(CommonFrameLayout), 0, 0x1000),
                "Fake jitTop pointer should be within the first page.");
     cx->jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
 
-    JitActivationIterator jitActivations(cx->runtime());
+    JitActivationIterator jitActivations(cx);
     BailoutFrameInfo bailoutData(jitActivations, sp);
     JitFrameIterator iter(jitActivations);
     MOZ_ASSERT(!iter.ionScript()->invalidated());
     CommonFrameLayout* currentFramePtr = iter.current();
 
     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
     TraceLogTimestamp(logger, TraceLogger_Bailout);
 
@@ -105,17 +105,17 @@ jit::InvalidationBailout(InvalidationBai
 {
     sp->checkInvariants();
 
     JSContext* cx = TlsContext.get();
 
     // We don't have an exit frame.
     cx->jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
 
-    JitActivationIterator jitActivations(cx->runtime());
+    JitActivationIterator jitActivations(cx);
     BailoutFrameInfo bailoutData(jitActivations, sp);
     JitFrameIterator iter(jitActivations);
     CommonFrameLayout* currentFramePtr = iter.current();
 
     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
     TraceLogTimestamp(logger, TraceLogger_Invalidation);
 
     JitSpew(JitSpew_IonBailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());
@@ -193,17 +193,17 @@ jit::ExceptionHandlerBailout(JSContext* 
     MOZ_ASSERT_IF(!excInfo.propagatingIonExceptionForDebugMode(), cx->isExceptionPending());
 
     uint8_t* prevJitTop = cx->jitTop;
     auto restoreJitTop = mozilla::MakeScopeExit([&]() { cx->jitTop = prevJitTop; });
     cx->jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
 
     gc::AutoSuppressGC suppress(cx);
 
-    JitActivationIterator jitActivations(cx->runtime());
+    JitActivationIterator jitActivations(cx);
     BailoutFrameInfo bailoutData(jitActivations, frame.frame());
     JitFrameIterator iter(jitActivations);
     CommonFrameLayout* currentFramePtr = iter.current();
 
     BaselineBailoutInfo* bailoutInfo = nullptr;
     uint32_t retval;
 
     {
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -27,40 +27,44 @@ CacheRegisterAllocator::addressOf(MacroA
 {
     uint32_t offset = stackPushed_ + ICStackValueOffset + slot.slot() * sizeof(JS::Value);
     return Address(masm.getStackPointer(), offset);
 }
 
 // BaselineCacheIRCompiler compiles CacheIR to BaselineIC native code.
 class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler
 {
+#ifdef DEBUG
     // Some Baseline IC stubs can be used in IonMonkey through SharedStubs.
     // Those stubs have different machine code, so we need to track whether
     // we're compiling for Baseline or Ion.
     ICStubEngine engine_;
+#endif
 
     uint32_t stubDataOffset_;
     bool inStubFrame_;
     bool makesGCCalls_;
 
     MOZ_MUST_USE bool callVM(MacroAssembler& masm, const VMFunction& fun);
 
-    MOZ_MUST_USE bool callTypeUpdateIC(AutoStubFrame& stubFrame, Register obj, ValueOperand val,
-                                       Register scratch, LiveGeneralRegisterSet saveRegs);
+    MOZ_MUST_USE bool callTypeUpdateIC(Register obj, ValueOperand val, Register scratch,
+                                       LiveGeneralRegisterSet saveRegs);
 
     MOZ_MUST_USE bool emitStoreSlotShared(bool isFixed);
     MOZ_MUST_USE bool emitAddAndStoreSlotShared(CacheOp op);
 
   public:
     friend class AutoStubFrame;
 
     BaselineCacheIRCompiler(JSContext* cx, const CacheIRWriter& writer, ICStubEngine engine,
                             uint32_t stubDataOffset)
       : CacheIRCompiler(cx, writer, Mode::Baseline),
+#ifdef DEBUG
         engine_(engine),
+#endif
         stubDataOffset_(stubDataOffset),
         inStubFrame_(false),
         makesGCCalls_(false)
     {}
 
     MOZ_MUST_USE bool init(CacheKind kind);
 
     JitCode* compile();
@@ -79,75 +83,62 @@ class MOZ_RAII BaselineCacheIRCompiler :
 
 #define DEFINE_SHARED_OP(op) \
     bool BaselineCacheIRCompiler::emit##op() { return CacheIRCompiler::emit##op(); }
     CACHE_IR_SHARED_OPS(DEFINE_SHARED_OP)
 #undef DEFINE_SHARED_OP
 
 enum class CallCanGC { CanGC, CanNotGC };
 
-// Instructions that have to perform a callVM require a stub frame. Use
-// AutoStubFrame before allocating any registers, then call its enter() and
-// leave() methods to enter/leave the stub frame.
+// Instructions that have to perform a callVM require a stub frame. Call its
+// enter() and leave() methods to enter/leave the stub frame.
 class MOZ_RAII AutoStubFrame
 {
     BaselineCacheIRCompiler& compiler;
 #ifdef DEBUG
     uint32_t framePushedAtEnterStubFrame_;
 #endif
-    Maybe<AutoScratchRegister> tail;
 
     AutoStubFrame(const AutoStubFrame&) = delete;
     void operator=(const AutoStubFrame&) = delete;
 
   public:
     explicit AutoStubFrame(BaselineCacheIRCompiler& compiler)
-      : compiler(compiler),
+      : compiler(compiler)
 #ifdef DEBUG
-        framePushedAtEnterStubFrame_(0),
+        , framePushedAtEnterStubFrame_(0)
 #endif
-        tail()
-    {
-        // We use ICTailCallReg when entering the stub frame, so ensure it's not
-        // used for something else.
-        if (compiler.allocator.isAllocatable(ICTailCallReg))
-            tail.emplace(compiler.allocator, compiler.masm, ICTailCallReg);
-    }
+    { }
 
     void enter(MacroAssembler& masm, Register scratch, CallCanGC canGC = CallCanGC::CanGC) {
         MOZ_ASSERT(compiler.allocator.stackPushed() == 0);
-        if (compiler.engine_ == ICStubEngine::Baseline) {
-            EmitBaselineEnterStubFrame(masm, scratch);
+        MOZ_ASSERT(compiler.engine_ == ICStubEngine::Baseline);
+
+        EmitBaselineEnterStubFrame(masm, scratch);
+
 #ifdef DEBUG
-            framePushedAtEnterStubFrame_ = masm.framePushed();
+        framePushedAtEnterStubFrame_ = masm.framePushed();
 #endif
-        } else {
-            EmitIonEnterStubFrame(masm, scratch);
-        }
 
         MOZ_ASSERT(!compiler.inStubFrame_);
         compiler.inStubFrame_ = true;
         if (canGC == CallCanGC::CanGC)
             compiler.makesGCCalls_ = true;
     }
     void leave(MacroAssembler& masm, bool calledIntoIon = false) {
         MOZ_ASSERT(compiler.inStubFrame_);
         compiler.inStubFrame_ = false;
 
-        if (compiler.engine_ == ICStubEngine::Baseline) {
 #ifdef DEBUG
-            masm.setFramePushed(framePushedAtEnterStubFrame_);
-            if (calledIntoIon)
-                masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
+        masm.setFramePushed(framePushedAtEnterStubFrame_);
+        if (calledIntoIon)
+            masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
 #endif
 
-            EmitBaselineLeaveStubFrame(masm, calledIntoIon);
-        } else {
-            EmitIonLeaveStubFrame(masm);
-        }
+        EmitBaselineLeaveStubFrame(masm, calledIntoIon);
     }
 
 #ifdef DEBUG
     ~AutoStubFrame() {
         MOZ_ASSERT(!compiler.inStubFrame_);
     }
 #endif
 };
@@ -157,20 +148,19 @@ BaselineCacheIRCompiler::callVM(MacroAss
 {
     MOZ_ASSERT(inStubFrame_);
 
     JitCode* code = cx_->runtime()->jitRuntime()->getVMWrapper(fun);
     if (!code)
         return false;
 
     MOZ_ASSERT(fun.expectTailCall == NonTailCall);
-    if (engine_ == ICStubEngine::Baseline)
-        EmitBaselineCallVM(code, masm);
-    else
-        EmitIonCallVM(code, fun.explicitStackSlots(), masm);
+    MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
+
+    EmitBaselineCallVM(code, masm);
     return true;
 }
 
 JitCode*
 BaselineCacheIRCompiler::compile()
 {
 #ifndef JS_USE_LINK_REGISTER
     // The first value contains the return addres,
@@ -372,18 +362,16 @@ BaselineCacheIRCompiler::emitLoadDynamic
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitCallScriptedGetterResult()
 {
     MOZ_ASSERT(engine_ == ICStubEngine::Baseline);
 
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address getterAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegisterExcluding code(allocator, masm, ArgumentsRectifierReg);
     AutoScratchRegister callee(allocator, masm);
     AutoScratchRegister scratch(allocator, masm);
 
     // First, ensure our getter is non-lazy and has JIT code.
@@ -395,16 +383,17 @@ BaselineCacheIRCompiler::emitCallScripte
         masm.loadPtr(getterAddr, callee);
         masm.branchIfFunctionHasNoScript(callee, failure->label());
         masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
         masm.loadBaselineOrIonRaw(code, code, failure->label());
     }
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     // Align the stack such that the JitFrameLayout is aligned on
     // JitStackAlignment.
     masm.alignJitStackBasedOnNArgs(0);
 
     // Getter is called with 0 arguments, just |obj| as thisv.
     // Note that we use Push, not push, so that callJit will align the stack
@@ -439,25 +428,24 @@ BaselineCacheIRCompiler::emitCallScripte
 
 typedef bool (*CallNativeGetterFn)(JSContext*, HandleFunction, HandleObject, MutableHandleValue);
 static const VMFunction CallNativeGetterInfo =
     FunctionInfo<CallNativeGetterFn>(CallNativeGetter, "CallNativeGetter");
 
 bool
 BaselineCacheIRCompiler::emitCallNativeGetterResult()
 {
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address getterAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     // Load the callee in the scratch register.
     masm.loadPtr(getterAddr, scratch);
 
     masm.Push(obj);
     masm.Push(scratch);
 
@@ -470,25 +458,24 @@ BaselineCacheIRCompiler::emitCallNativeG
 
 typedef bool (*ProxyGetPropertyFn)(JSContext*, HandleObject, HandleId, MutableHandleValue);
 static const VMFunction ProxyGetPropertyInfo =
     FunctionInfo<ProxyGetPropertyFn>(ProxyGetProperty, "ProxyGetProperty");
 
 bool
 BaselineCacheIRCompiler::emitCallProxyGetResult()
 {
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address idAddr(stubAddress(reader.stubOffset()));
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     // Load the jsid in the scratch register.
     masm.loadPtr(idAddr, scratch);
 
     masm.Push(scratch);
     masm.Push(obj);
 
@@ -501,25 +488,24 @@ BaselineCacheIRCompiler::emitCallProxyGe
 
 typedef bool (*ProxyGetPropertyByValueFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
 static const VMFunction ProxyGetPropertyByValueInfo =
     FunctionInfo<ProxyGetPropertyByValueFn>(ProxyGetPropertyByValue, "ProxyGetPropertyByValue");
 
 bool
 BaselineCacheIRCompiler::emitCallProxyGetByValueResult()
 {
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     masm.Push(idVal);
     masm.Push(obj);
 
     if (!callVM(masm, ProxyGetPropertyByValueInfo))
         return false;
 
@@ -666,18 +652,18 @@ BaselineCacheIRCompiler::emitLoadEnviron
     masm.branchTestMagic(Assembler::Equal, slot, failure->label());
 
     // Load the value.
     masm.loadValue(slot, output.valueReg());
     return true;
 }
 
 bool
-BaselineCacheIRCompiler::callTypeUpdateIC(AutoStubFrame& stubFrame, Register obj, ValueOperand val,
-                                          Register scratch, LiveGeneralRegisterSet saveRegs)
+BaselineCacheIRCompiler::callTypeUpdateIC(Register obj, ValueOperand val, Register scratch,
+                                          LiveGeneralRegisterSet saveRegs)
 {
     // Ensure the stack is empty for the VM call below.
     allocator.discardStack(masm);
 
     // R0 contains the value that needs to be typechecked.
     MOZ_ASSERT(val == R0);
     MOZ_ASSERT(scratch == R1.scratchReg());
 
@@ -698,16 +684,17 @@ BaselineCacheIRCompiler::callTypeUpdateI
     if (CallClobbersTailReg)
         masm.pop(ICTailCallReg);
 
     // The update IC will store 0 or 1 in |scratch|, R1.scratchReg(), reflecting
     // if the value in R0 type-checked properly or not.
     Label done;
     masm.branch32(Assembler::Equal, scratch, Imm32(1), &done);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch, CallCanGC::CanNotGC);
 
     masm.PushRegsInMask(saveRegs);
 
     masm.Push(val);
     masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
     masm.Push(ICStubReg);
 
@@ -729,46 +716,45 @@ BaselineCacheIRCompiler::callTypeUpdateI
 bool
 BaselineCacheIRCompiler::emitStoreSlotShared(bool isFixed)
 {
     ObjOperandId objId = reader.objOperandId();
     Address offsetAddr = stubAddress(reader.stubOffset());
 
     // Allocate the fixed registers first. These need to be fixed for
     // callTypeUpdateIC.
-    AutoStubFrame stubFrame(*this);
-    AutoScratchRegister scratch(allocator, masm, R1.scratchReg());
+    AutoScratchRegister scratch1(allocator, masm, R1.scratchReg());
     ValueOperand val = allocator.useFixedValueRegister(masm, reader.valOperandId(), R0);
 
     Register obj = allocator.useRegister(masm, objId);
+    Maybe<AutoScratchRegister> scratch2;
+    if (!isFixed)
+        scratch2.emplace(allocator, masm);
 
     LiveGeneralRegisterSet saveRegs;
     saveRegs.add(obj);
     saveRegs.add(val);
-    if (!callTypeUpdateIC(stubFrame, obj, val, scratch, saveRegs))
+    if (!callTypeUpdateIC(obj, val, scratch1, saveRegs))
         return false;
 
-    masm.load32(offsetAddr, scratch);
+    masm.load32(offsetAddr, scratch1);
 
     if (isFixed) {
-        BaseIndex slot(obj, scratch, TimesOne);
+        BaseIndex slot(obj, scratch1, TimesOne);
         EmitPreBarrier(masm, slot, MIRType::Value);
         masm.storeValue(val, slot);
     } else {
-        // To avoid running out of registers on x86, use ICStubReg as scratch.
-        // We don't need it anymore.
-        Register slots = ICStubReg;
-        masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), slots);
-        BaseIndex slot(slots, scratch, TimesOne);
+        masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), scratch2.ref());
+        BaseIndex slot(scratch2.ref(), scratch1, TimesOne);
         EmitPreBarrier(masm, slot, MIRType::Value);
         masm.storeValue(val, slot);
     }
 
     if (cx_->nursery().exists())
-        BaselineEmitPostWriteBarrierSlot(masm, obj, val, scratch, LiveGeneralRegisterSet(), cx_);
+        BaselineEmitPostWriteBarrierSlot(masm, obj, val, scratch1, LiveGeneralRegisterSet(), cx_);
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitStoreFixedSlot()
 {
     return emitStoreSlotShared(true);
 }
@@ -782,21 +768,22 @@ BaselineCacheIRCompiler::emitStoreDynami
 bool
 BaselineCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
 {
     ObjOperandId objId = reader.objOperandId();
     Address offsetAddr = stubAddress(reader.stubOffset());
 
     // Allocate the fixed registers first. These need to be fixed for
     // callTypeUpdateIC.
-    AutoStubFrame stubFrame(*this);
-    AutoScratchRegister scratch(allocator, masm, R1.scratchReg());
+    AutoScratchRegister scratch1(allocator, masm, R1.scratchReg());
     ValueOperand val = allocator.useFixedValueRegister(masm, reader.valOperandId(), R0);
 
     Register obj = allocator.useRegister(masm, objId);
+    AutoScratchRegister scratch2(allocator, masm);
+
     bool changeGroup = reader.readBool();
     Address newGroupAddr = stubAddress(reader.stubOffset());
     Address newShapeAddr = stubAddress(reader.stubOffset());
 
     if (op == CacheOp::AllocateAndStoreDynamicSlot) {
         // We have to (re)allocate dynamic slots. Do this first, as it's the
         // only fallible operation here. This simplifies the callTypeUpdateIC
         // call below: it does not have to worry about saving registers used by
@@ -805,90 +792,83 @@ BaselineCacheIRCompiler::emitAddAndStore
 
         FailurePath* failure;
         if (!addFailurePath(&failure))
             return false;
 
         AllocatableRegisterSet regs(RegisterSet::Volatile());
         LiveRegisterSet save(regs.asLiveSet());
 
-        // Use ICStubReg as second scratch.
-        if (!save.has(ICStubReg))
-            save.add(ICStubReg);
-
         masm.PushRegsInMask(save);
 
-        masm.setupUnalignedABICall(scratch);
-        masm.loadJSContext(scratch);
-        masm.passABIArg(scratch);
+        masm.setupUnalignedABICall(scratch1);
+        masm.loadJSContext(scratch1);
+        masm.passABIArg(scratch1);
         masm.passABIArg(obj);
-        masm.load32(numNewSlotsAddr, ICStubReg);
-        masm.passABIArg(ICStubReg);
+        masm.load32(numNewSlotsAddr, scratch2);
+        masm.passABIArg(scratch2);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsDontReportOOM));
-        masm.mov(ReturnReg, scratch);
+        masm.mov(ReturnReg, scratch1);
 
         LiveRegisterSet ignore;
-        ignore.add(scratch);
+        ignore.add(scratch1);
         masm.PopRegsInMaskIgnore(save, ignore);
 
-        masm.branchIfFalseBool(scratch, failure->label());
+        masm.branchIfFalseBool(scratch1, failure->label());
     }
 
     LiveGeneralRegisterSet saveRegs;
     saveRegs.add(obj);
     saveRegs.add(val);
-    if (!callTypeUpdateIC(stubFrame, obj, val, scratch, saveRegs))
+    if (!callTypeUpdateIC(obj, val, scratch1, saveRegs))
         return false;
 
     if (changeGroup) {
         // Changing object's group from a partially to fully initialized group,
         // per the acquired properties analysis. Only change the group if the
         // old group still has a newScript. This only applies to PlainObjects.
         Label noGroupChange;
-        masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
+        masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch1);
         masm.branchPtr(Assembler::Equal,
-                       Address(scratch, ObjectGroup::offsetOfAddendum()),
+                       Address(scratch1, ObjectGroup::offsetOfAddendum()),
                        ImmWord(0),
                        &noGroupChange);
 
         // Reload the new group from the cache.
-        masm.loadPtr(newGroupAddr, scratch);
+        masm.loadPtr(newGroupAddr, scratch1);
 
         Address groupAddr(obj, JSObject::offsetOfGroup());
         EmitPreBarrier(masm, groupAddr, MIRType::ObjectGroup);
-        masm.storePtr(scratch, groupAddr);
+        masm.storePtr(scratch1, groupAddr);
 
         masm.bind(&noGroupChange);
     }
 
     // Update the object's shape.
     Address shapeAddr(obj, ShapedObject::offsetOfShape());
-    masm.loadPtr(newShapeAddr, scratch);
+    masm.loadPtr(newShapeAddr, scratch1);
     EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
-    masm.storePtr(scratch, shapeAddr);
+    masm.storePtr(scratch1, shapeAddr);
 
     // Perform the store. No pre-barrier required since this is a new
     // initialization.
-    masm.load32(offsetAddr, scratch);
+    masm.load32(offsetAddr, scratch1);
     if (op == CacheOp::AddAndStoreFixedSlot) {
-        BaseIndex slot(obj, scratch, TimesOne);
+        BaseIndex slot(obj, scratch1, TimesOne);
         masm.storeValue(val, slot);
     } else {
         MOZ_ASSERT(op == CacheOp::AddAndStoreDynamicSlot ||
                    op == CacheOp::AllocateAndStoreDynamicSlot);
-        // To avoid running out of registers on x86, use ICStubReg as scratch.
-        // We don't need it anymore.
-        Register slots = ICStubReg;
-        masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), slots);
-        BaseIndex slot(slots, scratch, TimesOne);
+        masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), scratch2);
+        BaseIndex slot(scratch2, scratch1, TimesOne);
         masm.storeValue(val, slot);
     }
 
     if (cx_->nursery().exists())
-        BaselineEmitPostWriteBarrierSlot(masm, obj, val, scratch, LiveGeneralRegisterSet(), cx_);
+        BaselineEmitPostWriteBarrierSlot(masm, obj, val, scratch1, LiveGeneralRegisterSet(), cx_);
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitAddAndStoreFixedSlot()
 {
     return emitAddAndStoreSlotShared(CacheOp::AddAndStoreFixedSlot);
 }
@@ -909,28 +889,27 @@ bool
 BaselineCacheIRCompiler::emitStoreUnboxedProperty()
 {
     ObjOperandId objId = reader.objOperandId();
     JSValueType fieldType = reader.valueType();
     Address offsetAddr = stubAddress(reader.stubOffset());
 
     // Allocate the fixed registers first. These need to be fixed for
     // callTypeUpdateIC.
-    AutoStubFrame stubFrame(*this);
     AutoScratchRegister scratch(allocator, masm, R1.scratchReg());
     ValueOperand val = allocator.useFixedValueRegister(masm, reader.valOperandId(), R0);
 
     Register obj = allocator.useRegister(masm, objId);
 
     // We only need the type update IC if we are storing an object.
     if (fieldType == JSVAL_TYPE_OBJECT) {
         LiveGeneralRegisterSet saveRegs;
         saveRegs.add(obj);
         saveRegs.add(val);
-        if (!callTypeUpdateIC(stubFrame, obj, val, scratch, saveRegs))
+        if (!callTypeUpdateIC(obj, val, scratch, saveRegs))
             return false;
     }
 
     masm.load32(offsetAddr, scratch);
     BaseIndex fieldAddr(obj, scratch, TimesOne);
 
     // Note that the storeUnboxedProperty call here is infallible, as the
     // IR emitter is responsible for guarding on |val|'s type.
@@ -949,40 +928,36 @@ BaselineCacheIRCompiler::emitStoreTypedO
 {
     ObjOperandId objId = reader.objOperandId();
     Address offsetAddr = stubAddress(reader.stubOffset());
     TypedThingLayout layout = reader.typedThingLayout();
     ReferenceTypeDescr::Type type = reader.referenceTypeDescrType();
 
     // Allocate the fixed registers first. These need to be fixed for
     // callTypeUpdateIC.
-    AutoStubFrame stubFrame(*this);
     AutoScratchRegister scratch1(allocator, masm, R1.scratchReg());
     ValueOperand val = allocator.useFixedValueRegister(masm, reader.valOperandId(), R0);
 
     Register obj = allocator.useRegister(masm, objId);
+    AutoScratchRegister scratch2(allocator, masm);
 
-    // We don't need a type update IC if the property is always a string.
+    // We don't need a type update IC if the property is always a string.scratch
     if (type != ReferenceTypeDescr::TYPE_STRING) {
         LiveGeneralRegisterSet saveRegs;
         saveRegs.add(obj);
         saveRegs.add(val);
-        if (!callTypeUpdateIC(stubFrame, obj, val, scratch1, saveRegs))
+        if (!callTypeUpdateIC(obj, val, scratch1, saveRegs))
             return false;
     }
 
     // Compute the address being written to.
     LoadTypedThingData(masm, layout, obj, scratch1);
     masm.addPtr(offsetAddr, scratch1);
     Address dest(scratch1, 0);
 
-    // To avoid running out of registers on x86, use ICStubReg as second
-    // scratch. It won't be used after this.
-    Register scratch2 = ICStubReg;
-
     switch (type) {
       case ReferenceTypeDescr::TYPE_ANY:
         EmitPreBarrier(masm, dest, MIRType::Value);
         masm.storeValue(val, dest);
         break;
 
       case ReferenceTypeDescr::TYPE_OBJECT: {
         EmitPreBarrier(masm, dest, MIRType::Object);
@@ -1038,26 +1013,25 @@ BaselineCacheIRCompiler::emitStoreTypedO
 
 typedef bool (*CallNativeSetterFn)(JSContext*, HandleFunction, HandleObject, HandleValue);
 static const VMFunction CallNativeSetterInfo =
     FunctionInfo<CallNativeSetterFn>(CallNativeSetter, "CallNativeSetter");
 
 bool
 BaselineCacheIRCompiler::emitCallNativeSetter()
 {
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address setterAddr(stubAddress(reader.stubOffset()));
     ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     // Load the callee in the scratch register.
     masm.loadPtr(setterAddr, scratch);
 
     masm.Push(val);
     masm.Push(obj);
     masm.Push(scratch);
@@ -1067,106 +1041,102 @@ BaselineCacheIRCompiler::emitCallNativeS
 
     stubFrame.leave(masm);
     return true;
 }
 
 bool
 BaselineCacheIRCompiler::emitCallScriptedSetter()
 {
-    AutoStubFrame stubFrame(*this);
-
-    // We don't have many registers available on x86, so we use a single
-    // scratch register.
-    AutoScratchRegisterExcluding scratch(allocator, masm, ArgumentsRectifierReg);
+    AutoScratchRegisterExcluding scratch1(allocator, masm, ArgumentsRectifierReg);
+    AutoScratchRegister scratch2(allocator, masm);
 
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Address setterAddr(stubAddress(reader.stubOffset()));
     ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
 
-    // First, ensure our setter is non-lazy and has JIT code.
+    // First, ensure our setter is non-lazy and has JIT code. This also loads
+    // the callee in scratch1.
     {
         FailurePath* failure;
         if (!addFailurePath(&failure))
             return false;
 
-        masm.loadPtr(setterAddr, scratch);
-        masm.branchIfFunctionHasNoScript(scratch, failure->label());
-        masm.loadPtr(Address(scratch, JSFunction::offsetOfNativeOrScript()), scratch);
-        masm.loadBaselineOrIonRaw(scratch, scratch, failure->label());
+        masm.loadPtr(setterAddr, scratch1);
+        masm.branchIfFunctionHasNoScript(scratch1, failure->label());
+        masm.loadPtr(Address(scratch1, JSFunction::offsetOfNativeOrScript()), scratch2);
+        masm.loadBaselineOrIonRaw(scratch2, scratch2, failure->label());
     }
 
     allocator.discardStack(masm);
 
-    stubFrame.enter(masm, scratch);
+    AutoStubFrame stubFrame(*this);
+    stubFrame.enter(masm, scratch2);
 
     // Align the stack such that the JitFrameLayout is aligned on
     // JitStackAlignment.
     masm.alignJitStackBasedOnNArgs(1);
 
     // Setter is called with 1 argument, and |obj| as thisv. Note that we use
     // Push, not push, so that callJit will align the stack properly on ARM.
     masm.Push(val);
     masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
 
     // Now that the object register is no longer needed, use it as second
     // scratch.
-    Register scratch2 = obj;
     EmitBaselineCreateStubFrameDescriptor(masm, scratch2, JitFrameLayout::Size());
     masm.Push(Imm32(1));  // ActualArgc
 
     // Push callee.
-    masm.loadPtr(setterAddr, scratch);
-    masm.Push(scratch);
+    masm.Push(scratch1);
 
     // Push frame descriptor.
     masm.Push(scratch2);
 
     // Load callee->nargs in scratch2 and the JIT code in scratch.
     Label noUnderflow;
-    masm.load16ZeroExtend(Address(scratch, JSFunction::offsetOfNargs()), scratch2);
-    masm.loadPtr(Address(scratch, JSFunction::offsetOfNativeOrScript()), scratch);
-    masm.loadBaselineOrIonRaw(scratch, scratch, nullptr);
+    masm.load16ZeroExtend(Address(scratch1, JSFunction::offsetOfNargs()), scratch2);
+    masm.loadPtr(Address(scratch1, JSFunction::offsetOfNativeOrScript()), scratch1);
+    masm.loadBaselineOrIonRaw(scratch1, scratch1, nullptr);
 
     // Handle arguments underflow.
     masm.branch32(Assembler::BelowOrEqual, scratch2, Imm32(1), &noUnderflow);
     {
         // Call the arguments rectifier.
-        MOZ_ASSERT(ArgumentsRectifierReg != scratch);
+        MOZ_ASSERT(ArgumentsRectifierReg != scratch1);
 
         JitCode* argumentsRectifier = cx_->runtime()->jitRuntime()->getArgumentsRectifier();
-        masm.movePtr(ImmGCPtr(argumentsRectifier), scratch);
-        masm.loadPtr(Address(scratch, JitCode::offsetOfCode()), scratch);
+        masm.movePtr(ImmGCPtr(argumentsRectifier), scratch1);
+        masm.loadPtr(Address(scratch1, JitCode::offsetOfCode()), scratch1);
         masm.movePtr(ImmWord(1), ArgumentsRectifierReg);
     }
 
     masm.bind(&noUnderflow);
-    masm.callJit(scratch);
+    masm.callJit(scratch1);
 
     stubFrame.leave(masm, true);
     return true;
 }
 
 typedef bool (*SetArrayLengthFn)(JSContext*, HandleObject, HandleValue, bool);
 static const VMFunction SetArrayLengthInfo =
     FunctionInfo<SetArrayLengthFn>(SetArrayLength, "SetArrayLength");
 
 bool
 BaselineCacheIRCompiler::emitCallSetArrayLength()
 {
-    AutoStubFrame stubFrame(*this);
-
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     bool strict = reader.readBool();
     ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
 
     AutoScratchRegister scratch(allocator, masm);
 
     allocator.discardStack(masm);
 
+    AutoStubFrame stubFrame(*this);
     stubFrame.enter(masm, scratch);
 
     masm.Push(Imm32(strict));
     masm.Push(val);
     masm.Push(obj);
 
     if (!callVM(masm, SetArrayLengthInfo))
         return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -545,17 +545,17 @@ BaselineCompiler::emitStackCheck(bool ea
     Label forceCall;
     if (!earlyCheck && needsEarlyStackCheck()) {
         masm.branchTest32(Assembler::NonZero,
                           frame.addressOfFlags(),
                           Imm32(BaselineFrame::OVER_RECURSED),
                           &forceCall);
     }
 
-    void* contextAddr = &cx->zone()->group()->context;
+    void* contextAddr = cx->zone()->group()->addressOfOwnerContext();
     masm.loadPtr(AbsoluteAddress(contextAddr), R0.scratchReg());
     masm.branchPtr(Assembler::BelowOrEqual,
                    Address(R0.scratchReg(), offsetof(JSContext, jitStackLimit)), R1.scratchReg(),
                    &skipCall);
 
     if (!earlyCheck && needsEarlyStackCheck())
         masm.bind(&forceCall);
 
@@ -694,17 +694,17 @@ static const VMFunction InterruptCheckIn
     FunctionInfo<InterruptCheckFn>(InterruptCheck, "InterruptCheck");
 
 bool
 BaselineCompiler::emitInterruptCheck()
 {
     frame.syncStack(0);
 
     Label done;
-    void* context = &cx->zone()->group()->context;
+    void* context = cx->zone()->group()->addressOfOwnerContext();
     masm.loadPtr(AbsoluteAddress(context), R0.scratchReg());
     masm.branch32(Assembler::Equal,
                   Address(R0.scratchReg(), offsetof(JSContext, interrupt_)), Imm32(0),
                   &done);
 
     prepareVMCall();
     if (!callVM(InterruptCheckInfo))
         return false;
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -342,17 +342,18 @@ static void
 SpewPatchStubFrame(ICStub* oldStub, ICStub* newStub)
 {
     JitSpew(JitSpew_BaselineDebugModeOSR,
             "Patch   stub %p -> %p on BaselineStub frame (%s)",
             oldStub, newStub, newStub ? ICStub::KindString(newStub->kind()) : "exception handler");
 }
 
 static void
-PatchBaselineFramesForDebugMode(JSContext* cx, const Debugger::ExecutionObservableSet& obs,
+PatchBaselineFramesForDebugMode(JSContext* cx, const CooperatingContext& target,
+                                const Debugger::ExecutionObservableSet& obs,
                                 const ActivationIterator& activation,
                                 DebugModeOSREntryVector& entries, size_t* start)
 {
     //
     // Recompile Patching Overview
     //
     // When toggling debug mode with live baseline scripts on the stack, we
     // could have entered the VM via the following ways from the baseline
@@ -416,17 +417,17 @@ PatchBaselineFramesForDebugMode(JSContex
                 // the baseline frame here, we resume right after the IC
                 // returns.
                 //
                 // Since we're using the same IC stub code, we can resume
                 // directly to the IC resume address.
                 uint8_t* retAddr = bl->returnAddressForIC(bl->icEntryFromPCOffset(pcOffset));
                 SpewPatchBaselineFrame(prev->returnAddress(), retAddr, script, kind, pc);
                 DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(
-                    cx, prev->returnAddress(), retAddr);
+                    target, prev->returnAddress(), retAddr);
                 prev->setReturnAddress(retAddr);
                 entryIndex++;
                 break;
             }
 
             if (kind == ICEntry::Kind_Invalid) {
                 // Case H above.
                 //
@@ -445,17 +446,17 @@ PatchBaselineFramesForDebugMode(JSContex
                 uint8_t* retAddr;
                 if (cx->runtime()->geckoProfiler().enabled())
                     retAddr = bl->nativeCodeForPC(script, pc);
                 else
                     retAddr = nullptr;
                 SpewPatchBaselineFrameFromExceptionHandler(prev->returnAddress(), retAddr,
                                                            script, pc);
                 DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(
-                    cx, prev->returnAddress(), retAddr);
+                    target, prev->returnAddress(), retAddr);
                 prev->setReturnAddress(retAddr);
                 entryIndex++;
                 break;
             }
 
             // Case F above.
             //
             // We undo a previous recompile by handling cases B, C, D, E, I or J
@@ -832,23 +833,25 @@ bool
 jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext* cx,
                                                  const Debugger::ExecutionObservableSet& obs,
                                                  Debugger::IsObserving observing)
 {
     // First recompile the active scripts on the stack and patch the live
     // frames.
     Vector<DebugModeOSREntry> entries(cx);
 
-    for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
-        if (iter->isJit()) {
-            if (!CollectJitStackScripts(cx, obs, iter, entries))
-                return false;
-        } else if (iter->isInterpreter()) {
-            if (!CollectInterpreterStackScripts(cx, obs, iter, entries))
-                return false;
+    for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
+        for (ActivationIterator iter(cx, target); !iter.done(); ++iter) {
+            if (iter->isJit()) {
+                if (!CollectJitStackScripts(cx, obs, iter, entries))
+                    return false;
+            } else if (iter->isInterpreter()) {
+                if (!CollectInterpreterStackScripts(cx, obs, iter, entries))
+                    return false;
+            }
         }
     }
 
     if (entries.empty())
         return true;
 
     // When the profiler is enabled, we need to have suppressed sampling,
     // since the basline jit scripts are in a state of flux.
@@ -887,21 +890,23 @@ jit::RecompileOnStackBaselineScriptsForD
 
     for (UniqueScriptOSREntryIter iter(entries); !iter.done(); ++iter) {
         const DebugModeOSREntry& entry = iter.entry();
         if (entry.recompiled())
             BaselineScript::Destroy(cx->runtime()->defaultFreeOp(), entry.oldBaselineScript);
     }
 
     size_t processed = 0;
-    for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
-        if (iter->isJit())
-            PatchBaselineFramesForDebugMode(cx, obs, iter, entries, &processed);
-        else if (iter->isInterpreter())
-            SkipInterpreterFrameEntries(obs, iter, entries, &processed);
+    for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
+        for (ActivationIterator iter(cx, target); !iter.done(); ++iter) {
+            if (iter->isJit())
+                PatchBaselineFramesForDebugMode(cx, target, obs, iter, entries, &processed);
+            else if (iter->isInterpreter())
+                SkipInterpreterFrameEntries(obs, iter, entries, &processed);
+        }
     }
     MOZ_ASSERT(processed == entries.length());
 
     return true;
 }
 
 void
 BaselineDebugModeOSRInfo::popValueInto(PCMappingSlotInfo::SlotLocation loc, Value* vp)
@@ -1158,17 +1163,17 @@ JitRuntime::generateBaselineDebugModeOSR
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "BaselineDebugModeOSRHandler");
 #endif
 
     return code;
 }
 
 /* static */ void
-DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(JSContext* cx,
+DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(const CooperatingContext& cx,
                                                            uint8_t* oldAddr, uint8_t* newAddr)
 {
     DebugModeOSRVolatileJitFrameIterator* iter;
-    for (iter = cx->liveVolatileJitFrameIterators_; iter; iter = iter->prev) {
+    for (iter = cx.context()->liveVolatileJitFrameIterators_; iter; iter = iter->prev) {
         if (iter->returnAddressToFp_ == oldAddr)
             iter->returnAddressToFp_ = newAddr;
     }
 }
--- a/js/src/jit/BaselineDebugModeOSR.h
+++ b/js/src/jit/BaselineDebugModeOSR.h
@@ -99,17 +99,18 @@ class DebugModeOSRVolatileJitFrameIterat
         *stack = this;
     }
 
     ~DebugModeOSRVolatileJitFrameIterator() {
         MOZ_ASSERT(*stack == this);
         *stack = prev;
     }
 
-    static void forwardLiveIterators(JSContext* cx, uint8_t* oldAddr, uint8_t* newAddr);
+    static void forwardLiveIterators(const CooperatingContext& target,
+                                     uint8_t* oldAddr, uint8_t* newAddr);
 };
 
 //
 // Auxiliary info to help the DebugModeOSRHandler fix up state.
 //
 struct BaselineDebugModeOSRInfo
 {
     uint8_t* resumeAddr;
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -1210,17 +1210,17 @@ jit::ToggleBaselineTraceLoggerEngine(JSR
                 continue;
             script->baselineScript()->toggleTraceLoggerEngine(enable);
         }
     }
 }
 #endif
 
 static void
-MarkActiveBaselineScripts(JSRuntime* rt, const JitActivationIterator& activation)
+MarkActiveBaselineScripts(JSContext* cx, const JitActivationIterator& activation)
 {
     for (jit::JitFrameIterator iter(activation); !iter.done(); ++iter) {
         switch (iter.type()) {
           case JitFrame_BaselineJS:
             iter.script()->baselineScript()->setActive();
             break;
           case JitFrame_Exit:
             if (iter.exitFrame()->is<LazyLinkExitFrameLayout>()) {
@@ -1228,26 +1228,28 @@ MarkActiveBaselineScripts(JSRuntime* rt,
                 ScriptFromCalleeToken(ll->jsFrame()->calleeToken())->baselineScript()->setActive();
             }
             break;
           case JitFrame_Bailout:
           case JitFrame_IonJS: {
             // Keep the baseline script around, since bailouts from the ion
             // jitcode might need to re-enter into the baseline jitcode.
             iter.script()->baselineScript()->setActive();
-            for (InlineFrameIterator inlineIter(rt, &iter); inlineIter.more(); ++inlineIter)
+            for (InlineFrameIterator inlineIter(cx, &iter); inlineIter.more(); ++inlineIter)
                 inlineIter.script()->baselineScript()->setActive();
             break;
           }
           default:;
         }
     }
 }
 
 void
 jit::MarkActiveBaselineScripts(Zone* zone)
 {
-    JSRuntime* rt = zone->runtimeFromMainThread();
-    for (JitActivationIterator iter(rt); !iter.done(); ++iter) {
+    if (zone->isAtomsZone())
+        return;
+    JSContext* cx = TlsContext.get();
+    for (JitActivationIterator iter(cx, zone->group()->ownerContext()); !iter.done(); ++iter) {
         if (iter->compartment()->zone() == zone)
-            MarkActiveBaselineScripts(rt, iter);
+            MarkActiveBaselineScripts(cx, iter);
     }
 }
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -350,16 +350,17 @@ class MOZ_RAII CacheRegisterAllocator
 
     void allocateFixedRegister(MacroAssembler& masm, Register reg);
     void allocateFixedValueRegister(MacroAssembler& masm, ValueOperand reg);
 
     // Releases a register so it can be reused later.
     void releaseRegister(Register reg) {
         MOZ_ASSERT(currentOpRegs_.has(reg));
         availableRegs_.add(reg);
+        currentOpRegs_.take(reg);
     }
     void releaseValueRegister(ValueOperand reg) {
 #ifdef JS_NUNBOX32
         releaseRegister(reg.payloadReg());
         releaseRegister(reg.typeReg());
 #else
         releaseRegister(reg.valueReg());
 #endif
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -50,16 +50,22 @@ CompileRuntime::jitSupportsFloatingPoint
 }
 
 bool
 CompileRuntime::hadOutOfMemory()
 {
     return runtime()->hadOutOfMemory;
 }
 
+bool
+CompileRuntime::profilingScripts()
+{
+    return runtime()->profilingScripts;
+}
+
 const JSAtomState&
 CompileRuntime::names()
 {
     return *runtime()->commonNames;
 }
 
 const PropertyName*
 CompileRuntime::emptyString()
@@ -147,17 +153,17 @@ CompileZone::addressOfIonBailAfter()
 {
     return zone()->group()->addressOfIonBailAfter();
 }
 #endif
 
 const void*
 CompileZone::addressOfJSContext()
 {
-    return &zone()->group()->context;
+    return zone()->group()->addressOfOwnerContext();
 }
 
 const void*
 CompileZone::addressOfNeedsIncrementalBarrier()
 {
     return zone()->addressOfNeedsIncrementalBarrier();
 }
 
@@ -188,22 +194,16 @@ CompileZone::nurseryExists()
 
 void
 CompileZone::setMinorGCShouldCancelIonCompilations()
 {
     MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
     zone()->group()->storeBuffer().setShouldCancelIonCompilations();
 }
 
-bool
-CompileZone::profilingScripts()
-{
-    return zone()->group()->profilingScripts;
-}
-
 JSCompartment*
 CompileCompartment::compartment()
 {
     return reinterpret_cast<JSCompartment*>(this);
 }
 
 /* static */ CompileCompartment*
 CompileCompartment::get(JSCompartment* comp)
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -33,16 +33,17 @@ class CompileRuntime
 
     const JitRuntime* jitRuntime();
 
     // Compilation does not occur off thread when the Gecko Profiler is enabled.
     GeckoProfiler& geckoProfiler();
 
     bool jitSupportsFloatingPoint();
     bool hadOutOfMemory();
+    bool profilingScripts();
 
     const JSAtomState& names();
     const PropertyName* emptyString();
     const StaticStrings& staticStrings();
     const Value& NaNValue();
     const Value& positiveInfinityValue();
     const WellKnownSymbols& wellKnownSymbols();
     const void* addressOfActiveJSContext();
@@ -74,18 +75,16 @@ class CompileZone
     const void* addressOfJSContext();
     const void* addressOfNeedsIncrementalBarrier();
     const void* addressOfFreeList(gc::AllocKind allocKind);
     const void* addressOfNurseryPosition();
     const void* addressOfNurseryCurrentEnd();
 
     bool nurseryExists();
     void setMinorGCShouldCancelIonCompilations();
-
-    bool profilingScripts();
 };
 
 class JitCompartment;
 
 class CompileCompartment
 {
     JSCompartment* compartment();
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -3189,18 +3189,20 @@ InvalidateActivation(FreeOp* fop, const 
 void
 jit::InvalidateAll(FreeOp* fop, Zone* zone)
 {
     // The caller should previously have cancelled off thread compilation.
 #ifdef DEBUG
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
         MOZ_ASSERT(!HasOffThreadIonCompile(comp));
 #endif
-
-    for (JitActivationIterator iter(fop->runtime()); !iter.done(); ++iter) {
+    if (zone->isAtomsZone())
+        return;
+    JSContext* cx = TlsContext.get();
+    for (JitActivationIterator iter(cx, zone->group()->ownerContext()); !iter.done(); ++iter) {
         if (iter->compartment()->zone() == zone) {
             JitSpew(JitSpew_IonInvalidate, "Invalidating all frames for GC");
             InvalidateActivation(fop, iter, true);
         }
     }
 }
 
 
@@ -3236,17 +3238,25 @@ jit::Invalidate(TypeZone& types, FreeOp*
         numInvalidations++;
     }
 
     if (!numInvalidations) {
         JitSpew(JitSpew_IonInvalidate, " No IonScript invalidation.");
         return;
     }
 
-    for (JitActivationIterator iter(fop->runtime()); !iter.done(); ++iter)
+    // This method can be called both during GC and during the course of normal
+    // script execution. In the former case this class will already be on the
+    // stack, and in the latter case the invalidations will all be on the
+    // current thread's stack, but the assertion under ActivationIterator can't
+    // tell that this is a thread local use of the iterator.
+    JSRuntime::AutoProhibitActiveContextChange apacc(fop->runtime());
+
+    JSContext* cx = TlsContext.get();
+    for (JitActivationIterator iter(cx, types.zone()->group()->ownerContext()); !iter.done(); ++iter)
         InvalidateActivation(fop, iter, false);
 
     // Drop the references added above. If a script was never active, its
     // IonScript will be immediately destroyed. Otherwise, it will be held live
     // until its last invalidated frame is destroyed.
     for (size_t i = 0; i < invalid.length(); i++) {
         CompilerOutput* co = invalid[i].compilerOutput(types);
         if (!co)
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -83,17 +83,17 @@ class JitContext
     TempAllocator* temp;
 
     // Wrappers with information about the current runtime/compartment for use
     // during compilation.
     CompileRuntime* runtime;
     CompileCompartment* compartment;
 
     bool hasProfilingScripts() const {
-        return compartment && compartment->zone()->profilingScripts();
+        return runtime && !!runtime->profilingScripts();
     }
 
     int getNextAssemblerId() {
         return assemblerCount_++;
     }
   private:
     JitContext* prev_;
     int assemblerCount_;
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -651,17 +651,16 @@ class InlineFrameIterator
 
   private:
     void findNextFrame();
     JSObject* computeEnvironmentChain(const Value& envChainValue, MaybeReadFallback& fallback,
                                       bool* hasInitialEnv = nullptr) const;
 
   public:
     InlineFrameIterator(JSContext* cx, const JitFrameIterator* iter);
-    InlineFrameIterator(JSRuntime* rt, const JitFrameIterator* iter);
     InlineFrameIterator(JSContext* cx, const InlineFrameIterator* iter);
 
     bool more() const {
         return frame_ && framesRead_ < frameCount_;
     }
 
     // Due to optimizations, we are not always capable of reading the callee of
     // inlined frames without invalidating the IonCode. This function might
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -1501,54 +1501,54 @@ TraceJitActivation(JSTracer* trc, const 
             break;
           default:
             MOZ_CRASH("unexpected frame type");
         }
     }
 }
 
 void
-TraceJitActivations(JSRuntime* rt, JSTracer* trc)
+TraceJitActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc)
 {
-    for (JitActivationIterator activations(rt); !activations.done(); ++activations)
+    for (JitActivationIterator activations(cx, target); !activations.done(); ++activations)
         TraceJitActivation(trc, activations);
 }
 
 JSCompartment*
-TopmostIonActivationCompartment(JSRuntime* rt)
+TopmostIonActivationCompartment(JSContext* cx)
 {
-    for (JitActivationIterator activations(rt); !activations.done(); ++activations) {
+    for (JitActivationIterator activations(cx); !activations.done(); ++activations) {
         for (JitFrameIterator frames(activations); !frames.done(); ++frames) {
             if (frames.type() == JitFrame_IonJS)
                 return activations.activation()->compartment();
         }
     }
     return nullptr;
 }
 
-void UpdateJitActivationsForMinorGC(JSRuntime* rt, JSTracer* trc)
+void UpdateJitActivationsForMinorGC(ZoneGroup* group, JSTracer* trc)
 {
     MOZ_ASSERT(JS::CurrentThreadIsHeapMinorCollecting());
-    for (JitActivationIterator activations(rt); !activations.done(); ++activations) {
+    JSContext* cx = TlsContext.get();
+    for (JitActivationIterator activations(cx, group->ownerContext()); !activations.done(); ++activations) {
         for (JitFrameIterator frames(activations); !frames.done(); ++frames) {
             if (frames.type() == JitFrame_IonJS)
                 UpdateIonJSFrameForMinorGC(trc, frames);
         }
     }
 }
 
 void
 GetPcScript(JSContext* cx, JSScript** scriptRes, jsbytecode** pcRes)
 {
     JitSpew(JitSpew_IonSnapshots, "Recover PC & Script from the last frame.");
 
     // Recover the return address so that we can look it up in the
     // PcScriptCache, as script/pc computation is expensive.
-    JSRuntime* rt = cx->runtime();
-    JitActivationIterator iter(rt);
+    JitActivationIterator iter(cx);
     JitFrameIterator it(iter);
     uint8_t* retAddr;
     if (it.isExitFrame()) {
         ++it;
 
         // Skip rectifier frames.
         if (it.isRectifier()) {
             ++it;
@@ -1586,20 +1586,20 @@ GetPcScript(JSContext* cx, JSScript** sc
     uint32_t hash;
     if (retAddr) {
         hash = PcScriptCache::Hash(retAddr);
 
         // Lazily initialize the cache. The allocation may safely fail and will not GC.
         if (MOZ_UNLIKELY(cx->ionPcScriptCache == nullptr)) {
             cx->ionPcScriptCache = (PcScriptCache*)js_malloc(sizeof(struct PcScriptCache));
             if (cx->ionPcScriptCache)
-                cx->ionPcScriptCache->clear(rt->gc.gcNumber());
+                cx->ionPcScriptCache->clear(cx->runtime()->gc.gcNumber());
         }
 
-        if (cx->ionPcScriptCache && cx->ionPcScriptCache->get(rt, hash, retAddr, scriptRes, pcRes))
+        if (cx->ionPcScriptCache && cx->ionPcScriptCache->get(cx->runtime(), hash, retAddr, scriptRes, pcRes))
             return;
     }
 
     // Lookup failed: undertake expensive process to recover the innermost inlined frame.
     jsbytecode* pc = nullptr;
     if (it.isIonJS() || it.isBailoutJS()) {
         InlineFrameIterator ifi(cx, &it);
         *scriptRes = ifi.script();
@@ -2300,24 +2300,16 @@ JitFrameIterator::osiIndex() const
 InlineFrameIterator::InlineFrameIterator(JSContext* cx, const JitFrameIterator* iter)
   : calleeTemplate_(cx),
     calleeRVA_(),
     script_(cx)
 {
     resetOn(iter);
 }
 
-InlineFrameIterator::InlineFrameIterator(JSRuntime* rt, const JitFrameIterator* iter)
-  : calleeTemplate_(TlsContext.get()),
-    calleeRVA_(),
-    script_(TlsContext.get())
-{
-    resetOn(iter);
-}
-
 InlineFrameIterator::InlineFrameIterator(JSContext* cx, const InlineFrameIterator* iter)
   : frame_(iter ? iter->frame_ : nullptr),
     framesRead_(0),
     frameCount_(iter ? iter->frameCount_ : UINT32_MAX),
     calleeTemplate_(cx),
     calleeRVA_(),
     script_(cx)
 {
@@ -3145,17 +3137,17 @@ InvalidationBailoutStack::checkInvariant
     uint8_t* osiPoint = osiPointReturnAddress();
     MOZ_ASSERT(rawBase <= osiPoint && osiPoint <= rawLimit);
 #endif
 }
 
 void
 AssertJitStackInvariants(JSContext* cx)
 {
-    for (JitActivationIterator activations(cx->runtime()); !activations.done(); ++activations) {
+    for (JitActivationIterator activations(cx); !activations.done(); ++activations) {
         JitFrameIterator frames(activations);
         size_t prevFrameSize = 0;
         size_t frameSize = 0;
         bool isScriptedCallee = false;
         for (; !frames.done(); ++frames) {
             size_t calleeFp = reinterpret_cast<size_t>(frames.fp());
             size_t callerFp = reinterpret_cast<size_t>(frames.prevFp());
             MOZ_ASSERT(callerFp >= calleeFp);
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -279,22 +279,22 @@ struct ResumeFromException
 
     BaselineBailoutInfo* bailoutInfo;
 };
 
 void HandleException(ResumeFromException* rfe);
 
 void EnsureBareExitFrame(JSContext* cx, JitFrameLayout* frame);
 
-void TraceJitActivations(JSRuntime* rt, JSTracer* trc);
+void TraceJitActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc);
 
 JSCompartment*
-TopmostIonActivationCompartment(JSRuntime* rt);
+TopmostIonActivationCompartment(JSContext* cx);
 
-void UpdateJitActivationsForMinorGC(JSRuntime* rt, JSTracer* trc);
+void UpdateJitActivationsForMinorGC(ZoneGroup* group, JSTracer* trc);
 
 static inline uint32_t
 EncodeFrameHeaderSize(size_t headerSize)
 {
     MOZ_ASSERT((headerSize % sizeof(uintptr_t)) == 0);
 
     uint32_t headerSizeWords = headerSize / sizeof(uintptr_t);
     MOZ_ASSERT(headerSizeWords <= FRAME_HEADER_SIZE_MASK);
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -595,50 +595,43 @@ ICStubCompiler::callTypeUpdateIC(MacroAs
 
     EmitCallTypeUpdateIC(masm, code, objectOffset);
     return true;
 }
 
 void
 ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch)
 {
-    if (engine_ == Engine::Baseline) {
-        EmitBaselineEnterStubFrame(masm, scratch);
+    MOZ_ASSERT(engine_ == Engine::Baseline);
+    EmitBaselineEnterStubFrame(masm, scratch);
 #ifdef DEBUG
-        framePushedAtEnterStubFrame_ = masm.framePushed();
+    framePushedAtEnterStubFrame_ = masm.framePushed();
 #endif
-    } else {
-        EmitIonEnterStubFrame(masm, scratch);
-    }
 
     MOZ_ASSERT(!inStubFrame_);
     inStubFrame_ = true;
 
 #ifdef DEBUG
     entersStubFrame_ = true;
 #endif
 }
 
 void
 ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon)
 {
     MOZ_ASSERT(entersStubFrame_ && inStubFrame_);
     inStubFrame_ = false;
 
-    if (engine_ == Engine::Baseline) {
+    MOZ_ASSERT(engine_ == Engine::Baseline);
 #ifdef DEBUG
-        masm.setFramePushed(framePushedAtEnterStubFrame_);
-        if (calledIntoIon)
-            masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
+    masm.setFramePushed(framePushedAtEnterStubFrame_);
+    if (calledIntoIon)
+        masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
 #endif
-
-        EmitBaselineLeaveStubFrame(masm, calledIntoIon);
-    } else {
-        EmitIonLeaveStubFrame(masm);
-    }
+    EmitBaselineLeaveStubFrame(masm, calledIntoIon);
 }
 
 void
 ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch)
 {
     if (engine_ == Engine::IonSharedIC) {
         masm.push(Imm32(0));
         return;
@@ -700,17 +693,17 @@ SharedStubInfo::SharedStubInfo(JSContext
         // outerScript_ is initialized lazily.
     }
 }
 
 HandleScript
 SharedStubInfo::outerScript(JSContext* cx)
 {
     if (!outerScript_) {
-        js::jit::JitActivationIterator iter(cx->runtime());
+        js::jit::JitActivationIterator iter(cx);
         JitFrameIterator it(iter);
         MOZ_ASSERT(it.isExitFrame());
         ++it;
         MOZ_ASSERT(it.isIonJS());
         outerScript_ = it.script();
         MOZ_ASSERT(!it.ionScript()->invalidated());
     }
     return outerScript_;
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1123,17 +1123,17 @@ StringReplace(JSContext* cx, HandleStrin
 
     return str_replace_string_raw(cx, string, pattern, repl);
 }
 
 bool
 RecompileImpl(JSContext* cx, bool force)
 {
     MOZ_ASSERT(cx->currentlyRunningInJit());
-    JitActivationIterator activations(cx->runtime());
+    JitActivationIterator activations(cx);
     JitFrameIterator iter(activations);
 
     MOZ_ASSERT(iter.type() == JitFrame_Exit);
     ++iter;
 
     RootedScript script(cx, iter.script());
     MOZ_ASSERT(script->hasIonScript());
 
--- a/js/src/jit/arm/SharedICHelpers-arm.h
+++ b/js/src/jit/arm/SharedICHelpers-arm.h
@@ -195,30 +195,16 @@ EmitBaselineEnterStubFrame(MacroAssemble
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 
     // We pushed 4 words, so the stack is still aligned to 8 bytes.
     masm.checkStackAlignment();
 }
 
 inline void
-EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
-{
-    MOZ_ASSERT(ICTailCallReg == lr);
-
-    // In arm the link register contains the return address,
-    // but in jit frames we expect it to be on the stack. As a result
-    // push the link register (which is actually part of the previous frame.
-    // Therefore using push instead of Push).
-    masm.push(ICTailCallReg);
-
-    masm.Push(ICStubReg);
-}
-
-inline void
 EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
 {
     ScratchRegisterScope scratch(masm);
 
     // Ion frames do not save and restore the frame pointer. If we called into
     // Ion, we have to restore the stack pointer from the frame descriptor. If
     // we performed a VM call, the descriptor has been popped already so in that
     // case we use the frame pointer.
@@ -236,23 +222,16 @@ EmitBaselineLeaveStubFrame(MacroAssemble
     // Load the return address.
     masm.Pop(ICTailCallReg);
 
     // Discard the frame descriptor.
     masm.Pop(scratch);
 }
 
 inline void
-EmitIonLeaveStubFrame(MacroAssembler& masm)
-{
-    masm.Pop(ICStubReg);
-    masm.pop(ICTailCallReg); // See EmitIonEnterStubFrame for explanation on pop/Pop.
-}
-
-inline void
 EmitStowICValues(MacroAssembler& masm, int values)
 {
     MOZ_ASSERT(values >= 0 && values <= 2);
     switch(values) {
       case 1:
         // Stow R0.
         masm.Push(R0);
         break;
--- a/js/src/jit/arm64/SharedICHelpers-arm64.h
+++ b/js/src/jit/arm64/SharedICHelpers-arm64.h
@@ -168,22 +168,16 @@ EmitBaselineEnterStubFrame(MacroAssemble
     // Update the frame register.
     masm.Mov(BaselineFrameReg64, masm.GetStackPointer64());
 
     // Stack should remain 16-byte aligned.
     masm.checkStackAlignment();
 }
 
 inline void
-EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
-{
-    MOZ_CRASH("Not implemented yet.");
-}
-
-inline void
 EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
 {
     vixl::UseScratchRegisterScope temps(&masm.asVIXL());
     const ARMRegister scratch64 = temps.AcquireX();
 
     // Ion frames do not save and restore the frame pointer. If we called
     // into Ion, we have to restore the stack pointer from the frame descriptor.
     // If we performed a VM call, the descriptor has been popped already so
@@ -199,22 +193,16 @@ EmitBaselineLeaveStubFrame(MacroAssemble
     // Pop values, discarding the frame descriptor.
     masm.pop(BaselineFrameReg, ICStubReg, ICTailCallReg, scratch64.asUnsized());
 
     // Stack should remain 16-byte aligned.
     masm.checkStackAlignment();
 }
 
 inline void
-EmitIonLeaveStubFrame(MacroAssembler& masm)
-{
-    MOZ_CRASH("Not implemented yet.");
-}
-
-inline void
 EmitStowICValues(MacroAssembler& masm, int values)
 {
     switch (values) {
       case 1:
         // Stow R0.
         masm.Push(R0);
         break;
       case 2:
--- a/js/src/jit/mips-shared/SharedICHelpers-mips-shared.h
+++ b/js/src/jit/mips-shared/SharedICHelpers-mips-shared.h
@@ -198,30 +198,16 @@ EmitBaselineEnterStubFrame(MacroAssemble
                                             offsetof(BaselineStubFrame, savedFrame)));
     masm.movePtr(BaselineStackReg, BaselineFrameReg);
 
     // Stack should remain aligned.
     masm.assertStackAlignment(sizeof(Value), 0);
 }
 
 inline void
-EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
-{
-    MOZ_ASSERT(ICTailCallReg == ra);
-
-    // In MIPS the ra register contains the return address,
-    // but in jit frames we expect it to be on the stack. As a result
-    // push the link register (which is actually part of the previous frame.
-    // Therefore using push instead of Push).
-    masm.push(ICTailCallReg);
-
-    masm.Push(ICStubReg);
-}
-
-inline void
 EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
 {
     // Ion frames do not save and restore the frame pointer. If we called
     // into Ion, we have to restore the stack pointer from the frame descriptor.
     // If we performed a VM call, the descriptor has been popped already so
     // in that case we use the frame pointer.
     if (calledIntoIon) {
         masm.pop(ScratchRegister);
@@ -241,23 +227,16 @@ EmitBaselineLeaveStubFrame(MacroAssemble
                  ICTailCallReg);
 
     // Discard the frame descriptor.
     masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, descriptor)), ScratchRegister);
     masm.addPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
 }
 
 inline void
-EmitIonLeaveStubFrame(MacroAssembler& masm)
-{
-    masm.Pop(ICStubReg);
-    masm.pop(ICTailCallReg); // See EmitIonEnterStubFrame for explanation on pop/Pop.
-}
-
-inline void
 EmitStowICValues(MacroAssembler& masm, int values)
 {
     MOZ_ASSERT(values >= 0 && values <= 2);
     switch(values) {
       case 1:
         // Stow R0
         masm.Push(R0);
         break;
--- a/js/src/jit/none/SharedICHelpers-none.h
+++ b/js/src/jit/none/SharedICHelpers-none.h
@@ -21,19 +21,17 @@ inline void EmitEnterTypeMonitorIC(Macro
 inline void EmitReturnFromIC(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitChangeICReturnAddress(MacroAssembler&, Register) { MOZ_CRASH(); }
 inline void EmitBaselineTailCallVM(JitCode*, MacroAssembler&, uint32_t) { MOZ_CRASH(); }
 inline void EmitIonTailCallVM(JitCode*, MacroAssembler&, uint32_t) { MOZ_CRASH(); }
 inline void EmitBaselineCreateStubFrameDescriptor(MacroAssembler&, Register, uint32_t) { MOZ_CRASH(); }
 inline void EmitBaselineCallVM(JitCode*, MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitIonCallVM(JitCode*, size_t, MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitBaselineEnterStubFrame(MacroAssembler&, Register) { MOZ_CRASH(); }
-inline void EmitIonEnterStubFrame(MacroAssembler&, Register) { MOZ_CRASH(); }
 inline void EmitBaselineLeaveStubFrame(MacroAssembler&, bool v = false) { MOZ_CRASH(); }
-inline void EmitIonLeaveStubFrame(MacroAssembler&) { MOZ_CRASH(); }
 inline void EmitStowICValues(MacroAssembler&, int) { MOZ_CRASH(); }
 inline void EmitUnstowICValues(MacroAssembler&, int, bool v = false) { MOZ_CRASH(); }
 inline void EmitCallTypeUpdateIC(MacroAssembler&, JitCode*, uint32_t) { MOZ_CRASH(); }
 inline void EmitStubGuardFailure(MacroAssembler&) { MOZ_CRASH(); }
 
 template <typename T> inline void EmitPreBarrier(MacroAssembler&, T, MIRType) { MOZ_CRASH(); }
 
 } // namespace jit
--- a/js/src/jit/x64/SharedICHelpers-x64.h
+++ b/js/src/jit/x64/SharedICHelpers-x64.h
@@ -157,49 +157,54 @@ EmitIonCallVM(JitCode* target, size_t st
 
 // Size of vales pushed by EmitEnterStubFrame.
 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void*);
 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void*);
 
 inline void
 EmitBaselineEnterStubFrame(MacroAssembler& masm, Register)
 {
-    EmitRestoreTailCallReg(masm);
-
     ScratchRegisterScope scratch(masm);
 
-    // Compute frame size.
+    // Compute frame size. Because the return address is still on the stack,
+    // this is:
+    //
+    //   BaselineFrameReg
+    //   + BaselineFrame::FramePointerOffset
+    //   - BaselineStackReg
+    //   - sizeof(return address)
+    //
+    // The two constants cancel each other out, so we can just calculate
+    // BaselineFrameReg - BaselineStackReg.
+
+    static_assert(BaselineFrame::FramePointerOffset == sizeof(void*),
+                  "FramePointerOffset must be the same as the return address size");
+
     masm.movq(BaselineFrameReg, scratch);
-    masm.addq(Imm32(BaselineFrame::FramePointerOffset), scratch);
     masm.subq(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
     // if needed.
 
-    // Push frame descriptor and return address.
+    // Push the return address that's currently on top of the stack.
+    masm.Push(Operand(BaselineStackReg, 0));
+
+    // Replace the original return address with the frame descriptor.
     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
-    masm.Push(scratch);
-    masm.Push(ICTailCallReg);
+    masm.storePtr(scratch, Address(BaselineStackReg, sizeof(uintptr_t)));
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.Push(ICStubReg);
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 }
 
 inline void
-EmitIonEnterStubFrame(MacroAssembler& masm, Register)
-{
-    masm.loadPtr(Address(masm.getStackPointer(), 0), ICTailCallReg);
-    masm.Push(ICStubReg);
-}
-
-inline void
 EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
 {
     // Ion frames do not save and restore the frame pointer. If we called
     // into Ion, we have to restore the stack pointer from the frame descriptor.
     // If we performed a VM call, the descriptor has been popped already so
     // in that case we use the frame pointer.
     if (calledIntoIon) {
         ScratchRegisterScope scratch(masm);
@@ -208,28 +213,21 @@ EmitBaselineLeaveStubFrame(MacroAssemble
         masm.addq(scratch, BaselineStackReg);
     } else {
         masm.mov(BaselineFrameReg, BaselineStackReg);
     }
 
     masm.Pop(BaselineFrameReg);
     masm.Pop(ICStubReg);
 
-    // Pop return address.
-    masm.Pop(ICTailCallReg);
-
-    // Overwrite frame descriptor with return address, so that the stack matches
-    // the state before entering the stub frame.
-    masm.storePtr(ICTailCallReg, Address(BaselineStackReg, 0));
-}
-
-inline void
-EmitIonLeaveStubFrame(MacroAssembler& masm)
-{
-    masm.Pop(ICStubReg);
+    // The return address is on top of the stack, followed by the frame
+    // descriptor. Use a pop instruction to overwrite the frame descriptor
+    // with the return address. Note that pop increments the stack pointer
+    // before computing the address.
+    masm.Pop(Operand(BaselineStackReg, 0));
 }
 
 inline void
 EmitStowICValues(MacroAssembler& masm, int values)
 {
     MOZ_ASSERT(values >= 0 && values <= 2);
     switch(values) {
       case 1:
--- a/js/src/jit/x86/SharedICHelpers-x86.h
+++ b/js/src/jit/x86/SharedICHelpers-x86.h
@@ -155,81 +155,75 @@ EmitIonCallVM(JitCode* target, size_t st
 
 // Size of vales pushed by EmitEnterStubFrame.
 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void*);
 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void*);
 
 inline void
 EmitBaselineEnterStubFrame(MacroAssembler& masm, Register scratch)
 {
-    MOZ_ASSERT(scratch != ICTailCallReg);
-
-    EmitRestoreTailCallReg(masm);
+    // Compute frame size. Because the return address is still on the stack,
+    // this is:
+    //
+    //   BaselineFrameReg
+    //   + BaselineFrame::FramePointerOffset
+    //   - BaselineStackReg
+    //   - sizeof(return address)
+    //
+    // The two constants cancel each other out, so we can just calculate
+    // BaselineFrameReg - BaselineStackReg.
 
-    // Compute frame size.
+    static_assert(BaselineFrame::FramePointerOffset == sizeof(void*),
+                  "FramePointerOffset must be the same as the return address size");
+
     masm.movl(BaselineFrameReg, scratch);
-    masm.addl(Imm32(BaselineFrame::FramePointerOffset), scratch);
     masm.subl(BaselineStackReg, scratch);
 
     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
 
     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
     // if needed.
 
-    // Push frame descriptor and return address.
+    // Push the return address that's currently on top of the stack.
+    masm.Push(Operand(BaselineStackReg, 0));
+
+    // Replace the original return address with the frame descriptor.
     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
-    masm.Push(scratch);
-    masm.Push(ICTailCallReg);
+    masm.storePtr(scratch, Address(BaselineStackReg, sizeof(uintptr_t)));
 
     // Save old frame pointer, stack pointer and stub reg.
     masm.Push(ICStubReg);
     masm.Push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
 }
 
 inline void
-EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
-{
-    MOZ_ASSERT(scratch != ICTailCallReg);
-
-    masm.loadPtr(Address(masm.getStackPointer(), 0), ICTailCallReg);
-    masm.Push(ICStubReg);
-}
-
-inline void
 EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
 {
     // Ion frames do not save and restore the frame pointer. If we called
     // into Ion, we have to restore the stack pointer from the frame descriptor.
     // If we performed a VM call, the descriptor has been popped already so
     // in that case we use the frame pointer.
     if (calledIntoIon) {
-        Register scratch = ICTailCallReg;
+        Register scratch = ICStubReg;
         masm.Pop(scratch);
         masm.shrl(Imm32(FRAMESIZE_SHIFT), scratch);
         masm.addl(scratch, BaselineStackReg);
     } else {
         masm.mov(BaselineFrameReg, BaselineStackReg);
     }
 
     masm.Pop(BaselineFrameReg);
     masm.Pop(ICStubReg);
 
-    // Pop return address.
-    masm.Pop(ICTailCallReg);
-
-    // Overwrite frame descriptor with return address, so that the stack matches
-    // the state before entering the stub frame.
-    masm.storePtr(ICTailCallReg, Address(BaselineStackReg, 0));
-}
-
-inline void
-EmitIonLeaveStubFrame(MacroAssembler& masm)
-{
-    masm.Pop(ICStubReg);
+    // The return address is on top of the stack, followed by the frame
+    // descriptor. Use a pop instruction to overwrite the frame descriptor
+    // with the return address. Note that pop increments the stack pointer
+    // before computing the address.
+    masm.Pop(Operand(BaselineStackReg, 0));
 }
 
 inline void
 EmitStowICValues(MacroAssembler& masm, int values)
 {
     MOZ_ASSERT(values >= 0 && values <= 2);
     switch(values) {
       case 1:
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6626,17 +6626,17 @@ DescribeScriptedCaller(JSContext* cx, Au
 // 'outer' frames. That's fine: each activation is tied to a single compartment,
 // so if an activation contains at least one non-self-hosted frame, we can use
 // the activation's global for GetScriptedCallerGlobal. If, however, all 'outer'
 // frames are self-hosted, it's possible Ion inlined a non-self-hosted script,
 // so we must return false and use the slower path.
 static bool
 GetScriptedCallerActivationFast(JSContext* cx, Activation** activation)
 {
-    ActivationIterator activationIter(cx->runtime());
+    ActivationIterator activationIter(cx);
 
     if (activationIter.done()) {
         *activation = nullptr;
         return true;
     }
 
     *activation = activationIter.activation();
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -201,77 +201,77 @@ ToId(JSContext* cx, double index, Mutabl
 {
     if (index == uint32_t(index))
         return IndexToId(cx, uint32_t(index), id);
 
     Value tmp = DoubleValue(index);
     return ValueToId<CanGC>(cx, HandleValue::fromMarkedLocation(&tmp), id);
 }
 
+/*
+ * If the property at the given index exists, get its value into |vp| and set
+ * |*hole| to false. Otherwise set |*hole| to true and |vp| to Undefined.
+ */
 static bool
-ToId(JSContext* cx, uint32_t index, MutableHandleId id)
+GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index, bool* hole,
+           MutableHandleValue vp)
 {
-    return IndexToId(cx, index, id);
-}
-
-/*
- * If the property at the given index exists, get its value into location
- * pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
- * to JSVAL_VOID. This function assumes that the location pointed by vp is
- * properly rooted and can be used as GC-protected storage for temporaries.
- */
-static inline bool
-DoGetElement(JSContext* cx, HandleObject obj, HandleObject receiver,
-             uint32_t index, bool* hole, MutableHandleValue vp)
-{
+    if (index < GetAnyBoxedOrUnboxedInitializedLength(obj)) {
+        vp.set(GetAnyBoxedOrUnboxedDenseElement(obj, index));
+        if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
+            *hole = false;
+            return true;
+        }
+    }
+    if (obj->is<ArgumentsObject>()) {
+        if (obj->as<ArgumentsObject>().maybeGetElement(index, vp)) {
+            *hole = false;
+            return true;
+        }
+    }
+
     RootedId id(cx);
-    if (!ToId(cx, index, &id))
+    if (!IndexToId(cx, index, &id))
         return false;
 
     bool found;
     if (!HasProperty(cx, obj, id, &found))
         return false;
 
     if (found) {
         if (!GetProperty(cx, obj, receiver, id, vp))
             return false;
     } else {
         vp.setUndefined();
     }
     *hole = !found;
     return true;
 }
 
-static bool
-GetElement(JSContext* cx, HandleObject obj, HandleObject receiver,
-           uint32_t index, bool* hole, MutableHandleValue vp)
-{
-    if (index < GetAnyBoxedOrUnboxedInitializedLength(obj)) {
-        vp.set(GetAnyBoxedOrUnboxedDenseElement(obj, uint32_t(index)));
-        if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
-            *hole = false;
-            return true;
-        }
-    }
-    if (obj->is<ArgumentsObject>()) {
-        if (obj->as<ArgumentsObject>().maybeGetElement(uint32_t(index), vp)) {
-            *hole = false;
-            return true;
-        }
-    }
-
-    return DoGetElement(cx, obj, receiver, index, hole, vp);
-}
-
 static inline bool
 GetElement(JSContext* cx, HandleObject obj, uint32_t index, bool* hole, MutableHandleValue vp)
 {
     return GetElement(cx, obj, obj, index, hole, vp);
 }
 
+static bool
+GetElement(JSContext* cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
+{
+    if (index < GetAnyBoxedOrUnboxedInitializedLength(obj)) {
+        vp.set(GetAnyBoxedOrUnboxedDenseElement(obj, index));
+        if (!vp.isMagic(JS_ELEMENTS_HOLE))
+            return true;
+    }
+    if (obj->is<ArgumentsObject>()) {
+        if (obj->as<ArgumentsObject>().maybeGetElement(index, vp))
+            return true;
+    }
+    return GetElement(cx, obj, obj, index, vp);
+}
+
 bool
 ElementAdder::append(JSContext* cx, HandleValue v)
 {
     MOZ_ASSERT(index_ < length_);
     if (resObj_) {
         DenseElementResult result =
             SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
         if (result == DenseElementResult::Failure)
@@ -1055,18 +1055,20 @@ ArrayJoinDenseKernel(JSContext* cx, Sepa
     // length > initLength we rely on the second loop to add the
     // other elements.
     MOZ_ASSERT(*numProcessed == 0);
     uint32_t initLength = Min<uint32_t>(GetBoxedOrUnboxedInitializedLength<Type>(obj), length);
     while (*numProcessed < initLength) {
         if (!CheckForInterrupt(cx))
             return DenseElementResult::Failure;
 
+        // Step 7.b.
         const Value& elem = GetBoxedOrUnboxedDenseElement<Type>(obj, *numProcessed);
 
+        // Steps 7.c-d.
         if (elem.isString()) {
             if (!sb.append(elem.toString()))
                 return DenseElementResult::Failure;
         } else if (elem.isNumber()) {
             if (!NumberValueToStringBuffer(cx, elem, sb))
                 return DenseElementResult::Failure;
         } else if (elem.isBoolean()) {
             if (!BooleanToStringBuffer(elem.toBoolean(), sb))
@@ -1080,16 +1082,17 @@ ArrayJoinDenseKernel(JSContext* cx, Sepa
              * Symbol stringifying is a TypeError, so into the slow path
              * with those as well.
              */
             break;
         } else {
             MOZ_ASSERT(elem.isMagic(JS_ELEMENTS_HOLE) || elem.isNullOrUndefined());
         }
 
+        // Steps 7.a, 7.e.
         if (++(*numProcessed) != length && !sepOp(cx, sb))
             return DenseElementResult::Failure;
     }
 
     return DenseElementResult::Incomplete;
 }
 
 template <typename SeparatorOp>
@@ -1112,118 +1115,123 @@ struct ArrayJoinDenseKernelFunctor {
     }
 };
 
 template <typename SeparatorOp>
 static bool
 ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
                StringBuffer& sb)
 {
+    // Step 6.
     uint32_t i = 0;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         ArrayJoinDenseKernelFunctor<SeparatorOp> functor(cx, sepOp, obj, length, sb, &i);
         DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
         if (result == DenseElementResult::Failure)
             return false;
     }
 
+    // Step 7.
     if (i != length) {
         RootedValue v(cx);
         while (i < length) {
             if (!CheckForInterrupt(cx))
                 return false;
 
-            bool hole;
-            if (!GetElement(cx, obj, i, &hole, &v))
+            // Step 7.b.
+            if (!GetElement(cx, obj, i, &v))
                 return false;
-            if (!hole && !v.isNullOrUndefined()) {
+
+            // Steps 7.c-d.
+            if (!v.isNullOrUndefined()) {
                 if (!ValueToStringBuffer(cx, v, sb))
                     return false;
             }
 
+            // Steps 7.a, 7.e.
             if (++i != length && !sepOp(cx, sb))
                 return false;
         }
     }
 
     return true;
 }
 
-/* ES5 15.4.4.5 */
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.13 Array.prototype.join ( separator )
 bool
 js::array_join(JSContext* cx, unsigned argc, Value* vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.join");
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    // Step 1
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     AutoCycleDetector detector(cx, obj);
     if (!detector.init())
         return false;
 
     if (detector.foundCycle()) {
         args.rval().setString(cx->names().empty);
         return true;
     }
 
-    // Steps 2 and 3
+    // Step 2.
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
-    // Steps 4 and 5
+    // Steps 3-4.
     RootedLinearString sepstr(cx);
     if (args.hasDefined(0)) {
         JSString *s = ToString<CanGC>(cx, args[0]);
         if (!s)
             return false;
         sepstr = s->ensureLinear(cx);
         if (!sepstr)
             return false;
     } else {
         sepstr = cx->names().comma;
     }
 
-    // Step 6 is implicit in the loops below.
-
-    // An optimized version of a special case of steps 7-11: when length==1 and
+    // An optimized version of a special case of steps 5-8: when length==1 and
     // the 0th element is a string, ToString() of that element is a no-op and
     // so it can be immediately returned as the result.
     if (length == 1 && GetAnyBoxedOrUnboxedInitializedLength(obj) == 1) {
         Value elem0 = GetAnyBoxedOrUnboxedDenseElement(obj, 0);
         if (elem0.isString()) {
             args.rval().set(elem0);
             return true;
         }
     }
 
+    // Step 5.
     StringBuffer sb(cx);
     if (sepstr->hasTwoByteChars() && !sb.ensureTwoByteChars())
         return false;
 
     // The separator will be added |length - 1| times, reserve space for that
     // so that we don't have to unnecessarily grow the buffer.
     size_t seplen = sepstr->length();
     CheckedInt<uint32_t> res = CheckedInt<uint32_t>(seplen) * (length - 1);
     if (length > 0 && !res.isValid()) {
         ReportAllocationOverflow(cx);
         return false;
     }
 
     if (length > 0 && !sb.reserve(res.value()))
         return false;
 
-    // Various optimized versions of steps 7-10.
+    // Various optimized versions of steps 6-7.
     if (seplen == 0) {
         EmptySeparatorOp op;
         if (!ArrayJoinKernel(cx, op, obj, length, sb))
             return false;
     } else if (seplen == 1) {
         char16_t c = sepstr->latin1OrTwoByteChar(0);
         if (c <= JSString::MAX_LATIN1_CHAR) {
             CharSeparatorOp<Latin1Char> op(c);
@@ -1235,17 +1243,17 @@ js::array_join(JSContext* cx, unsigned a
                 return false;
         }
     } else {
         StringSeparatorOp op(sepstr);
         if (!ArrayJoinKernel(cx, op, obj, length, sb))
             return false;
     }
 
-    // Step 11
+    // Step 8.
     JSString *str = sb.finishString();
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
@@ -1402,25 +1410,30 @@ ArrayReverseDenseKernel(JSContext* cx, H
     }
 
     return DenseElementResult::Success;
 }
 
 DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
                              JSContext*, HandleObject, uint32_t);
 
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.21 Array.prototype.reverse ( )
 bool
 js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.reverse");
     CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
+    // Step 2.
     uint32_t len;
     if (!GetLengthProperty(cx, obj, &len))
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         ArrayReverseDenseKernelFunctor functor(cx, obj, len);
         DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
         if (result != DenseElementResult::Incomplete) {
@@ -1429,16 +1442,17 @@ js::array_reverse(JSContext* cx, unsigne
              * array has trailing holes (and thus the original array began with
              * holes).
              */
             args.rval().setObject(*obj);
             return result == DenseElementResult::Success;
         }
     }
 
+    // Steps 3-5.
     RootedValue lowval(cx), hival(cx);
     for (uint32_t i = 0, half = len / 2; i < half; i++) {
         bool hole, hole2;
         if (!CheckForInterrupt(cx) ||
             !GetElement(cx, obj, i, &hole, &lowval) ||
             !GetElement(cx, obj, len - i - 1, &hole2, &hival))
         {
             return false;
@@ -1458,16 +1472,18 @@ js::array_reverse(JSContext* cx, unsigne
             if (!DeletePropertyOrThrow(cx, obj, i))
                 return false;
             if (!SetElement(cx, obj, len - i - 1, lowval))
                 return false;
         } else {
             // No action required.
         }
     }
+
+    // Step 6.
     args.rval().setObject(*obj);
     return true;
 }
 
 static inline bool
 CompareStringValues(JSContext* cx, const Value& a, const Value& b, bool* lessOrEqualp)
 {
     if (!CheckForInterrupt(cx))
@@ -2067,29 +2083,30 @@ js::NewbornArrayPush(JSContext* cx, Hand
         return false;
 
     arr->setDenseInitializedLength(length + 1);
     arr->setLengthInt32(length + 1);
     arr->initDenseElementWithType(cx, length, v);
     return true;
 }
 
-/* ES5 15.4.4.7 */
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.18 Array.prototype.push ( ...items )
 bool
 js::array_push(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.push");
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    /* Step 1. */
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
-    /* Steps 2-3. */
+    // Step 2.
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         DenseElementResult result =
             SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, length,
                                                       args.array(), args.length());
@@ -2107,62 +2124,62 @@ js::array_push(JSContext* cx, unsigned a
                 MOZ_ASSERT(obj->is<NativeObject>());
                 return SetLengthProperty(cx, obj, newlength);
             }
 
             return true;
         }
     }
 
-    /* Steps 4-5. */
+    // Steps 3-6.
     if (!SetArrayElements(cx, obj, length, args.length(), args.array()))
         return false;
 
-    /* Steps 6-7. */
+    // Steps 7-8.
     double newlength = length + double(args.length());
     args.rval().setNumber(newlength);
     return SetLengthProperty(cx, obj, newlength);
 }
 
-/* ES6 20130308 draft 15.4.4.6. */
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.17 Array.prototype.pop ( )
 bool
 js::array_pop(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.pop");
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    /* Step 1. */
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
-    /* Steps 2-3. */
+    // Step 2.
     uint32_t index;
     if (!GetLengthProperty(cx, obj, &index))
         return false;
 
-    /* Steps 4-5. */
+    // Steps 3-4.
     if (index == 0) {
-        /* Step 4b. */
+        // Step 3.b.
         args.rval().setUndefined();
     } else {
-        /* Step 5a. */
+        // Steps 4.a-b.
         index--;
 
-        /* Step 5b, 5e. */
-        bool hole;
-        if (!GetElement(cx, obj, index, &hole, args.rval()))
+        // Steps 4.c, 4.f.
+        if (!GetElement(cx, obj, index, args.rval()))
             return false;
 
-        /* Step 5c. */
-        if (!hole && !DeletePropertyOrThrow(cx, obj, index))
+        // Steps 4.d.
+        if (!DeletePropertyOrThrow(cx, obj, index))
             return false;
     }
 
-    /* Steps 4a, 5d. */
+    // Steps 3.a, 4.e.
     return SetLengthProperty(cx, obj, index);
 }
 
 template <JSValueType Type>
 static inline DenseElementResult
 ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
 {
     MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj));
@@ -2251,99 +2268,105 @@ ArrayShiftDenseKernel(JSContext* cx, Han
 
     SetBoxedOrUnboxedInitializedLength<Type>(cx, obj, initlen - 1);
     return DenseElementResult::Success;
 }
 
 DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
                              JSContext*, HandleObject, MutableHandleValue);
 
-/* ES5 15.4.4.9 */
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.22 Array.prototype.shift ( )
 bool
 js::array_shift(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.shift");
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    /* Step 1. */
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
-    /* Steps 2-3. */
+    // Step 2.
     uint32_t len;
     if (!GetLengthProperty(cx, obj, &len))
         return false;
 
-    /* Step 4. */
+    // Step 3.
     if (len == 0) {
-        /* Step 4a. */
+        // Step 3.a.
         if (!SetLengthProperty(cx, obj, 0))
             return false;
 
-        /* Step 4b. */
+        // Step 3.b.
         args.rval().setUndefined();
         return true;
     }
 
     uint32_t newlen = len - 1;
 
     /* Fast paths. */
     ArrayShiftDenseKernelFunctor functor(cx, obj, args.rval());
     DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
     if (result != DenseElementResult::Incomplete) {
         if (result == DenseElementResult::Failure)
             return false;
 
         return SetLengthProperty(cx, obj, newlen);
     }
 
-    /* Steps 5, 10. */
-    bool hole;
-    if (!GetElement(cx, obj, 0, &hole, args.rval()))
+    // Steps 4, 9.
+    if (!GetElement(cx, obj, 0, args.rval()))
         return false;
 
-    /* Steps 6-7. */
+    // Steps 5-6.
     RootedValue value(cx);
     for (uint32_t i = 0; i < newlen; i++) {
         if (!CheckForInterrupt(cx))
             return false;
+        bool hole;
         if (!GetElement(cx, obj, i + 1, &hole, &value))
             return false;
         if (hole) {
             if (!DeletePropertyOrThrow(cx, obj, i))
                 return false;
         } else {
             if (!SetElement(cx, obj, i, value))
                 return false;
         }
     }
 
-    /* Step 8. */
+    // Step 7.
     if (!DeletePropertyOrThrow(cx, obj, newlen))
         return false;
 
-    /* Step 9. */
+    // Step 8.
     return SetLengthProperty(cx, obj, newlen);
 }
 
+// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+// 22.1.3.29 Array.prototype.unshift ( ...items )
 bool
 js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.unshift");
     CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Step 1.
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
+    // Step 2.
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
-    double newlen = length;
+    // Steps 3-4.
     if (args.length() > 0) {
         /* Slide up the array to make room for all args at the bottom. */
         if (length > 0) {
             // Only include a fast path for boxed arrays. Unboxed arrays can't
             // be optimized here because unshifting temporarily places holes at
             // the start of the array.
             // TODO: Implement unboxed array optimization similar to the one in
             // array_splice_impl(), unshift() is a special version of splice():
@@ -2369,49 +2392,53 @@ js::array_unshift(JSContext* cx, unsigne
                     break;
                 }
                 aobj->moveDenseElements(args.length(), 0, length);
                 for (uint32_t i = 0; i < args.length(); i++)
                     aobj->setDenseElement(i, MagicValue(JS_ELEMENTS_HOLE));
                 optimized = true;
             } while (false);
 
+            // Steps 4.b-c.
             if (!optimized) {
                 uint32_t last = length;
                 double upperIndex = double(last) + args.length();
                 RootedValue value(cx);
                 do {
                     --last, --upperIndex;
-                    bool hole;
                     if (!CheckForInterrupt(cx))
                         return false;
+                    bool hole;
                     if (!GetElement(cx, obj, last, &hole, &value))
                         return false;
                     if (hole) {
                         if (!DeletePropertyOrThrow(cx, obj, upperIndex))
                             return false;
                     } else {
                         if (!SetElement(cx, obj, upperIndex, value))
                             return false;
                     }
                 } while (last != 0);
             }
         }
 
+        // Steps 4.d-f.
         /* Copy from args to the bottom of the array. */
         if (!SetArrayElements(cx, obj, 0, args.length(), args.array()))
             return false;
-
-        newlen += args.length();
     }
-    if (!SetLengthProperty(cx, obj, newlen))
+
+    // Step 5.
+    double newlength = length + double(args.length());
+    if (!SetLengthProperty(cx, obj, newlength))
         return false;
 
+    // Step 6.
     /* Follow Perl by returning the new array length. */
-    args.rval().setNumber(newlen);
+    args.rval().setNumber(newlength);
     return true;
 }
 
 /*
  * Returns true if this is a dense or unboxed array whose |count| properties
  * starting from |startingIndex| may be accessed (get, set, delete) directly
  * through its contiguous vector of elements without fear of getters, setters,
  * etc. along the prototype chain, or of enumerators requiring notification of
@@ -2453,38 +2480,38 @@ js::array_splice(JSContext* cx, unsigned
 {
     return array_splice_impl(cx, argc, vp, true);
 }
 
 static inline bool
 ArraySpliceCopy(JSContext* cx, HandleObject arr, HandleObject obj,
                 uint32_t actualStart, uint32_t actualDeleteCount)
 {
-    /* Steps 14, 15, 15.e. */
+    // Steps 10, 11, 11.d.
     RootedValue fromValue(cx);
     for (uint32_t k = 0; k < actualDeleteCount; k++) {
-        /* Step 15.a (implicit). */
+        // Step 11.a (implicit).
 
         if (!CheckForInterrupt(cx))
             return false;
 
-        /* Steps 15.b-c, 15.d.i-ii. */
+        // Steps 11.b, 11.c.i.
         bool hole;
         if (!GetElement(cx, obj, actualStart + k, &hole, &fromValue))
             return false;
 
-        /* Step 15.d. */
+        // Step 11.c.
         if (!hole) {
-            /* Step 15.d.iii-iv. */
+            // Step 11.c.ii.
             if (!DefineElement(cx, arr, k, fromValue))
                 return false;
         }
     }
 
-    /* Steps 16-17. */
+    // Step 12.
     return SetLengthProperty(cx, arr, actualDeleteCount);
 }
 
 bool
 js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed)
 {
     AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.splice");
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -173,23 +173,16 @@ js::DestroyContext(JSContext* cx)
 
     if (cx->outstandingRequests != 0)
         MOZ_CRASH("Attempted to destroy a context while it is in a request.");
 
     cx->checkNoGCRooters();
 
     js_delete(cx->ionPcScriptCache.ref());
 
-    /*
-     * Dump remaining type inference results while we still have a context.
-     * This printing depends on atoms still existing.
-     */
-    for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next())
-        PrintTypes(cx, c, false);
-
     cx->runtime()->destroyRuntime();
     js_delete(cx->runtime());
 
     js_delete_poison(cx);
 }
 
 void
 JS::RootingContext::checkNoGCRooters() {
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -498,17 +498,17 @@ JSContext::setCompartment(JSCompartment*
     // Both the current and the new compartment should be properly marked as
     // entered at this point.
     MOZ_ASSERT_IF(compartment_, compartment_->hasBeenEntered());
     MOZ_ASSERT_IF(comp, comp->hasBeenEntered());
 
     // This context must have exclusive access to the zone's group. There is an
     // exception, for now, for zones used by exclusive threads.
     MOZ_ASSERT_IF(comp && !comp->zone()->isAtomsZone() && !comp->zone()->usedByExclusiveThread,
-                  comp->zone()->group()->context == this);
+                  comp->zone()->group()->ownedByCurrentThread());
 
     compartment_ = comp;
     zone_ = comp ? comp->zone() : nullptr;
     arenas_ = zone_ ? &zone_->arenas : nullptr;
 }
 
 inline void
 JSContext::enterZoneGroup(js::ZoneGroup* group)
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -687,17 +687,17 @@ JSCompartment::traceRoots(JSTracer* trc,
     // the data alive for the JSScript::finalize call. Thus, we do not trace the
     // keys of the HashMap to avoid adding a strong reference to the JSScript
     // pointers.
     //
     // If the code coverage is either enabled with the --dump-bytecode command
     // line option, or with the PCCount JSFriend API functions, then we mark the
     // keys of the map to hold the JSScript alive.
     if (scriptCountsMap &&
-        zone()->group()->profilingScripts &&
+        trc->runtime()->profilingScripts &&
         !JS::CurrentThreadIsHeapMinorCollecting())
     {
         MOZ_ASSERT_IF(!trc->runtime()->isBeingDestroyed(), collectCoverage());
         for (ScriptCountsMap::Range r = scriptCountsMap->all(); !r.empty(); r.popFront()) {
             JSScript* script = const_cast<JSScript*>(r.front().key());
             MOZ_ASSERT(script->hasScriptCounts());
             TraceRoot(trc, &script, "profilingScripts");
             MOZ_ASSERT(script == r.front().key(), "const_cast is only a work-around");
@@ -1166,17 +1166,19 @@ JSCompartment::updateDebuggerObservesCov
     bool previousState = debuggerObservesCoverage();
     updateDebuggerObservesFlag(DebuggerObservesCoverage);
     if (previousState == debuggerObservesCoverage())
         return;
 
     if (debuggerObservesCoverage()) {
         // Interrupt any running interpreter frame. The scriptCounts are
         // allocated on demand when a script resume its execution.
-        for (ActivationIterator iter(runtimeFromMainThread()); !iter.done(); ++iter) {
+        JSContext* cx = TlsContext.get();
+        MOZ_ASSERT(zone()->group()->ownedByCurrentThread());
+        for (ActivationIterator iter(cx); !iter.done(); ++iter) {
             if (iter->isInterpreter())
                 iter->asInterpreter()->enableInterruptsUnconditionally();
         }
         return;
     }
 
     // If code coverage is enabled by any other means, keep it.
     if (collectCoverage())
@@ -1197,17 +1199,17 @@ JSCompartment::collectCoverageForPGO() c
 {
     return !JitOptions.disablePgo;
 }
 
 bool
 JSCompartment::collectCoverageForDebug() const
 {
     return debuggerObservesCoverage() ||
-           zone()->group()->profilingScripts ||
+           runtimeFromAnyThread()->profilingScripts ||
            runtimeFromAnyThread()->lcovOutput().isEnabled();
 }
 
 void
 JSCompartment::clearScriptCounts()
 {
     if (!scriptCountsMap)
         return;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3792,17 +3792,17 @@ GCRuntime::beginMarkPhase(JS::gcreason::
         c->marked = false;
         c->scheduledForDestruction = false;
         c->maybeAlive = c->hasBeenEntered() || !c->zone()->isGCScheduled();
         if (shouldPreserveJITCode(c, currentTime, reason, canAllocateMoreCode))
             c->zone()->setPreservingCode(true);
     }
 
     if (!rt->gc.cleanUpEverything && canAllocateMoreCode) {
-        if (JSCompartment* comp = jit::TopmostIonActivationCompartment(rt))
+        if (JSCompartment* comp = jit::TopmostIonActivationCompartment(TlsContext.get()))
             comp->zone()->setPreservingCode(true);
     }
 
     /*
      * If keepAtoms() is true then either an instance of AutoKeepAtoms is
      * currently on the stack or parsing is currently happening on another
      * thread. In either case we don't have information about which atoms are
      * roots, so we must skip collecting atoms.
@@ -5621,17 +5621,18 @@ HeapStateToLabel(JS::HeapState heapState
     return nullptr;
 }
 
 /* Start a new heap session. */
 AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState)
   : lock(rt),
     runtime(rt),
     prevState(TlsContext.get()->heapState),
-    pseudoFrame(rt, HeapStateToLabel(heapState), ProfileEntry::Category::GC)
+    pseudoFrame(rt, HeapStateToLabel(heapState), ProfileEntry::Category::GC),
+    prohibitActiveContextChange(rt)
 {
     MOZ_ASSERT(prevState == JS::HeapState::Idle);
     MOZ_ASSERT(heapState != JS::HeapState::Idle);
     MOZ_ASSERT_IF(heapState == JS::HeapState::MajorCollecting, rt->zoneGroupFromMainThread()->nursery().isEmpty());
     TlsContext.get()->heapState = heapState;
 }
 
 AutoTraceSession::~AutoTraceSession()
@@ -6901,16 +6902,18 @@ void PreventGCDuringInteractiveDebug()
 }
 
 #endif
 
 void
 js::ReleaseAllJITCode(FreeOp* fop)
 {
     js::CancelOffThreadIonCompile(fop->runtime());
+
+    JSRuntime::AutoProhibitActiveContextChange apacc(fop->runtime());
     for (ZonesIter zone(fop->runtime(), SkipAtoms); !zone.done(); zone.next()) {
         zone->setPreservingCode(false);
         zone->discardJitCode(fop);
     }
 }
 
 void
 js::PurgeJITCaches(Zone* zone)
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1750,46 +1750,46 @@ js::IsValidBytecodeOffset(JSContext* cx,
  * StopPCCountProfiling     None      Query     Query
  * PurgePCCounts            None      None      None
  */
 
 static void
 ReleaseScriptCounts(FreeOp* fop)
 {
     JSRuntime* rt = fop->runtime();
-    MOZ_ASSERT(rt->zoneGroupFromMainThread()->scriptAndCountsVector);
+    MOZ_ASSERT(rt->scriptAndCountsVector);
 
-    fop->delete_(rt->zoneGroupFromMainThread()->scriptAndCountsVector.ref());
-    rt->zoneGroupFromMainThread()->scriptAndCountsVector = nullptr;
+    fop->delete_(rt->scriptAndCountsVector.ref());
+    rt->scriptAndCountsVector = nullptr;
 }
 
 JS_FRIEND_API(void)
 js::StartPCCountProfiling(JSContext* cx)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (rt->zoneGroupFromMainThread()->profilingScripts)
+    if (rt->profilingScripts)
         return;
 
-    if (rt->zoneGroupFromMainThread()->scriptAndCountsVector)
+    if (rt->scriptAndCountsVector)
         ReleaseScriptCounts(rt->defaultFreeOp());
 
     ReleaseAllJITCode(rt->defaultFreeOp());
 
-    rt->zoneGroupFromMainThread()->profilingScripts = true;
+    rt->profilingScripts = true;
 }
 
 JS_FRIEND_API(void)
 js::StopPCCountProfiling(JSContext* cx)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (!rt->zoneGroupFromMainThread()->profilingScripts)
+    if (!rt->profilingScripts)
         return;
-    MOZ_ASSERT(!rt->zoneGroupFromMainThread()->scriptAndCountsVector);
+    MOZ_ASSERT(!rt->scriptAndCountsVector);
 
     ReleaseAllJITCode(rt->defaultFreeOp());
 
     auto* vec = cx->new_<PersistentRooted<ScriptAndCountsVector>>(cx,
         ScriptAndCountsVector(SystemAllocPolicy()));
     if (!vec)
         return;
 
@@ -1797,41 +1797,41 @@ js::StopPCCountProfiling(JSContext* cx)
         for (auto script = zone->cellIter<JSScript>(); !script.done(); script.next()) {
             if (script->hasScriptCounts() && script->types()) {
                 if (!vec->append(script))
                     return;
             }
         }
     }
 
-    rt->zoneGroupFromMainThread()->profilingScripts = false;
-    rt->zoneGroupFromMainThread()->scriptAndCountsVector = vec;
+    rt->profilingScripts = false;
+    rt->scriptAndCountsVector = vec;
 }
 
 JS_FRIEND_API(void)
 js::PurgePCCounts(JSContext* cx)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (!rt->zoneGroupFromMainThread()->scriptAndCountsVector)
+    if (!rt->scriptAndCountsVector)
         return;
-    MOZ_ASSERT(!rt->zoneGroupFromMainThread()->profilingScripts);
+    MOZ_ASSERT(!rt->profilingScripts);
 
     ReleaseScriptCounts(rt->defaultFreeOp());
 }
 
 JS_FRIEND_API(size_t)
 js::GetPCCountScriptCount(JSContext* cx)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (!rt->zoneGroupFromMainThread()->scriptAndCountsVector)
+    if (!rt->scriptAndCountsVector)
         return 0;
 
-    return rt->zoneGroupFromMainThread()->scriptAndCountsVector->length();
+    return rt->scriptAndCountsVector->length();
 }
 
 enum MaybeComma {NO_COMMA, COMMA};
 
 static MOZ_MUST_USE bool
 AppendJSONProperty(StringBuffer& buf, const char* name, MaybeComma comma = COMMA)
 {
     if (comma && !buf.append(','))
@@ -1842,24 +1842,22 @@ AppendJSONProperty(StringBuffer& buf, co
            buf.append("\":", 2);
 }
 
 JS_FRIEND_API(JSString*)
 js::GetPCCountScriptSummary(JSContext* cx, size_t index)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (!rt->zoneGroupFromMainThread()->scriptAndCountsVector ||
-        index >= rt->zoneGroupFromMainThread()->scriptAndCountsVector->length())
-    {
+    if (!rt->scriptAndCountsVector || index >= rt->scriptAndCountsVector->length()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
         return nullptr;
     }
 
-    const ScriptAndCounts& sac = (*rt->zoneGroupFromMainThread()->scriptAndCountsVector)[index];
+    const ScriptAndCounts& sac = (*rt->scriptAndCountsVector)[index];
     RootedScript script(cx, sac.script);
 
     /*
      * OOM on buffer appends here will not be caught immediately, but since
      * StringBuffer uses a TempAllocPolicy will trigger an exception on the
      * context if they occur, which we'll catch before returning.
      */
     StringBuffer buf(cx);
@@ -2128,24 +2126,22 @@ GetPCCountJSON(JSContext* cx, const Scri
     return true;
 }
 
 JS_FRIEND_API(JSString*)
 js::GetPCCountScriptContents(JSContext* cx, size_t index)
 {
     JSRuntime* rt = cx->runtime();
 
-    if (!rt->zoneGroupFromMainThread()->scriptAndCountsVector ||
-        index >= rt->zoneGroupFromMainThread()->scriptAndCountsVector->length())
-    {
+    if (!rt->scriptAndCountsVector || index >= rt->scriptAndCountsVector->length()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
         return nullptr;
     }
 
-    const ScriptAndCounts& sac = (*rt->zoneGroupFromMainThread()->scriptAndCountsVector)[index];
+    const ScriptAndCounts& sac = (*rt->scriptAndCountsVector)[index];
     JSScript* script = sac.script;
 
     StringBuffer buf(cx);
 
     {
         AutoCompartment ac(cx, &script->global());
         if (!GetPCCountJSON(cx, sac, buf))
             return nullptr;
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1101,17 +1101,17 @@ JSScript::initScriptCounts(JSContext* cx
     }
 
     // safe to set this;  we can't fail after this point.
     hasScriptCounts_ = true;
     guardScriptCounts.release();
 
     // Enable interrupts in any interpreter frames running on this script. This
     // is used to let the interpreter increment the PCCounts, if present.
-    for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
+    for (ActivationIterator iter(cx); !iter.done(); ++iter) {
         if (iter->isInterpreter())
             iter->asInterpreter()->enableInterruptsIfRunning(this);
     }
 
     return true;
 }
 
 static inline ScriptCountsMap::Ptr GetScriptCountsMapEntry(JSScript* script)
@@ -3618,17 +3618,17 @@ JSScript::ensureHasDebugScript(JSContext
     }
     hasDebugScript_ = true; // safe to set this;  we can't fail after this point
 
     /*
      * Ensure that any Interpret() instances running on this script have
      * interrupts enabled. The interrupts must stay enabled until the
      * debug state is destroyed.
      */
-    for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
+    for (ActivationIterator iter(cx); !iter.done(); ++iter) {
         if (iter->isInterpreter())
             iter->asInterpreter()->enableInterruptsIfRunning(this);
     }
 
     return true;
 }
 
 void
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -7675,17 +7675,17 @@ SetContextOptions(JSContext* cx, const O
         jit::Simulator::StopSimAt = stopAt;
 #endif
 
     reportWarnings = op.getBoolOption('w');
     compileOnly = op.getBoolOption('c');
     printTiming = op.getBoolOption('b');
     enableCodeCoverage = op.getBoolOption("code-coverage");
     enableDisassemblyDumps = op.getBoolOption('D');
-    cx->runtime()->zoneGroupFromMainThread()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
+    cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
     jsCacheDir = op.getStringOption("js-cache");
     if (jsCacheDir) {
         if (!op.getBoolOption("no-js-cache-per-process"))
             jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
         else
             jsCacheDir = JS_strdup(cx, jsCacheDir);
         if (!jsCacheDir)
@@ -7717,17 +7717,17 @@ SetWorkerContextOptions(JSContext* cx)
     JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
                              .setIon(enableIon)
                              .setAsmJS(enableAsmJS)
                              .setWasm(enableWasm)
                              .setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
                              .setNativeRegExp(enableNativeRegExp)
                              .setUnboxedArrays(enableUnboxedArrays);
     cx->runtime()->setOffthreadIonCompilationEnabled(offthreadCompilation);
-    cx->runtime()->zoneGroupFromMainThread()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
+    cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
 #ifdef JS_GC_ZEAL
     if (gZealBits && gZealFrequency) {
 #define ZEAL_MODE(_, value)                        \
         if (gZealBits & (1 << value))              \
             cx->runtime()->gc.setZeal(value, gZealFrequency);
         JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
 #undef ZEAL_MODE
@@ -7789,16 +7789,23 @@ Shell(JSContext* cx, OptionParser* op, c
             JS_free(cx, const_cast<char*>(jsCacheAsmJSPath));
         }
         if (jsCacheDir) {
             rmdir(jsCacheDir);
             JS_free(cx, const_cast<char*>(jsCacheDir));
         }
     }
 
+    /*
+     * Dump remaining type inference results while we still have a context.
+     * This printing depends on atoms still existing.
+     */
+    for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next())
+        PrintTypes(cx, c, false);
+
     return result;
 }
 
 static void
 SetOutputFile(const char* const envVar,
               RCFile* defaultOut,
               RCFile** outFileP)
 {
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Array/join-no-has-trap.js
@@ -0,0 +1,36 @@
+// Test that Array.prototype.join doesn't call the [[HasProperty]] internal
+// method of objects.
+
+var log = [];
+var array = [];
+var proxy = new Proxy(array, new Proxy({}, {
+    get(t, trap, r) {
+      return (t, pk, ...more) => {
+        log.push(`${trap}:${String(pk)}`);
+        return Reflect[trap](t, pk, ...more);
+      };
+    }
+}));
+
+var result;
+
+result = Array.prototype.join.call(proxy);
+assertEqArray(log, [ "get:length" ]);
+assertEq(result, "");
+
+log.length = 0;
+array.push(1);
+
+result = Array.prototype.join.call(proxy);
+assertEqArray(log, [ "get:length", "get:0" ]);
+assertEq(result, "1");
+
+log.length = 0;
+array.push(2);
+
+result = Array.prototype.join.call(proxy);
+assertEqArray(log, [ "get:length", "get:0", "get:1" ]);
+assertEq(result, "1,2");
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Array/pop-no-has-trap.js
@@ -0,0 +1,58 @@
+// Test that Array.prototype.pop doesn't call the [[HasProperty]] internal
+// method of objects when retrieving the element at the last index.
+
+var log = [];
+var array = [];
+var proxy = new Proxy(array, new Proxy({}, {
+    get(t, trap, r) {
+      return (t, pk, ...more) => {
+        log.push(`${trap}:${String(pk)}`);
+        return Reflect[trap](t, pk, ...more);
+      };
+    }
+}));
+
+var result;
+
+result = Array.prototype.pop.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, undefined);
+
+log.length = 0;
+array.push(1);
+
+result = Array.prototype.pop.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:0", "deleteProperty:0",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 1);
+
+log.length = 0;
+array.push(2, 3);
+
+result = Array.prototype.pop.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:1", "deleteProperty:1",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 3);
+
+log.length = 0;
+array.push(4, 5);
+
+result = Array.prototype.pop.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:2", "deleteProperty:2",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 5);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Array/shift-no-has-trap.js
@@ -0,0 +1,64 @@
+// Test that Array.prototype.shift doesn't call the [[HasProperty]] internal
+// method of objects when retrieving the element at index 0.
+
+var log = [];
+var array = [];
+var proxy = new Proxy(array, new Proxy({}, {
+    get(t, trap, r) {
+      return (t, pk, ...more) => {
+        log.push(`${trap}:${String(pk)}`);
+        return Reflect[trap](t, pk, ...more);
+      };
+    }
+}));
+
+var result;
+
+result = Array.prototype.shift.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, undefined);
+
+log.length = 0;
+array.push(1);
+
+result = Array.prototype.shift.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:0",
+  "deleteProperty:0",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 1);
+
+log.length = 0;
+array.push(2, 3);
+
+result = Array.prototype.shift.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:0",
+  "has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0",
+  "deleteProperty:1",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 2);
+
+log.length = 0;
+array.push(4, 5);
+
+result = Array.prototype.shift.call(proxy);
+assertEqArray(log, [
+  "get:length",
+  "get:0",
+  "has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0",
+  "has:2", "get:2", "set:1", "getOwnPropertyDescriptor:1", "defineProperty:1",
+  "deleteProperty:2",
+  "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
+]);
+assertEq(result, 3);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2399,17 +2399,22 @@ class MOZ_RAII ExecutionObservableCompar
                                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : compartments_(cx),
         zones_(cx)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     bool init() { return compartments_.init() && zones_.init(); }
-    bool add(JSCompartment* comp) { return compartments_.put(comp) && zones_.put(comp->zone()); }
+    bool add(JSCompartment* comp) {
+        // The current cx should have exclusive access to observed content,
+        // since debuggees must be in the same zone group as ther debugger.
+        MOZ_ASSERT(comp->zone()->group() == TlsContext.get()->zone()->group());
+        return compartments_.put(comp) && zones_.put(comp->zone());
+    }
 
     typedef HashSet<JSCompartment*>::Range CompartmentRange;
     const HashSet<JSCompartment*>* compartments() const { return &compartments_; }
 
     const HashSet<Zone*>* zones() const { return &zones_; }
     bool shouldRecompileOrInvalidate(JSScript* script) const {
         return script->hasBaselineScript() && compartments_.has(script->compartment());
     }
@@ -2493,16 +2498,19 @@ class MOZ_RAII ExecutionObservableScript
 {
     RootedScript script_;
 
   public:
     ExecutionObservableScript(JSContext* cx, JSScript* script
                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : script_(cx, script)
     {
+        // The current cx should have exclusive access to observed content,
+        // since debuggees must be in the same zone group as ther debugger.
+        MOZ_ASSERT(singleZone()->group() == cx->zone()->group());
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     Zone* singleZone() const { return script_->compartment()->zone(); }
     JSScript* singleScriptForZoneInvalidation() const { return script_; }
     bool shouldRecompileOrInvalidate(JSScript* script) const {
         return script->hasBaselineScript() && script == script_;
     }
@@ -2597,17 +2605,16 @@ static bool
 UpdateExecutionObservabilityOfScriptsInZone(JSContext* cx, Zone* zone,
                                             const Debugger::ExecutionObservableSet& obs,
                                             Debugger::IsObserving observing)
 {
     using namespace js::jit;
 
     AutoSuppressProfilerSampling suppressProfilerSampling(cx);
 
-    JSRuntime* rt = cx->runtime();
     FreeOp* fop = cx->runtime()->defaultFreeOp();
 
     Vector<JSScript*> scripts(cx);
 
     // Iterate through observable scripts, invalidating their Ion scripts and
     // appending them to a vector for discarding their baseline scripts later.
     {
         AutoEnterAnalysis enter(fop, zone);
@@ -2629,28 +2636,28 @@ UpdateExecutionObservabilityOfScriptsInZ
         }
     }
 
     // Code below this point must be infallible to ensure the active bit of
     // BaselineScripts is in a consistent state.
     //
     // Mark active baseline scripts in the observable set so that they don't
     // get discarded. They will be recompiled.
-    for (JitActivationIterator actIter(rt); !actIter.done(); ++actIter) {
+    for (JitActivationIterator actIter(cx, zone->group()->ownerContext()); !actIter.done(); ++actIter) {
         if (actIter->compartment()->zone() != zone)
             continue;
 
         for (JitFrameIterator iter(actIter); !iter.done(); ++iter) {
             switch (iter.type()) {
               case JitFrame_BaselineJS:
                 MarkBaselineScriptActiveIfObservable(iter.script(), obs);
                 break;
               case JitFrame_IonJS:
                 MarkBaselineScriptActiveIfObservable(iter.script(), obs);
-                for (InlineFrameIterator inlineIter(rt, &iter); inlineIter.more(); ++inlineIter)
+                for (InlineFrameIterator inlineIter(cx, &iter); inlineIter.more(); ++inlineIter)
                     MarkBaselineScriptActiveIfObservable(inlineIter.script(), obs);
                 break;
               default:;
             }
         }
     }
 
     // Iterate through the scripts again and finish discarding
@@ -3936,16 +3943,23 @@ Debugger::construct(JSContext* cx, unsig
 
     args.rval().setObject(*obj);
     return true;
 }
 
 bool
 Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
 {
+    // Debuggers are required to be in the same zone group as their debuggees.
+    // The debugger must be able to observe all activity in the debuggee
+    // compartment, which requires that its thread have exclusive access to
+    // that compartment's contents.
+    MOZ_ASSERT(cx->zone() == object->zone());
+    MOZ_RELEASE_ASSERT(global->zone()->group() == cx->zone()->group());
+
     if (debuggees.has(global))
         return true;
 
     // Callers should generally be unable to get a reference to a debugger-
     // invisible global in order to pass it to addDebuggee. But this is possible
     // with certain testing aides we expose in the shell, so just make addDebuggee
     // throw in that case.
     JSCompartment* debuggeeCompartment = global->compartment();
@@ -7707,25 +7721,28 @@ UpdateFrameIterPc(FrameIter& iter)
         // because when returning to debuggee code, we would have bailed out
         // to baseline.
         //
         // We walk the stack to assert that it doesn't need updating.
         jit::RematerializedFrame* frame = iter.abstractFramePtr().asRematerializedFrame();
         jit::JitFrameLayout* jsFrame = (jit::JitFrameLayout*)frame->top();
         jit::JitActivation* activation = iter.activation()->asJit();
 
-        ActivationIterator activationIter(activation->cx()->runtime());
+        JSContext* cx = TlsContext.get();
+        MOZ_ASSERT(cx == activation->cx());
+
+        ActivationIterator activationIter(cx);
         while (activationIter.activation() != activation)
             ++activationIter;
 
         jit::JitFrameIterator jitIter(activationIter);
         while (!jitIter.isIonJS() || jitIter.jsFrame() != jsFrame)
             ++jitIter;
 
-        jit::InlineFrameIterator ionInlineIter(activation->cx(), &jitIter);
+        jit::InlineFrameIterator ionInlineIter(cx, &jitIter);
         while (ionInlineIter.frameNo() != frame->frameNo())
             ++ionInlineIter;
 
         MOZ_ASSERT(ionInlineIter.pc() == iter.pc());
 #endif
         return;
     }
 
--- a/js/src/vm/GeckoProfiler.cpp
+++ b/js/src/vm/GeckoProfiler.cpp
@@ -82,52 +82,50 @@ GeckoProfiler::enable(bool enabled)
     // JitcodeGlobalTable as expired and reset the buffer generation and lap
     // count.
     if (rt->hasJitRuntime() && rt->jitRuntime()->hasJitcodeGlobalTable())
         rt->jitRuntime()->getJitcodeGlobalTable()->setAllEntriesAsExpired(rt);
     rt->resetProfilerSampleBufferGen();
     rt->resetProfilerSampleBufferLapCount();
 
     // Ensure that lastProfilingFrame is null for all threads before 'enabled' becomes true.
-    for (size_t i = 0; i < rt->cooperatingContexts().length(); i++) {
-        JSContext* cx = rt->cooperatingContexts()[i];
-        if (cx->jitActivation) {
-            cx->jitActivation->setLastProfilingFrame(nullptr);
-            cx->jitActivation->setLastProfilingCallSite(nullptr);
+    for (const CooperatingContext& target : rt->cooperatingContexts()) {
+        if (target.context()->jitActivation) {
+            target.context()->jitActivation->setLastProfilingFrame(nullptr);
+            target.context()->jitActivation->setLastProfilingCallSite(nullptr);
         }
     }
 
     enabled_ = enabled;
 
     /* Toggle Gecko Profiler-related jumps on baseline jitcode.
      * The call to |ReleaseAllJITCode| above will release most baseline jitcode, but not
      * jitcode for scripts with active frames on the stack.  These scripts need to have
      * their profiler state toggled so they behave properly.
      */
     jit::ToggleBaselineProfiling(rt, enabled);
 
     /* Update lastProfilingFrame to point to the top-most JS jit-frame currently on
      * stack.
      */
-    for (size_t i = 0; i < rt->cooperatingContexts().length(); i++) {
-        JSContext* cx = rt->cooperatingContexts()[i];
-        if (cx->jitActivation) {
+    for (const CooperatingContext& target : rt->cooperatingContexts()) {
+        if (target.context()->jitActivation) {
             // Walk through all activations, and set their lastProfilingFrame appropriately.
             if (enabled) {
-                void* lastProfilingFrame = GetTopProfilingJitFrame(cx->jitTop);
-                jit::JitActivation* jitActivation = cx->jitActivation;
+                void* lastProfilingFrame = GetTopProfilingJitFrame(target.context()->jitTop);
+                jit::JitActivation* jitActivation = target.context()->jitActivation;
                 while (jitActivation) {
                     jitActivation->setLastProfilingFrame(lastProfilingFrame);
                     jitActivation->setLastProfilingCallSite(nullptr);
 
                     lastProfilingFrame = GetTopProfilingJitFrame(jitActivation->prevJitTop());
                     jitActivation = jitActivation->prevJitActivation();
                 }
             } else {
-                jit::JitActivation* jitActivation = cx->jitActivation;
+                jit::JitActivation* jitActivation = target.context()->jitActivation;
                 while (jitActivation) {
                     jitActivation->setLastProfilingFrame(nullptr);
                     jitActivation->setLastProfilingCallSite(nullptr);
                     jitActivation = jitActivation->prevJitActivation();
                 }
             }
         }
     }
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -133,16 +133,18 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
 #ifdef DEBUG
     mainThreadHasExclusiveAccess(false),
 #endif
     numExclusiveThreads(0),
     numCompartments(0),
     localeCallbacks(nullptr),
     defaultLocale(nullptr),
     defaultVersion_(JSVERSION_DEFAULT),
+    profilingScripts(false),
+    scriptAndCountsVector(nullptr),
     lcovOutput_(),
     jitRuntime_(nullptr),
     selfHostingGlobal_(nullptr),
     singletonContext(nullptr),
     singletonZoneGroup(nullptr),
     gc(thisFromCtor()),
     gcInitialized(false),
     NaNValue(DoubleNaNValue()),
@@ -206,17 +208,17 @@ JSRuntime::init(JSContext* cx, uint32_t 
     ScopedJSDeletePtr<ZoneGroup> zoneGroup(js_new<ZoneGroup>(this));
     if (!zoneGroup)
         return false;
     singletonZoneGroup = zoneGroup;
 
     if (!gc.init(maxbytes, maxNurseryBytes))
         return false;
 
-    if (!zoneGroup->init(maxNurseryBytes))
+    if (!zoneGroup->init(maxNurseryBytes) || !gc.groups.ref().append(zoneGroup))
         return false;
     zoneGroup.forget();
 
     ScopedJSDeletePtr<Zone> atomsZone(new_<Zone>(this, nullptr));
     if (!atomsZone || !atomsZone->init(true))
         return false;
 
     JS::CompartmentOptions options;
@@ -298,17 +300,17 @@ JSRuntime::destroyRuntime()
 
         /*
          * Flag us as being destroyed. This allows the GC to free things like
          * interned atoms and Ion trampolines.
          */
         beingDestroyed_ = true;
 
         /* Allow the GC to release scripts that were being profiled. */
-        zoneGroupFromMainThread()->profilingScripts = false;
+        profilingScripts = false;
 
         /* Set the profiler sampler buffer generation to invalid. */
         profilerSampleBufferGen_ = UINT32_MAX;
 
         JS::PrepareForFullGC(cx);
         gc.gc(GC_NORMAL, JS::gcreason::DESTROY_RUNTIME);
     }
 
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -248,16 +248,18 @@ inline bool
 CanUseExtraThreads()
 {
     extern bool gCanUseExtraThreads;
     return gCanUseExtraThreads;
 }
 
 void DisableExtraThreads();
 
+using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
+
 class AutoLockForExclusiveAccess;
 } // namespace js
 
 struct JSRuntime : public js::MallocProvider<JSRuntime>
 {
   private:
     friend class js::Activation;
     friend class js::ActivationIterator;
@@ -300,35 +302,35 @@ struct JSRuntime : public js::MallocProv
   private:
     // The context for the thread which currently has exclusive access to most
     // contents of the runtime. When execution on the runtime is cooperatively
     // scheduled, this is the thread which is currently running.
     mozilla::Atomic<JSContext*, mozilla::ReleaseAcquire> activeContext_;
 
     // All contexts participating in cooperative scheduling. All threads other
     // than |activeContext_| are suspended.
-    js::ActiveThreadData<js::Vector<JSContext*, 4, js::SystemAllocPolicy>> cooperatingContexts_;
+    js::ActiveThreadData<js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>> cooperatingContexts_;
 
     // Count of AutoProhibitActiveContextChange instances on the active context.
     js::ActiveThreadData<size_t> activeContextChangeProhibited_;
 
   public:
     JSContext* activeContext() { return activeContext_; }
     const void* addressOfActiveContext() { return &activeContext_; }
 
     void setActiveContext(JSContext* cx);
 
-    js::Vector<JSContext*, 4, js::SystemAllocPolicy>& cooperatingContexts() {
+    js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>& cooperatingContexts() {
         return cooperatingContexts_.ref();
     }
 
 #ifdef DEBUG
     bool isCooperatingContext(JSContext* cx) {
-        for (size_t i = 0; i < cooperatingContexts().length(); i++) {
-            if (cooperatingContexts()[i] == cx)
+        for (const js::CooperatingContext& target : cooperatingContexts()) {
+            if (target.context() == cx)
                 return true;
         }
         return false;
     }
 #endif
 
     class MOZ_RAII AutoProhibitActiveContextChange
     {
@@ -566,16 +568,22 @@ struct JSRuntime : public js::MallocProv
     js::ActiveThreadData<const JSLocaleCallbacks*> localeCallbacks;
 
     /* Default locale for Internationalization API */
     js::ActiveThreadData<char*> defaultLocale;
 
     /* Default JSVersion. */
     js::ActiveThreadData<JSVersion> defaultVersion_;
 
+    /* If true, new scripts must be created with PC counter information. */
+    js::ActiveThreadOrIonCompileData<bool> profilingScripts;
+
+    /* Strong references on scripts held for PCCount profiling API. */
+    js::ActiveThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*> scriptAndCountsVector;
+
   private:
     /* Code coverage output. */
     js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
   public:
     js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
 
   private:
     js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -417,19 +417,19 @@ TraceInterpreterActivation(JSTracer* trc
 {
     for (InterpreterFrameIterator frames(act); !frames.done(); ++frames) {
         InterpreterFrame* fp = frames.frame();
         fp->trace(trc, frames.sp(), frames.pc());
     }
 }
 
 void
-js::TraceInterpreterActivations(JSRuntime* rt, JSTracer* trc)
+js::TraceInterpreterActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc)
 {
-    for (ActivationIterator iter(rt); !iter.done(); ++iter) {
+    for (ActivationIterator iter(cx, target); !iter.done(); ++iter) {
         Activation* act = iter.activation();
         if (act->isInterpreter())
             TraceInterpreterActivation(trc, act->asInterpreter());
     }
 }
 
 /*****************************************************************************/
 
@@ -583,17 +583,17 @@ FrameIter::settleOnActivation()
 FrameIter::Data::Data(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
                       JSPrincipals* principals)
   : cx_(cx),
     debuggerEvalOption_(debuggerEvalOption),
     principals_(principals),
     state_(DONE),
     pc_(nullptr),
     interpFrames_(nullptr),
-    activations_(cx->runtime()),
+    activations_(cx),
     jitFrames_(),
     ionInlineFrameNo_(0),
     wasmFrames_()
 {
 }
 
 FrameIter::Data::Data(const FrameIter::Data& other)
   : cx_(other.cx_),
@@ -1014,17 +1014,17 @@ FrameIter::updatePcQuadratic()
       }
       case JIT:
         if (data_.jitFrames_.isBaselineJS()) {
             jit::BaselineFrame* frame = data_.jitFrames_.baselineFrame();
             jit::JitActivation* activation = data_.activations_->asJit();
 
             // ActivationIterator::jitTop_ may be invalid, so create a new
             // activation iterator.
-            data_.activations_ = ActivationIterator(data_.cx_->runtime());
+            data_.activations_ = ActivationIterator(data_.cx_);
             while (data_.activations_.activation() != activation)
                 ++data_.activations_;
 
             // Look for the current frame.
             data_.jitFrames_ = jit::JitFrameIterator(data_.activations_);
             while (!data_.jitFrames_.isBaselineJS() || data_.jitFrames_.baselineFrame() != frame)
                 ++data_.jitFrames_;
 
@@ -1706,20 +1706,39 @@ Activation::unregisterProfiling()
     // There may be a non-active jit activation in the linked list.  Skip past it.
     Activation* prevProfiling = prevProfiling_;
     while (prevProfiling && prevProfiling->isJit() && !prevProfiling->asJit()->isActive())
         prevProfiling = prevProfiling->prevProfiling_;
 
     cx_->profilingActivation_ = prevProfiling;
 }
 
-ActivationIterator::ActivationIterator(JSRuntime* rt)
-  : jitTop_(TlsContext.get()->jitTop),
-    activation_(TlsContext.get()->activation_)
+ActivationIterator::ActivationIterator(JSContext* cx)
+    : jitTop_(cx->jitTop)
+    , activation_(cx->activation_)
+{
+    MOZ_ASSERT(cx == TlsContext.get());
+    settle();
+}
+
+ActivationIterator::ActivationIterator(JSContext* cx, const CooperatingContext& target)
 {
+    MOZ_ASSERT(cx == TlsContext.get());
+
+    // If target was specified --- even if it is the same as cx itself --- then
+    // we must be in a scope where changes of the active context are prohibited.
+    // Otherwise our state would be corrupted if the target thread resumed
+    // execution while we are iterating over its state.
+    MOZ_ASSERT(cx->runtime()->activeContextChangeProhibited());
+
+    // Tolerate a null target context, in case we are iterating over the
+    // activations for a zone group that is not in use by any thread.
+    jitTop_ = target.context() ? target.context()->jitTop.ref() : nullptr;
+    activation_ = target.context() ? target.context()->activation_.ref() : nullptr;
+
     settle();
 }
 
 ActivationIterator&
 ActivationIterator::operator++()
 {
     MOZ_ASSERT(activation_);
     if (activation_->isJit() && activation_->asJit()->isActive())
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -931,17 +931,34 @@ class InterpreterStack
 
     inline void purge(JSRuntime* rt);
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return allocator_.sizeOfExcludingThis(mallocSizeOf);
     }
 };
 
-void TraceInterpreterActivations(JSRuntime* rt, JSTracer* trc);
+// CooperatingContext is a wrapper for a JSContext that is participating in
+// cooperative scheduling and may be different from the current thread. It is
+// in place to make it clearer when we might be operating on another thread,
+// and harder to accidentally pass in another thread's context to an API that
+// expects the current thread's context.
+class CooperatingContext
+{
+    JSContext* cx;
+
+  public:
+    explicit CooperatingContext(JSContext* cx) : cx(cx) {}
+    JSContext* context() const { return cx; }
+
+    // For &cx. The address should not be taken for other CooperatingContexts.
+    friend class ZoneGroup;
+};
+
+void TraceInterpreterActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc);
 
 /*****************************************************************************/
 
 /** Base class for all function call args. */
 class AnyInvokeArgs : public JS::CallArgs
 {
 };
 
@@ -1404,30 +1421,34 @@ class InterpreterActivation : public Act
     void enableInterruptsUnconditionally() {
         opMask_ = EnableInterruptsPseudoOpcode;
     }
     void clearInterruptsMask() {
         opMask_ = 0;
     }
 };
 
-// Iterates over a thread's activation list. If given a runtime, iterate over
-// the runtime's main thread's activation list.
+// Iterates over a thread's activation list.
 class ActivationIterator
 {
     uint8_t* jitTop_;
 
   protected:
     Activation* activation_;
 
   private:
     void settle();
 
   public:
-    explicit ActivationIterator(JSRuntime* rt);
+    explicit ActivationIterator(JSContext* cx);
+
+    // ActivationIterator can be used to iterate over a different thread's
+    // activations, for use by the GC, invalidation, and other operations that
+    // don't have a user-visible effect on the target thread's JS behavior.
+    ActivationIterator(JSContext* cx, const CooperatingContext& target);
 
     ActivationIterator& operator++();
 
     Activation* operator->() const {
         return activation_;
     }
     Activation* activation() const {
         return activation_;
@@ -1609,18 +1630,24 @@ class JitActivation : public Activation
 class JitActivationIterator : public ActivationIterator
 {
     void settle() {
         while (!done() && !activation_->isJit())
             ActivationIterator::operator++();
     }
 
   public:
-    explicit JitActivationIterator(JSRuntime* rt)
-      : ActivationIterator(rt)
+    explicit JitActivationIterator(JSContext* cx)
+      : ActivationIterator(cx)
+    {
+        settle();
+    }
+
+    JitActivationIterator(JSContext* cx, const CooperatingContext& target)
+      : ActivationIterator(cx, target)
     {
         settle();
     }
 
     JitActivationIterator& operator++() {
         ActivationIterator::operator++();
         settle();
         return *this;
@@ -1717,17 +1744,17 @@ class WasmActivation : public Activation
     // Read/written from SIGSEGV handler:
     void setResumePC(void* pc) { resumePC_ = pc; }
     void* resumePC() const { return resumePC_; }
 
     // Used by wasm::FrameIterator during stack unwinding.
     void unwindFP(uint8_t* fp) { fp_ = fp; }
 };
 
-// A FrameIter walks over the runtime's stack of JS script activations,
+// A FrameIter walks over a context's stack of JS script activations,
 // abstracting over whether the JS scripts were running in the interpreter or
 // different modes of compiled code.
 //
 // FrameIter is parameterized by what it includes in the stack iteration:
 //  - When provided, the optional JSPrincipal argument will cause FrameIter to
 //    only show frames in globals whose JSPrincipals are subsumed (via
 //    JSSecurityCallbacks::subsume) by the given JSPrincipal.
 //
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -219,17 +219,17 @@ TraceLoggerThread::silentFail(const char
 bool
 TraceLoggerThread::enable(JSContext* cx)
 {
     if (!enable())
         return fail(cx, "internal error");
 
     if (enabled_ == 1) {
         // Get the top Activation to log the top script/pc (No inlined frames).
-        ActivationIterator iter(cx->runtime());
+        ActivationIterator iter(cx);
         Activation* act = iter.activation();
 
         if (!act)
             return fail(cx, "internal error");
 
         JSScript* script = nullptr;
         int32_t engine = 0;
 
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -365,17 +365,17 @@ FuncCast(F* pf, ABIFunctionType type)
     return pv;
 }
 
 void*
 wasm::AddressOf(SymbolicAddress imm, JSContext* cx)
 {
     switch (imm) {
       case SymbolicAddress::ContextPtr:
-        return &cx->zone()->group()->context;
+        return cx->zone()->group()->addressOfOwnerContext();
       case SymbolicAddress::ReportOverRecursed:
         return FuncCast(WasmReportOverRecursed, Args_General0);
       case SymbolicAddress::HandleExecutionInterrupt:
         return FuncCast(WasmHandleExecutionInterrupt, Args_General0);
       case SymbolicAddress::HandleDebugTrap:
         return FuncCast(WasmHandleDebugTrap, Args_General0);
       case SymbolicAddress::HandleThrow:
         return FuncCast(WasmHandleThrow, Args_General0);
--- a/layout/base/OverflowChangedTracker.h
+++ b/layout/base/OverflowChangedTracker.h
@@ -135,16 +135,24 @@ public:
         overflowChanged = true;
       }
 
       // If the frame style changed (e.g. positioning offsets)
       // then we need to update the parent with the overflow areas of its
       // children.
       if (overflowChanged) {
         nsIFrame *parent = frame->GetParent();
+        while (parent &&
+               parent != mSubtreeRoot &&
+               parent->Combines3DTransformWithAncestors()) {
+          // Passing frames in between the frame and the establisher of
+          // 3D rendering context.
+          parent = parent->GetParent();
+          MOZ_ASSERT(parent, "Root frame should never return true for Combines3DTransformWithAncestors");
+        }
         if (parent && parent != mSubtreeRoot) {
           Entry* parentEntry = mEntryList.find(Entry(parent, entry->mDepth - 1));
           if (parentEntry) {
             parentEntry->mChangeKind = std::max(parentEntry->mChangeKind, CHILDREN_CHANGED);
           } else {
             mEntryList.insert(new Entry(parent, entry->mDepth - 1, CHILDREN_CHANGED));
           }
         }
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -284,17 +284,17 @@ load 468491-1.html
 load 468546-1.xhtml
 load 468555-1.xhtml
 load 468563-1.html
 load 468578-1.xhtml
 # These three didn't actually crash without the resizing that the
 # browser does when setting up print preview, but adding them anyway.
 load 468645-1.xhtml
 load 468645-2.xhtml
-load 468645-3.xhtml
+asserts-if(stylo,1) load 468645-3.xhtml # bug 1337696
 load 469861-1.xhtml
 load 469861-2.xhtml
 load 470851-1.xhtml
 load 471594-1.xhtml
 asserts-if(Android&&!asyncPan,1-2) load 473042.xhtml # bug 1034369 (may also cause a few assertions to be registered on the next test)
 asserts(0-5) load 474075.html # bug 847368
 load 477333-1.xhtml
 load 477731-1.html
@@ -408,17 +408,17 @@ needs-focus pref(accessibility.browsewit
 load 701504.html
 load 707098.html
 load 709536-1.xhtml
 load 722137.html
 skip-if(stylo) load 725535.html # bug 1323652
 skip-if(stylo) load 727601.html # bug 1323652
 skip-if(Android) asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966, for android bug 760271
 asserts(0-2) load 736389-1.xhtml # sometimes the above assertions are delayed and is reported on this test instead
-load 736924-1.html
+skip-if(stylo) load 736924-1.html # bug 1337695
 load 749816-1.html
 load 763223-1.html
 test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.lineThreshold,100) load 763702.xhtml
 load 767593-1.html
 load 767593-2.html
 load 770381-1.html
 load 772306.html
 skip-if(stylo) load 788360.html # bug 1323652
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -96,16 +96,17 @@
 #include "nsGfxScrollFrame.h"
 #include "nsPageFrame.h"
 #include "nsSimplePageSequenceFrame.h"
 #include "nsTableWrapperFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsBackdropFrame.h"
 #include "nsTransitionManager.h"
 #include "DetailsFrame.h"
+#include "nsThemeConstants.h"
 
 #ifdef MOZ_XUL
 #include "nsIRootBox.h"
 #endif
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
@@ -3699,17 +3700,33 @@ nsCSSFrameConstructor::FindInputData(Ele
                                  nsCSSAnonBoxes::buttonContent) }
     // Keeping hidden inputs out of here on purpose for so they get frames by
     // display (in practice, none).
   };
 
   nsCOMPtr<nsIFormControl> control = do_QueryInterface(aElement);
   NS_ASSERTION(control, "input doesn't implement nsIFormControl?");
 
-  return FindDataByInt(control->GetType(), aElement, aStyleContext,
+  auto controlType = control->GetType();
+
+  // Note that Android/Gonk widgets don't have theming support and thus
+  // appearance:none is the same as any other appearance value.
+  // So this chunk doesn't apply there:
+#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
+  // radio and checkbox inputs with appearance:none should be constructed
+  // by display type.  (Note that we're not checking that appearance is
+  // not (respectively) NS_THEME_RADIO and NS_THEME_CHECKBOX.)
+  if ((controlType == NS_FORM_INPUT_CHECKBOX ||
+       controlType == NS_FORM_INPUT_RADIO) &&
+      aStyleContext->StyleDisplay()->mAppearance == NS_THEME_NONE) {
+    return nullptr;
+  }
+#endif
+
+  return FindDataByInt(controlType, aElement, aStyleContext,
                        sInputData, ArrayLength(sInputData));
 }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindObjectData(Element* aElement,
                                       nsStyleContext* aStyleContext)
 {
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -44,61 +44,50 @@ NS_QUERYFRAME_HEAD(nsFormControlFrame)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
 
 /* virtual */ nscoord
 nsFormControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
-  result = GetIntrinsicISize();
+  result = StyleDisplay()->mAppearance == NS_THEME_NONE ? 0 : DefaultSize();
   return result;
 }
 
 /* virtual */ nscoord
 nsFormControlFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_PREF_WIDTH(this, result);
-  result = GetIntrinsicISize();
+  result = StyleDisplay()->mAppearance == NS_THEME_NONE ? 0 : DefaultSize();
   return result;
 }
 
 /* virtual */
 LogicalSize
-nsFormControlFrame::ComputeAutoSize(nsRenderingContext* aRenderingContext,
+nsFormControlFrame::ComputeAutoSize(nsRenderingContext* aRC,
                                     WritingMode         aWM,
                                     const LogicalSize&  aCBSize,
                                     nscoord             aAvailableISize,
                                     const LogicalSize&  aMargin,
                                     const LogicalSize&  aBorder,
                                     const LogicalSize&  aPadding,
                                     ComputeSizeFlags    aFlags)
 {
-  const WritingMode wm = GetWritingMode();
-  LogicalSize result(wm, GetIntrinsicISize(), GetIntrinsicBSize());
-  return result.ConvertTo(aWM, wm);
-}
-
-nscoord
-nsFormControlFrame::GetIntrinsicISize()
-{
-  // Provide a reasonable default for sites that use an "auto" height.
-  // Note that if you change this, you should change the values in forms.css
-  // as well.  This is the 13px default width minus the 2px default border.
-  return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2);
-}
-
-nscoord
-nsFormControlFrame::GetIntrinsicBSize()
-{
-  // Provide a reasonable default for sites that use an "auto" height.
-  // Note that if you change this, you should change the values in forms.css
-  // as well. This is the 13px default width minus the 2px default border.
-  return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2);
+  LogicalSize size(aWM, 0, 0);
+  if (StyleDisplay()->mAppearance == NS_THEME_NONE) {
+    return size;
+  }
+  // Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
+  size = nsAtomicContainerFrame::ComputeAutoSize(aRC, aWM, aCBSize,
+                                                 aAvailableISize, aMargin,
+                                                 aBorder, aPadding, aFlags);
+  size.BSize(aWM) = DefaultSize();
+  return size;
 }
 
 nscoord
 nsFormControlFrame::GetLogicalBaseline(WritingMode aWritingMode) const
 {
   NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
                "frame must not be dirty");
 
--- a/layout/forms/nsFormControlFrame.h
+++ b/layout/forms/nsFormControlFrame.h
@@ -103,27 +103,26 @@ public:
    * draw dropdowns.
    */
   static nsRect GetUsableScreenRect(nsPresContext* aPresContext);
 
 protected:
 
   virtual ~nsFormControlFrame();
 
-  nscoord GetIntrinsicISize();
-  nscoord GetIntrinsicBSize();
+  static nscoord DefaultSize()
+  {
+    // XXXmats We have traditionally always returned 9px for GetMin/PrefISize
+    // but we might want to factor in what the theme says, something like:
+    // GetMinimumWidgetSize - GetWidgetPadding - GetWidgetBorder.
+    return nsPresContext::CSSPixelsToAppUnits(9);
+  }
 
-//
-//-------------------------------------------------------------------------------------
-//  Utility methods for managing checkboxes and radiobuttons
-//-------------------------------------------------------------------------------------
-//
-   /**
-    * Get the state of the checked attribute.
-    * @param aState set to true if the checked attribute is set,
-    * false if the checked attribute has been removed
-    */
-
+  /**
+   * Get the state of the checked attribute.
+   * @param aState set to true if the checked attribute is set,
+   * false if the checked attribute has been removed
+   */
   void GetCurrentCheckState(bool* aState);
 };
 
 #endif
 
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -10,19 +10,19 @@ load 255982-4.html
 load 264937-1.html
 asserts-if(stylo,4) load 265867-1.html # bug 1324703
 load 265867-2.html
 load 286491.html
 load 289864-1.html
 asserts(0-1) load 295292-1.html # Bug 1315855
 load 295292-2.html
 load 302260-1.html
-load 307979-1.html
-load 309322-1.html
-load 309322-2.html
+skip-if(stylo) load 307979-1.html # bug 1338007
+skip-if(stylo) load 309322-1.html # bug 1338007
+skip-if(stylo) load 309322-2.html # bug 1338007
 load 309322-3.html
 load 309322-4.html
 load 310556-1.xhtml
 load 321224.xul
 load 322780-1.xul
 load 323381-1.html
 load 323381-2.html
 asserts-if(gtkWidget,1) asserts-if(Android&&asyncPan,1) asserts-if(stylo,0) load 323386-1.html # Bug 718883
--- a/layout/media/moz.build
+++ b/layout/media/moz.build
@@ -8,16 +8,18 @@ with Files('**'):
     BUG_COMPONENT = ('Core', 'Video/Audio')
 
 # media/webrtc/signaling/test/common.build uses the gkmedias library,
 # expecting at least some of what it contains to be linked, but not libxul,
 # so we need to keep an independent pseudo-library, as well as the OS_LIBS
 # on Windows for them to propagate there.
 Library('gkmedias')
 
+FINAL_LIBRARY = 'xul'
+
 if CONFIG['MOZ_WEBRTC']:
     DIRS += ['webrtc']
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     OS_LIBS += [
         'usp10',
         'ole32',
         'msimg32',
--- a/layout/printing/crashtests/crashtests.list
+++ b/layout/printing/crashtests/crashtests.list
@@ -1,4 +1,4 @@
 load 509839-1.html
 load 509839-2.html
-load 576878.xhtml
+asserts-if(stylo,2) load 576878.xhtml # bug 1324645
 load 793844.html
--- a/layout/reftests/abs-pos/reftest-stylo.list
+++ b/layout/reftests/abs-pos/reftest-stylo.list
@@ -1,15 +1,15 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 == font-size-wrap.html font-size-wrap.html
 == abs-pos-auto-margin-1.html abs-pos-auto-margin-1.html
 fails == auto-offset-inline-block-1.html auto-offset-inline-block-1.html
 == fieldset-1.html fieldset-1.html
-== table-1.html table-1.html
-== table-2.html table-2.html
+fails asserts-if(stylo,4) == table-1.html table-1.html # bug 1324661
+fails asserts-if(stylo,4) == table-2.html table-2.html # bug 1324661
 == table-3.html table-3.html
 == table-caption-1.html table-caption-1.html
 == table-caption-2.html table-caption-2.html
 == table-caption-3.html table-caption-3.html
 == table-caption-4.html table-caption-4.html
 == table-caption-5.html table-caption-5.html
 == table-cell-1.html table-cell-1.html
 == table-cell-2.html table-cell-2.html
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -90,34 +90,34 @@ fails == 82711-3.html 82711-3.html
 # == 82711-1-ref.html 82711-1-ref.html
 fails == 82711-2-ref.html 82711-2-ref.html
 fails == 84400-1.html 84400-1.html
 fails == 84400-2.html 84400-2.html
 == 97777-1.html 97777-1.html
 fails == 97777-2.html 97777-2.html
 == 98223-1.html 98223-1.html
 == 98223-2.html 98223-2.html
-fails == 99850-1a.html 99850-1a.html
-random == 99850-1b.html 99850-1b.html
+# == 99850-1a.html 99850-1a.html # bug 1337695
+# == 99850-1b.html 99850-1b.html # bug 1337695
 fails == 99850-1c.html 99850-1c.html
-fails == 99850-1d.html 99850-1d.html
-== 105030-1.html 105030-1.html
+# == 99850-1d.html 99850-1d.html # bug 1337695
+asserts-if(stylo,8) == 105030-1.html 105030-1.html # bug 1324661
 == 109735-1.html 109735-1.html
 == 116882-1.html 116882-1.html
 == 120834-1a.html 120834-1a.html
 == 120834-2a.html 120834-2a.html
 # == 120834-2b.html 120834-2b.html
-fails == 120834-2c.html 120834-2c.html
-fails == 120834-2d.html 120834-2d.html
-fails == 120834-2e.html 120834-2e.html
-fails == 120834-2f.html 120834-2f.html
-fails == 120834-2g.html 120834-2g.html
-fails == 120834-2h.html 120834-2h.html
-fails == 120834-2i.html 120834-2i.html
-fails == 120834-2j.html 120834-2j.html
+== 120834-2c.html 120834-2c.html
+== 120834-2d.html 120834-2d.html
+== 120834-2e.html 120834-2e.html
+== 120834-2f.html 120834-2f.html
+== 120834-2g.html 120834-2g.html
+== 120834-2h.html 120834-2h.html
+== 120834-2i.html 120834-2i.html
+== 120834-2j.html 120834-2j.html
 fails == 124903-1.html 124903-1.html
 == 128896.html 128896.html
 == 130767-1.html 130767-1.html
 fails == 134706-1-left-scrollframe.html 134706-1-left-scrollframe.html
 fails == 134706-1-left-table.html 134706-1-left-table.html
 fails == 134706-1-right-scrollframe.html 134706-1-right-scrollframe.html
 fails == 134706-1-right-table.html 134706-1-right-table.html
 fails == 134706-2-left-scrollframe.html 134706-2-left-scrollframe.html
@@ -139,17 +139,17 @@ fails == 139550-1b.html 139550-1b.html
 fails == 142233-1.html 142233-1.html
 == 144004-1.html 144004-1.html
 == 144004-2.html 144004-2.html
 == 144004-3.html 144004-3.html
 fails == 163504-1a.html 163504-1a.html
 fails == 163504-1b.html 163504-1b.html
 fails == 163504-2a.html 163504-2a.html
 fails == 163504-2b.html 163504-2b.html
-== 167496-1.html 167496-1.html
+asserts-if(stylo,4) == 167496-1.html 167496-1.html # bug 1324661
 == 169749-1.html 169749-1.html
 == 172073-1.html 172073-1.html
 fails == 175190-1.html 175190-1.html
 fails == 179596-1a.html 179596-1a.html
 fails == 179596-1b.html 179596-1b.html
 # == 179596-2.html 179596-2.html
 # == 179596-2.html 179596-2.html
 # == 179596-2.html 179596-2.html
@@ -206,17 +206,17 @@ asserts-if(stylo,1) == 212563-2.html 212
 fails == 213834-1.html 213834-1.html
 fails == 214077-1a.html 214077-1a.html
 fails == 214077-1b.html 214077-1b.html
 == 218473-1.html 218473-1.html
 fuzzy-if(skiaContent,1,4) == 220165-1.svg 220165-1.svg
 fails == 223809-1.html 223809-1.html
 == 228856-1.html 228856-1.html
 == 228856-2.html 228856-2.html
-== 229591-1.html 229591-1.html
+asserts-if(stylo,4) == 229591-1.html 229591-1.html # bug 1324661
 # == 231823-1.html 231823-1.html
 == 232990-1a.xhtml 232990-1a.xhtml
 == 232990-1b.xhtml 232990-1b.xhtml
 fails == 233094-1.html 233094-1.html
 fails == 233094-2a.html 233094-2a.html
 fails == 233094-2b.html 233094-2b.html
 fails == 233094-2c.html 233094-2c.html
 == 234686-1.html 234686-1.html
@@ -248,24 +248,24 @@ fails == 240933-1.html 240933-1.html
 fails == 240933-2.html 240933-2.html
 == 243266-1.html 243266-1.html
 == 243302-1.html 243302-1.html
 fails == 243519-1.html 243519-1.html
 == 243519-2.html 243519-2.html
 == 243519-3.html 243519-3.html
 == 243519-4a.html 243519-4a.html
 == 243519-4b.html 243519-4b.html
-== 243519-4c.html 243519-4c.html
-== 243519-4d.html 243519-4d.html
+asserts-if(stylo,2) == 243519-4c.html 243519-4c.html # bug 1324661
+asserts-if(stylo,1) == 243519-4d.html 243519-4d.html # bug 1324661
 == 243519-4e.html 243519-4e.html
 == 243519-4f.html 243519-4f.html
 == 243519-5a.html 243519-5a.html
-== 243519-5b.html 243519-5b.html
+asserts-if(stylo,2) == 243519-5b.html 243519-5b.html # bug 1324661
 == 243519-5c.html 243519-5c.html
-== 243519-5d.html 243519-5d.html
+asserts-if(stylo,1) == 243519-5d.html 243519-5d.html # bug 1324661
 == 243519-6.html 243519-6.html
 fails == 243519-7.html 243519-7.html
 == 243519-8.svg 243519-8.svg
 == 243519-9a.html 243519-9a.html
 == 243519-9b.html 243519-9b.html
 == 243519-9c.html 243519-9c.html
 == 243519-9d.html 243519-9d.html
 == 243519-9e.html 243519-9e.html
@@ -308,17 +308,17 @@ fails == 281241-2.xhtml 281241-2.xhtml
 fails == 289384-1.xhtml 289384-1.xhtml
 # == 289480.html#top 289480.html#top
 fails == 290129-1.html 290129-1.html
 fails == 291078-1.html 291078-1.html
 fails == 291078-2.html 291078-2.html
 == 291262-1.html 291262-1.html
 # == 294306-1.html 294306-1.html
 # == 294306-1.html 294306-1.html
-fails == 296361-1.html 296361-1.html
+asserts-if(stylo,4) fails == 296361-1.html 296361-1.html # bug 1324661
 == 296904-1.html 296904-1.html
 fails == 299136-1.html 299136-1.html
 == 299837-1.html 299837-1.html
 == 299837-2.xul 299837-2.xul
 random-if(d2d) == 299837-3.xul 299837-3.xul
 fails == 300691-1a.html 300691-1a.html
 fails == 300691-1b.html 300691-1b.html
 fails == 300691-1c.html 300691-1c.html
@@ -389,23 +389,23 @@ fails == 315920-18a.html 315920-18a.html
 fails == 315920-18b.html 315920-18b.html
 fails == 315920-18c.html 315920-18c.html
 fails == 315920-18d.html 315920-18d.html
 fails == 315920-18e.html 315920-18e.html
 fails == 315920-18f.html 315920-18f.html
 fails == 315920-18g.html 315920-18g.html
 == 315920-18h.html 315920-18h.html
 == 315920-18i.html 315920-18i.html
-fails == 315920-19.html 315920-19.html
+== 315920-19.html 315920-19.html
 == 315920-20.svg 315920-20.svg
 == 315920-21.svg 315920-21.svg
 fails == 315920-22.html 315920-22.html
 fails == 315920-23.html 315920-23.html
-fails == 315920-24.html 315920-24.html
-fails == 315920-25.html 315920-25.html
+== 315920-24.html 315920-24.html
+== 315920-25.html 315920-25.html
 fails == 315920-26.html 315920-26.html
 fails == 315920-27.html 315920-27.html
 fails == 315920-28a.html 315920-28a.html
 fails == 315920-28b.html 315920-28b.html
 fails == 315920-28c.html 315920-28c.html
 fails == 315920-29a.html 315920-29a.html
 fails == 315920-29b.html 315920-29b.html
 fails == 315920-30.html 315920-30.html
@@ -420,18 +420,18 @@ fails == 315920-30.html 315920-30.html
 == 321738-1.html 321738-1.html
 == 322436-1.html 322436-1.html
 == 322461-1.xml 322461-1.xml
 == 323656-1.html 323656-1.html
 == 323656-2.html 323656-2.html
 fails == 323656-3.html 323656-3.html
 == 323656-4.html 323656-4.html
 == 323656-5.svg 323656-5.svg
-== 323656-6.html 323656-6.html
-fails == 325292-1.html 325292-1.html
+fails asserts-if(stylo,12) == 323656-6.html 323656-6.html # bug 1324661
+fails asserts-if(stylo,4) == 325292-1.html 325292-1.html
 fails == 325486-1.html 325486-1.html
 == 328111-1.html 328111-1.html
 random == 328829-1.xhtml 328829-1.xhtml
 == 328829-2.xhtml 328829-2.xhtml
 == 329359-1.html 329359-1.html
 fails == 331809-1.html 331809-1.html
 == 332360.html 332360.html
 # == 332360-ltr.html 332360-ltr.html
@@ -468,21 +468,21 @@ fails == 346774-1c.html 346774-1c.html
 fails == 347348-1.xhtml 347348-1.xhtml
 fails == 347496-1.xhtml 347496-1.xhtml
 == 347912-1.html 347912-1.html
 fails == 348049-1.xhtml 348049-1.xhtml
 fails == 348516-1.html 348516-1.html
 # == 348516-2.html 348516-2.html
 # == 348516-2.html 348516-2.html
 fails == 348516-3.html 348516-3.html
-== 348597-1.html 348597-1.html
+asserts-if(stylo,6) == 348597-1.html 348597-1.html # bug 1324661
 == 348809-1a.html 348809-1a.html
 == 348809-1b.html 348809-1b.html
-fails == 348809-1c.html 348809-1c.html
-fails == 348809-1d.html 348809-1d.html
+== 348809-1c.html 348809-1c.html
+== 348809-1d.html 348809-1d.html
 == 348809-1e.html 348809-1e.html
 == 348809-1f.html 348809-1f.html
 fails == 348809-2a.html 348809-2a.html
 fails == 348809-2b.html 348809-2b.html
 fails == 348809-2c.html 348809-2c.html
 fails == 348809-2d.html 348809-2d.html
 fails == 348809-2e.html 348809-2e.html
 fails == 348809-2f.html 348809-2f.html
@@ -520,17 +520,17 @@ fails == 352980-3c.html 352980-3c.html
 fails == 352980-3d.html 352980-3d.html
 fails == 352980-3e.html 352980-3e.html
 fails == 352980-3f.html 352980-3f.html
 == 355548-1.xml 355548-1.xml
 == 355548-2.xml 355548-2.xml
 == 355548-3.xml 355548-3.xml
 == 355548-4.xml 355548-4.xml
 == 355548-5.xml 355548-5.xml
-== 356774-1.html 356774-1.html
+asserts-if(stylo,4) == 356774-1.html 356774-1.html # bug 1324661
 == 356775-1.html 356775-1.html
 fails == 359869-1.html 359869-1.html
 fails == 359903-1.html 359903-1.html
 fails == 359903-2.html 359903-2.html
 == 360065-1.html 360065-1.html
 # == 360746-1.html 360746-1.html
 == 360757-1a.html 360757-1a.html
 == 360757-1b.html 360757-1b.html
@@ -590,20 +590,20 @@ fails == 367247-l-scroll.html 367247-l-s
 == 367332-1g.html 367332-1g.html
 fails == 367375-1.html 367375-1.html
 fails == 367375-2.html 367375-2.html
 == 367489-1.html 367489-1.html
 fails == 367504-margin-1.html 367504-margin-1.html
 fails == 367504-float-1.html 367504-float-1.html
 == 367612-1a.html 367612-1a.html
 == 367612-1b.html 367612-1b.html
-fails == 367612-1c.html 367612-1c.html
+== 367612-1c.html 367612-1c.html
 == 367612-1d.html 367612-1d.html
 == 367612-1e.html 367612-1e.html
-fails == 367612-1f.html 367612-1f.html
+== 367612-1f.html 367612-1f.html
 == 367612-1g.html 367612-1g.html
 fails == 368020-1.html 368020-1.html
 fails == 368020-2.html 368020-2.html
 fails == 368020-3.html 368020-3.html
 fails pref(layout.css.box-decoration-break.enabled,true) == 368020-5.html 368020-5.html
 == 368155-1.xhtml 368155-1.xhtml
 fails asserts(4-8) == 368155-negative-margins-1.html 368155-negative-margins-1.html
 # we can't test this because there's antialiasing involved, and our comparison
@@ -668,23 +668,23 @@ fails == 373433-1.html 373433-1.html
 == 373533-2.xhtml 373533-2.xhtml
 == 373533-3.xhtml 373533-3.xhtml
 == 374038-1.xul 374038-1.xul
 == 374038-2.xul 374038-2.xul
 random-if(d2d) == 374719-1.xul 374719-1.xul
 == 374927-1.html 374927-1.html
 fails == 375508-1.html 375508-1.html
 == 375716-1.html 375716-1.html
-== 375827-1.html 375827-1.html
+asserts-if(stylo,6) == 375827-1.html 375827-1.html # bug 1324661
 fails == 376375-1.html 376375-1.html
 == 376484-1.html 376484-1.html
 == 376532-1.html 376532-1.html
 == 376532-2.html 376532-2.html
 == 376532-3.html 376532-3.html
-fails asserts-if(stylo,2) == 377603-1.html 377603-1.html # bug 1324661
+fails asserts-if(stylo,4) == 377603-1.html 377603-1.html # bug 1324661
 == 377918.html 377918.html
 == 378535-1.html 378535-1.html
 fails == 378933-1.html 378933-1.html
 fails == 378935-1.html 378935-1.html
 fails == 378937-1.html 378937-1.html
 == 379178-xhtml.xhtml 379178-xhtml.xhtml
 fails == 379178-html.html 379178-html.html
 == 379178-svg.svg 379178-svg.svg
@@ -704,25 +704,25 @@ fails == 379361-2.html 379361-2.html
 fails == 379361-3.html 379361-3.html
 == 379461-1.xhtml 379461-1.xhtml
 == 379461-2.xhtml 379461-2.xhtml
 # == 379461-3-container-xhtml.html 379461-3-container-xhtml.html
 # == 379461-3-container-xhtml.html 379461-3-container-xhtml.html
 fails == 380004-1.html 380004-1.html
 fails == 380227-1.html 380227-1.html
 fails == 380825-1.html 380825-1.html
-== 380842-1.html 380842-1.html
+fails == 380842-1.html 380842-1.html
 == 381130-1.html 381130-1.html
 fails == 381507-1.html 381507-1.html
 == 381746-1.html 381746-1.html
 fails == 382600-1.html 382600-1.html
 fails == 382916-1.html 382916-1.html
 fails == 383035-1.html 383035-1.html
 fails == 383035-2.html 383035-2.html
-fails == 383488-1.html 383488-1.html
+== 383488-1.html 383488-1.html
 == 383551-1.html 383551-1.html
 fails == 383883-1.html 383883-1.html
 fails == 383883-2.html 383883-2.html
 fails == 383883-3.html 383883-3.html
 fails == 383883-4.html 383883-4.html
 fails == 383884-1.html 383884-1.html
 fails == 383885-1.html 383885-1.html
 fails == 384322-1.html 384322-1.html
@@ -734,19 +734,19 @@ fails HTTP(..) == 385569-1a.html 385569-
 fails HTTP(..) == 385569-1b.html 385569-1b.html
 == 385607-1.html 385607-1.html
 fails == 385823-1.html 385823-1.html
 fails == 385823-2a.html 385823-2a.html
 fails == 385823-2b.html 385823-2b.html
 fails == 385823-2c.html 385823-2c.html
 fails == 385870-1.html 385870-1.html
 fails == 385870-2.html 385870-2.html
-== 386014-1a.html 386014-1a.html
-== 386014-1b.html 386014-1b.html
-== 386014-1c.html 386014-1c.html
+fails asserts-if(stylo,3) == 386014-1a.html 386014-1a.html # bug 1324661
+fails asserts-if(stylo,6) == 386014-1b.html 386014-1b.html # bug 1324661
+fails == 386014-1c.html 386014-1c.html
 fails == 386065-1.html 386065-1.html
 == 386065-2.html 386065-2.html
 fails test-pref(layout.float-fragments-inside-column.enabled,false) fails == 386147-1.html 386147-1.html
 fails test-pref(layout.float-fragments-inside-column.enabled,true) == 386147-1.html 386147-1.html
 == 386310-1a.html 386310-1a.html
 == 386310-1b.html 386310-1b.html
 == 386310-1c.html 386310-1c.html
 == 386310-1d.html 386310-1d.html
@@ -766,21 +766,21 @@ fails == 386470-1b.html 386470-1b.html
 == 387876-1.html 387876-1.html
 == 387876-2.html 387876-2.html
 == 387876-3a.html 387876-3a.html
 == 387876-3b.html 387876-3b.html
 == 388026-1.html 388026-1.html
 fails == 389074-1.html 389074-1.html
 # == 389224-1.html 389224-1.html
 # == 389224-2.html 389224-2.html
-fails asserts-if(stylo,5) == 389468-1.html 389468-1.html # bug 1324661
+fails asserts-if(stylo,9) == 389468-1.html 389468-1.html # bug 1324661
 == 389623-1.html 389623-1.html
 == 389636-1.html 389636-1.html
 # == 389924-1a.html 389924-1a.html
-== 389924-1b.html 389924-1b.html
+fails asserts-if(stylo,10) == 389924-1b.html 389924-1b.html # bug 1324661
 # == 389924-1a.html 389924-1a.html
 == 390318-1a.html 390318-1a.html
 == 390318-1b.html 390318-1b.html
 == 390318-1c.html 390318-1c.html
 == 390318-1d.html 390318-1d.html
 == 390318-1e.html 390318-1e.html
 == 390318-1f.html 390318-1f.html
 skip-if(!winWidget) == 391045.html 391045.html
@@ -802,17 +802,17 @@ fails == 393490-1.html 393490-1.html
 == 393655-4.html 393655-4.html
 == 393655-5.html 393655-5.html
 == 393671-1.html 393671-1.html
 == 393671-2.html 393671-2.html
 == 393671-3.html 393671-3.html
 == 393760-1.xml 393760-1.xml
 fuzzy-if(skiaContent,1,500) == 393760-2.xml 393760-2.xml
 == 394111-1.html 394111-1.html
-fails == 394534-1.html 394534-1.html
+== 394534-1.html 394534-1.html
 # == 394676-1.xhtml 394676-1.xhtml
 fails == 395107-1.html 395107-1.html
 fails == 395107-2.html 395107-2.html
 fails == 395107-3.html 395107-3.html
 fails == 395107-4.html 395107-4.html
 fails == 395107-5.html 395107-5.html
 fails == 395130-1.html 395130-1.html
 fails == 395130-2.html 395130-2.html
@@ -827,17 +827,17 @@ fails == 398101-1.html 398101-1.html
 fails == 398682-1.html 398682-1.html
 == 398797-1a.html 398797-1a.html
 == 398797-1b.html 398797-1b.html
 == 398797-1c.html 398797-1c.html
 == 398797-1d.html 398797-1d.html
 == 399209-1.html 399209-1.html
 == 399209-2.html 399209-2.html
 fails == 399258-1.html 399258-1.html
-== 399384-1.html 399384-1.html
+fails == 399384-1.html 399384-1.html
 random-if(gtkWidget) == 399636-standards-css.html 399636-standards-css.html
 random-if(gtkWidget) == 399636-standards-html.html 399636-standards-html.html
 random-if(gtkWidget) == 399636-quirks-css.html 399636-quirks-css.html
 # We can't rely on this test working on platforms other than Windows and
 # Mac because they need not have a font called "Symbol".
 fails-if(winWidget) fails-if(cocoaWidget) random-if(!cocoaWidget&&!winWidget) == 399636-quirks-html.html 399636-quirks-html.html
 == 400081-1.html 400081-1.html
 == 400171-1a.html 400171-1a.html
@@ -874,17 +874,17 @@ fails == 403249-1a.html 403249-1a.html
 fails == 403249-1b.html 403249-1b.html
 fails == 403249-2a.html 403249-2a.html
 fails == 403249-2b.html 403249-2b.html
 == 403328-1.html 403328-1.html
 == 403426-1.html 403426-1.html
 fails == 403455-1.html 403455-1.html
 == 403505-1.xml 403505-1.xml
 #== 403519-1.html 403519-1.html
-== 403519-2.html 403519-2.html
+asserts-if(stylo,4) == 403519-2.html 403519-2.html # bug 1324661
 fails == 403656-1.html 403656-1.html
 fails == 403656-2.html 403656-2.html
 fails == 403656-3.html 403656-3.html
 fails == 403656-4.html 403656-4.html
 fails == 403656-5.html 403656-5.html
 #== 403657-1.html 403657-1.html
 fails == 403733-1.html 403733-1.html
 # == 403962-1.xhtml 403962-1.xhtml
@@ -909,18 +909,18 @@ fails == 404666-2.html 404666-2.html
 fails == 405305-1.html 405305-1.html
 == 405380-1.html 405380-1.html
 == 405517-1.xhtml 405517-1.xhtml
 fails == 405577-1.html 405577-1.html
 == 405584-1.html 405584-1.html
 # == 405952-1.html 405952-1.html
 == 406484-1.html 406484-1.html
 == 406568-1.html 406568-1.html
-fails == 407016-1-a.html 407016-1-a.html
-fails == 407016-1-b.html 407016-1-b.html
+fails asserts-if(stylo,8) == 407016-1-a.html 407016-1-a.html # bug 1324661
+fails asserts-if(stylo,8) == 407016-1-b.html 407016-1-b.html # bug 1324661
 fails == 407078-1.html 407078-1.html
 fails == 407095-1.html 407095-1.html
 fails == 407111-1.html 407111-1.html
 fails == 407227-1.html 407227-1.html
 fails == 407243-1.html 407243-1.html
 == 407419-1.html 407419-1.html
 == 407937-1.html 407937-1.html
 == 408493-1.html 408493-1.html
@@ -1013,17 +1013,17 @@ fails == 420790-1.xhtml 420790-1.xhtml
 == 421239-2.html 421239-2.html
 == 421419-1.html 421419-1.html
 == 421436-1a.html 421436-1a.html
 == 421436-1b.html 421436-1b.html
 fails asserts-if(stylo,0-4) == 421632-1.html 421632-1.html # bug 1335314
 fails == 421710-1.html 421710-1.html
 fails-if(Android) fails-if(usesRepeatResampling) == 421885-1.xml 421885-1.xml
 == 421955-1.html 421955-1.html
-fails == 422249-1.html 422249-1.html
+fails asserts-if(stylo,2) == 422249-1.html 422249-1.html # bug 1324661
 fails == 422394-1.html 422394-1.html
 fails == 422678-1.html 422678-1.html
 == 423130-1.html 423130-1.html
 == 423385-1.html 423385-1.html
 fails == 423599-1.html 423599-1.html
 fails == 423676-1.html 423676-1.html
 fails == 423823-1.html 423823-1.html
 == 424074-1.xul 424074-1.xul
@@ -1035,33 +1035,33 @@ fails == 424236-3.html 424236-3.html
 == 424236-4.html 424236-4.html
 fails == 424236-5.html 424236-5.html
 == 424236-6.html 424236-6.html
 == 424236-7.html 424236-7.html
 fails == 424236-8.html 424236-8.html
 fails == 424236-9.html 424236-9.html
 == 424236-10.html 424236-10.html
 fails == 424236-11.html 424236-11.html
-== 424434-1.html 424434-1.html
-fails == 424465-1.html 424465-1.html
+asserts-if(stylo,4) == 424434-1.html 424434-1.html # bug 1324661
+fails asserts-if(stylo,4) == 424465-1.html 424465-1.html # bug 1324661
 == 424631-1.html 424631-1.html
 == 424710-1.html 424710-1.html
 fails == 424766-1.html 424766-1.html
 # == 425972-1.html 425972-1.html
 fails == 425972-2.html 425972-2.html
 # == 425972-1.html 425972-1.html
 fails == 426629-1.html 426629-1.html
 asserts(3-6) == 427017-1.xhtml 427017-1.xhtml
 == 427129-scrollframe.html 427129-scrollframe.html
 == 427129-table.html 427129-table.html
 == 427129-image.html 427129-image.html
 == 427129-table-caption.html 427129-table-caption.html
 == 427370-1.html 427370-1.html
 fails == 427730-1.html 427730-1.html
-== 428278.html 428278.html
+asserts-if(stylo,6) == 428278.html 428278.html # bug 1324661
 == 428423-1a.html 428423-1a.html
 == 428423-1b.html 428423-1b.html
 fails == 428521-1a.html 428521-1a.html
 fails == 428521-1b.html 428521-1b.html
 fails == 428521-1c.html 428521-1c.html
 # == 428810-1a-ltr.html 428810-1a-ltr.html
 # == 428810-1b-ltr.html 428810-1b-ltr.html
 # == 428810-1c-ltr.html 428810-1c-ltr.html
@@ -1159,18 +1159,18 @@ fails == 444015-1.html 444015-1.html
 == 444375-1.html 444375-1.html
 fails == 444928-1.html 444928-1.html
 fails == 444928-2.html 444928-2.html
 fails == 444928-3.html 444928-3.html
 fails random asserts-if(stylo,2) == 445004-1.html 445004-1.html # bug 1324683
 == 445142-1a.html 445142-1a.html
 == 445142-1b.html 445142-1b.html
 == 445142-1c.html 445142-1c.html
-== 445142-2a.html 445142-2a.html
-== 445142-2b.html 445142-2b.html
+asserts-if(stylo,72) == 445142-2a.html 445142-2a.html # bug 1324661
+asserts-if(stylo,72) == 445142-2b.html 445142-2b.html # bug 1324661
 fails-if(usesRepeatResampling) == 446100-1a.html 446100-1a.html
 fails-if(Android) fails-if(usesRepeatResampling) == 446100-1b.html 446100-1b.html
 fails-if(Android) fails-if(usesRepeatResampling) == 446100-1c.html 446100-1c.html
 fails-if(usesRepeatResampling) == 446100-1d.html 446100-1d.html
 fails-if(usesRepeatResampling) == 446100-1e.html 446100-1e.html
 == 446100-1f.html 446100-1f.html
 fails-if(usesRepeatResampling) fails-if(Android) == 446100-1g.html 446100-1g.html
 == 446100-1h.html 446100-1h.html
@@ -1182,18 +1182,18 @@ fails asserts-if(stylo,8) == 449149-1b.h
 fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) asserts-if(stylo,8) == 449149-1a.html 449149-1a.html # bug 1324671
 fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) asserts-if(stylo,8) == 449149-1b.html 449149-1b.html # bug 1324671
 == 449149-2.html 449149-2.html
 == 449171-1.html 449171-1.html
 fails == 449362-1.html 449362-1.html
 == 449519-1.html 449519-1.html
 == 450670-1.html 450670-1.html
 fails == 451168-1.html 451168-1.html
-== 451876-1.html 451876-1.html
-== 451876-2.html 451876-2.html
+asserts-if(stylo,2) == 451876-1.html 451876-1.html # bug 1324661
+asserts-if(stylo,2) == 451876-2.html 451876-2.html # bug 1324661
 == 452915-1.html 452915-1.html
 == 452964-1.html 452964-1.html
 # == 454361.html 454361.html
 == 455105-1.html 455105-1.html
 == 455105-2.html 455105-2.html
 fails == 455171-5.html 455171-5.html
 fails == 455280-1.xhtml 455280-1.xhtml
 fails == 455826-1.html 455826-1.html
@@ -1325,18 +1325,18 @@ fails-if(Android) random-if(winWidget) f
 == 482398-1.html 482398-1.html
 fails == 482592-1a.xhtml 482592-1a.xhtml
 fails == 482592-1b.xhtml 482592-1b.xhtml
 == 482659-1a.html 482659-1a.html
 == 482659-1b.html 482659-1b.html
 asserts-if(stylo,1) == 482659-1c.html 482659-1c.html # bug 1324683
 asserts-if(stylo,1) == 482659-1d.html 482659-1d.html # bug 1324683
 == 483565.xul 483565.xul
-== 484256-1.html 484256-1.html
-== 484256-2.html 484256-2.html
+asserts-if(stylo,4) == 484256-1.html 484256-1.html # bug 1324661
+asserts-if(stylo,4) == 484256-2.html 484256-2.html # bug 1324661
 == 485012-1.html 485012-1.html
 fails == 485275-1.html 485275-1.html
 fails == 485275-1.svg 485275-1.svg
 == 486052-1.html 486052-1.html
 == 486052-2a.html 486052-2a.html
 == 486052-2b.html 486052-2b.html
 == 486052-2c.html 486052-2c.html
 == 486052-2d.html 486052-2d.html
@@ -1548,17 +1548,17 @@ fails == 564054-1.html 564054-1.html
 == 564991-1.html 564991-1.html
 == 565819-1.html 565819-1.html
 fails == 565819-2.html 565819-2.html
 fails needs-focus == 568441.html 568441.html
 == 569006-1.html 569006-1.html
 == 571281-1a.html 571281-1a.html
 == 571281-1b.html 571281-1b.html
 == 571281-1c.html 571281-1c.html
-fails == 571347-1a.html 571347-1a.html
+== 571347-1a.html 571347-1a.html
 # == 571347-1b.html 571347-1b.html
 # == 571347-2a.html 571347-2a.html
 # == 571347-2b.html 571347-2b.html
 fails == 571347-2c.html 571347-2c.html
 == 571347-2d.html 571347-2d.html
 fails == 571347-3.html 571347-3.html
 fails == 572598-1.html 572598-1.html
 fails == 574898-1.html 574898-1.html
@@ -1613,17 +1613,17 @@ fails == 600974-2.html 600974-2.html
 == 600974-3.html 600974-3.html
 == 602200-1.html 602200-1.html
 == 602200-2.html 602200-2.html
 fuzzy-if(Android,8,20) == 602200-3.html 602200-3.html
 fails == 602200-4.html 602200-4.html
 == 603423-1.html 603423-1.html
 fails == 604737.html 604737.html
 fails == 605138-1.html 605138-1.html
-fails == 605157-1.xhtml 605157-1.xhtml
+== 605157-1.xhtml 605157-1.xhtml
 == 607267-1.html 607267-1.html
 fails == 608636-1.html 608636-1.html
 == 608756-1a.html 608756-1a.html
 == 608756-1b.html 608756-1b.html
 asserts-if(stylo,4) == 608756-2.html 608756-2.html # bug 1324633
 == 609272-1.html 609272-1.html
 # == 613433-1.html 613433-1.html
 # == 613433-1.html 613433-1.html
@@ -1675,17 +1675,17 @@ fails == 645647-2.html 645647-2.html
 fails == 645768-1.html 645768-1.html
 == 650228-1.html 650228-1.html
 fails needs-focus == 652301-1a.html 652301-1a.html
 fails needs-focus == 652301-1b.html 652301-1b.html
 fails == 652775-1.html 652775-1.html
 fails == 653930-1.html 653930-1.html
 fails HTTP(..) == 654057-1.html 654057-1.html
 fails == 654950-1.html 654950-1.html
-fails == 655549-1.html 655549-1.html
+== 655549-1.html 655549-1.html
 == 655836-1.html 655836-1.html
 fails == 656875.html 656875.html
 fails == 658952.html 658952.html
 == 660682-1.html 660682-1.html
 fuzzy-if(d2d,1,256) skip-if(Android) fuzzy-if(skiaContent,1,68000) == 664127-1.xul 664127-1.xul
 fails == 665597-1.html 665597-1.html
 == 665597-2.html 665597-2.html
 == 668319-1.xul 668319-1.xul
@@ -1753,17 +1753,17 @@ fails == 776265-2d.html 776265-2d.html
 == 814677.html 814677.html
 fails == 814952-1.html 814952-1.html
 fails == 815593-1.html 815593-1.html
 == 816359-1.html 816359-1.html
 fails == 816458-1.html 816458-1.html
 fails == 816948-1.html 816948-1.html
 == 817019-1.html 817019-1.html
 fails == 818276-1.html 818276-1.html
-fails == 825999.html 825999.html
+fails asserts-if(stylo,0-4) == 825999.html 825999.html # bug 1324661
 == 827577-1a.html 827577-1a.html
 == 827577-1b.html 827577-1b.html
 fails == 827799-1.html 827799-1.html
 == 829958.html 829958.html
 == 836844-1.html 836844-1.html
 == 841192-1.html 841192-1.html
 fails == 844178.html 844178.html
 == 846144-1.html 846144-1.html
@@ -1942,17 +1942,17 @@ fails == 1174332-1.html 1174332-1.html
 fails == 1202512-1.html 1202512-1.html
 fails == 1202512-2.html 1202512-2.html
 == 1207326-1.html 1207326-1.html
 == 1209603-1.html 1209603-1.html
 == 1209994-1.html 1209994-1.html
 fails == 1209994-2.html 1209994-2.html
 == 1209994-3.html 1209994-3.html
 fails == 1209994-4.html 1209994-4.html
-fails == 1222226-1.html 1222226-1.html
+== 1222226-1.html 1222226-1.html
 fails pref(layout.css.overflow-clip-box.enabled,true) == 1226278.html 1226278.html
 == 1230466.html 1230466.html
 == 1238243-1.html 1238243-1.html
 == 1238243-2.html 1238243-2.html
 fails == 1239564.html 1239564.html
 fails == 1242172-1.html 1242172-1.html
 fails == 1242172-2.html 1242172-2.html
 == 1242781.html 1242781.html
--- a/layout/reftests/css-display/reftest-stylo.list
+++ b/layout/reftests/css-display/reftest-stylo.list
@@ -1,16 +1,16 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # Tests for CSS Display spec features.
 # http://dev.w3.org/csswg/css-display
 
 fails == display-contents-acid.html display-contents-acid.html
 # fuzzy-if(Android,8,604) == display-contents-acid-dyn-1.html display-contents-acid-dyn-1.html
-fails == display-contents-acid-dyn-2.html display-contents-acid-dyn-2.html
-fails == display-contents-acid-dyn-3.html display-contents-acid-dyn-3.html
+fails asserts-if(stylo,5) == display-contents-acid-dyn-2.html display-contents-acid-dyn-2.html # bug 1337700
+fails asserts-if(stylo,2) == display-contents-acid-dyn-3.html display-contents-acid-dyn-3.html # bug 1324661
 # == display-contents-generated-content.html display-contents-generated-content.html
 # == display-contents-generated-content-2.html display-contents-generated-content-2.html
 fails == display-contents-style-inheritance-1.html display-contents-style-inheritance-1.html
 fails == display-contents-style-inheritance-1-stylechange.html display-contents-style-inheritance-1-stylechange.html
 # == display-contents-style-inheritance-1-dom-mutations.html display-contents-style-inheritance-1-dom-mutations.html
 == display-contents-tables.xhtml display-contents-tables.xhtml
 == display-contents-tables-2.xhtml display-contents-tables-2.xhtml
 == display-contents-tables-3.xhtml display-contents-tables-3.xhtml
--- a/layout/reftests/css-transitions/reftest-stylo.list
+++ b/layout/reftests/css-transitions/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-== transitions-inline-already-wrapped-1.html transitions-inline-already-wrapped-1.html
+fails == transitions-inline-already-wrapped-1.html transitions-inline-already-wrapped-1.html
 == transitions-inline-already-wrapped-2.html transitions-inline-already-wrapped-2.html
-== transitions-inline-rewrap-1.html transitions-inline-rewrap-1.html
+fails == transitions-inline-rewrap-1.html transitions-inline-rewrap-1.html
 == transitions-inline-rewrap-2.html transitions-inline-rewrap-2.html
 fails == stacking-context-opacity-lose-to-animation.html stacking-context-opacity-lose-to-animation.html
 fails == stacking-context-transform-lose-to-animation.html stacking-context-transform-lose-to-animation.html
 # == stacking-context-opacity-wins-over-important-style.html stacking-context-opacity-wins-over-important-style.html
 # == stacking-context-transform-wins-over-important-style.html stacking-context-transform-wins-over-important-style.html
 # == transition-and-animation-with-different-durations.html transition-and-animation-with-different-durations.html
--- a/layout/reftests/flexbox/reftest-stylo.list
+++ b/layout/reftests/flexbox/reftest-stylo.list
@@ -89,18 +89,18 @@ fails == flexbox-inlinecontent-horiz-1b.
 fails == flexbox-inlinecontent-horiz-2.xhtml flexbox-inlinecontent-horiz-2.xhtml
 fails == flexbox-inlinecontent-horiz-3a.xhtml flexbox-inlinecontent-horiz-3a.xhtml
 fails == flexbox-inlinecontent-horiz-3b.xhtml flexbox-inlinecontent-horiz-3b.xhtml
 fails == flexbox-inlinecontent-horiz-3c.xhtml flexbox-inlinecontent-horiz-3c.xhtml
 fails == flexbox-inlinecontent-horiz-4.xhtml flexbox-inlinecontent-horiz-4.xhtml
 fails == flexbox-inlinecontent-horiz-5.xhtml flexbox-inlinecontent-horiz-5.xhtml
 
 # Tests for intrinsic sizing of flexboxes
-fails == flexbox-intrinsic-sizing-horiz-1a.xhtml flexbox-intrinsic-sizing-horiz-1a.xhtml
-fails == flexbox-intrinsic-sizing-horiz-1b.xhtml flexbox-intrinsic-sizing-horiz-1b.xhtml
+fails asserts-if(stylo,36) == flexbox-intrinsic-sizing-horiz-1a.xhtml flexbox-intrinsic-sizing-horiz-1a.xhtml # bug 1324661
+fails asserts-if(stylo,36) == flexbox-intrinsic-sizing-horiz-1b.xhtml flexbox-intrinsic-sizing-horiz-1b.xhtml # bug 1324661
 fails == flexbox-intrinsic-sizing-horiz-2a.xhtml flexbox-intrinsic-sizing-horiz-2a.xhtml
 fails == flexbox-intrinsic-sizing-horiz-2b.xhtml flexbox-intrinsic-sizing-horiz-2b.xhtml
 
 # Tests for invalidation after dynamic modifications
 fails == flexbox-invalidation-1.html flexbox-invalidation-1.html
 
 # Tests for flexbox in an iframe that gets resized.
 fails == flexbox-resizeviewport-1.xhtml flexbox-resizeviewport-1.xhtml
--- a/layout/reftests/forms/input/checkbox/checkbox-baseline-ref.html
+++ b/layout/reftests/forms/input/checkbox/checkbox-baseline-ref.html
@@ -19,12 +19,21 @@ x {
   border: 25px solid black;
   width:0;
   height:0;
 }
 
    </style>
   </head>
   <body>
+    <div><x style="border:unset; outline: 10px solid"></x>Block</div>
+    <div><x style="border:unset; outline: 1px solid"></x>Block</div>
     <div><x></x>Block</div>
+    <div><x></x>Block</div>
+    <div><x></x>Block</div>
+    <div><x></x>Block</div>
+    <div><x style="border:0; margin:0; width:20px; height:20px; background:pink"></x>Block</div>
+    <div><x style="border:0; margin:0; width:20px; height:20px; background:black"></x>Block</div>
+    <div><x style="border:0; margin:0; width:20px; height:20px; background:pink"></x>Block</div>
+    <div><x style="border:0; margin:0; width:20px; height:20px; background:black"></x>Block</div>
     <div style="font-size:72px"><x style="border-width:3px"></x>Block</div>
   </body>
 </html>
--- a/layout/reftests/forms/input/checkbox/checkbox-baseline.html
+++ b/layout/reftests/forms/input/checkbox/checkbox-baseline.html
@@ -18,18 +18,28 @@ div { border: 1px dashed blue; }
 .none {
      -moz-appearance: none; appearance: none;
   -webkit-appearance: none;
       -ms-appearance: none;
           appearance: none;
   width:0px;
   height:0px;
 }
+.intrinsic { width:unset; height:unset; }
 .border { border: 25px solid black; }
 input { margin: 20px; }
 
    </style>
   </head>
   <body>
+    <div><input class="none intrinsic" type="checkbox" style="background:pink; outline:10px solid black">Block</div>
+    <div><input class="none intrinsic" type="radio" style="background:pink; outline:1px solid black">Block</div>
+    <div><input class="none intrinsic border" type="checkbox">Block</div>
+    <div><input class="none intrinsic border" type="radio">Block</div>
     <div><input class="none border" type="checkbox">Block</div>
+    <div><input class="none border" type="radio">Block</div>
+    <div><input class="none" style="margin:0; width:20px; height:20px; background-color:pink" type="checkbox" checked>Block</div>
+    <div><input class="none" style="margin:0; width:20px; height:20px; background-color:black" type="checkbox">Block</div>
+    <div><input class="none" style="margin:0; width:20px; height:20px; background-color:pink" type="radio" checked>Block</div>
+    <div><input class="none" style="margin:0; width:20px; height:20px; background-color:black" type="radio">Block</div>
     <div style="font-size:72px"><input class="none border" type="checkbox" style="border-width:3px">Block</div>
   </body>
 </html>
rename from layout/reftests/forms/input/checkbox/checked.html
rename to layout/reftests/forms/input/checkbox/checked-appearance-none.html
--- a/layout/reftests/forms/input/checkbox/reftest.list
+++ b/layout/reftests/forms/input/checkbox/reftest.list
@@ -1,15 +1,15 @@
 == label-dynamic.html label-dynamic-ref.html
 fails-if(Android) == radio-stretched.html radio-stretched-ref.html # test for bug 464589
-!= checked.html checked-notref.html
 != checked-native.html checked-native-notref.html
-!= checked.html about:blank
-!= checked-notref.html about:blank
+fails-if(Android) == checked-appearance-none.html about:blank
+fails-if(Android) == unchecked-appearance-none.html about:blank
 != checked-native.html about:blank
 != checked-native-notref.html about:blank
-!= indeterminate-checked.html indeterminate-checked-notref.html
-!= indeterminate-unchecked.html indeterminate-unchecked-notref.html
+fails-if(Android) == indeterminate-checked.html about:blank
+fails-if(Android) == indeterminate-checked-notref.html about:blank
+fails-if(Android) == indeterminate-unchecked.html about:blank
 != indeterminate-native-checked.html indeterminate-native-checked-notref.html
 != indeterminate-native-unchecked.html indeterminate-native-unchecked-notref.html
 == indeterminate-selector.html indeterminate-selector-ref.html
 skip-if(!gtkWidget) == gtk-theme-width-height.html gtk-theme-width-height-ref.html
 skip-if(Android) == checkbox-baseline.html checkbox-baseline-ref.html # skip-if(Android) because Android use appearance:none by default for checkbox/radio.
\ No newline at end of file
rename from layout/reftests/forms/input/checkbox/checked-notref.html
rename to layout/reftests/forms/input/checkbox/unchecked-appearance-none.html
rename from layout/reftests/forms/input/radio/checked.html
rename to layout/reftests/forms/input/radio/checked-appearance-none.html
--- a/layout/reftests/forms/input/radio/reftest.list
+++ b/layout/reftests/forms/input/radio/reftest.list
@@ -1,8 +1,7 @@
 == label-dynamic.html label-dynamic-ref.html
-!= checked.html checked-notref.html
 != checked-native.html checked-native-notref.html
-!= checked.html about:blank
-!= checked-notref.html about:blank
+fails-if(Android) == checked-appearance-none.html about:blank
+fails-if(Android) == unchecked-appearance-none.html about:blank
 != checked-native.html about:blank
 != checked-native-notref.html about:blank
 skip-if(!gtkWidget) == gtk-theme-width-height.html gtk-theme-width-height-ref.html
rename from layout/reftests/forms/input/radio/checked-notref.html
rename to layout/reftests/forms/input/radio/unchecked-appearance-none.html
--- a/layout/reftests/image/reftest-stylo.list
+++ b/layout/reftests/image/reftest-stylo.list
@@ -9,20 +9,20 @@ fails == image-zoom-2.html image-zoom-2.
 fails == invalid-url-image-1.html invalid-url-image-1.html
 random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == sync-image-switch-1a.html sync-image-switch-1a.html
 random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == sync-image-switch-1b.html sync-image-switch-1b.html
 random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == sync-image-switch-1c.html sync-image-switch-1c.html
 random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == sync-image-switch-1d.html sync-image-switch-1d.html
 
 # Tests for "object-fit" & "object-position"
 test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-dyn-1.html image-object-fit-dyn-1.html
-fails test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-1.html image-object-fit-with-background-1.html
+# test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-1.html image-object-fit-with-background-1.html
 fails test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-fit-with-background-2.html image-object-fit-with-background-2.html
 # test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-position-dyn-1.html image-object-position-dyn-1.html
-fails test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-position-with-background-1.html image-object-position-with-background-1.html
+# fails test-pref(layout.css.object-fit-and-position.enabled,true) == image-object-position-with-background-1.html image-object-position-with-background-1.html
 fails == image-object-position-with-background-2.html image-object-position-with-background-2.html
 
 # Tests for image-orientation used with 'from-image' (note that all
 # image-orientation tests are fuzzy because the JPEG images do not perfectly
 # reproduce blocks of solid color, even at maximum quality):
 fuzzy(2,5) == image-orientation-from-image.html?none image-orientation-from-image.html?none
 fuzzy(1,1) == image-orientation-from-image.html?0 image-orientation-from-image.html?0
 fails == image-orientation-from-image.html?90 image-orientation-from-image.html?90
--- a/layout/reftests/margin-collapsing/reftest-stylo.list
+++ b/layout/reftests/margin-collapsing/reftest-stylo.list
@@ -685,24 +685,24 @@ fails == block-overflow-5c-dyn.html bloc
 == table-caption-bottom-outside-1-dyn.html table-caption-bottom-outside-1-dyn.html
 == table-caption-bottom-outside-2-dyn.html table-caption-bottom-outside-2-dyn.html
 == caption-sibling-1a.html caption-sibling-1a.html
 == caption-sibling-1a.html caption-sibling-1a.html
 == caption-sibling-1b.html caption-sibling-1b.html
 == caption-sibling-1b.html caption-sibling-1b.html
 == caption-sibling-1c.html caption-sibling-1c.html
 == caption-sibling-1c.html caption-sibling-1c.html
-== caption-sibling-1a-dyn.html caption-sibling-1a-dyn.html
-== caption-sibling-1a-dyn.html caption-sibling-1a-dyn.html
-== caption-sibling-1b-dyn.html caption-sibling-1b-dyn.html
-== caption-sibling-1b-dyn.html caption-sibling-1b-dyn.html
-== caption-sibling-1c-dyn.html caption-sibling-1c-dyn.html
-== caption-sibling-1c-dyn.html caption-sibling-1c-dyn.html
-== caption-sibling-2-dyn.html caption-sibling-2-dyn.html
-== caption-sibling-2-dyn.html caption-sibling-2-dyn.html
+asserts-if(stylo,2) == caption-sibling-1a-dyn.html caption-sibling-1a-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-1a-dyn.html caption-sibling-1a-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-1b-dyn.html caption-sibling-1b-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-1b-dyn.html caption-sibling-1b-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-1c-dyn.html caption-sibling-1c-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-1c-dyn.html caption-sibling-1c-dyn.html # bug 1337703
+asserts-if(stylo,2) == caption-sibling-2-dyn.html caption-sibling-2-dyn.html # bug 1337700
+asserts-if(stylo,2) == caption-sibling-2-dyn.html caption-sibling-2-dyn.html # bug 1337700
 == caption-child-1.html caption-child-1.html
 == caption-child-1-dyn.html caption-child-1-dyn.html
 # * Multi-column elements, per CSS Multi-column Layout Module
 # (Candidate Recommendation 12 April 2011):
 # "A multi-column element establishes a new block formatting context [...]"
 == column-sibling-1a.html column-sibling-1a.html
 == column-sibling-1b.html column-sibling-1b.html
 == column-sibling-1c.html column-sibling-1c.html
--- a/layout/reftests/mathml/reftest-stylo.list
+++ b/layout/reftests/mathml/reftest-stylo.list
@@ -1,13 +1,13 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == dir-1.html dir-1.html
 fails == dir-2.html dir-2.html
 random-if(gtkWidget) == dir-3.html dir-3.html
-== dir-4.html dir-4.html
+fails == dir-4.html dir-4.html
 == dir-5.html dir-5.html
 fails == dir-6.html dir-6.html
 fails == dir-6a.html dir-6a.html
 fails == dir-7.html dir-7.html
 fails == dir-8.html dir-8.html
 fails == dir-9.html dir-9.html
 fails == dir-10.html dir-10.html
 fails == dir-11.html dir-11.html
@@ -319,17 +319,17 @@ fails == rowlines-1c.html rowlines-1c.ht
 fails == rowlines-2a.html rowlines-2a.html
 fails == rowlines-2b.html rowlines-2b.html
 fails == rowlines-3-1.html rowlines-3-1.html
 fails == rowlines-3-2.html rowlines-3-2.html
 fails == tablespacing-1.html tablespacing-1.html
 fails == tablespacing-2.html tablespacing-2.html
 fails == tablespacing-3.html tablespacing-3.html
 fails == tablespacing-4.html tablespacing-4.html
-fails == tablespacing-5.html tablespacing-5.html
+fails asserts-if(stylo,0-2) == tablespacing-5.html tablespacing-5.html # bug 1324661
 fails == tablespacing-5a.html tablespacing-5a.html
 fails == tablespacing-6.html tablespacing-6.html
 fails == tablespacing-7.html tablespacing-7.html
 fails == tablespacing-8a.html tablespacing-8a.html
 fails == tablespacing-8b.html tablespacing-8b.html
 fails == op-dict-1.html op-dict-1.html
 fails == op-dict-2.html op-dict-2.html
 == op-dict-3.html op-dict-3.html
--- a/layout/reftests/pixel-rounding/reftest-stylo.list
+++ b/layout/reftests/pixel-rounding/reftest-stylo.list
@@ -76,28 +76,28 @@
 == background-image-height-top-5.html background-image-height-top-5.html
 == background-image-height-top-6.html background-image-height-top-6.html
 == background-image-width-left-4.html background-image-width-left-4.html
 == background-image-width-left-5.html background-image-width-left-5.html
 == background-image-width-left-6.html background-image-width-left-6.html
 
 
 # These all fail due bug 371180, plus a bunch of other bugs that ought to be filed.
-== collapsed-border-height-4.html collapsed-border-height-4.html
-== collapsed-border-height-5.html collapsed-border-height-5.html
-== collapsed-border-height-6.html collapsed-border-height-6.html
-== collapsed-border-width-4.html collapsed-border-width-4.html
-== collapsed-border-width-5.html collapsed-border-width-5.html
-== collapsed-border-width-6.html collapsed-border-width-6.html
-== collapsed-border-left-4.html collapsed-border-left-4.html
-== collapsed-border-left-5.html collapsed-border-left-5.html
-== collapsed-border-left-6.html collapsed-border-left-6.html
-== collapsed-border-top-4.html collapsed-border-top-4.html
-== collapsed-border-top-5.html collapsed-border-top-5.html
-== collapsed-border-top-6.html collapsed-border-top-6.html
+asserts-if(stylo,40) == collapsed-border-height-4.html collapsed-border-height-4.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-height-5.html collapsed-border-height-5.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-height-6.html collapsed-border-height-6.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-width-4.html collapsed-border-width-4.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-width-5.html collapsed-border-width-5.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-width-6.html collapsed-border-width-6.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-left-4.html collapsed-border-left-4.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-left-5.html collapsed-border-left-5.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-left-6.html collapsed-border-left-6.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-top-4.html collapsed-border-top-4.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-top-5.html collapsed-border-top-5.html # bug 1324661
+asserts-if(stylo,40) == collapsed-border-top-6.html collapsed-border-top-6.html # bug 1324661
 
 
 == image-base-ref.html image-base-ref.html
 == image-height-4.html image-height-4.html
 == image-height-5.html image-height-5.html
 == image-height-6.html image-height-6.html
 == image-base-ref.html image-base-ref.html
 == image-top-4.html image-top-4.html
--- a/layout/reftests/scoped-style/reftest-stylo.list
+++ b/layout/reftests/scoped-style/reftest-stylo.list
@@ -17,17 +17,17 @@ fails == scoped-style-015.html scoped-st
 == scoped-style-016.html scoped-style-016.html
 fails == scoped-style-017.html scoped-style-017.html
 fails == scoped-style-018.html scoped-style-018.html
 == scoped-style-019.svg scoped-style-019.svg
 == scoped-style-020.html scoped-style-020.html
 == scoped-style-021.html scoped-style-021.html
 == scoped-style-022.html scoped-style-022.html
 fails == scoped-style-023.html scoped-style-023.html
-fails == scoped-style-024.html scoped-style-024.html
+== scoped-style-024.html scoped-style-024.html
 == scoped-style-important-001.html scoped-style-important-001.html
 fails == scoped-style-important-002.html scoped-style-important-002.html
 == scoped-style-important-003.html scoped-style-important-003.html
 == scoped-style-important-004.html scoped-style-important-004.html
 == scoped-style-important-005.html scoped-style-important-005.html
 == scoped-style-important-006.html scoped-style-important-006.html
 == scoped-style-important-007.html scoped-style-important-007.html
 fails == scoped-style-dynamic-001.html scoped-style-dynamic-001.html
--- a/layout/reftests/table-background/reftest-stylo.list
+++ b/layout/reftests/table-background/reftest-stylo.list
@@ -1,63 +1,63 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # these could be moved to crashtests
-fails == backgr_border-table-cell.html backgr_border-table-cell.html
-fails == backgr_border-table-column-group.html backgr_border-table-column-group.html
+fails asserts-if(stylo,4) == backgr_border-table-cell.html backgr_border-table-cell.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_border-table-column-group.html backgr_border-table-column-group.html # bug 1324661
 # This seems to be caused by bug 527825
-fails == backgr_border-table-column.html backgr_border-table-column.html
-fails == backgr_border-table-quirks.html backgr_border-table-quirks.html
-fails == backgr_border-table-row-group.html backgr_border-table-row-group.html
-fails == backgr_border-table-row.html backgr_border-table-row.html
-fails == backgr_border-table.html backgr_border-table.html
-fails == backgr_fixed-bg.html backgr_fixed-bg.html
+fails asserts-if(stylo,4) == backgr_border-table-column.html backgr_border-table-column.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_border-table-quirks.html backgr_border-table-quirks.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_border-table-row-group.html backgr_border-table-row-group.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_border-table-row.html backgr_border-table-row.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_border-table.html backgr_border-table.html # bug 1324661
+fails asserts-if(stylo,8) == backgr_fixed-bg.html backgr_fixed-bg.html # bug 1324661
 fails == backgr_index.html backgr_index.html
-fails == backgr_layers-hide.html backgr_layers-hide.html
-fails == backgr_layers-opacity.html backgr_layers-opacity.html
-fails == backgr_layers-show.html backgr_layers-show.html
-fails == backgr_position-table-cell.html backgr_position-table-cell.html
-fails == backgr_position-table-column-group.html backgr_position-table-column-group.html
-fails == backgr_position-table-column.html backgr_position-table-column.html
-fails == backgr_position-table-row-group.html backgr_position-table-row-group.html
-fails == backgr_position-table-row.html backgr_position-table-row.html
-fails == backgr_position-table.html backgr_position-table.html
-fails == backgr_simple-table-cell.html backgr_simple-table-cell.html
-fails == backgr_simple-table-column-group.html backgr_simple-table-column-group.html
-fails == backgr_simple-table-column.html backgr_simple-table-column.html
-fails == backgr_simple-table-row-group.html backgr_simple-table-row-group.html
-fails == backgr_simple-table-row.html backgr_simple-table-row.html
-fails == backgr_simple-table.html backgr_simple-table.html
+fails asserts-if(stylo,4) == backgr_layers-hide.html backgr_layers-hide.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_layers-opacity.html backgr_layers-opacity.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_layers-show.html backgr_layers-show.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table-cell.html backgr_position-table-cell.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table-column-group.html backgr_position-table-column-group.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table-column.html backgr_position-table-column.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table-row-group.html backgr_position-table-row-group.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table-row.html backgr_position-table-row.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_position-table.html backgr_position-table.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table-cell.html backgr_simple-table-cell.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table-column-group.html backgr_simple-table-column-group.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table-column.html backgr_simple-table-column.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table-row-group.html backgr_simple-table-row-group.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table-row.html backgr_simple-table-row.html # bug 1324661
+fails asserts-if(stylo,4) == backgr_simple-table.html backgr_simple-table.html # bug 1324661
 
 # would also be good to test table-header-group and table-footer-group
 # (and rows and row groups in the presence of their reordering)
 # Also need to test different values of background-origin and background-clip.
-== border-separate-table-cell.html border-separate-table-cell.html
-== border-separate-table-column-group.html border-separate-table-column-group.html
-== border-separate-table-column.html border-separate-table-column.html
-== border-separate-table-row-group.html border-separate-table-row-group.html
-== border-separate-table-row.html border-separate-table-row.html
-== border-separate-table.html border-separate-table.html
-== border-collapse-table-cell.html border-collapse-table-cell.html
-== border-collapse-table-column-group.html border-collapse-table-column-group.html
-== border-collapse-table-column.html border-collapse-table-column.html
-== border-collapse-table-row-group.html border-collapse-table-row-group.html
-== border-collapse-table-row.html border-collapse-table-row.html
-== border-collapse-table.html border-collapse-table.html
-== border-collapse-opacity-table-cell.html border-collapse-opacity-table-cell.html
-== border-collapse-opacity-table-column-group.html border-collapse-opacity-table-column-group.html
-== border-collapse-opacity-table-column.html border-collapse-opacity-table-column.html
-fuzzy-if(d2d,1,16359) fuzzy-if(skiaContent,1,17000) == border-collapse-opacity-table-row-group.html border-collapse-opacity-table-row-group.html
-fuzzy-if(d2d,1,5453) fuzzy-if(skiaContent,1,11000) == border-collapse-opacity-table-row.html border-collapse-opacity-table-row.html
-fuzzy-if(d2d||skiaContent,1,60000) == border-collapse-opacity-table.html border-collapse-opacity-table.html
-== border-separate-opacity-table-cell.html border-separate-opacity-table-cell.html
-== border-separate-opacity-table-column-group.html border-separate-opacity-table-column-group.html
-== border-separate-opacity-table-column.html border-separate-opacity-table-column.html
-fuzzy-if(d2d,1,37170) fuzzy-if(skiaContent,1,38000) == border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group.html
-fuzzy-if(d2d,1,12390) fuzzy-if(skiaContent,1,13000) == border-separate-opacity-table-row.html border-separate-opacity-table-row.html
-fuzzy-if(d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-separate-opacity-table.html
+asserts-if(stylo,12) == border-separate-table-cell.html border-separate-table-cell.html # bug 1324661
+asserts-if(stylo,12) == border-separate-table-column-group.html border-separate-table-column-group.html # bug 1324661
+asserts-if(stylo,12) == border-separate-table-column.html border-separate-table-column.html # bug 1324661
+asserts-if(stylo,12) == border-separate-table-row-group.html border-separate-table-row-group.html # bug 1324661
+asserts-if(stylo,12) == border-separate-table-row.html border-separate-table-row.html # bug 1324661
+asserts-if(stylo,12) == border-separate-table.html border-separate-table.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table-cell.html border-collapse-table-cell.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table-column-group.html border-collapse-table-column-group.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table-column.html border-collapse-table-column.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table-row-group.html border-collapse-table-row-group.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table-row.html border-collapse-table-row.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-table.html border-collapse-table.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-opacity-table-cell.html border-collapse-opacity-table-cell.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-opacity-table-column-group.html border-collapse-opacity-table-column-group.html # bug 1324661
+asserts-if(stylo,12) == border-collapse-opacity-table-column.html border-collapse-opacity-table-column.html # bug 1324661
+# asserts-if(stylo,12) fuzzy-if(d2d,1,16359) fuzzy-if(skiaContent,1,17000) == border-collapse-opacity-table-row-group.html border-collapse-opacity-table-row-group.html # bug 1324661
+asserts-if(stylo,12) fuzzy-if(d2d,1,5453) fuzzy-if(skiaContent,1,11000) == border-collapse-opacity-table-row.html border-collapse-opacity-table-row.html # bug 1324661
+# asserts-if(stylo,12) fuzzy-if(stylo||d2d||skiaContent,1,60000) == border-collapse-opacity-table.html border-collapse-opacity-table.html # bug 1324661
+asserts-if(stylo,12) == border-separate-opacity-table-cell.html border-separate-opacity-table-cell.html # bug 1324661
+asserts-if(stylo,12) == border-separate-opacity-table-column-group.html border-separate-opacity-table-column-group.html # bug 1324661
+asserts-if(stylo,12) == border-separate-opacity-table-column.html border-separate-opacity-table-column.html # bug 1324661
+asserts-if(stylo,12) fuzzy-if(d2d,1,37170) fuzzy-if(skiaContent,1,38000) == border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group.html # bug 1324661
+asserts-if(stylo,12) fuzzy-if(d2d,1,12390) fuzzy-if(skiaContent,1,13000) == border-separate-opacity-table-row.html border-separate-opacity-table-row.html # bug 1324661
+# asserts-if(stylo,12) fuzzy-if(stylo||d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-separate-opacity-table.html # bug 1324661
 # == scrollable-rowgroup-collapse-background.html scrollable-rowgroup-collapse-background.html
 == scrollable-rowgroup-collapse-border.html scrollable-rowgroup-collapse-border.html
 # == scrollable-rowgroup-separate-background.html scrollable-rowgroup-separate-background.html
 == scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-border.html
 == empty-cells-default-1.html empty-cells-default-1.html
 == empty-cells-default-2.html empty-cells-default-2.html
 == table-row-opacity-dynamic-1.html table-row-opacity-dynamic-1.html
 # == table-row-opacity-dynamic-2.html table-row-opacity-dynamic-2.html
--- a/layout/reftests/table-bordercollapse/reftest-stylo.list
+++ b/layout/reftests/table-bordercollapse/reftest-stylo.list
@@ -11,75 +11,75 @@
 == bc_dyn_rg2.html bc_dyn_rg2.html
 == bc_dyn_rg3.html bc_dyn_rg3.html
 == bc_dyn_col1.html bc_dyn_col1.html
 == bc_dyn_col2.html bc_dyn_col2.html
 == bc_dyn_col3.html bc_dyn_col3.html
 == bc_dyn_cg1.html bc_dyn_cg1.html
 == bc_dyn_cg2.html bc_dyn_cg2.html
 == bc_dyn_cg3.html bc_dyn_cg3.html
-fails asserts-if(stylo,2) == bc_dyn_table1.html bc_dyn_table1.html # bug 1324661
-fails asserts-if(stylo,2) == bc_dyn_table2.html bc_dyn_table2.html # bug 1324661
+fails asserts-if(stylo,4) == bc_dyn_table1.html bc_dyn_table1.html # bug 1324661
+fails asserts-if(stylo,6) == bc_dyn_table2.html bc_dyn_table2.html # bug 1324661
 fails asserts-if(stylo,2) == bc_dyn_table3.html bc_dyn_table3.html # bug 1324661
 == bc_borderoffset1.html bc_borderoffset1.html
 == bc_borderoffset2.html bc_borderoffset2.html
-== frame_above_rules_all.html frame_above_rules_all.html
-== frame_above_rules_cols.html frame_above_rules_cols.html
-== frame_above_rules_groups.html frame_above_rules_groups.html
-== frame_above_rules_none.html frame_above_rules_none.html
-== frame_above_rules_rows.html frame_above_rules_rows.html
-== frame_below_rules_all.html frame_below_rules_all.html
-== frame_below_rules_cols.html frame_below_rules_cols.html
-== frame_below_rules_groups.html frame_below_rules_groups.html
-== frame_below_rules_none.html frame_below_rules_none.html
-== frame_below_rules_rows.html frame_below_rules_rows.html
-== frame_border_rules_all.html frame_border_rules_all.html
-== frame_border_rules_cols.html frame_border_rules_cols.html
-== frame_border_rules_groups.html frame_border_rules_groups.html
-== frame_border_rules_none.html frame_border_rules_none.html
-== frame_border_rules_rows.html frame_border_rules_rows.html
-== frame_box_rules_all.html frame_box_rules_all.html
-== frame_box_rules_cols.html frame_box_rules_cols.html
-== frame_box_rules_groups.html frame_box_rules_groups.html
-== frame_box_rules_none.html frame_box_rules_none.html
-== frame_box_rules_none-collapse.html frame_box_rules_none-collapse.html
-== frame_box_rules_rows.html frame_box_rules_rows.html
-== frame_hsides_rules_all.html frame_hsides_rules_all.html
-== frame_hsides_rules_cols.html frame_hsides_rules_cols.html
-== frame_hsides_rules_groups.html frame_hsides_rules_groups.html
-== frame_hsides_rules_none.html frame_hsides_rules_none.html
-== frame_hsides_rules_rows.html frame_hsides_rules_rows.html
-== frame_lhs_rules_all.html frame_lhs_rules_all.html
-== frame_lhs_rules_cols.html frame_lhs_rules_cols.html
-== frame_lhs_rules_groups.html frame_lhs_rules_groups.html
-== frame_lhs_rules_none.html frame_lhs_rules_none.html
-== frame_lhs_rules_rows.html frame_lhs_rules_rows.html
-== frame_rhs_rules_all.html frame_rhs_rules_all.html
-== frame_rhs_rules_cols.html frame_rhs_rules_cols.html
-== frame_rhs_rules_groups.html frame_rhs_rules_groups.html
-== frame_rhs_rules_none.html frame_rhs_rules_none.html
-== frame_rhs_rules_rows.html frame_rhs_rules_rows.html
+asserts-if(stylo,4) == frame_above_rules_all.html frame_above_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_above_rules_cols.html frame_above_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_above_rules_groups.html frame_above_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_above_rules_none.html frame_above_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_above_rules_rows.html frame_above_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_below_rules_all.html frame_below_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_below_rules_cols.html frame_below_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_below_rules_groups.html frame_below_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_below_rules_none.html frame_below_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_below_rules_rows.html frame_below_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_border_rules_all.html frame_border_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_border_rules_cols.html frame_border_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_border_rules_groups.html frame_border_rules_groups.html # bug 1324661
+asserts-if(stylo,7) == frame_border_rules_none.html frame_border_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_border_rules_rows.html frame_border_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_box_rules_all.html frame_box_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_box_rules_cols.html frame_box_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_box_rules_groups.html frame_box_rules_groups.html # bug 1324661
+asserts-if(stylo,7) == frame_box_rules_none.html frame_box_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_box_rules_none-collapse.html frame_box_rules_none-collapse.html # bug 1324661
+asserts-if(stylo,4) == frame_box_rules_rows.html frame_box_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_hsides_rules_all.html frame_hsides_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_hsides_rules_cols.html frame_hsides_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_hsides_rules_groups.html frame_hsides_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_hsides_rules_none.html frame_hsides_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_hsides_rules_rows.html frame_hsides_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_lhs_rules_all.html frame_lhs_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_lhs_rules_cols.html frame_lhs_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_lhs_rules_groups.html frame_lhs_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_lhs_rules_none.html frame_lhs_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_lhs_rules_rows.html frame_lhs_rules_rows.html # bug 1324661
+asserts-if(stylo,4) == frame_rhs_rules_all.html frame_rhs_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_rhs_rules_cols.html frame_rhs_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_rhs_rules_groups.html frame_rhs_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_rhs_rules_none.html frame_rhs_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_rhs_rules_rows.html frame_rhs_rules_rows.html # bug 1324661
 == frame_void_rules_all.html frame_void_rules_all.html
 == frame_void_rules_cols.html frame_void_rules_cols.html
 == frame_void_rules_groups.html frame_void_rules_groups.html
 == frame_void_rules_none.html frame_void_rules_none.html
 == frame_void_rules_rows.html frame_void_rules_rows.html
-== frame_vsides_rules_all.html frame_vsides_rules_all.html
-== frame_vsides_rules_cols.html frame_vsides_rules_cols.html
-== frame_vsides_rules_groups.html frame_vsides_rules_groups.html
-== frame_vsides_rules_none.html frame_vsides_rules_none.html
-== frame_vsides_rules_rows.html frame_vsides_rules_rows.html
+asserts-if(stylo,4) == frame_vsides_rules_all.html frame_vsides_rules_all.html # bug 1324661
+asserts-if(stylo,4) == frame_vsides_rules_cols.html frame_vsides_rules_cols.html # bug 1324661
+asserts-if(stylo,4) == frame_vsides_rules_groups.html frame_vsides_rules_groups.html # bug 1324661
+asserts-if(stylo,4) == frame_vsides_rules_none.html frame_vsides_rules_none.html # bug 1324661
+asserts-if(stylo,4) == frame_vsides_rules_rows.html frame_vsides_rules_rows.html # bug 1324661
 fails == borderhandling-1.html borderhandling-1.html
 fails == borderhandling-2.html borderhandling-2.html
 fails == borderhandling-3.html borderhandling-3.html
 fails == borderhandling-4.html borderhandling-4.html
 fails == borderhandling-5.xhtml borderhandling-5.xhtml
 fails == borderhandling-6.xhtml borderhandling-6.xhtml
 fails == borderhandling-7.xhtml borderhandling-7.xhtml
-== borderhandling-8.html borderhandling-8.html
+asserts-if(stylo,4) == borderhandling-8.html borderhandling-8.html # bug 1324661
 fails == borderhandling-frame-border.html borderhandling-frame-border.html
 fails == borderhandling-rules-border-empty-quirks.html borderhandling-rules-border-empty-quirks.html
 fails == borderhandling-rules-border-rules-quirks.html borderhandling-rules-border-rules-quirks.html
 fails == borderhandling-rules-border-none-quirks.html borderhandling-rules-border-none-quirks.html
 fails == borderhandling-rules-border-groups-quirks.html borderhandling-rules-border-groups-quirks.html
 fails == borderhandling-rules-border-rows-quirks.html borderhandling-rules-border-rows-quirks.html
 fails == borderhandling-rules-border-cols-quirks.html borderhandling-rules-border-cols-quirks.html
 fails == borderhandling-rules-border-all-quirks.html borderhandling-rules-border-all-quirks.html
@@ -87,20 +87,20 @@ fails == borderhandling-rules-border-emp
 fails == borderhandling-rules-border-rules-strict.html borderhandling-rules-border-rules-strict.html
 fails == borderhandling-rules-border-none-strict.html borderhandling-rules-border-none-strict.html
 fails == borderhandling-rules-border-groups-strict.html borderhandling-rules-border-groups-strict.html
 fails == borderhandling-rules-border-rows-strict.html borderhandling-rules-border-rows-strict.html
 fails == borderhandling-rules-border-cols-strict.html borderhandling-rules-border-cols-strict.html
 fails == borderhandling-rules-border-all-strict.html borderhandling-rules-border-all-strict.html
 fails == bordercolor-1.html bordercolor-1.html
 fails == bordercolor-2.html bordercolor-2.html
-fails == bordercolor-3.html bordercolor-3.html
+fails asserts-if(stylo,4) == bordercolor-3.html bordercolor-3.html # bug 1324661
 fails == bordercolor-4.html bordercolor-4.html
-== empty-toprow.html empty-toprow.html
-== double_borders.html double_borders.html
+asserts-if(stylo,4) == empty-toprow.html empty-toprow.html # bug 1324661
+asserts-if(stylo,4) == double_borders.html double_borders.html # bug 1324661
 # == border-collapse-rtl.html border-collapse-rtl.html
 # Fuzzy because for some reason the corner beveling is antialiased differently.
 # So get 40 pixels of fuzz, 20 at each beveled corner (because the border width
 # is 20px).
 == border-style-outset-becomes-groove.html border-style-outset-becomes-groove.html
 # Fuzzy because for some reason the corner beveling is antialiased differently.
 # So get 40 pixels of fuzz, 20 at each beveled corner (because the border width
 # is 20px).
--- a/layout/reftests/table-dom/reftest-stylo.list
+++ b/layout/reftests/table-dom/reftest-stylo.list
@@ -16,20 +16,20 @@ fails == deleteCol2.html deleteCol2.html
 fails == deleteCol3.html deleteCol3.html
 fails == deleteColGroup1.html deleteColGroup1.html
 fails == deleteColGroup2.html deleteColGroup2.html
 fails == deleteRowsRebuild1.html deleteRowsRebuild1.html
 fails == deleteRowsRebuild1a.html deleteRowsRebuild1a.html
 fails == deleteRowsShrink1.html deleteRowsShrink1.html
 fails == deleteTbodyExpand1.html deleteTbodyExpand1.html
 fails == deleteTbodyRebuild1.html deleteTbodyRebuild1.html
-== insertCaptionsAndRows1.html insertCaptionsAndRows1.html
-== insertCaptionsAndRows2.html insertCaptionsAndRows2.html
-== insertCaptionsAndRows3.html insertCaptionsAndRows3.html
-== insertCaptionsAndRows4.html insertCaptionsAndRows4.html
+# == insertCaptionsAndRows1.html insertCaptionsAndRows1.html
+# == insertCaptionsAndRows2.html insertCaptionsAndRows2.html
+# == insertCaptionsAndRows3.html insertCaptionsAndRows3.html
+# == insertCaptionsAndRows4.html insertCaptionsAndRows4.html
 fails == insertCellsExpand1.html insertCellsExpand1.html
 fails == insertCellsExpand2.html insertCellsExpand2.html
 fails == insertCellsExpandZeroRowspan.html insertCellsExpandZeroRowspan.html
 fails == insertCellsRebuild1.html insertCellsRebuild1.html
 fails == insertCellsRebuild2.html insertCellsRebuild2.html
 fails == insertCellsZeroColspan.html insertCellsZeroColspan.html
 fails == insertColGroups1.html insertColGroups1.html
 fails == insertColGroups2.html insertColGroups2.html
--- a/layout/reftests/table-width/reftest-stylo.list
+++ b/layout/reftests/table-width/reftest-stylo.list
@@ -1,51 +1,51 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == spacing-invariance-quirks-min.html spacing-invariance-quirks-min.html
 fails == spacing-invariance-quirks-pref.html spacing-invariance-quirks-pref.html
 fails == spacing-invariance-standards-min.html spacing-invariance-standards-min.html
 fails == spacing-invariance-standards-pref.html spacing-invariance-standards-pref.html
 # == min-width.html min-width.html
 == pref-width.html pref-width.html
 == min-width-ref.html min-width-ref.html
-fails == percent-large.html percent-large.html
+fails asserts-if(stylo,4) == percent-large.html percent-large.html # bug 1324661
 == percent-large-min.html percent-large-min.html
-fails == percent-large-nested.html percent-large-nested.html
-fails == percent-small.html percent-small.html
+fails == percent-large-nested.html percent-large-nested.html # bug 1324661
+fails asserts-if(stylo,4) == percent-small.html percent-small.html
 == percent-small-min.html percent-small-min.html
 fails == percent-small-nested.html percent-small-nested.html
-fails == percent-small-2.html percent-small-2.html
-fails == percent-zero.html percent-zero.html
+fails asserts-if(stylo,8) == percent-small-2.html percent-small-2.html # bug 1324661
+fails asserts-if(stylo,8) == percent-zero.html percent-zero.html # bug 1324661
 == shrink-wrap-pref.html shrink-wrap-pref.html
 == shrink-wrap-avail.html shrink-wrap-avail.html
 == shrink-wrap-min.html shrink-wrap-min.html
 == shrink-wrap-min-ref.html shrink-wrap-min-ref.html
 == shrink-wrap-pref-ref.html shrink-wrap-pref-ref.html
 == shrink-wrap-avail-ref.html shrink-wrap-avail-ref.html
-fails == conflicting-widths-1.html conflicting-widths-1.html
-fails == conflicting-widths-2.html conflicting-widths-2.html
-fails == conflicting-widths-3.html conflicting-widths-3.html
-fails == conflicting-widths-4.html conflicting-widths-4.html
-fails == conflicting-widths-5.html conflicting-widths-5.html
-== conflicting-widths-6.html conflicting-widths-6.html
-fails == conflicting-widths-7.html conflicting-widths-7.html
-fails == conflicting-widths-8.html conflicting-widths-8.html
-== conflicting-widths-9.html conflicting-widths-9.html
-== conflicting-widths-10.html conflicting-widths-10.html
+fails asserts-if(stylo,4) == conflicting-widths-1.html conflicting-widths-1.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-2.html conflicting-widths-2.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-3.html conflicting-widths-3.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-4.html conflicting-widths-4.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-5.html conflicting-widths-5.html # bug 1324661
+asserts-if(stylo,4) == conflicting-widths-6.html conflicting-widths-6.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-7.html conflicting-widths-7.html # bug 1324661
+fails asserts-if(stylo,4) == conflicting-widths-8.html conflicting-widths-8.html # bug 1324661
+asserts-if(stylo,4) == conflicting-widths-9.html conflicting-widths-9.html # bug 1324661
+asserts-if(stylo,4) == conflicting-widths-10.html conflicting-widths-10.html # bug 1324661
 fails == conflicting-percent-widths-1.html conflicting-percent-widths-1.html
 == conflicting-percent-widths-2.html conflicting-percent-widths-2.html
 == conflicting-percent-widths-3.html conflicting-percent-widths-3.html
-fails == percent-truncation-1.html percent-truncation-1.html
+fails asserts-if(stylo,4) == percent-truncation-1.html percent-truncation-1.html # bug 1324661
 fails == percent-truncation-2.html percent-truncation-2.html
 fails == percent-truncation-3.html percent-truncation-3.html
 fails == balancing-1.html balancing-1.html
 fails == balancing-2.html balancing-2.html
 # == cellpadding.html cellpadding.html
-fails == cellspacing.html cellspacing.html
-fails == percent-basis.html percent-basis.html
+fails asserts-if(stylo,4) == cellspacing.html cellspacing.html # bug 1324661
+fails asserts-if(stylo,16) == percent-basis.html percent-basis.html # bug 1324661
 fails == default-box-sizing-separate-standards.html default-box-sizing-separate-standards.html
 fails == default-box-sizing-separate-quirks.html default-box-sizing-separate-quirks.html
 fails == default-box-sizing-collapse-standards.html default-box-sizing-collapse-standards.html
 fails == default-box-sizing-collapse-quirks.html default-box-sizing-collapse-quirks.html
 fails == colspan-percent-distribution-1.html colspan-percent-distribution-1.html
 == colspan-percent-distribution-2.html colspan-percent-distribution-2.html
 == spanning-cell-sort-1-small.html spanning-cell-sort-1-small.html
 == spanning-cell-sort-1-large.html spanning-cell-sort-1-large.html
--- a/layout/reftests/text-decoration/reftest-stylo.list
+++ b/layout/reftests/text-decoration/reftest-stylo.list
@@ -1,19 +1,19 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == complex-decoration-style-quirks.html complex-decoration-style-quirks.html
 fails == complex-decoration-style-standards.html complex-decoration-style-standards.html
 fails == decoration-color-quirks.html decoration-color-quirks.html
 == decoration-color-standards.html decoration-color-standards.html
 fails == decoration-style-quirks.html decoration-style-quirks.html
 == decoration-style-standards.html decoration-style-standards.html
 fails == dynamic-underline-vertical-align-quirks-1.html dynamic-underline-vertical-align-quirks-1.html
-fails == dynamic-underline-vertical-align-standards-1.html dynamic-underline-vertical-align-standards-1.html
+== dynamic-underline-vertical-align-standards-1.html dynamic-underline-vertical-align-standards-1.html
 fails == dynamic-underline-vertical-align-quirks-2.html dynamic-underline-vertical-align-quirks-2.html
-fails == dynamic-underline-vertical-align-standards-2.html dynamic-underline-vertical-align-standards-2.html
+== dynamic-underline-vertical-align-standards-2.html dynamic-underline-vertical-align-standards-2.html
 fails == line-through-style-block-solid-quirks.html line-through-style-block-solid-quirks.html
 fails == line-through-style-block-dotted-quirks.html line-through-style-block-dotted-quirks.html
 fails == line-through-style-block-dashed-quirks.html line-through-style-block-dashed-quirks.html
 fails == line-through-style-block-double-quirks.html line-through-style-block-double-quirks.html
 fails == line-through-style-block-wavy-quirks.html line-through-style-block-wavy-quirks.html
 fails == line-through-style-inline-solid-quirks.html line-through-style-inline-solid-quirks.html
 fails == line-through-style-inline-dotted-quirks.html line-through-style-inline-dotted-quirks.html
 fails == line-through-style-inline-dashed-quirks.html line-through-style-inline-dashed-quirks.html
@@ -93,17 +93,17 @@ fails == underline-block-propagation-2-s
 == text-decoration-zorder-1-quirks.html text-decoration-zorder-1-quirks.html
 == table-quirk-1.html table-quirk-1.html
 fails == table-quirk-2.html table-quirk-2.html
 fails == text-decoration-propagation-1-quirks.html text-decoration-propagation-1-quirks.html
 == text-decoration-propagation-1-standards.html text-decoration-propagation-1-standards.html
 fails == 641444-1.html 641444-1.html
 fails == decoration-css21.html decoration-css21.html
 fails == decoration-color-override-quirks.html decoration-color-override-quirks.html
-fails == decoration-color-override-standards.html decoration-color-override-standards.html
+== decoration-color-override-standards.html decoration-color-override-standards.html
 == decoration-color-override-standards-ref.html decoration-color-override-standards-ref.html
 == decoration-css21-block.html decoration-css21-block.html
 == inline-baseline-almost-standards.html inline-baseline-almost-standards.html
 fails == inline-baseline-quirks.html inline-baseline-quirks.html
 == 676538-1.html 676538-1.html
 fails == underline-button-1.html underline-button-1.html
 fails == underline-button-2.html underline-button-2.html
 fails == underline-select-1.html underline-select-1.html
--- a/layout/reftests/text/reftest-stylo.list
+++ b/layout/reftests/text/reftest-stylo.list
@@ -40,17 +40,17 @@ fails == pre-wrap-1.html pre-wrap-1.html
 == soft-hyphens-1b.html soft-hyphens-1b.html
 == soft-hyphens-1c.html soft-hyphens-1c.html
 == soft-hyphens-break-word-1a.html soft-hyphens-break-word-1a.html
 == soft-hyphens-break-word-1b.html soft-hyphens-break-word-1b.html
 == soft-hyphens-break-word-1c.html soft-hyphens-break-word-1c.html
 # Tests for soft hyphens in table cells, bug 418975
 # == soft-hyphen-in-table-1.html soft-hyphen-in-table-1.html
 # == soft-hyphen-in-table-1.html soft-hyphen-in-table-1.html
-== soft-hyphen-in-table-2.html soft-hyphen-in-table-2.html
+asserts-if(stylo,4) == soft-hyphen-in-table-2.html soft-hyphen-in-table-2.html # bug 1324661
 # Cairo's FreeType and GDI backends snap glyphs to pixels, while Mac (usually),
 # D2D, and Skia have subpixel positioning.  The tests for pixel-snapping assume that
 # 1 CSS pixel == 1 device device
 fails-if(Android) skip-if(d2d||cocoaWidget||skiaContent) == subpixel-glyphs-x-1a.html subpixel-glyphs-x-1a.html
 # Platforms with subpixel positioning already have inconsistent glyphs by
 # design, but that is considered more tolerable because they are subpixel
 # inconsistencies.  On those platforms we just test that glyph positions are
 # subpixel.
@@ -334,10 +334,10 @@ pref(layout.css.control-characters.visib
 pref(layout.css.control-characters.visible,true) == control-chars-04b.html control-chars-04b.html
 pref(layout.css.control-characters.visible,true) == control-chars-04c.html control-chars-04c.html
 pref(layout.css.control-characters.visible,true) == control-chars-04d.html control-chars-04d.html
 
 # font fallback for <space> when not supported in the primary font family - bug 970891
 fails HTTP(..) == space-font-1.html space-font-1.html
 
 # handling of highly negative letter-spacing and intrinsic width
-fails == negative-letter-spacing-1.html negative-letter-spacing-1.html
+== negative-letter-spacing-1.html negative-letter-spacing-1.html
 == segment-break-transformation-1.html segment-break-transformation-1.html
--- a/layout/reftests/w3c-css/received/reftest-stylo.list
+++ b/layout/reftests/w3c-css/received/reftest-stylo.list
@@ -110,17 +110,17 @@ fails == css-multicol-1/multicol-margin-
 fails == css-multicol-1/multicol-nested-002.xht css-multicol-1/multicol-nested-002.xht
 fails == css-multicol-1/multicol-nested-005.xht css-multicol-1/multicol-nested-005.xht
 fails == css-multicol-1/multicol-nested-column-rule-001.xht css-multicol-1/multicol-nested-column-rule-001.xht
 fails == css-multicol-1/multicol-nested-margin-001.xht css-multicol-1/multicol-nested-margin-001.xht
 fails == css-multicol-1/multicol-nested-margin-002.xht css-multicol-1/multicol-nested-margin-002.xht
 fails == css-multicol-1/multicol-nested-margin-003.xht css-multicol-1/multicol-nested-margin-003.xht
 fails == css-multicol-1/multicol-nested-margin-004.xht css-multicol-1/multicol-nested-margin-004.xht
 fails == css-multicol-1/multicol-nested-margin-005.xht css-multicol-1/multicol-nested-margin-005.xht
-fails == css-multicol-1/multicol-overflow-000.xht css-multicol-1/multicol-overflow-000.xht
+fails asserts-if(stylo,4) == css-multicol-1/multicol-overflow-000.xht css-multicol-1/multicol-overflow-000.xht # bug 1324661
 fails == css-multicol-1/multicol-overflowing-001.xht css-multicol-1/multicol-overflowing-001.xht
 fails == css-multicol-1/multicol-reduce-000.xht css-multicol-1/multicol-reduce-000.xht
 fails == css-multicol-1/multicol-rule-000.xht css-multicol-1/multicol-rule-000.xht
 fails == css-multicol-1/multicol-rule-001.xht css-multicol-1/multicol-rule-001.xht
 fails == css-multicol-1/multicol-rule-002.xht css-multicol-1/multicol-rule-002.xht
 fails == css-multicol-1/multicol-rule-003.xht css-multicol-1/multicol-rule-003.xht
 == css-multicol-1/multicol-rule-004.xht css-multicol-1/multicol-rule-004.xht
 fails == css-multicol-1/multicol-rule-color-001.xht css-multicol-1/multicol-rule-color-001.xht
@@ -140,20 +140,20 @@ fails == css-multicol-1/multicol-rule-la
 fails == css-multicol-1/multicol-rule-outset-000.xht css-multicol-1/multicol-rule-outset-000.xht
 fails == css-multicol-1/multicol-rule-percent-001.xht css-multicol-1/multicol-rule-percent-001.xht
 fails == css-multicol-1/multicol-rule-px-001.xht css-multicol-1/multicol-rule-px-001.xht
 fails == css-multicol-1/multicol-rule-ridge-000.xht css-multicol-1/multicol-rule-ridge-000.xht
 == css-multicol-1/multicol-rule-samelength-001.xht css-multicol-1/multicol-rule-samelength-001.xht
 == css-multicol-1/multicol-rule-shorthand-001.xht css-multicol-1/multicol-rule-shorthand-001.xht
 fails == css-multicol-1/multicol-rule-solid-000.xht css-multicol-1/multicol-rule-solid-000.xht
 fails == css-multicol-1/multicol-rule-stacking-001.xht css-multicol-1/multicol-rule-stacking-001.xht
-== css-multicol-1/multicol-rule-style-groove-001.xht css-multicol-1/multicol-rule-style-groove-001.xht
-== css-multicol-1/multicol-rule-style-inset-001.xht css-multicol-1/multicol-rule-style-inset-001.xht
-== css-multicol-1/multicol-rule-style-outset-001.xht css-multicol-1/multicol-rule-style-outset-001.xht
-== css-multicol-1/multicol-rule-style-ridge-001.xht css-multicol-1/multicol-rule-style-ridge-001.xht
+asserts-if(stylo,4) == css-multicol-1/multicol-rule-style-groove-001.xht css-multicol-1/multicol-rule-style-groove-001.xht # bug 1324661
+asserts-if(stylo,4) == css-multicol-1/multicol-rule-style-inset-001.xht css-multicol-1/multicol-rule-style-inset-001.xht # bug 1324661
+asserts-if(stylo,4) == css-multicol-1/multicol-rule-style-outset-001.xht css-multicol-1/multicol-rule-style-outset-001.xht # bug 1324661
+asserts-if(stylo,4) == css-multicol-1/multicol-rule-style-ridge-001.xht css-multicol-1/multicol-rule-style-ridge-001.xht # bug 1324661
 fails == css-multicol-1/multicol-shorthand-001.xht css-multicol-1/multicol-shorthand-001.xht
 fails == css-multicol-1/multicol-span-000.xht css-multicol-1/multicol-span-000.xht
 fails == css-multicol-1/multicol-span-all-001.xht css-multicol-1/multicol-span-all-001.xht
 fails == css-multicol-1/multicol-span-all-002.xht css-multicol-1/multicol-span-all-002.xht
 fails == css-multicol-1/multicol-span-all-003.xht css-multicol-1/multicol-span-all-003.xht
 == css-multicol-1/multicol-span-all-block-sibling-003.xht css-multicol-1/multicol-span-all-block-sibling-003.xht
 fails == css-multicol-1/multicol-span-all-child-001.xht css-multicol-1/multicol-span-all-child-001.xht
 == css-multicol-1/multicol-span-all-child-002.xht css-multicol-1/multicol-span-all-child-002.xht
--- a/layout/reftests/w3c-css/submitted/images3/reftest-stylo.list
+++ b/layout/reftests/w3c-css/submitted/images3/reftest-stylo.list
@@ -1,30 +1,30 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 default-preferences test-pref(layout.css.object-fit-and-position.enabled,true)
 # Tests for 'object-fit' / 'object-position' with a PNG image
 fails == object-fit-fill-png-001c.html object-fit-fill-png-001c.html
-fails == object-fit-fill-png-001e.html object-fit-fill-png-001e.html
+# fails == object-fit-fill-png-001e.html object-fit-fill-png-001e.html
 fails == object-fit-fill-png-001i.html object-fit-fill-png-001i.html
-fails == object-fit-fill-png-001o.html object-fit-fill-png-001o.html
+# fails == object-fit-fill-png-001o.html object-fit-fill-png-001o.html
 fails == object-fit-fill-png-001p.html object-fit-fill-png-001p.html
 fails == object-fit-fill-png-002c.html object-fit-fill-png-002c.html
-fails == object-fit-fill-png-002e.html object-fit-fill-png-002e.html
+# fails == object-fit-fill-png-002e.html object-fit-fill-png-002e.html
 fails == object-fit-fill-png-002i.html object-fit-fill-png-002i.html
-fails == object-fit-fill-png-002o.html object-fit-fill-png-002o.html
+# fails == object-fit-fill-png-002o.html object-fit-fill-png-002o.html
 fails == object-fit-fill-png-002p.html object-fit-fill-png-002p.html
 fails == object-fit-contain-png-001c.html object-fit-contain-png-001c.html
 fails == object-fit-contain-png-001e.html object-fit-contain-png-001e.html
 fails == object-fit-contain-png-001i.html object-fit-contain-png-001i.html
 fails == object-fit-contain-png-001o.html object-fit-contain-png-001o.html
 fails == object-fit-contain-png-001p.html object-fit-contain-png-001p.html
 fails == object-fit-contain-png-002c.html object-fit-contain-png-002c.html
-fails == object-fit-contain-png-002e.html object-fit-contain-png-002e.html
+# fails == object-fit-contain-png-002e.html object-fit-contain-png-002e.html
 fails == object-fit-contain-png-002i.html object-fit-contain-png-002i.html
-fails == object-fit-contain-png-002o.html object-fit-contain-png-002o.html
+# fails == object-fit-contain-png-002o.html object-fit-contain-png-002o.html
 fails == object-fit-contain-png-002p.html object-fit-contain-png-002p.html
 fails == object-fit-cover-png-001c.html object-fit-cover-png-001c.html
 fails == object-fit-cover-png-001e.html object-fit-cover-png-001e.html
 fails == object-fit-cover-png-001i.html object-fit-cover-png-001i.html
 fails == object-fit-cover-png-001o.html object-fit-cover-png-001o.html
 fails == object-fit-cover-png-001p.html object-fit-cover-png-001p.html
 fails == object-fit-cover-png-002c.html object-fit-cover-png-002c.html
 fails == object-fit-cover-png-002e.html object-fit-cover-png-002e.html
@@ -169,25 +169,25 @@ fails == object-fit-scale-down-svg-005e.
 fails == object-fit-scale-down-svg-005i.html object-fit-scale-down-svg-005i.html
 fails == object-fit-scale-down-svg-005o.html object-fit-scale-down-svg-005o.html
 fails == object-fit-scale-down-svg-005p.html object-fit-scale-down-svg-005p.html
 fails == object-fit-scale-down-svg-006e.html object-fit-scale-down-svg-006e.html
 fails == object-fit-scale-down-svg-006i.html object-fit-scale-down-svg-006i.html
 fails == object-fit-scale-down-svg-006o.html object-fit-scale-down-svg-006o.html
 fails == object-fit-scale-down-svg-006p.html object-fit-scale-down-svg-006p.html
 fails == object-position-png-001c.html object-position-png-001c.html
-fails == object-position-png-001e.html object-position-png-001e.html
+# fails == object-position-png-001e.html object-position-png-001e.html
 fails == object-position-png-001i.html object-position-png-001i.html
-fails == object-position-png-001o.html object-position-png-001o.html
+# fails == object-position-png-001o.html object-position-png-001o.html
 fails == object-position-png-001p.html object-position-png-001p.html
 fails == object-position-png-002c.html object-position-png-002c.html
-fails == object-position-png-002e.html object-position-png-002e.html
+# fails == object-position-png-002e.html object-position-png-002e.html
 fails == object-position-png-002i.html object-position-png-002i.html
-fails == object-position-png-002o.html object-position-png-002o.html
+# fails == object-position-png-002o.html object-position-png-002o.html
 fails == object-position-png-002p.html object-position-png-002p.html
 fails == object-position-svg-001e.html object-position-svg-001e.html
 fails == object-position-svg-001i.html object-position-svg-001i.html
 fails == object-position-svg-001o.html object-position-svg-001o.html
 fails == object-position-svg-001p.html object-position-svg-001p.html
-fails == object-position-svg-002e.html object-position-svg-002e.html
+# fails == object-position-svg-002e.html object-position-svg-002e.html
 fails == object-position-svg-002i.html object-position-svg-002i.html
 fails == object-position-svg-002o.html object-position-svg-002o.html
 fails == object-position-svg-002p.html object-position-svg-002p.html
--- a/layout/reftests/writing-mode/tables/reftest-stylo.list
+++ b/layout/reftests/writing-mode/tables/reftest-stylo.list
@@ -4,18 +4,18 @@
 == vertical-table-2a.html vertical-table-2a.html
 == vertical-table-2b.html vertical-table-2b.html
 == vertical-table-rowspan-1.html vertical-table-rowspan-1.html
 == vertical-table-rowspan-2.html vertical-table-rowspan-2.html
 == vertical-table-colspan-1.html vertical-table-colspan-1.html
 == vertical-table-colspan-2.html vertical-table-colspan-2.html
 == vertical-table-specified-width-1.html vertical-table-specified-width-1.html
 asserts(1-2) == vertical-table-specified-width-2.html vertical-table-specified-width-2.html
-== vertical-border-collapse-1.html vertical-border-collapse-1.html
-== vertical-border-collapse-2.html vertical-border-collapse-2.html
+asserts-if(stylo,4) == vertical-border-collapse-1.html vertical-border-collapse-1.html # bug 1324661
+asserts-if(stylo,4) == vertical-border-collapse-2.html vertical-border-collapse-2.html # bug 1324661
 
 # == fixed-table-layout-002-vlr.html fixed-table-layout-002-vlr.html
 # == fixed-table-layout-003-vlr.html fixed-table-layout-003-vlr.html
 # == fixed-table-layout-004-vlr.html fixed-table-layout-004-vlr.html
 # == fixed-table-layout-005-vlr.html fixed-table-layout-005-vlr.html
 # == fixed-table-layout-006-vlr.html fixed-table-layout-006-vlr.html
 # == fixed-table-layout-007-vlr.html fixed-table-layout-007-vlr.html
 # == fixed-table-layout-009-vlr.html fixed-table-layout-009-vlr.html
@@ -63,22 +63,22 @@ asserts(1-2) == vertical-table-specified
 # == fixed-table-layout-029-vrl.html fixed-table-layout-029-vrl.html
 # == fixed-table-layout-030-vrl.html fixed-table-layout-030-vrl.html
 # == fixed-table-layout-031-vrl.html fixed-table-layout-031-vrl.html
 
 # HTTP(../..) == s72-border-spacing-002.xht s72-border-spacing-002.xht
 # HTTP(../..) == s72-border-spacing-003.xht s72-border-spacing-003.xht
 # HTTP(../..) == s72-border-spacing-004.xht s72-border-spacing-004.xht
 # HTTP(../..) == s72-border-spacing-005.xht s72-border-spacing-005.xht
-fails == wm-row-progression-002.xht wm-row-progression-002.xht
-fails == wm-row-progression-003.xht wm-row-progression-003.xht
-fails == wm-row-progression-004.xht wm-row-progression-004.xht
-fails == wm-row-progression-005.xht wm-row-progression-005.xht
-fails == wm-row-progression-006.xht wm-row-progression-006.xht
-fails == wm-row-progression-007.xht wm-row-progression-007.xht
+fails asserts-if(stylo,4) == wm-row-progression-002.xht wm-row-progression-002.xht # bug 1324661
+fails asserts-if(stylo,4) == wm-row-progression-003.xht wm-row-progression-003.xht # bug 1324661
+fails asserts-if(stylo,4) == wm-row-progression-004.xht wm-row-progression-004.xht # bug 1324661
+fails asserts-if(stylo,4) == wm-row-progression-005.xht wm-row-progression-005.xht # bug 1324661
+fails asserts-if(stylo,4) == wm-row-progression-006.xht wm-row-progression-006.xht # bug 1324661
+fails asserts-if(stylo,4) == wm-row-progression-007.xht wm-row-progression-007.xht # bug 1324661
 
 # == table-caption-top-1.html table-caption-top-1.html
 # == table-caption-bottom-1.html table-caption-bottom-1.html
 # == table-caption-left-1.html table-caption-left-1.html
 # == table-caption-right-1.html table-caption-right-1.html
 
 == border-collapse-bevels-1a.html border-collapse-bevels-1a.html
 fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1b.html border-collapse-bevels-1b.html
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -68,17 +68,17 @@ load 580685.html
 load 585185-1.html
 load 588627-1.html
 load 592698-1.html
 load 601437-1.html
 load 601439-1.html
 load 605689-1.html
 load 611922-1.html
 load 621596-1.html
-load 622314-1.xhtml
+skip-if(stylo) load 622314-1.xhtml # bug 1337695
 load 637242.xhtml
 load 645142.html
 fails-if(stylo) == 645951-1.html 645951-1-ref.html
 load 652976-1.svg
 load 665209-1.html
 load 671799-1.html
 load 671799-2.html
 skip-if(stylo) load 690990-1.html # bug 1323708
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -541,77 +541,98 @@ input[type="color"]:-moz-system-metric(c
    input labels and remove this override -- bug 1161482 */
 input[type="file"]:dir(rtl) > xul|label {
   padding-inline-start: 0px;
   padding-inline-end: 5px;
 }
 
 /* radio buttons */
 input[type="radio"] {
+  display: inline-block;
   -moz-appearance: radio;
   margin-block-start: 3px;
   margin-block-end: 0px;
   margin-inline-start: 5px;
   margin-inline-end: 3px;
-  border-radius: 100%;
 }
 
 /* check boxes */
 input[type="checkbox"] {
+  display: inline-block;
   -moz-appearance: checkbox;
   margin-block-start: 3px;
   margin-block-end: 3px;
   margin-inline-start: 4px;
   margin-inline-end: 3px;
-  border-radius: 0;
 }
 
 /* common features of radio buttons and check boxes */
 
+input[type="radio"],
+input[type="checkbox"] {
+  box-sizing: border-box;
+  cursor: default;
+  /* unset some values from the general 'input' rule above: */
+  padding: unset;
+  -moz-binding: unset;
+  border: unset;
+  background-color: unset;
+}
+
+input[type="radio"]:disabled,
+input[type="radio"]:disabled:active,
+input[type="radio"]:disabled:hover,
+input[type="radio"]:disabled:hover:active,
+input[type="checkbox"]:disabled,
+input[type="checkbox"]:disabled:active,
+input[type="checkbox"]:disabled:hover,
+input[type="checkbox"]:disabled:hover:active {
+  cursor: inherit;
+}
+
+%if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+/*
+ * These platforms doesn't have any theming support and thus appearance:none
+ * is the same as any other appearance value.
+ * XXX This is not web-compatible and should be fixed.
+ */
+input[type="radio"] {
+  border-radius: 100%;
+}
+
+input[type="checkbox"] {
+  border-radius: 0;
+}
+
 /* NOTE: The width, height, border-width, and padding here must all
    add up the way nsFormControlFrame::GetIntrinsic(Width|Height)
    expects them to, or they will not come out with total width equal
    to total height on sites that set their 'width' or 'height' to 'auto'.
    (Should we maybe set !important on width and height, then?)  */
 input[type="radio"],
 input[type="checkbox"] {
-  box-sizing: border-box;
   inline-size: 13px;
   block-size: 13px;
-  cursor: default;
-  padding: 0;
-  -moz-binding: none;
   border: 2px inset ThreeDLightShadow;
   background-repeat: no-repeat;
   background-position: center;
 }
 
 input[type="radio"]:disabled,
 input[type="radio"]:disabled:active,
 input[type="radio"]:disabled:hover,
 input[type="radio"]:disabled:hover:active,
 input[type="checkbox"]:disabled,
 input[type="checkbox"]:disabled:active,
 input[type="checkbox"]:disabled:hover,
 input[type="checkbox"]:disabled:hover:active {
   padding: 1px;
   border: 1px inset ThreeDShadow;
-  cursor: inherit;
 }
 
-% On Mac, the native theme takes care of this.
-% See nsNativeThemeCocoa::ThemeDrawsFocusForWidget.
-%ifndef XP_MACOSX
-input[type="checkbox"]:-moz-focusring,
-input[type="radio"]:-moz-focusring {
-  /* Don't specify the outline-color, we should always use initial value. */
-  outline: 1px dotted;
-}
-%endif
-
 input[type="checkbox"]:hover:active,
 input[type="radio"]:hover:active {
   background-color: ThreeDFace;
   border-style: inset;
 }
 
 input[type="radio"] {
   background-size: calc(100% - 4px) calc(100% - 4px);
@@ -640,16 +661,28 @@ input[type="checkbox"]:disabled:checked 
 input[type="checkbox"]:indeterminate {
   background-image: url(indeterminate-checkmark.svg);
 }
 
 input[type="checkbox"]:indeterminate:disabled {
   background-image: url(indeterminate-checkmark.svg#disabled);
 }
 
+%endif /* defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) */
+
+% On Mac, the native theme takes care of this.
+% See nsNativeThemeCocoa::ThemeDrawsFocusForWidget.
+%ifndef XP_MACOSX
+input[type="checkbox"]:-moz-focusring,
+input[type="radio"]:-moz-focusring {
+  /* Don't specify the outline-color, we should always use initial value. */
+  outline: 1px dotted;
+}
+%endif
+
 input[type="search"] {
   box-sizing: border-box;
 }
 
 /* buttons */
 
 /* Note: Values in nsNativeTheme IsWidgetStyled function
    need to match button background/border values here */
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -100,17 +100,17 @@ load 515288-1.html
 load 522394-1.svg
 load 522394-2.svg
 load 522394-3.svg
 load 566216-1.svg
 load 587336-1.html
 load 590291-1.svg
 load 601999-1.html
 load 605626-1.svg
-asserts(2) asserts-if(stylo,0) load 606914.xhtml # bug 606914
+asserts(2) load 606914.xhtml # bug 606914
 load 610594-1.html
 load 610954-1.html
 load 612662-1.svg
 load 612662-2.svg
 load 612736-1.svg
 load 612736-2.svg
 load 614367-1.svg
 load 620034-1.html
--- a/layout/tables/crashtests/crashtests.list
+++ b/layout/tables/crashtests/crashtests.list
@@ -5,31 +5,31 @@ load 55789-1.html
 load 78623-1.html
 load 110523-1.html
 load 138725-1.html
 load 159359-1.html
 load 187779-1.html
 load 189751-1.html
 load 197015-1.html
 load 220536-1.html
-load 223458-1.html
+asserts-if(stylo,4) load 223458-1.html # bug 1324661
 load 237421-1.html
 load 237421-2.html
 load 238909-1.html
 load 239294-1.html
 load 240854-1.html
 load 266015-1.html
-load 267418.html
+asserts-if(stylo,10) load 267418.html # bug 1324661
 load 275625.html
 load 277062-1.html
 load 278385-1.html
 load 282175-1.html
 load 284844-1.html
 load 284844-1.html
-load 284852.html
+asserts-if(stylo,12) load 284852.html # bug 1324661
 load 300912.html
 load 308752-1.html
 load 308752-2.html
 load 316636-1.html
 load 317876.html
 load 322779-1.xul
 load 323489-1.html
 load 323604-1.html
@@ -63,17 +63,17 @@ load 367673-1.xhtml
 load 367749.html
 load 367755.xhtml
 load 368013.html
 load 368166-1.xhtml
 load 370360-1.html
 load 370710.xhtml
 load 370713-1.html
 load 370876-1.html
-asserts-if(stylo,6-7) load 370897-1.html # bug 1324643
+load 370897-1.html
 load 371290.html
 load 373400-1.html
 load 373400-2.html
 load 373400-3.html
 load 373611-1.html
 load 373946-1.html
 load 374356-1.html
 load 374819-1.html
@@ -97,18 +97,18 @@ load 403579-1.html
 skip-if(stylo) load 404301-1.xhtml # bug 1323652
 load 408753-1.xhtml
 load 410426-1.html
 load 410428-1.xhtml
 load 411582.xhtml
 load 413091.xhtml
 load 413180-1.html
 load 416845-1.xhtml
-load 416845-2.xhtml
-load 416845-3.html   
+asserts-if(stylo,4) load 416845-2.xhtml # bug 1324661
+asserts-if(stylo,2) load 416845-3.html # bug 1324661
 load 420242-1.xhtml
 asserts(8) asserts-if(stylo,4) load 420654-1.xhtml # bug 458238, bug 436123, bug 457397 # bug 1324682
 load 423514-1.xhtml
 load 430374.html
 load 444431-1.html
 load 444702-1.html
 asserts-if(stylo,1) load 448988-1.xhtml # bug 1324681
 load 450311-1.html
@@ -135,25 +135,25 @@ load 573354-1.xhtml
 load 576890-1.html
 load 576890-2.html
 load 576890-3.html
 load 580481-1.xhtml
 asserts(1) asserts-if(stylo,0) load 595758-1.xhtml # Bug 714667
 load 595758-2.xhtml
 load 678447-1.html
 load 691824-1.xhtml
-load 695430-1.html
+asserts-if(stylo,4) load 695430-1.html # bug 1324661
 load 696640-1.html
 load 696640-2.html
 load 705996-1.html
 load 705996-2.html
 load 707622-1.html
 load 710098-1.html
 load 711864-1.html
-asserts-if(gtkWidget&&browserIsRemote,5) asserts-if(stylo,1-6) load 759249-1.html # Bug 1195474 # bug 1324704
+asserts-if(gtkWidget&&browserIsRemote,5) asserts-if(stylo,1-7) load 759249-1.html # Bug 1195474 # bug 1324704
 load 759249-2.html
 load 814713.html
 load 1027611-1.html
 load 1031934.html
 load 1183896.html
 load 1223282.html
 load 1223232.html
 load 1243623-1.html
--- a/layout/tables/reftests/reftest-stylo.list
+++ b/layout/tables/reftests/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == 1031934.html 1031934.html
-== 1220621-1a.html 1220621-1a.html
-== 1220621-1b.html 1220621-1b.html
-== 1220621-1c.html 1220621-1c.html
-== 1220621-1d.html 1220621-1d.html
-== 1220621-1e.html 1220621-1e.html
-== 1220621-1f.html 1220621-1f.html
-== 1220621-2a.html 1220621-2a.html
-== 1220621-2b.html 1220621-2b.html
+asserts-if(stylo,6) == 1220621-1a.html 1220621-1a.html # bug 1324661
+asserts-if(stylo,6) == 1220621-1b.html 1220621-1b.html # bug 1324661
+asserts-if(stylo,6) == 1220621-1c.html 1220621-1c.html # bug 1324661
+asserts-if(stylo,6) == 1220621-1d.html 1220621-1d.html # bug 1324661
+asserts-if(stylo,6) == 1220621-1e.html 1220621-1e.html # bug 1324661
+asserts-if(stylo,6) == 1220621-1f.html 1220621-1f.html # bug 1324661
+asserts-if(stylo,6) == 1220621-2a.html 1220621-2a.html # bug 1324661
+asserts-if(stylo,6) == 1220621-2b.html 1220621-2b.html # bug 1324661
--- a/mobile/android/chrome/content/geckoview.js
+++ b/mobile/android/chrome/content/geckoview.js
@@ -1,34 +1,56 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm", "Services");
-
 XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
   "resource://gre/modules/Messaging.jsm");
-XPCOMUtils.defineLazyGetter(this, "GlobalEventDispatcher",
-  () => EventDispatcher.instance);
 XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher",
   () => EventDispatcher.for(window));
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "View");
 
-// GeckoView module imports.
-XPCOMUtils.defineLazyModuleGetter(this, "GeckoViewContent",
-  "resource://gre/modules/GeckoViewContent.jsm");
+// Creates and manages GeckoView modules.
+// A module must extend GeckoViewModule.
+// Instantiate a module by calling
+//   add(<resource path>, <type name>)
+// and remove by calling
+//   remove(<type name>)
+var ModuleManager = {
+  init: function() {
+    this.browser = document.getElementById("content");
+    this.modules = {};
+  },
 
-var content;
+  add: function(resource, type, ...args) {
+    this.remove(type);
+    let scope = {};
+    Cu.import(resource, scope);
+    this.modules[type] = new scope[type](
+      window, this.browser, WindowEventDispatcher, ...args);
+  },
+
+  remove: function(type) {
+    if (!(type in this.modules)) {
+      return;
+    }
+    delete this.modules[type];
+  }
+};
 
 function startup() {
-  dump("zerdatime " + Date.now() + " - geckoview chrome startup finished.");
+  ModuleManager.init();
+  ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
+                    "GeckoViewContent");
+  ModuleManager.add("resource://gre/modules/GeckoViewNavigation.jsm",
+                    "GeckoViewNavigation");
 
-  content = new GeckoViewContent(window, document.getElementById("content"), WindowEventDispatcher);
+  dump("zerdatime " + Date.now() + " - geckoview chrome startup finished.");
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
@@ -42,17 +42,17 @@ public class GeckoView extends LayerView
     private static final String LOGTAG = "GeckoView";
 
     private static final boolean DEBUG = false;
 
     private final EventDispatcher eventDispatcher = new EventDispatcher();
 
     private ChromeDelegate mChromeDelegate;
     /* package */ ContentListener mContentListener;
-
+    /* package */ NavigationListener mNavigationListener;
     private InputConnectionListener mInputConnectionListener;
 
     protected boolean onAttachedToWindowCalled;
     protected String chromeURI;
     protected int screenId = 0; // default to the primary screen
 
     @WrapForJNI(dispatchTo = "proxy")
     protected static final class Window extends JNIObject {
@@ -111,30 +111,40 @@ public class GeckoView extends LayerView
                 }
             };
     }
 
     private class Listener implements BundleEventListener {
         /* package */ void registerListeners() {
             getEventDispatcher().registerUiThreadListener(this,
                 "GeckoView:DOMTitleChanged",
+                "GeckoView:LocationChange",
                 null);
         }
 
         @Override
         public void handleMessage(final String event, final GeckoBundle message,
                                   final EventCallback callback) {
             if (DEBUG) {
                 Log.d(LOGTAG, "handleMessage: event = " + event);
             }
 
             if ("GeckoView:DOMTitleChanged".equals(event)) {
                 if (mContentListener != null) {
                     mContentListener.onTitleChanged(GeckoView.this, message.getString("title"));
                 }
+            } else if ("GeckoView:LocationChange".equals(event)) {
+                if (mNavigationListener == null) {
+                    // We shouldn't be getting this event.
+                    eventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
+                } else {
+                    mNavigationListener.onLocationChange(GeckoView.this, message.getString("uri"));
+                    mNavigationListener.onCanGoBack(GeckoView.this, message.getBoolean("canGoBack"));
+                    mNavigationListener.onCanGoForward(GeckoView.this, message.getBoolean("canGoForward"));
+                }
             }
         }
     }
 
     protected Window window;
     private boolean stateSaved;
     private final Listener listener = new Listener();
 
@@ -261,32 +271,51 @@ public class GeckoView extends LayerView
 
         onAttachedToWindowCalled = false;
     }
 
     @WrapForJNI public static final int LOAD_DEFAULT = 0;
     @WrapForJNI public static final int LOAD_NEW_TAB = 1;
     @WrapForJNI public static final int LOAD_SWITCH_TAB = 2;
 
+    /**
+    * Load the given URI.
+    * @param uri The URI of the resource to load.
+    * @param flags The load flags (TODO).
+    */
     public void loadUri(String uri, int flags) {
         if (window == null) {
             throw new IllegalStateException("Not attached to window");
         }
 
         if (GeckoThread.isRunning()) {
             window.loadUri(uri, flags);
         }  else {
             GeckoThread.queueNativeCall(window, "loadUri", String.class, uri, flags);
         }
     }
 
     /* package */ void setInputConnectionListener(final InputConnectionListener icl) {
         mInputConnectionListener = icl;
     }
 
+    /**
+    * Go back in history.
+    */
+    public void goBack() {
+        eventDispatcher.dispatch("GeckoView:GoBack", null);
+    }
+
+    /**
+    * Go forward in history.
+    */
+    public void goForward() {
+        eventDispatcher.dispatch("GeckoView:GoForward", null);
+    }
+
     @Override
     public Handler getHandler() {
         if (mInputConnectionListener != null) {
             return mInputConnectionListener.getHandler(super.getHandler());
         }
         return super.getHandler();
     }
 
@@ -378,16 +407,42 @@ public class GeckoView extends LayerView
     /**
     * Get the content callback handler.
     * @return The current content callback handler.
     */
     public ContentListener getContentListener() {
         return mContentListener;
     }
 
+    /**
+    * Set the navigation callback handler.
+    * This will replace the current handler.
+    * @param navigation An implementation of NavigationListener.
+    */
+    public void setNavigationDelegate(NavigationListener listener) {
+        if (mNavigationListener == listener) {
+            return;
+        }
+        if (listener == null) {
+            eventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
+        } else if (mNavigationListener == null) {
+            eventDispatcher.dispatch("GeckoViewNavigation:Active", null);
+        }
+
+        mNavigationListener = listener;
+    }
+
+    /**
+    * Get the navigation callback handler.
+    * @return The current navigation callback handler.
+    */
+    public NavigationListener getNavigationListener() {
+        return mNavigationListener;
+    }
+
     public static void setGeckoInterface(final BaseGeckoInterface geckoInterface) {
         GeckoAppShell.setGeckoInterface(geckoInterface);
     }
 
     public static GeckoAppShell.GeckoInterface getGeckoInterface() {
         return GeckoAppShell.getGeckoInterface();
     }
 
@@ -474,9 +529,32 @@ public class GeckoView extends LayerView
         /**
         * A page title was discovered in the content or updated after the content
         * loaded.
         * @param view The GeckoView that initiated the callback.
         * @param title The title sent from the content.
         */
         public void onTitleChanged(GeckoView view, String title);
     }
+
+    public interface NavigationListener {
+        /**
+        * A view has started loading content from the network.
+        * @param view The GeckoView that initiated the callback.
+        * @param url The resource being loaded.
+        */
+        public void onLocationChange(GeckoView view, String url);
+
+        /**
+        * The view's ability to go back has changed.
+        * @param view The GeckoView that initiated the callback.
+        * @param canGoBack The new value for the ability.
+        */
+        public void onCanGoBack(GeckoView view, boolean canGoBack);
+
+        /**
+        * The view's ability to go forward has changed.
+        * @param view The GeckoView that initiated the callback.
+        * @param canGoForward The new value for the ability.
+        */
+        public void onCanGoForward(GeckoView view, boolean canGoForward);
+    }
 }
--- a/mobile/android/modules/GeckoViewContent.jsm
+++ b/mobile/android/modules/GeckoViewContent.jsm
@@ -3,48 +3,42 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["GeckoViewContent"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
+Cu.import("resource://gre/modules/GeckoViewModule.jsm");
+
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewContent");
 
 var DEBUG = false;
 
-class GeckoViewContent {
-  constructor(_window, _browser, _windowEventDispatcher) {
-    this.window = _window;
-    this.browser = _browser;
-    this.windowEventDispatcher = _windowEventDispatcher;
-
+class GeckoViewContent extends GeckoViewModule {
+  init() {
     this.window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = this;
 
     this.messageManager.loadFrameScript("chrome://browser/content/GeckoViewContent.js", true);
     this.messageManager.addMessageListener("GeckoView:DOMTitleChanged", this);
   }
 
-  get messageManager() {
-    return this.browser.messageManager;
-  }
-
   handleEvent(event) {
     if (DEBUG) {
       dump("handleEvent: event.type=" + event.type);
     }
   }
 
   // Message manager event handler.
   receiveMessage(msg) {
     if (DEBUG) {
       dump("receiveMessage " + msg.name);
     }
 
     switch (msg.name) {
       case "GeckoView:DOMTitleChanged":
-        this.windowEventDispatcher.sendRequest({ type: "GeckoView:DOMTitleChanged", title: msg.data.title });
+        this.eventDispatcher.sendRequest({ type: "GeckoView:DOMTitleChanged", title: msg.data.title });
         break;
     }
   }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/modules/GeckoViewModule.jsm
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["GeckoViewModule"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+class GeckoViewModule {
+  constructor(window, browser, eventDispatcher) {
+    this.window = window;
+    this.browser = browser;
+    this.eventDispatcher = eventDispatcher;
+
+    this.init();
+  }
+
+  init() {}
+
+  get messageManager() {
+    return this.browser.messageManager;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/modules/GeckoViewNavigation.jsm
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["GeckoViewNavigation"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/GeckoViewModule.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
+  "resource://gre/modules/Messaging.jsm");
+
+var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
+           .AndroidLog.d.bind(null, "ViewNavigation");
+
+function debug(msg) {
+  // dump(msg);
+}
+
+// Handles navigation requests between Gecko and a GeckoView.
+// Implements GeckoView.loadUri via openURI.
+// Handles GeckoView:GoBack and :GoForward requests dispatched by
+// GeckoView.goBack and .goForward.
+// Dispatches GeckoView:LocationChange to the GeckoView on location change when
+// active.
+// Can be activated and deactivated by GeckoViewNavigation:Active and :Inactive
+// events.
+class GeckoViewNavigation extends GeckoViewModule {
+  init() {
+    this.window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = this;
+
+    // We need to listen initially because the "GeckoViewNavigation:Active"
+    // event may be dispatched before this object is constructed.
+    this.registerProgressListener();
+
+    this.eventDispatcher.registerListener(this, [
+      "GeckoViewNavigation:Active",
+      "GeckoViewNavigation:Inactive",
+      "GeckoView:GoBack",
+      "GeckoView:GoForward",
+    ]);
+  }
+
+  // Bundle event handler.
+  onEvent(event, data, callback) {
+    debug("onEvent: event=" + event + ", data=" + JSON.stringify(data));
+
+    switch (event) {
+      case "GeckoViewNavigation:Active":
+        this.registerProgressListener();
+        break;
+      case "GeckoViewNavigation:Inactive":
+        this.unregisterProgressListener();
+        break;
+      case "GeckoView:GoBack":
+        this.browser.goBack();
+        break;
+      case "GeckoView:GoForward":
+        this.browser.goForward();
+        break;
+    }
+  }
+
+  // Message manager event handler.
+  receiveMessage(msg) {
+    debug("receiveMessage " + msg.name);
+  }
+
+  // nsIBrowserDOMWindow::openURI implementation.
+  openURI(uri, opener, where, flags) {
+    debug("openURI: uri.spec=" + uri.spec);
+    // nsIWebNavigation::loadURI(URI, loadFlags, referrer, postData, headers).
+    this.browser.loadURI(uri.spec, null, null, null);
+  }
+
+  // nsIBrowserDOMWindow::canClose implementation.
+  canClose() {
+    debug("canClose");
+    return false;
+  }
+
+  registerProgressListener() {
+    debug("registerProgressListener");
+    let flags = Ci.nsIWebProgress.NOTIFY_LOCATION;
+    this.progressFilter =
+      Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
+      .createInstance(Ci.nsIWebProgress);
+    this.progressFilter.addProgressListener(this, flags);
+    this.browser.addProgressListener(this.progressFilter, flags);
+  }
+
+  unregisterProgressListener() {
+    debug("unregisterProgressListener");
+    if (!this.progressFilter) {
+      return;
+    }
+    this.progressFilter.removeProgressListener(this);
+    this.browser.removeProgressListener(this.progressFilter);
+  }
+
+  // WebProgress event handler.
+  onLocationChange(webProgress, request, locationURI, flags) {
+    debug("onLocationChange");
+
+    let fixedURI = locationURI;
+
+    try {
+      fixedURI = URIFixup.createExposableURI(locationURI);
+    } catch (ex) { }
+
+    let message = {
+      type: "GeckoView:LocationChange",
+      uri: fixedURI.spec,
+      canGoBack: this.browser.canGoBack,
+      canGoForward: this.browser.canGoForward,
+    };
+
+    debug("dispatch " + JSON.stringify(message));
+
+    this.eventDispatcher.sendRequest(message);
+  }
+}
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -28,10 +28,12 @@ EXTRA_JS_MODULES += [
     'SharedPreferences.jsm',
     'Snackbars.jsm',
     'SSLExceptions.jsm',
     'WebsiteMetadata.jsm'
 ]
 
 # GeckoView-sepcific modules added separately.
 EXTRA_JS_MODULES += [
-    'GeckoViewContent.jsm'
+    'GeckoViewContent.jsm',
+    'GeckoViewModule.jsm',
+    'GeckoViewNavigation.jsm'
 ]
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -772,27 +772,34 @@ nsJARChannel::AsyncOpen(nsIStreamListene
     mListenerContext = ctx;
     mIsPending = true;
 
     nsresult rv = LookupFile(true);
     if (NS_FAILED(rv)) {
         mIsPending = false;
         mListenerContext = nullptr;
         mListener = nullptr;
+        mCallbacks = nullptr;
+        mProgressSink = nullptr;
         return rv;
     }
 
     nsCOMPtr<nsIChannel> channel;
 
     if (!mJarFile) {
         // Not a local file...
 
         // Check preferences to see if all remote jar support should be disabled
         if (mBlockRemoteFiles) {
             mIsUnsafe = true;
+            mIsPending = false;
+            mListenerContext = nullptr;
+            mListener = nullptr;
+            mCallbacks = nullptr;
+            mProgressSink = nullptr;
             return NS_ERROR_UNSAFE_CONTENT_TYPE;
         }
 
         static bool reportedRemoteJAR = false;
         if (!reportedRemoteJAR) {
             reportedRemoteJAR = true;
             Telemetry::Accumulate(Telemetry::REMOTE_JAR_PROTOCOL_USED, 1);
         }
@@ -806,16 +813,18 @@ nsJARChannel::AsyncOpen(nsIStreamListene
                                    mLoadInfo,
                                    mLoadGroup,
                                    mCallbacks,
                                    loadFlags);
         if (NS_FAILED(rv)) {
             mIsPending = false;
             mListenerContext = nullptr;
             mListener = nullptr;
+            mCallbacks = nullptr;
+            mProgressSink = nullptr;
             return rv;
         }
         if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
             rv = channel->AsyncOpen2(downloader);
         }
         else {
             rv = channel->AsyncOpen(downloader, nullptr);
         }
@@ -823,33 +832,43 @@ nsJARChannel::AsyncOpen(nsIStreamListene
     else {
         rv = OpenLocalFile();
     }
 
     if (NS_FAILED(rv)) {
         mIsPending = false;
         mListenerContext = nullptr;
         mListener = nullptr;
+        mCallbacks = nullptr;
+        mProgressSink = nullptr;
         return rv;
     }
 
     if (mLoadGroup)
         mLoadGroup->AddRequest(this, nullptr);
 
     mOpened = true;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJARChannel::AsyncOpen2(nsIStreamListener *aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+      mIsPending = false;
+      mListenerContext = nullptr;
+      mListener = nullptr;
+      mCallbacks = nullptr;
+      mProgressSink = nullptr;
+      return rv;
+  }
+
   return AsyncOpen(listener, nullptr);
 }
 
 //-----------------------------------------------------------------------------
 // nsIJARChannel
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 nsJARChannel::GetIsUnsafe(bool *isUnsafe)
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -696,17 +696,20 @@ nsBaseChannel::AsyncOpen(nsIStreamListen
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::AsyncOpen2(nsIStreamListener *aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mCallbacks = nullptr;
+    return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsITransportEventSink
 
 NS_IMETHODIMP
 nsBaseChannel::OnTransportStatus(nsITransport *transport, nsresult status,
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -1407,17 +1407,17 @@ nsFtpState::R_pasv() {
         if (*ptr++ != delim || *ptr != ')')
             return FTP_ERROR;
     } else {
         // The returned address string can be of the form
         // (xxx,xxx,xxx,xxx,ppp,ppp) or
         //  xxx,xxx,xxx,xxx,ppp,ppp (without parens)
         int32_t h0, h1, h2, h3, p0, p1;
 
-        uint32_t fields = 0;
+        int32_t fields = 0;
         // First try with parens
         while (*ptr && *ptr != '(')
             ++ptr;
         if (*ptr) {
             ++ptr;
             fields = PR_sscanf(ptr, 
                                "%ld,%ld,%ld,%ld,%ld,%ld",
                                &h0, &h1, &h2, &h3, &p0, &p1);
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -641,16 +641,17 @@ WyciwygChannelChild::AsyncOpen(nsIStream
     mLoadGroup->AddRequest(this, nullptr);
   }
 
   URIParams originalURI;
   SerializeURI(mOriginalURI, originalURI);
 
   mozilla::dom::TabChild* tabChild = GetTabChild(this);
   if (MissingRequiredTabChild(tabChild, "wyciwyg")) {
+    mCallbacks = nullptr;
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   PBrowserOrId browser = static_cast<ContentChild*>(Manager()->Manager())
                          ->GetBrowserOrId(tabChild);
 
   SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), browser);
 
@@ -660,17 +661,20 @@ WyciwygChannelChild::AsyncOpen(nsIStream
   return NS_OK;
 }
 
 NS_IMETHODIMP
 WyciwygChannelChild::AsyncOpen2(nsIStreamListener *aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mCallbacks = nullptr;
+    return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 //-----------------------------------------------------------------------------
 // nsIWyciwygChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
@@ -441,16 +441,17 @@ nsWyciwygChannel::AsyncOpen(nsIStreamLis
   // mIsPending set to true since OnCacheEntryAvailable may be called
   // synchronously and fails when mIsPending found false.
   mIsPending = true;
   nsresult rv = OpenCacheEntry(mURI, nsICacheStorage::OPEN_READONLY |
                                      nsICacheStorage::CHECK_MULTITHREADED);
   if (NS_FAILED(rv)) {
     LOG(("nsWyciwygChannel::OpenCacheEntry failed [rv=%x]\n", rv));
     mIsPending = false;
+    mCallbacks = nullptr;
     return rv;
   }
 
   // There is no code path that would invoke the listener sooner than
   // we get to this line in case OnCacheEntryAvailable is invoked
   // synchronously.
   mListener = listener;
   mListenerContext = ctx;
@@ -461,17 +462,21 @@ nsWyciwygChannel::AsyncOpen(nsIStreamLis
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWyciwygChannel::AsyncOpen2(nsIStreamListener *aListener)
 {
   nsCOMPtr<nsIStreamListener> listener = aListener;
   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    mIsPending = false;
+    mCallbacks = nullptr;
+    return rv;
+  }
   return AsyncOpen(listener, nullptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // nsIWyciwygChannel
 //////////////////////////////////////////////////////////////////////////////
 
 nsresult
--- a/python/mozbuild/mozbuild/compilation/database.py
+++ b/python/mozbuild/mozbuild/compilation/database.py
@@ -113,20 +113,23 @@ class CompileDBBackend(CommonBackend):
 
         return True
 
     def consume_finished(self):
         CommonBackend.consume_finished(self)
 
         db = []
 
-        for (directory, filename), cmd in self._db.iteritems():
+        for (directory, filename, unified), cmd in self._db.iteritems():
             env = self._envs[directory]
             cmd = list(cmd)
-            cmd.append(filename)
+            if unified is None:
+                cmd.append(filename)
+            else:
+                cmd.append(unified)
             local_extra = list(self._extra_includes[directory])
             if directory not in self._gyp_dirs:
                 for var in (
                     'NSPR_CFLAGS',
                     'NSS_CFLAGS',
                     'MOZ_JPEG_CFLAGS',
                     'MOZ_PNG_CFLAGS',
                     'MOZ_ZLIB_CFLAGS',
@@ -168,16 +171,19 @@ class CompileDBBackend(CommonBackend):
             json.dump(db, jsonout, indent=0)
 
     def _process_unified_sources(self, obj):
         # For unified sources, only include the unified source file.
         # Note that unified sources are never used for host sources.
         for f in obj.unified_source_mapping:
             self._build_db_line(obj.objdir, obj.relativedir, obj.config, f[0],
                                 obj.canonical_suffix)
+            for entry in f[1]:
+                self._build_db_line(obj.objdir, obj.relativedir, obj.config,
+                                    entry, obj.canonical_suffix, unified=f[0])
 
     def _handle_idl_manager(self, idl_manager):
         pass
 
     def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources,
                              unified_ipdl_cppsrcs_mapping):
         for f in unified_ipdl_cppsrcs_mapping:
             self._build_db_line(ipdl_dir, None, self.environment, f[0],
@@ -199,20 +205,21 @@ class CompileDBBackend(CommonBackend):
 
     CFLAGS = {
         '.c': 'CFLAGS',
         '.cpp': 'CXXFLAGS',
         '.m': 'CFLAGS',
         '.mm': 'CXXFLAGS',
     }
 
-    def _build_db_line(self, objdir, reldir, cenv, filename, canonical_suffix):
+    def _build_db_line(self, objdir, reldir, cenv, filename,
+                       canonical_suffix, unified=None):
         if canonical_suffix not in self.COMPILERS:
             return
-        db = self._db.setdefault((objdir, filename),
+        db = self._db.setdefault((objdir, filename, unified),
             cenv.substs[self.COMPILERS[canonical_suffix]].split() +
             ['-o', '/dev/null', '-c'])
         reldir = reldir or mozpath.relpath(objdir, cenv.topobjdir)
 
         def append_var(name):
             value = cenv.substs.get(name)
             if not value:
                 return
--- a/taskcluster/ci/toolchain/linux.yml
+++ b/taskcluster/ci/toolchain/linux.yml
@@ -127,8 +127,28 @@ linux64-hfsplus/opt:
         implementation: docker-worker
         docker-image: {in-tree: desktop-build}
         max-run-time: 36000
     when:
         files-changed:
             - 'build/unix/build-hfsplus/**'
             - 'taskcluster/scripts/misc/build-hfsplus-linux.sh'
             - 'taskcluster/taskgraph/transforms/job/toolchain.py'
+
+linux64-libdmg/opt:
+    description: "libdmg-hfsplus toolchain build"
+    treeherder:
+        kind: build
+        platform: linux64/opt
+        symbol: Cc(libdmg)
+        tier: 1
+    run:
+        using: toolchain-script
+        script: build-libdmg-hfsplus.sh
+    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
+    worker:
+        implementation: docker-worker
+        docker-image: {in-tree: desktop-build}
+        max-run-time: 36000
+    when:
+        files-changed:
+            - 'taskcluster/scripts/misc/build-libdmg-hfsplus.sh'
+            - 'taskcluster/taskgraph/transforms/job/toolchain.py'
new file mode 100755
--- /dev/null
+++ b/taskcluster/scripts/misc/build-libdmg-hfsplus.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+set -x -e -v
+
+# This script is for building libdmg-hfsplus to get the `dmg` and `hfsplus`
+# tools for producing DMG archives on Linux.
+
+WORKSPACE=$HOME/workspace
+STAGE=$WORKSPACE/dmg
+UPLOAD_DIR=$WORKSPACE/artifacts
+
+# There's no single well-maintained fork of libdmg-hfsplus, but this
+# branch currently has some fixes we need.
+: LIBDMG_REPOSITORY    ${LIBDMG_REPOSITORY:=https://github.com/andreas56/libdmg-hfsplus}
+# This is the current head of the `from_zarvox` branch.
+: LIBDMG_REV           ${LIBDMG_REV:=81dd75fd1549b24bf8af9736ac25518b367e6b63}
+
+mkdir -p $UPLOAD_DIR $STAGE
+
+cd $WORKSPACE
+tc-vcs checkout --force-clone libdmg-hfsplus $LIBDMG_REPOSITORY $LIBDMG_REPOSITORY $LIBDMG_REV
+cd libdmg-hfsplus
+# Make a source archive
+git archive ${LIBDMG_REV} | xz > $UPLOAD_DIR/libdmg-hfsplus.tar.xz
+cmake .
+make -j$(getconf _NPROCESSORS_ONLN)
+
+# We only need the dmg and hfsplus tools.
+strip dmg/dmg hfs/hfsplus
+cp dmg/dmg hfs/hfsplus $STAGE
+
+cat >$STAGE/README<<EOF
+Built from ${LIBDMG_REPOSITORY} rev `git rev-parse ${LIBDMG_REV}`.
+Source is available in tooltool, digest `sha512sum $UPLOAD_DIR/libdmg-hfsplus.tar.xz`.
+EOF
+tar cf - -C $WORKSPACE `basename $STAGE` | xz > $UPLOAD_DIR/dmg.tar.xz
--- a/testing/gtest/rungtests.py
+++ b/testing/gtest/rungtests.py
@@ -15,17 +15,17 @@ import mozinfo
 import mozlog
 import mozprocess
 from mozrunner.utils import get_stack_fixer_function
 
 log = mozlog.unstructured.getLogger('gtest')
 
 class GTests(object):
     # Time (seconds) to wait for test process to complete
-    TEST_PROC_TIMEOUT = 1200
+    TEST_PROC_TIMEOUT = 1800
     # Time (seconds) in which process will be killed if it produces no output.
     TEST_PROC_NO_OUTPUT_TIMEOUT = 300
 
     def run_gtest(self, prog, xre_path, cwd, symbols_path=None,
                   utility_path=None):
         """
         Run a single C++ unit test program.
 
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -51736,16 +51736,26 @@
      {}
     ]
    ],
    "html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt": [
     [
      {}
     ]
    ],
+   "html/semantics/embedded-content/resources/should-load.html": [
+    [
+     {}
+    ]
+   ],
+   "html/semantics/embedded-content/resources/should-not-load.html": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/svg/.gitkeep": [
     [
      {}
     ]
    ],
    "html/semantics/embedded-content/the-area-element/.gitkeep": [
     [
      {}
@@ -60026,21 +60036,16 @@
      {}
     ]
    ],
    "service-workers/service-worker/resources/frame-for-getregistrations.html": [
     [
      {}
     ]
    ],
-   "service-workers/service-worker/resources/get-host-info.sub.js": [
-    [
-     {}
-    ]
-   ],
    "service-workers/service-worker/resources/indexeddb-worker.js": [
     [
      {}
     ]
    ],
    "service-workers/service-worker/resources/install-event-type-worker.js": [
     [
      {}
@@ -92186,16 +92191,22 @@
     ]
    ],
    "html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html": [
     [
      "/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html",
      {}
     ]
    ],
+   "html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html": [
+    [
+     "/html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html",
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/the-embed-element/embed-in-object-fallback.html": [
     [
      "/html/semantics/embedded-content/the-embed-element/embed-in-object-fallback.html",
      {}
     ]
    ],
    "html/semantics/embedded-content/the-embed-element/historical.html": [
     [
@@ -92446,16 +92457,28 @@
     ]
    ],
    "html/semantics/embedded-content/the-object-element/object-handler.html": [
     [
      "/html/semantics/embedded-content/the-object-element/object-handler.html",
      {}
     ]
    ],
+   "html/semantics/embedded-content/the-object-element/object-ignored-in-media-element.html": [
+    [
+     "/html/semantics/embedded-content/the-object-element/object-ignored-in-media-element.html",
+     {}
+    ]
+   ],
+   "html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html": [
+    [
+     "/html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html",
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/the-object-element/usemap-casing.html": [
     [
      "/html/semantics/embedded-content/the-object-element/usemap-casing.html",
      {}
     ]
    ],
    "html/semantics/embedded-content/the-video-element/video-tabindex.html": [
     [
@@ -138456,17 +138479,17 @@
    "22fd0012458685b4bce13e5f15cc650726482f26",
    "support"
   ],
   "common/form-submission.py": [
    "079aedef390e883d1a1815238f7a04c058dfb9bf",
    "support"
   ],
   "common/get-host-info.sub.js": [
-   "4feb5667d2093736391c71b8f0224f6d868c8cf4",
+   "eade85ef5ac0eb56ba5ecf8057ab7a4ea05a22e1",
    "support"
   ],
   "common/large.py": [
    "19d0b8d5fec34f080c37f1b1b837ea0c2401ad82",
    "support"
   ],
   "common/media.js": [
    "a575b8135e6ddb1501fc2a082d7544ee86011b7d",
@@ -173839,16 +173862,24 @@
   "html/semantics/embedded-content/media-elements/video_volume_silent-manual.html": [
    "1a49e63bead4193320af13bb6deaf130ff4397eb",
    "manual"
   ],
   "html/semantics/embedded-content/media-elements/volume_nonfinite.html": [
    "8840fa9072d9367f358721ed757bd3d23dd64967",
    "testharness"
   ],
+  "html/semantics/embedded-content/resources/should-load.html": [
+   "7cc95b9b2eb8c3f2d89278d22db271b9ae42e107",
+   "support"
+  ],
+  "html/semantics/embedded-content/resources/should-not-load.html": [
+   "a1657fc9e655ad0a30ced47a1412b6c34ba964b9",
+   "support"
+  ],
   "html/semantics/embedded-content/svg/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "html/semantics/embedded-content/the-area-element/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
@@ -174520,17 +174551,21 @@
    "e6611c20a50884639a51010836bb2b1bdfb9cab8",
    "testharness"
   ],
   "html/semantics/embedded-content/the-embed-element/embed-iframe.html": [
    "96a043e993bccf1896f5a19960a1bff5dce0e79d",
    "support"
   ],
   "html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html": [
-   "94a08a7a5b5ec5c26f1974d5e5d8b4381a60baf5",
+   "cb57cbe52e4f586006461b8eae6bc233b5ed5ad5",
+   "testharness"
+  ],
+  "html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html": [
+   "a7da1fefb2403084205bf1ead77b422e69dc33b6",
    "testharness"
   ],
   "html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-subdocument.html": [
    "1b60c4e5c8868fe87553b78047e711d63702a673",
    "support"
   ],
   "html/semantics/embedded-content/the-embed-element/embed-in-object-fallback.html": [
    "db06f508b6f178c4e0deb19b6820df02b058bd32",
@@ -174839,16 +174874,24 @@
   "html/semantics/embedded-content/the-object-element/object-fallback.html": [
    "7bb46b36376a1afd004cf0537bdedd975088b2f2",
    "testharness"
   ],
   "html/semantics/embedded-content/the-object-element/object-handler.html": [
    "bf051d12a045698b2f9c3870ad4236f65bb85f51",
    "testharness"
   ],
+  "html/semantics/embedded-content/the-object-element/object-ignored-in-media-element.html": [
+   "62a6c079bc00ae6ebeca363fd42d8701c4791222",
+   "testharness"
+  ],
+  "html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html": [
+   "a5bb885111ac7ea02241957ee7233491c2277516",
+   "testharness"
+  ],
   "html/semantics/embedded-content/the-object-element/test0.html": [
    "04319dea2f1e0b00e8db1703f2072ec22f1a82ad",
    "support"
   ],
   "html/semantics/embedded-content/the-object-element/test1.html": [
    "c083a73f9b0f3d2f4a3796f113144227e6567d0f",
    "support"
   ],
@@ -177840,17 +177883,17 @@
    "febb81c38f530c81d9e9837df2c6d603225ecfd1",
    "testharness"
   ],
   "html/webappapis/idle-callbacks/callback-timeout.html": [
    "ba76964575cdf9b433f26c8a5d7a8183ab5c16e9",
    "testharness"
   ],
   "html/webappapis/idle-callbacks/cancel-invoked.html": [
-   "d0128b4d4b805a58926ad895f35b341321cf56ec",
+   "30787d765fa435c1392bd852559042bf3c2e2553",
    "testharness"
   ],
   "html/webappapis/idle-callbacks/idlharness.html": [
    "520ee58982b43875f3caa08d7f46b9c6311be0b6",
    "testharness"
   ],
   "html/webappapis/scripting/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
@@ -198248,25 +198291,25 @@
    "72da19e038b6ab32ea04a0e91d117bc67d25a301",
    "testharness"
   ],
   "service-workers/service-worker/claim-using-registration.https.html": [
    "fb56cc3ae802669bb7898e76ac55e75ba6ac1441",
    "testharness"
   ],
   "service-workers/service-worker/client-navigate.https.html": [
-   "79904ed11a3c53c4559c8f44603fcc1cf0a05844",
+   "e0c704605ec008a29662e1804d512284899ddd6f",
    "testharness"
   ],
   "service-workers/service-worker/clients-get-cross-origin.https.html": [
-   "7e9d0cd022aa70a0f38b2f15f05919e9ff185728",
+   "21ed1eab21bb6f0b342895c8185ecb92afe93b79",
    "testharness"
   ],
   "service-workers/service-worker/clients-get.https.html": [
-   "54c7ac17c93881644c202dbacf36de2fc507a3f5",
+   "32ccf7734a7d0d40205c4fd30b393b175e6507bd",
    "testharness"
   ],
   "service-workers/service-worker/clients-matchall-client-types.https.html": [
    "576b4306b0976071ec1c7e085e016b99b5ab12cc",
    "testharness"
   ],
   "service-workers/service-worker/clients-matchall-include-uncontrolled.https.html": [
    "f3fbc439d4352a9c781290d80373fce8ff3e7c40",
@@ -198292,113 +198335,113 @@
    "fe5c4595f528af34d83a64bae1fe94a14483cde5",
    "testharness"
   ],
   "service-workers/service-worker/extendable-event-waituntil.https.html": [
    "9232c93bc437aa6c32a2a82db03e622b96d23395",
    "testharness"
   ],
   "service-workers/service-worker/fetch-canvas-tainting-cache.https.html": [
-   "3401c0848a63c619c618d4a2cf3c59f3928ff162",
+   "b3f8375bc412c99099ac886673fd80f6cb0a312b",
    "testharness"
   ],
   "service-workers/service-worker/fetch-canvas-tainting.https.html": [
-   "1f2d87f214450395472fe3dffcb2783e71ec0d52",
+   "9c2e160f95d2915a961bd7da840ac53779c9387d",
    "testharness"
   ],
   "service-workers/service-worker/fetch-cors-xhr.https.html": [
-   "5a35a77eb5575e181aee035ffa103f51152fda54",
+   "448c071ddeaaaf828800d8fad20d8ce672e56590",
    "testharness"
   ],
   "service-workers/service-worker/fetch-csp.https.html": [
-   "b9ff203833b7af8b0181eea9a1778b9e4d20ccb1",
+   "97fff975592937acda3e8f363685dc9a835c12be",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event-after-navigation-within-page.https.html": [
    "3071523401bd9147ac4dab89361e07de99babc9c",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event-async-respond-with.https.html": [
    "6ea721f98b2d145eeeb07b762901b9cfa1b51fbd",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event-network-error.https.html": [
    "ee1cd2ed2c3204af53422116289c558f5eff68d9",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event-redirect.https.html": [
-   "5d4efd3504c37f5b728eef4941266b3d1d8842e7",
+   "e322139b14149fe9b3f3aff76a9af8a58437e715",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html": [
    "2feaa5022ee31fb980f97075d932b0d87d6efe75",
    "testharness"
   ],
   "service-workers/service-worker/fetch-event.https.html": [
-   "9197ebb50014905e02645c5dc71d467be0e7604c",
+   "ce7785af8286cd371cc08092903c333332deb862",
    "testharness"
   ],
   "service-workers/service-worker/fetch-frame-resource.https.html": [
-   "e5996d90c4c383eda2947cc2bc39e734448b3bde",
+   "77709ff94cfaeec0b01e157714244d1b568c6b18",
    "testharness"
   ],
   "service-workers/service-worker/fetch-header-visibility.https.html": [
-   "c12941b5e391a520b20f227fd515089ac922f50e",
+   "054a581d2585cf34e4f0626870c2a093d53dc09b",
    "testharness"
   ],
   "service-workers/service-worker/fetch-mixed-content-to-inscope.https.html": [
-   "16bf962ab092624da480de9a75ac767cdc00c2c7",
+   "e3035bdf8cec65bb0322b5dfce10a3a827bd415e",
    "testharness"
   ],
   "service-workers/service-worker/fetch-mixed-content-to-outscope.https.html": [
-   "431348eba25f6db93684b39dcdc9eb29071e27f1",
+   "45a83eeeb922301fc399a4808bb4d1014a541733",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-css-base-url.https.html": [
-   "e9e6bc4ecfe69bf5f1c8fa718f15fe19ca612143",
+   "01a5220ff2abe5735d7b03c2ee3ccbe21c9a260e",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-css-images.https.html": [
-   "14c5ad1b9e3971c994ec9134989f03ff4a01962c",
+   "ca776bff1f106f9a1e2dfe4d25ff3618d99758b7",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-fallback.https.html": [
-   "11b3e5fe92d27ea1058f725a904a4ed8e448a2dd",
+   "60dcb3a4c3b3ca2e79adfc7b779724cbe3ffa1c4",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-no-freshness-headers.https.html": [
    "9631947d3cec78547bd4666b8ca970d037648cc8",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-redirect.https.html": [
-   "ffe217a363c6db265aaa2f45661bdc3a4289c9a0",
+   "e0c2c7752674bd8bb65ce09bc1d49b2f5d458d54",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-resources.https.html": [
-   "6676e514ba04f2759346eaa94f1c87c8290e44cd",
+   "5ae2d1ae4eec846002635d6ff8d9d7c9a2aebd3f",
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-xhr.https.html": [
-   "760037db448b32b146c51ba8e7c453dd9c734a6e",
+   "840aafe30e5a0c8129c05e3b311084b8c00267a6",
    "testharness"
   ],
   "service-workers/service-worker/fetch-response-xhr.https.html": [
-   "b6fa000865a6961afabb592a09bbf686ee4302df",
+   "6d50c69d78a1eb077108209b94fdf0efe540883d",
    "testharness"
   ],
   "service-workers/service-worker/fetch-waits-for-activate.https.html": [
-   "9be9d969099e27be5edc15f6014ac2f06f81674c",
+   "04eeedc3f074aff32281a438acda62b7a6d86e2d",
    "testharness"
   ],
   "service-workers/service-worker/getregistration.https.html": [
    "989c30567eb1dd650dc7e2bf807e18961c991087",
    "testharness"
   ],
   "service-workers/service-worker/getregistrations.https.html": [
-   "8b66990c80dfb44f43a053829005dbca2264106c",
+   "d76c66c08bd5c1addbdb149447f2268ac52ffcb2",
    "testharness"
   ],
   "service-workers/service-worker/indexeddb.https.html": [
    "6b25a37ebe79c60e3645a1006e61f1f2c272ce86",
    "testharness"
   ],
   "service-workers/service-worker/install-event-type.https.html": [
    "55175d94a5d90a030c03d598c079455bb93c71c8",
@@ -198408,37 +198451,37 @@
    "dda1a1967e6e0be64b9bd2198a08aa0429e185ff",
    "testharness"
   ],
   "service-workers/service-worker/interfaces.https.html": [
    "9153cc6536203170ba8d2189d7646200a1ded72e",
    "testharness"
   ],
   "service-workers/service-worker/invalid-blobtype.https.html": [
-   "ff9dca8c16a3635b74a7dfbff8ae5061b89a86e5",
+   "ca29ab7c214d2fa4973cf7be633a7fb8507ae897",
    "testharness"
   ],
   "service-workers/service-worker/invalid-header.https.html": [
-   "559a924fa530f4a4082c306d5821d88f9d2ba064",
+   "393c3b3c393b58e74f82affecdd06c4e7be1787a",
    "testharness"
   ],
   "service-workers/service-worker/multiple-register.https.html": [
    "fe3fe5f2c11f721c8686553587534c2679f670ed",
    "testharness"
   ],
   "service-workers/service-worker/multiple-update.https.html": [
    "1cb6912164a02808f455538ea292f288b2f12ace",
    "testharness"
   ],
   "service-workers/service-worker/navigate-window.https.html": [
-   "fe503981bd965d0d424f4c2e404ab940a2d6db0b",
+   "669507683c98d99aa5dcfbddd71c23f8464b7c21",
    "testharness"
   ],
   "service-workers/service-worker/navigation-redirect.https.html": [
-   "919eb3d5d1203626cc6e23a5200033cb8a756347",
+   "7d9f8501624e1832170d427657d6dbf19253c989",
    "testharness"
   ],
   "service-workers/service-worker/onactivate-script-error.https.html": [
    "7c397361b27e4c4d90a84d92b16593ac40d443a9",
    "testharness"
   ],
   "service-workers/service-worker/oninstall-script-error.https.html": [
    "0497bf37f0e3b55a6a4745cae2ec700b6f963fd3",
@@ -198448,33 +198491,33 @@
    "23d9e3dc830b83370875387cd5d6e1d5e913452f",
    "testharness"
   ],
   "service-workers/service-worker/postmessage-msgport-to-client.https.html": [
    "21ae7fb96321dc75e7063c27b7e6838e6b9ff6c6",
    "testharness"
   ],
   "service-workers/service-worker/postmessage-to-client.https.html": [
-   "8a96689891c9e49456c48e47a09405fe2edb4cce",
+   "4f91d302091df45ca72567c2cedc1584ad9045a9",
    "testharness"
   ],
   "service-workers/service-worker/postmessage.https.html": [
    "5f713ca30ab26d1ee7f3e763911aeb41fcb660bb",
    "testharness"
   ],
   "service-workers/service-worker/ready.https.html": [
    "77199b966f0ef2d05fddaf33b975cc3e7c593546",
    "testharness"
   ],
   "service-workers/service-worker/referer.https.html": [
-   "3a78997f47e3f53bcb94f871032b0d6099361f10",
+   "a9e4073192f5b69984624ad7376ec7787101dfea",
    "testharness"
   ],
   "service-workers/service-worker/register-closed-window.https.html": [
-   "bc6e9bb358fdd6b66d49eaf99e9d5f2e111c874b",
+   "2e24c6664881449ab67f04b860a701c8b8ef93c1",
    "testharness"
   ],
   "service-workers/service-worker/register-default-scope.https.html": [
    "864f5435fc40124dbe2c1ffb0e1942fee58228d2",
    "testharness"
   ],
   "service-workers/service-worker/register-same-scope-different-script-url.https.html": [
    "7c32948fe5ff738a38b08ff2d2497ddb63f0a8ef",
@@ -198512,17 +198555,17 @@
    "785a18ac3c8001034f583a8e97195aa47093bd0d",
    "testharness"
   ],
   "service-workers/service-worker/request-end-to-end.https.html": [
    "751848110fcccb77528114424511fd53857e38ff",
    "testharness"
   ],
   "service-workers/service-worker/resource-timing.https.html": [
-   "003956c17576fa4e0f1c7a5cc7aaf6bb211510ff",
+   "587060940cb25ff8072fa83cb41d538a73320ca6",
    "testharness"
   ],
   "service-workers/service-worker/resources/404.py": [
    "567d0a7de3ef54adaa8339bb04632a2ecfcc57a5",
    "support"
   ],
   "service-workers/service-worker/resources/appcache-ordering.install.html": [
    "2fbe9f464383783774f08276b8e2cc7103fee83c",
@@ -198548,29 +198591,29 @@
    "2839599adca9049d31085e50504623576dc81643",
    "support"
   ],
   "service-workers/service-worker/resources/client-navigate-frame.html": [
    "ecad40948e5d00ca737ea91b702ebbecc268e53b",
    "support"
   ],
   "service-workers/service-worker/resources/client-navigate-worker.js": [
-   "28442dc3f2bb1b2761a17ae599b1300c50327a56",
+   "6b277e1dcde40babec32046f9e637a47830bf29b",
    "support"
   ],
   "service-workers/service-worker/resources/client-navigated-frame.html": [
    "efb9dd2b3468305396a3767fc780d07525bd8e61",
    "support"
   ],
   "service-workers/service-worker/resources/clients-get-frame.html": [
    "2a34fdfb584674ef7b534fb91b313fc630ac0ffa",
    "support"
   ],
   "service-workers/service-worker/resources/clients-get-other-origin.html": [
-   "2bcea64745be9b6aab7d91eb2c54774b8110bb6f",
+   "1b495621d4024d18579626cc5fd6049789bce115",
    "support"
   ],
   "service-workers/service-worker/resources/clients-get-worker.js": [
    "cab646738d3d9662756dcd337718ae02ea234313",
    "support"
   ],
   "service-workers/service-worker/resources/clients-matchall-client-types-iframe.html": [
    "3c8866699d99cfaf61c52ca7a5dafc058a8c349d",
@@ -198584,17 +198627,17 @@
    "e204fdb53a9ae84f1b463f4655d62d1182d77cd5",
    "support"
   ],
   "service-workers/service-worker/resources/dummy-shared-worker-interceptor.js": [
    "620e50059fabfdd4b5c61dbb3ed2d8dca872b9bf",
    "support"
   ],
   "service-workers/service-worker/resources/dummy-worker-interceptor.js": [
-   "5bad22ca85e049d9ccd1228cef98f58bbf21a16a",
+   "f631d35c4eed6be4a8e6d2cdc5258ac0b169e177",
    "support"
   ],
   "service-workers/service-worker/resources/dummy-worker-script.py": [
    "1cde5ac271154715f3e06139e594e6676746cfbe",
    "support"
   ],
   "service-workers/service-worker/resources/dummy.html": [
    "b15855240cf7dbc5df4ee30a544d7ff94935d146",
@@ -198640,25 +198683,25 @@
    "7603f015f115df4bc04e6c1b10d0d0b0abcd3f2d",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-access-control.py": [
    "fb2235ce343b51e958f73f7fc8d7ab7dbcc8f71e",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html": [
-   "238c7a5082169f5a96160aa298d0450c9e1ed60b",
+   "04c234d3cc210d24962ce2b7cbbefcbd16d335e8",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-cors-xhr-iframe.html": [
-   "a95c7def61681468026031380425f03d3020d66a",
+   "bbed4c0dcae12d91bcda4241103e674a6ffc73b1",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-csp-iframe.html": [
-   "b84cb08bd5e4504dc5509f78ca3a4c07be702814",
+   "0c82ccc773dc644bac0cef39faadcb3280c0c6f4",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-csp-iframe.html.sub.headers": [
    "fba766f6fb555fbd8fde44e8c71ab26d3191e85f",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-event-after-navigation-within-page-iframe.html": [
    "f13e8a4322df20dba937c2658d2c9d9d354a34c2",
@@ -198684,41 +198727,41 @@
    "900fd1c2080fbb386589f7d6ee52c49da9d4fcb8",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-event-test-worker.js": [
    "ca79da139169762737411cb6cffb66b55b901d04",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-header-visibility-iframe.html": [
-   "99c91098d8df9e0b840699770d240bb0aa2ee715",
+   "f5975491b4c516cdfc62eaaba019ab546451d6e7",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html": [
-   "7cf39eebde4a25c1af8690c28db50ef0a4b147cd",
+   "7485fa9c96fbbc4af9de634e0738957dd6ab2aa0",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html": [
-   "623898c5d5975ae661f8b2375af2a1aaf2859c23",
+   "c9a7ec401f8db3416e73694370be0b711f04110e",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-mixed-content-iframe.html": [
-   "bb8ade5c70097997726faf2624b11581e4cfe2f1",
+   "1b7a67809f06e5a14ca77da10d9c43e94f5dc1f0",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html": [
    "cb6f80953f58469e6c0048fb767d5e9561b0a19c",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-css-base-url-style.css": [
    "96f892f4359baa6c12bf8da068c4aeb76a60d657",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-css-base-url-worker.js": [
-   "4536000808809f0354c6b206380d92f4e2fddd0e",
+   "30e4285e144a5c9caa0dd48224cefc4b41973de1",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-fallback-iframe.html": [
    "a1202e192e51d625cc06c0f7a7e0a27efadc1f2d",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-fallback-worker.js": [
    "5195f7d76f6c77bd167c9192a0386c2f8b7863c1",
@@ -198740,25 +198783,25 @@
    "0023475ba862c10277efb63a18275a79facdd9c2",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-resources-worker.js": [
    "db66bb2ec1cb1b70e1dddc50748ff134e623e401",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html": [
-   "2a1cb00d377b6a3460daf9727828af0040756420",
+   "e28b416c027c2ed1a633c0804ef826cad99509ff",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-request-xhr-worker.js": [
    "fcbb50668ec1a3f7bdbd4331babda5b6e0295f2e",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html": [
-   "bdba81b06c43907a879b992ea20a77526a0e8810",
+   "8bef6d586f438fa912c7e40ac82a5aa73e05706a",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-response-xhr-worker.js": [
    "f94ad37a6f751b96a95c325b0787c1f0c28d2418",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-rewrite-worker.js": [
    "e390cdc4fa2324db03069193e2b049dde82fbc2d",
@@ -198767,20 +198810,16 @@
   "service-workers/service-worker/resources/fetch-waits-for-activate-worker.js": [
    "a557b92d3119f43bbbe10d46effc240d7f11c784",
    "support"
   ],
   "service-workers/service-worker/resources/frame-for-getregistrations.html": [
    "c5f88c11333ff1faba5d57812a36553d174ab711",
    "support"
   ],
-  "service-workers/service-worker/resources/get-host-info.sub.js": [
-   "b9310fbd533b9382c3413bbcf2d49f778d4737dd",
-   "support"
-  ],
   "service-workers/service-worker/resources/indexeddb-worker.js": [
    "ed0ff45423ba74ad0b82e46debd865fdae2fbcb6",
    "support"
   ],
   "service-workers/service-worker/resources/install-event-type-worker.js": [
    "b6949fcd3d82a99595356448fce6ac830366200e",
    "support"
   ],
@@ -198836,17 +198875,17 @@
    "c99d267d5d819bebae13b1866671c9c2460b0104",
    "support"
   ],
   "service-workers/service-worker/resources/navigate-window-worker.js": [
    "4d3b80c17efd78bda66333ba01ffde1b8f6e976b",
    "support"
   ],
   "service-workers/service-worker/resources/navigation-redirect-other-origin.html": [
-   "a43dcad198cad8b1589de1963342c75a0b70d1e9",
+   "8c51024d8e369bc5ae21e94c486c59690df2de3e",
    "support"
   ],
   "service-workers/service-worker/resources/navigation-redirect-out-scope.py": [
    "b41d084ce18e177e59b7caa0d305fc11f37fd4d5",
    "support"
   ],
   "service-workers/service-worker/resources/navigation-redirect-scope1.py": [
    "b41d084ce18e177e59b7caa0d305fc11f37fd4d5",
@@ -198928,17 +198967,17 @@
    "4ccc1681cd016327aafed77210afe6ed1cc8c04a",
    "support"
   ],
   "service-workers/service-worker/resources/redirect.py": [
    "3c5cc6f523aff39bb50a5a9ea1f65e494b49b3f7",
    "support"
   ],
   "service-workers/service-worker/resources/referer-iframe.html": [
-   "f7dc2c960e0bbe78ea14d66d9ee76e7876c29b90",
+   "6b549d0a185a0fb76c230274a672ef4843d33a90",
    "support"
   ],
   "service-workers/service-worker/resources/register-closed-window-iframe.html": [
    "18ee27c8d6a5497bf16b3315ba9eee2b474154b5",
    "support"
   ],
   "service-workers/service-worker/resources/registration-worker.js": [
    "048f75fc0d193765d6264e7be132c29e56dd7bcb",
@@ -198960,17 +198999,17 @@
    "0fc85a13c536aad45a87fb073fdcebf371d4476d",
    "support"
   ],
   "service-workers/service-worker/resources/resource-timing-worker.js": [
    "ee7888f2e145700cf2590b6d6de9bab39088a979",
    "support"
   ],
   "service-workers/service-worker/resources/service-worker-csp-worker.py": [
-   "f91ff42d4a88961aeb4c29cce61db8ad32261f4e",
+   "f7c6bb3ba222dc35a09ef806a7c6d145339f9eb2",
    "support"
   ],
   "service-workers/service-worker/resources/shared-worker-controlled.js": [
    "9ae937c2e8499991432caa4587eb68fe2998f503",
    "support"
   ],
   "service-workers/service-worker/resources/shared-worker-import.js": [
    "700fc039f3115019ab536924985ed9280f39ff0a",
@@ -199048,21 +199087,21 @@
    "29d35c8ffdc89278c6771b47544375145e2b23d5",
    "support"
   ],
   "service-workers/service-worker/resources/websocket.js": [
    "dbf752f9a356f51f6ddf96053b39b5cd3515ddc8",
    "support"
   ],
   "service-workers/service-worker/resources/worker-interception-iframe.https.html": [
-   "06594aaad28018acf9e670b23eb97e8b0b7e1b98",
+   "b9fd4ea281b328c1f21573d1563c968dac52cf22",
    "support"
   ],
   "service-workers/service-worker/resources/worker-load-interceptor.js": [
-   "8e92e777917d2e39558a7609d34ec839f24e5fac",
+   "de9cfcbef6528a4b5e6b2552f260501e4d165ea4",
    "support"
   ],
   "service-workers/service-worker/resources/worker-testharness.js": [
    "8624b498e37d44bf3a3a74ccd46f928f7b0338cb",
    "support"
   ],
   "service-workers/service-worker/resources/xhr.js": [
    "bb913597a735c33caac7aee8cb8de76a38484ae4",
@@ -199156,25 +199195,25 @@
    "73c129838eda3c18365f384b8b0a5c32b5e9cf6d",
    "testharness"
   ],
   "service-workers/service-worker/waiting.https.html": [
    "6e3c7a4c12d90b10651653e680615185eaf270bc",
    "testharness"
   ],
   "service-workers/service-worker/websocket.https.html": [
-   "41a6008966629c84ffba592e038adae1050c947a",
+   "40ec7850c61a3ee7578f055d3eef87293cfad482",
    "testharness"
   ],
   "service-workers/service-worker/worker-interception.https.html": [
    "2c5e8cb2b7be6d394aaa1400158d3f14895909f3",
    "testharness"
   ],
   "service-workers/service-worker/xhr.https.html": [
-   "e306f2662c779b7fe2b3727e6ee9a27c7c95a151",
+   "f5d565c95c7a08da139b0f3b95bb0cfb0ae2b936",
    "testharness"
   ],
   "service-workers/specgen.json": [
    "0d98c8249e25cd4c7a4d88f722cfe8f235fb7a66",
    "support"
   ],
   "service-workers/stub-3.1-service-worker-obj.html": [
    "26e7afb8569cc3c997c6338dc86bfbe7232a8c0e",
@@ -218024,17 +218063,17 @@
    "554d027aac3a5bd022d284fcd8bcb126ecca2cc4",
    "testharness"
   ],
   "workers/data-url.html": [
    "c736022a55eff0593172a20023da80b13bb1f31f",
    "testharness"
   ],
   "workers/interfaces.idl": [
-   "8b1a9f8688e38a009fa82936610ca221541bafbc",
+   "d8961ea6af91a92a064bcf0e0da5b56781f6bc6b",
    "support"
   ],
   "workers/interfaces.worker.js": [
    "e35e0f6de69052f24340bd887da469b85833953b",
    "testharness"
   ],
   "workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js": [
    "b613859a3c941384721e5331e39a3fc0931612ac",
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1793,160 +1793,16 @@
     expected: FAIL
 
   [PortCollection interface: operation clear()]
     expected: FAIL
 
   [PortCollection interface: operation iterate(PortCollectionCallback)]
     expected: FAIL
 
-  [WorkerGlobalScope interface object length]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute self]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute location]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation close()]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute onerror]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute onlanguagechange]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute onoffline]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute ononline]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation importScripts(DOMString)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: attribute navigator]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation createImageBitmap(ImageBitmapSource,long,long,long,long)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation setTimeout(Function,long,any)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation setTimeout(DOMString,long,any)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation clearTimeout(long)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation setInterval(Function,long,any)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation setInterval(DOMString,long,any)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation clearInterval(long)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation btoa(DOMString)]
-    expected: FAIL
-
-  [WorkerGlobalScope interface: operation atob(DOMString)]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface object length]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface: operation postMessage(any,[object Object\])]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface: attribute onmessage]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface object length]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface: attribute name]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface: attribute applicationCache]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface: attribute onconnect]
-    expected: FAIL
-
-  [WorkerNavigator interface object length]
-    expected: FAIL
-
-  [WorkerNavigator interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [WorkerNavigator interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute appCodeName]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute appName]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute appVersion]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute platform]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute product]
-    expected: FAIL
-
-  [WorkerNavigator interface: operation taintEnabled()]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute userAgent]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute language]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute languages]
-    expected: FAIL
-
-  [WorkerNavigator interface: attribute onLine]
-    expected: FAIL
-
-  [WorkerLocation interface object length]
-    expected: FAIL
-
-  [WorkerLocation interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [WorkerLocation interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
   [HTMLMarqueeElement interface: existence and properties of interface object]
     expected: FAIL
 
   [HTMLMarqueeElement interface object length]
     expected: FAIL
 
   [HTMLMarqueeElement interface: existence and properties of interface prototype object]
     expected: FAIL
@@ -2225,43 +2081,16 @@
     expected: FAIL
 
   [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onsort" with the proper type (149)]
     expected: FAIL
 
   [Location interface: window.location must have own property "ancestorOrigins"]
     expected: FAIL
 
-  [WorkerLocation interface: attribute href]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute origin]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute protocol]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute host]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute hostname]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute port]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute pathname]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute search]
-    expected: FAIL
-
-  [WorkerLocation interface: attribute hash]
-    expected: FAIL
-
   [DOMElementMap interface object name]
     expected: FAIL
 
   [AudioTrackList interface object name]
     expected: FAIL
 
   [AudioTrack interface object name]
     expected: FAIL
@@ -2297,31 +2126,16 @@
     expected: FAIL
 
   [ApplicationCache interface object name]
     expected: FAIL
 
   [PortCollection interface object name]
     expected: FAIL
 
-  [WorkerGlobalScope interface object name]
-    expected: FAIL
-
-  [DedicatedWorkerGlobalScope interface object name]
-    expected: FAIL
-
-  [SharedWorkerGlobalScope interface object name]
-    expected: FAIL
-
-  [WorkerNavigator interface object name]
-    expected: FAIL
-
-  [WorkerLocation interface object name]
-    expected: FAIL
-
   [HTMLMarqueeElement interface object name]
     expected: FAIL
 
   [HTMLAllCollection interface: document.all must inherit property "length" with the proper type (0)]
     expected: FAIL
 
   [HTMLAllCollection interface: document.all must inherit property "item" with the proper type (2)]
     expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/resources/should-load.html
@@ -0,0 +1,3 @@
+<script>
+  parent.loadedCount++;
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/resources/should-not-load.html
@@ -0,0 +1,5 @@
+<script>
+  parent.nestingTest.step(function() {
+    parent.assert_unreached(window.frameElement.getAttribute("test-description"));
+  });
+</script>
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html
@@ -1,22 +1,22 @@
 <!doctype html>
 <meta charset="utf-8">
 <title>HTML Test: The embed element represents a document</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <meta name="assert" content="Check if the embed element is ignored when used inside a media element">
 <script type="application/javascript">
- window.childLoaded = false;
- async_test(function() {
-   addEventListener("load", this.step_func_done(function() {
-     assert_false(window.childLoaded);
-   }));
- }, "Test embed being ignored inside media element");
+  var nestingTest = async_test("Test embed being ignored inside media element");
+  onload = nestingTest.step_func_done(function() {
+    assert_true(true, "We got to a load event without loading things we should not load");
+  });
 </script>
 <body>
   <video>
-    <embed type="text/html" src="embed-iframe.html" />
+    <embed type="text/html" src="../resources/should-not-load.html"
+           test-description="<embed> in <video>">
   </video>
   <audio>
-    <embed type="text/html" src="embed-iframe.html" />
+    <embed type="text/html" src="../resources/should-not-load.html"
+           test-description="<embed> in <audio>">
   </audio>
 </body>
rename from dom/base/test/test_bug1263696.html
rename to testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html
--- a/dom/base/test/test_bug1263696.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-in-object-fallback-2.html
@@ -1,53 +1,56 @@
-<!DOCTYPE html>
+<!doctype html>
 <html>
   <head>
-    <meta><charset="utf-8"/>
-    <title>Test Embed/Object Node Conflicts</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="application/javascript" src="plugin-utils.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-    <script type="application/javascript">
-     SimpleTest.waitForExplicitFinish();
-     var index = 0;
-     function startTest() {
-       is(index, 12, "Should have loaded all passing frames.");
-       SimpleTest.finish();
-     }
+    <meta charset=utf-8>
+    <title></title>
+    <script src=/resources/testharness.js></script>
+    <script src=/resources/testharnessreport.js></script>
+    <script>
+      var loadedCount = 0;
+      var nestingTest = async_test("Test <embed> nesting inside <object>");
+      onload = nestingTest.step_func_done(function() {
+        assert_equals(loadedCount, 12, "Should have loaded all should-load elements");
+      });
     </script>
+    <style>
+      object, embed { display: none }
+    </style>
   </head>
-  <body onload="startTest()">
-    <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px">
-      <embed type="text/html" src="file_bug1263696_frame_fail.html" />
+  <body>
+    <object data="../resources/should-load.html" style="width: 100px; height: 100px">
+      <embed type="text/html" src="../resources/should-not-load.html"
+             test-description="<embed> inside <object>">
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <embed type="text/html" src="../resources/should-load.html" />
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
       <div></div>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <embed type="text/html" src="../resources/should-load.html" />
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
       <div>
-        <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+        <embed type="text/html" src="../resources/should-load.html" />
       </div>
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <object data="file_bug1263696_frame_pass.html">
-        <embed type="text/html" src="file_bug1263696_frame_fail.html" />
+      <embed type="text/html" src="../resources/should-load.html" />
+      <embed type="text/html" src="../resources/should-load.html" />
+      <object data="../resources/should-load.html">
+        <embed type="text/html" src="../resources/should-not-load.html"
+               test-description="<embed> inside loaded <object> inside non-loaded <object>">
       </object>
       <object data="data:application/x-does-not-exist,test">
-        <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+        <embed type="text/html" src="../resources/should-load.html" />
       </object>
     </object>
     <div>
-      <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px"></object>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <object data="../resources/should-load.html" style="width: 100px; height: 100px"></object>
+      <embed type="text/html" src="../resources/should-load.html" />
     </div>
     <div>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px"></object>
+      <embed type="text/html" src="../resources/should-load.html" />
+      <object data="../resources/should-load.html" style="width: 100px; height: 100px"></object>
     </div>
   </body>
 </html>
copy from testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html
copy to testing/web-platform/tests/html/semantics/embedded-content/the-object-element/object-ignored-in-media-element.html
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/object-ignored-in-media-element.html
@@ -1,22 +1,22 @@
 <!doctype html>
 <meta charset="utf-8">
 <title>HTML Test: The embed element represents a document</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<meta name="assert" content="Check if the embed element is ignored when used inside a media element">
+<meta name="assert" content="Check if the object element is ignored when used inside a media element">
 <script type="application/javascript">
- window.childLoaded = false;
- async_test(function() {
-   addEventListener("load", this.step_func_done(function() {
-     assert_false(window.childLoaded);
-   }));
- }, "Test embed being ignored inside media element");
+  var nestingTest = async_test("Test <object> being ignored inside media element");
+  onload = nestingTest.step_func_done(function() {
+    assert_true(true, "We got to a load event without loading things we should not load");
+  });
 </script>
 <body>
   <video>
-    <embed type="text/html" src="embed-iframe.html" />
+    <object type="text/html" data="../resources/should-not-load.html"
+            test-description="<object> in <video>"></object>
   </video>
   <audio>
-    <embed type="text/html" src="embed-iframe.html" />
+    <object type="text/html" data="../resources/should-not-load.html"
+            test-description="<object> in <audio>"></object>
   </audio>
 </body>
copy from dom/base/test/test_bug1263696.html
copy to testing/web-platform/tests/html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html
--- a/dom/base/test/test_bug1263696.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-object-element/object-in-object-fallback-2.html
@@ -1,53 +1,56 @@
-<!DOCTYPE html>
+<!doctype html>
 <html>
   <head>
-    <meta><charset="utf-8"/>
-    <title>Test Embed/Object Node Conflicts</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="application/javascript" src="plugin-utils.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-    <script type="application/javascript">
-     SimpleTest.waitForExplicitFinish();
-     var index = 0;
-     function startTest() {
-       is(index, 12, "Should have loaded all passing frames.");
-       SimpleTest.finish();
-     }
+    <meta charset=utf-8>
+    <title></title>
+    <script src=/resources/testharness.js></script>
+    <script src=/resources/testharnessreport.js></script>
+    <script>
+      var loadedCount = 0;
+      var nestingTest = async_test("Test <object> nesting inside <object>");
+      onload = nestingTest.step_func_done(function() {
+        assert_equals(loadedCount, 12, "Should have loaded all should-load elements");
+      });
     </script>
+    <style>
+      object { display: none }
+    </style>
   </head>
-  <body onload="startTest()">
-    <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px">
-      <embed type="text/html" src="file_bug1263696_frame_fail.html" />
+  <body>
+    <object data="../resources/should-load.html" style="width: 100px; height: 100px">
+      <object type="text/html" data="../resources/should-not-load.html"
+              test-description="<object> inside <object>"></object>
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <object type="text/html" data="../resources/should-load.html"></object>
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
       <div></div>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <object type="text/html" data="../resources/should-load.html"></object>
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
       <div>
-        <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+        <object type="text/html" data="../resources/should-load.html"></object>
       </div>
     </object>
     <object style="width: 100px; height: 100px" data="data:application/x-does-not-exist,test">
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <object data="file_bug1263696_frame_pass.html">
-        <embed type="text/html" src="file_bug1263696_frame_fail.html" />
+      <object type="text/html" data="../resources/should-load.html"></object>
+      <object type="text/html" data="../resources/should-load.html"></object>
+      <object data="../resources/should-load.html">
+        <object type="text/html" data="../resources/should-not-load.html"
+                test-description="<object> inside loaded <object> inside non-loaded <object>"></object>
       </object>
       <object data="data:application/x-does-not-exist,test">
-        <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+        <object type="text/html" data="../resources/should-load.html"></object>
       </object>
     </object>
     <div>
-      <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px"></object>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
+      <object data="../resources/should-load.html" style="width: 100px; height: 100px"></object>
+      <object type="text/html" data="../resources/should-load.html"></object>
     </div>
     <div>
-      <embed type="text/html" src="file_bug1263696_frame_pass.html" />
-      <object data="file_bug1263696_frame_pass.html" style="width: 100px; height: 100px"></object>
+      <object type="text/html" data="../resources/should-load.html"></object>
+      <object data="../resources/should-load.html" style="width: 100px; height: 100px"></object>
     </div>
   </body>
 </html>
--- a/testing/web-platform/tests/service-workers/service-worker/client-navigate.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/client-navigate.https.html
@@ -1,14 +1,14 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>Service Worker: WindowClient.navigate</title>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
   function wait_for_message(msg) {
     return new Promise(function(resolve, reject) {
       var get_message_data = function get_message_data(e) {
         window.removeEventListener("message", get_message_data);
         resolve(e.data);
       }
--- a/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/clients-get-cross-origin.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: Clients.get across origins</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 var host_info = get_host_info();
 
 var scope = 'resources/blank.html?clients-get';
 var t = async_test('Test Clients.get() cross origin');
 var other_origin_iframe = host_info['HTTPS_REMOTE_ORIGIN'] + base_path() +
                           'resources/clients-get-other-origin.html';
--- a/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/clients-get.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: Clients.get</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 var host_info = get_host_info();
 
 var scope = 'resources/clients-get-frame.html';
 var t = async_test('Test Clients.get()');
 var clientIds = [];
 var frame;
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-canvas-tainting-cache.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: canvas tainting of the fetched image using cached responses</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <body>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-canvas-tainting-iframe.html?cache';
     var SCRIPT = 'resources/fetch-rewrite-worker.js';
     var host_info = get_host_info();
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-canvas-tainting.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-canvas-tainting.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: canvas tainting of the fetched image</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <body>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-canvas-tainting-iframe.html';
     var SCRIPT = 'resources/fetch-rewrite-worker.js';
     var host_info = get_host_info();
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-cors-xhr.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-cors-xhr.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: CORS XHR of fetch()</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <body>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-cors-xhr-iframe.html';
     var SCRIPT = 'resources/fetch-rewrite-worker.js';
     var host_info = get_host_info();
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-csp.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: CSP control of fetch()</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-csp-iframe.html';
     var SCRIPT = 'resources/fetch-rewrite-worker.js';
     var host_info = get_host_info();
     service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-event-redirect.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-event-redirect.https.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <title>Service Worker: Fetch Event Redirect Handling</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 
 // ------------------------
 // Utilities for testing non-navigation requests that are intercepted with
 // a redirect.
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-event.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-event.https.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 var worker = 'resources/fetch-event-test-worker.js';
 
 async_test(function(t) {
     var scope = 'resources/simple.html?string';
     service_worker_unregister_and_register(t, worker, scope)
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-frame-resource.https.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Service Worker: Fetch for the frame loading.</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 var worker = 'resources/fetch-rewrite-worker.js';
 var path = base_path() + 'resources/fetch-access-control.py';
 var host_info = get_host_info();
 
 if (window.testRunner) {
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-header-visibility.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-header-visibility.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: Visibility of headers during fetch.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
   var worker = 'resources/fetch-rewrite-worker.js';
   var path = base_path() + 'resources/fetch-access-control.py';
   var host_info = get_host_info();
   var frame;
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Service Worker: Mixed content of fetch()</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <body></body>
 <script>
 if (window.testRunner) {
   // In Chromium we need to change the setting to disallow displaying insecure
   // contents.
   testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
 }
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-mixed-content-to-outscope.https.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Service Worker: Mixed content of fetch()</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <body></body>
 <script>
 if (window.testRunner) {
   // In Chromium we need to change the setting to disallow displaying insecure
   // contents.
   testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
 }
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-css-base-url.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-css-base-url.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: CSS's base URL must be the request URL even when fetched from other URL</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
     var SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
     var worker;
     var testDonePromise;
 
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-css-images.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-css-images.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: FetchEvent for css image</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 var SCOPE = 'resources/fetch-request-resources-iframe.https.html';
 var SCRIPT = 'resources/fetch-request-resources-worker.js';
 var host_info = get_host_info();
 var LOCAL_URL =
   host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test';
 var REMOTE_URL =
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-fallback.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-fallback.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: the fallback behavior of FetchEvent</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 var expected_urls = [];
 
 function xhr_fail_test(frame, url) {
   expected_urls.push(url);
   return new Promise(function(resolve, reject) {
       frame.contentWindow.xhr(url)
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-redirect.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-redirect.https.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Service Worker: FetchEvent for resources</title>
 <meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 
 function assert_resolves(promise, description) {
   return promise.catch(function(reason) {
       throw new Error(description + ' - ' + reason.message);
   });
 }
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-resources.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-resources.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: FetchEvent for resources</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 var url_count = 0;
 var expected_results = {};
 
 function image_test(frame, url, cross_origin, expected_mode,
                     expected_credentials) {
   var actual_url = url + (++url_count);
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-request-xhr.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-request-xhr.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-request-xhr-iframe.https.html';
     var SCRIPT = 'resources/fetch-request-xhr-worker.js';
     var host_info = get_host_info();
     service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-response-xhr.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-response-xhr.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: the response of FetchEvent using XMLHttpRequest</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/fetch-response-xhr-iframe.https.html';
     var SCRIPT = 'resources/fetch-response-xhr-worker.js';
     var host_info = get_host_info();
 
     window.addEventListener('message', t.step_func(on_message), false);
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-waits-for-activate.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-waits-for-activate.https.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <title>Service Worker: Fetch Event Waits for Activate Event</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 
 var worker = 'resources/fetch-waits-for-activate-worker.js';
 var expected_url = normalizeURL(worker);
 var scope = 'resources/fetch-waits-for-activate/';
 
--- a/testing/web-platform/tests/service-workers/service-worker/getregistrations.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/getregistrations.https.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Service Worker: getRegistrations()</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="../fetch/resources/fetch-test-helpers.sub.js"></script>
 <script>
 // Purge the existing registrations for the origin.
 // getRegistrations() is used in order to avoid adding additional complexity
 // e.g. adding an internal function.
 promise_test(function(t) {
     return navigator.serviceWorker.getRegistrations()
       .then(function(registrations) {
--- a/testing/web-platform/tests/service-workers/service-worker/invalid-blobtype.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/invalid-blobtype.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: respondWith with header value containing a null byte</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/invalid-blobtype-iframe.https.html';
     var SCRIPT = 'resources/invalid-blobtype-worker.js';
     var host_info = get_host_info();
     service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
--- a/testing/web-platform/tests/service-workers/service-worker/invalid-header.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/invalid-header.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: respondWith with header value containing a null byte</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/invalid-header-iframe.https.html';
     var SCRIPT = 'resources/invalid-header-worker.js';
     var host_info = get_host_info();
     service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
--- a/testing/web-platform/tests/service-workers/service-worker/navigate-window.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/navigate-window.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: Navigate a Window</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 var host_info = get_host_info();
 var BASE_URL = host_info['HTTPS_ORIGIN'] + base_path();
 
 function wait_for_message(msg) {
   return new Promise(function(resolve, reject) {
--- a/testing/web-platform/tests/service-workers/service-worker/navigation-redirect.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/navigation-redirect.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: Navigation redirection</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 var host_info = get_host_info();
 
 // This test registers three Service Workers at SCOPE1, SCOPE2 and
 // OTHER_ORIGIN_SCOPE. And checks the redirected page's URL and the requests
 // which are intercepted by Service Worker while loading redirect page.
--- a/testing/web-platform/tests/service-workers/service-worker/postmessage-to-client.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/postmessage-to-client.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: postMessage to Client</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 var frame;
 var t = async_test('postMessage from ServiceWorker to Client');
 t.step(function() {
     var scope = 'resources/blank.html';
     var host_info = get_host_info();
     var sw;
--- a/testing/web-platform/tests/service-workers/service-worker/referer.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/referer.https.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <title>Service Worker: check referer of fetch()</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
 async_test(function(t) {
     var SCOPE = 'resources/referer-iframe.html';
     var SCRIPT = 'resources/fetch-rewrite-worker.js';
     var host_info = get_host_info();
     service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
--- a/testing/web-platform/tests/service-workers/service-worker/register-closed-window.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/register-closed-window.https.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <title>Service Worker: Register() on Closed Window</title>
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
 <script>
 
 var host_info = get_host_info();
 var frameURL = host_info['HTTPS_ORIGIN'] + base_path() +
                'resources/register-closed-window-iframe.html';
 
--- a/testing/web-platform/tests/service-workers/service-worker/resource-timing.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resource-timing.https.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 function resourceUrl(path) {
     return get_host_info()['HTTP_ORIGIN'] + base_path() + path;
 }
 
 function verify(performance, resource, description) {
     var entry = performance.getEntriesByName(resourceUrl(resource))[0];
--- a/testing/web-platform/tests/service-workers/service-worker/resources/client-navigate-worker.js
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/client-navigate-worker.js
@@ -1,11 +1,11 @@
 importScripts("worker-testharness.js");
 importScripts("test-helpers.sub.js");
-importScripts("get-host-info.sub.js")
+importScripts("/common/get-host-info.sub.js")
 importScripts("testharness-helpers.js")
 
 self.onfetch = function(e) {
   if (e.request.url.indexOf("client-navigate-frame.html") >= 0) {
     if (e.clientId === null) {
       e.respondWith(fetch(e.request));
     } else {
       e.respondWith(Response.error());
--- a/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-other-origin.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/clients-get-other-origin.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js"></script>
 <script>
 var host_info = get_host_info();
 var SCOPE = 'blank.html?clients-get';
 var SCRIPT = 'clients-get-worker.js';
 
 var registration;
 var worker;
--- a/testing/web-platform/tests/service-workers/service-worker/resources/dummy-worker-interceptor.js
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/dummy-worker-interceptor.js
@@ -1,9 +1,9 @@
-importScripts('get-host-info.sub.js');
+importScripts('/common/get-host-info.sub.js');
 
 var worker_text = 'postMessage("worker loading intercepted by service worker"); ';
 
 self.onfetch = function(event) {
   if (event.request.url.indexOf('synthesized') != -1) {
     event.respondWith(new Response(worker_text));
   } else if (event.request.url.indexOf('same-origin') != -1) {
     event.respondWith(fetch('dummy-worker-script.py'));
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-canvas-tainting-iframe.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var image_path = base_path() + 'fetch-access-control.py?PNGIMAGE';
 var host_info = get_host_info();
 var params = get_query_params(location.href);
 
 var NOT_TAINTED = 'NOT_TAINTED';
 var TAINTED = 'TAINTED';
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-cors-xhr-iframe.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-cors-xhr-iframe.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var path = base_path() + 'fetch-access-control.py';
 var host_info = get_host_info();
 var SUCCESS = 'SUCCESS';
 var FAIL = 'FAIL';
 
 function create_test_case_promise(url, with_credentials) {
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-csp-iframe.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var image_path = base_path() + 'fetch-access-control.py?PNGIMAGE';
 var host_info = get_host_info();
 var results = '';
 var port = undefined;
 
 function test1() {
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-header-visibility-iframe.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-header-visibility-iframe.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
   var host_info = get_host_info();
   var uri = document.location + '?check-ua-header';
 
   var headers = new Headers();
   headers.set('User-Agent', 'custom_ua');
 
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-inscope.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var image_path = base_path() + 'fetch-access-control.py?PNGIMAGE';
 var host_info = get_host_info();
 var results = '';
 
 function test1() {
   var img = document.createElement('img');
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe-inscope-to-outscope.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var image_path = base_path() + 'fetch-access-control.py?PNGIMAGE';
 var host_info = get_host_info();
 var results = '';
 
 function test1() {
   var img = document.createElement('img');
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-mixed-content-iframe.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var params = get_query_params(location.href);
 var SCOPE = 'fetch-mixed-content-iframe-inscope-to-' + params['target'] + '.html';
 var URL = 'fetch-rewrite-worker.js';
 var host_info = get_host_info();
 
 window.addEventListener('message', on_message, false);
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js
@@ -1,9 +1,9 @@
-importScripts('../resources/get-host-info.sub.js');
+importScripts('/common/get-host-info.sub.js');
 importScripts('test-helpers.sub.js');
 
 var port = undefined;
 
 self.onmessage = function(e) {
   var message = e.data;
   if ('port' in message) {
     port = message.port;
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-request-xhr-iframe.https.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var port;
 var host_info = get_host_info();
 
 function assert_equals(a, b) {
   port.postMessage({results: 'equals', got: a, expected: b});
 }
--- a/testing/web-platform/tests/service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/fetch-response-xhr-iframe.https.html
@@ -1,9 +1,9 @@
-<script src="../resources/get-host-info.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var host_info = get_host_info();
 
 function xhr_send(method, data) {
   return new Promise(function(resolve, reject) {
       var xhr = new XMLHttpRequest();
       xhr.onload = function() {
deleted file mode 100644
--- a/testing/web-platform/tests/service-workers/service-worker/resources/get-host-info.sub.js
+++ /dev/null
@@ -1,26 +0,0 @@
-function get_host_info() {
-  var ORIGINAL_HOST = '127.0.0.1';
-  var REMOTE_HOST = 'localhost';
-  var UNAUTHENTICATED_HOST = 'example.test';
-  var HTTP_PORT = 8000;
-  var HTTPS_PORT = 8443;
-  try {
-    // In W3C test, we can get the hostname and port number in config.json
-    // using wptserve's built-in pipe.
-    // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
-    HTTP_PORT = eval('{{ports[http][0]}}');
-    HTTPS_PORT = eval('{{ports[https][0]}}');
-    ORIGINAL_HOST = eval('\'{{host}}\'');
-    REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
-  } ca