Merge inbound to mozilla-central r=merge a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Sat, 09 Dec 2017 00:36:15 +0200
changeset 395864 5f52c2488a831edbc33fa0bc6003ed4df9a62732
parent 395863 6e2181b6137c87fde58434bb926ea3f21fc1ed11 (current diff)
parent 395862 75960f4bb234e7d51428323fb37c434330cc7b06 (diff)
child 395865 588916479e50d7979bbabc0801d1e7bb9767c6a4
child 395889 e92e79cacf0908afceb7a2eacbfc9c3a810bd32b
child 395921 848484362ba16d443458f62ef83f365cd46f2516
push id56841
push userrgurzau@mozilla.com
push dateFri, 08 Dec 2017 22:57:20 +0000
treeherderautoland@588916479e50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
5f52c2488a83 / 59.0a1 / 20171209100033 / files
nightly linux64
5f52c2488a83 / 59.0a1 / 20171209100033 / files
nightly mac
5f52c2488a83 / 59.0a1 / 20171209100033 / files
nightly win32
5f52c2488a83 / 59.0a1 / 20171209100033 / files
nightly win64
5f52c2488a83 / 59.0a1 / 20171209100033 / 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 mozilla-central r=merge a=merge
browser/base/content/test/performance/browser_favicon_load.js
browser/components/preferences/donottrack.xul
browser/components/selfsupport/SelfSupportService.js
browser/components/selfsupport/SelfSupportService.manifest
browser/components/selfsupport/moz.build
browser/components/selfsupport/test/.eslintrc.js
browser/components/selfsupport/test/browser.ini
browser/components/selfsupport/test/browser_selfsupportAPI.js
dom/webidl/Element.webidl
dom/webidl/MozSelfSupport.webidl
dom/webidl/moz.build
memory/mozalloc/mozalloc.h
modules/libpref/init/all.js
old-configure.in
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-007.html.ini
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-009.html.ini
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-017.html.ini
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-025.html.ini
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-027.html.ini
testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-035.html.ini
testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-012.html.ini
testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-013.html.ini
testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-014.html.ini
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -641,29 +641,31 @@ NotificationController::WillRefresh(mozi
     mDocument->AddScrollListener();
 
   // Process rendered text change notifications.
   for (auto iter = mTextHash.Iter(); !iter.Done(); iter.Next()) {
     nsCOMPtrHashKey<nsIContent>* entry = iter.Get();
     nsIContent* textNode = entry->GetKey();
     Accessible* textAcc = mDocument->GetAccessible(textNode);
 
-    // If the text node is not in tree or doesn't have frame then this case should
-    // have been handled already by content removal notifications.
+    // If the text node is not in tree or doesn't have a frame, or placed in
+    // another document, then this case should have been handled already by
+    // content removal notifications.
     nsINode* containerNode = textNode->GetParentNode();
-    if (!containerNode) {
-      NS_ASSERTION(!textAcc,
-                   "Text node was removed but accessible is kept alive!");
+    if (!containerNode ||
+        textNode->GetOwnerDocument() != mDocument->DocumentNode()) {
+      MOZ_ASSERT(!textAcc,
+                 "Text node was removed but accessible is kept alive!");
       continue;
     }
 
     nsIFrame* textFrame = textNode->GetPrimaryFrame();
     if (!textFrame) {
-      NS_ASSERTION(!textAcc,
-                   "Text node isn't rendered but accessible is kept alive!");
+      MOZ_ASSERT(!textAcc,
+                 "Text node isn't rendered but accessible is kept alive!");
       continue;
     }
 
   #ifdef A11Y_LOG
     nsIContent* containerElm = containerNode->IsElement() ?
       containerNode->AsElement() : nullptr;
   #endif
 
--- a/browser/base/content/test/favicons/browser.ini
+++ b/browser/base/content/test/favicons/browser.ini
@@ -2,13 +2,18 @@
 support-files =
   head.js
   discovery.html
   file_rich_icon.html
   file_mask_icon.html
   moz.png
   rich_moz_1.png
   rich_moz_2.png
+  file_favicon.html
+  file_favicon.png
+  file_favicon.png^headers^
+  file_favicon_thirdParty.html
 
 [browser_multiple_icons_in_short_timeframe.js]
 [browser_rich_icons.js]
 [browser_icon_discovery.js]
 [browser_preferred_icons.js]
+[browser_favicon_load.js]
rename from browser/base/content/test/performance/browser_favicon_load.js
rename to browser/base/content/test/favicons/browser_favicon_load.js
--- a/browser/base/content/test/performance/browser_favicon_load.js
+++ b/browser/base/content/test/favicons/browser_favicon_load.js
@@ -4,27 +4,29 @@
  * Note that this test is modified based on browser_favicon_userContextId.js.
  */
 
 const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
 
 const TEST_SITE = "http://example.net";
 const TEST_THIRD_PARTY_SITE = "http://mochi.test:8888";
 
-const TEST_PAGE = TEST_SITE + "/browser/browser/components/originattributes/" +
-                  "test/browser/file_favicon.html";
-const FAVICON_URI = TEST_SITE + "/browser/browser/components/originattributes/" +
-                    "test/browser/file_favicon.png";
-const TEST_THIRD_PARTY_PAGE = "http://example.com/browser/browser/components/" +
-                              "originattributes/test/browser/file_favicon_thirdParty.html";
-const THIRD_PARTY_FAVICON_URI = TEST_THIRD_PARTY_SITE + "/browser/browser/components/" +
-                                "originattributes/test/browser/file_favicon.png";
+const TEST_PAGE =
+  TEST_SITE + "/browser/browser/base/content/test/favicons/file_favicon.html";
+const FAVICON_URI =
+  TEST_SITE + "/browser/browser/base/content/test/favicons/file_favicon.png";
+const TEST_THIRD_PARTY_PAGE =
+  TEST_SITE + "/browser/browser/base/content/test/favicons/file_favicon_thirdParty.html";
+const THIRD_PARTY_FAVICON_URI =
+  TEST_THIRD_PARTY_SITE + "/browser/browser/base/content/test/favicons/file_favicon.png";
 
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
+                                  "resource://testing-common/PlacesTestUtils.jsm");
 
 let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
 
 function clearAllImageCaches() {
   var tools = Cc["@mozilla.org/image/tools;1"]
                 .getService(SpecialPowers.Ci.imgITools);
   var imageCache = tools.getImgCacheForDocument(window.document);
   imageCache.clearCache(true); // true=chrome
copy from browser/components/originattributes/test/browser/file_favicon.html
copy to browser/base/content/test/favicons/file_favicon.html
copy from browser/components/originattributes/test/browser/file_favicon.png
copy to browser/base/content/test/favicons/file_favicon.png
copy from browser/components/originattributes/test/browser/file_favicon.png^headers^
copy to browser/base/content/test/favicons/file_favicon.png^headers^
copy from browser/components/originattributes/test/browser/file_favicon_thirdParty.html
copy to browser/base/content/test/favicons/file_favicon_thirdParty.html
--- a/browser/components/originattributes/test/browser/file_favicon_thirdParty.html
+++ b/browser/base/content/test/favicons/file_favicon_thirdParty.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset='utf-8'>
     <title>Favicon Test for originAttributes</title>
-    <link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/file_favicon.png" />
+    <link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/base/content/test/favicons/file_favicon.png" />
   </head>
   <body>
     Third Party Favicon!!
   </body>
 </html>
--- a/browser/base/content/test/performance/browser.ini
+++ b/browser/base/content/test/performance/browser.ini
@@ -9,17 +9,16 @@ prefs =
   # representative of common startup.
   browser.migration.version=9999999
   browser.startup.record=true
   gfx.canvas.willReadFrequently.enable=true
 support-files =
   head.js
 [browser_appmenu_reflows.js]
 skip-if = asan || debug # Bug 1382809, bug 1369959
-[browser_favicon_load.js]
 [browser_startup.js]
 [browser_startup_content.js]
 skip-if = !e10s
 [browser_startup_flicker.js]
 [browser_tabclose_grow_reflows.js]
 [browser_tabclose_reflows.js]
 [browser_tabopen_reflows.js]
 [browser_tabopen_squeeze_reflows.js]
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -45,17 +45,16 @@ DIRS += [
     'originattributes',
     'places',
     'preferences',
     'privatebrowsing',
     'resistfingerprinting',
     'search',
     'sessionstore',
     'shell',
-    'selfsupport',
     'syncedtabs',
     'uitour',
     'translation',
 ]
 
 DIRS += ['build']
 
 XPIDL_SOURCES += [
deleted file mode 100644
--- a/browser/components/selfsupport/SelfSupportService.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* 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} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
-
-XPCOMUtils.defineLazyModuleGetter(this, "TelemetryArchive",
-                                  "resource://gre/modules/TelemetryArchive.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment",
-                                  "resource://gre/modules/TelemetryEnvironment.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "TelemetryController",
-                                  "resource://gre/modules/TelemetryController.jsm");
-
-function MozSelfSupportInterface() {
-}
-
-MozSelfSupportInterface.prototype = {
-  classDescription: "MozSelfSupport",
-  classID: Components.ID("{d30aae8b-f352-4de3-b936-bb9d875df0bb}"),
-  contractID: "@mozilla.org/mozselfsupport;1",
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]),
-
-  _window: null,
-
-  init(window) {
-    this._window = window;
-  },
-
-  get healthReportDataSubmissionEnabled() {
-    return Services.prefs.getBoolPref(PREF_FHR_UPLOAD_ENABLED, false);
-  },
-
-  set healthReportDataSubmissionEnabled(enabled) {
-    Services.prefs.setBoolPref(PREF_FHR_UPLOAD_ENABLED, enabled);
-  },
-
-  resetPref(name) {
-    Services.prefs.clearUserPref(name);
-  },
-
-  resetSearchEngines() {
-    Services.search.restoreDefaultEngines();
-    Services.search.resetToOriginalDefaultEngine();
-  },
-
-  getTelemetryPingList() {
-    return this._wrapPromise(TelemetryArchive.promiseArchivedPingList());
-  },
-
-  getTelemetryPing(pingId) {
-    return this._wrapPromise(TelemetryArchive.promiseArchivedPingById(pingId));
-  },
-
-  getCurrentTelemetryEnvironment() {
-    const current = TelemetryEnvironment.currentEnvironment;
-    return new this._window.Promise(resolve => resolve(current));
-  },
-
-  getCurrentTelemetrySubsessionPing() {
-    const current = TelemetryController.getCurrentPingData(true);
-    return new this._window.Promise(resolve => resolve(current));
-  },
-
-  _wrapPromise(promise) {
-    return new this._window.Promise(
-      (resolve, reject) => promise.then(resolve, reject));
-  },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozSelfSupportInterface]);
deleted file mode 100644
--- a/browser/components/selfsupport/SelfSupportService.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {d30aae8b-f352-4de3-b936-bb9d875df0bb} SelfSupportService.js
-contract @mozilla.org/mozselfsupport;1 {d30aae8b-f352-4de3-b936-bb9d875df0bb}
deleted file mode 100644
--- a/browser/components/selfsupport/moz.build
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-with Files("**"):
-    BUG_COMPONENT = ("Toolkit", "Telemetry")
-
-EXTRA_COMPONENTS += [
-    'SelfSupportService.js',
-    'SelfSupportService.manifest',
-]
-
-BROWSER_CHROME_MANIFESTS += [
-    'test/browser.ini',
-]
deleted file mode 100644
--- a/browser/components/selfsupport/test/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/selfsupport/test/browser.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[DEFAULT]
-
-[browser_selfsupportAPI.js]
deleted file mode 100644
--- a/browser/components/selfsupport/test/browser_selfsupportAPI.js
+++ /dev/null
@@ -1,92 +0,0 @@
-function prefHas(pref) {
-  return Services.prefs.getPrefType(pref) != Ci.nsIPrefBranch.PREF_INVALID;
-}
-
-function prefIsSet(pref) {
-  return Services.prefs.prefHasUserValue(pref);
-}
-
-function test_resetPref() {
-  const prefNewName = "browser.newpref.fake";
-  Assert.ok(!prefHas(prefNewName), "pref should not exist");
-
-  const prefExistingName = "extensions.hotfix.id";
-  Assert.ok(prefHas(prefExistingName), "pref should exist");
-  Assert.ok(!prefIsSet(prefExistingName), "pref should not be user-set");
-  let prefExistingOriginalValue = Services.prefs.getStringPref(prefExistingName);
-
-  registerCleanupFunction(function() {
-    Services.prefs.setStringPref(prefExistingName, prefExistingOriginalValue);
-    Services.prefs.deleteBranch(prefNewName);
-  });
-
-  // 1. do nothing on an inexistent pref
-  MozSelfSupport.resetPref(prefNewName);
-  Assert.ok(!prefHas(prefNewName), "pref should still not exist");
-
-  // 2. creation of a new pref
-  Services.prefs.setIntPref(prefNewName, 10);
-  Assert.ok(prefHas(prefNewName), "pref should exist");
-  Assert.equal(Services.prefs.getIntPref(prefNewName), 10, "pref value should be 10");
-
-  MozSelfSupport.resetPref(prefNewName);
-  Assert.ok(!prefHas(prefNewName), "pref should not exist any more");
-
-  // 3. do nothing on an unchanged existing pref
-  MozSelfSupport.resetPref(prefExistingName);
-  Assert.ok(prefHas(prefExistingName), "pref should still exist");
-  Assert.equal(Services.prefs.getStringPref(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
-
-  // 4. change the value of an existing pref
-  Services.prefs.setStringPref(prefExistingName, "anyone@mozilla.org");
-  Assert.ok(prefHas(prefExistingName), "pref should exist");
-  Assert.equal(Services.prefs.getStringPref(prefExistingName), "anyone@mozilla.org", "pref value should have changed");
-
-  MozSelfSupport.resetPref(prefExistingName);
-  Assert.ok(prefHas(prefExistingName), "pref should still exist");
-  Assert.equal(Services.prefs.getStringPref(prefExistingName), prefExistingOriginalValue, "pref value should be the same as original");
-
-  // 5. delete an existing pref
-  // deleteBranch is implemented in such a way that
-  // clearUserPref can't undo its action
-  // see discussion in bug 1075160
-}
-
-function test_resetSearchEngines() {
-  const defaultEngineOriginal = Services.search.defaultEngine;
-  const visibleEnginesOriginal = Services.search.getVisibleEngines();
-
-  // 1. do nothing on unchanged search configuration
-  MozSelfSupport.resetSearchEngines();
-  Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
-  Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
-                   "default visible engines set should be reset");
-
-  // 2. change the default search engine
-  const defaultEngineNew = visibleEnginesOriginal[3];
-  Assert.notEqual(defaultEngineOriginal, defaultEngineNew, "new default engine should be different from original");
-  Services.search.defaultEngine = defaultEngineNew;
-  Assert.equal(Services.search.defaultEngine, defaultEngineNew, "default engine should be set to new");
-  MozSelfSupport.resetSearchEngines();
-  Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
-  Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
-                   "default visible engines set should be reset");
-
-  // 3. remove an engine
-  const engineRemoved = visibleEnginesOriginal[2];
-  Services.search.removeEngine(engineRemoved);
-  Assert.ok(Services.search.getVisibleEngines().indexOf(engineRemoved) == -1,
-            "removed engine should not be visible any more");
-  MozSelfSupport.resetSearchEngines();
-  Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
-  Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
-                   "default visible engines set should be reset");
-
-  // 4. add an angine
-  // we don't remove user-added engines as they are only used if selected
-}
-
-function test() {
-  test_resetPref();
-  test_resetSearchEngines();
-}
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -485,20 +485,16 @@
 #endif
 #ifdef XP_MACOSX
 @RESPATH@/browser/components/SafariProfileMigrator.js
 #endif
 @RESPATH@/components/nsINIProcessor.manifest
 @RESPATH@/components/nsINIProcessor.js
 @RESPATH@/components/nsPrompter.manifest
 @RESPATH@/components/nsPrompter.js
-#ifdef MOZ_SERVICES_HEALTHREPORT
-@RESPATH@/browser/components/SelfSupportService.manifest
-@RESPATH@/browser/components/SelfSupportService.js
-#endif
 @RESPATH@/components/SyncComponents.manifest
 @RESPATH@/components/Weave.js
 @RESPATH@/components/FxAccountsComponents.manifest
 @RESPATH@/components/FxAccountsPush.js
 @RESPATH@/components/CaptivePortalDetectComponents.manifest
 @RESPATH@/components/captivedetect.js
 @RESPATH@/components/servicesComponents.manifest
 @RESPATH@/components/cryptoComponents.manifest
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -3,17 +3,17 @@
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml" dir="">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 
-  <link rel="stylesheet" href="chrome://devtools/skin/widgets.css"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/breadcrumbs.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/inspector.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/rules.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/computed.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/fonts.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/boxmodel.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/animation.css"/>
   <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3437,19 +3437,17 @@ nsDocShell::MaybeCreateInitialClientSour
   if (!win) {
     return;
   }
 
   mInitialClientSource =
     ClientManager::CreateSource(ClientType::Window,
                                 win->EventTargetFor(TaskCategory::Other),
                                 principal);
-  if (NS_WARN_IF(!mInitialClientSource)) {
-    return;
-  }
+  MOZ_DIAGNOSTIC_ASSERT(mInitialClientSource);
 
   // Mark the initial client as execution ready, but owned by the docshell.
   // If the client is actually used this will cause ClientSource to force
   // the creation of the initial about:blank by calling nsDocShell::GetDocument().
   mInitialClientSource->DocShellExecutionReady(this);
 
   // Next, check to see if the parent is controlled.
   nsCOMPtr<nsIDocShell> parent = GetParentDocshell();
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -230,17 +230,16 @@
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/IntlUtils.h"
-#include "mozilla/dom/MozSelfSupportBinding.h"
 #include "mozilla/dom/PopStateEvent.h"
 #include "mozilla/dom/PopupBlockedEvent.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsITabChild.h"
 #include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/NavigatorBinding.h"
@@ -1206,18 +1205,16 @@ nsGlobalWindowInner::CleanUp()
 
   mConsole = nullptr;
 
   mAudioWorklet = nullptr;
   mPaintWorklet = nullptr;
 
   mExternal = nullptr;
 
-  mMozSelfSupport = nullptr;
-
   mPerformance = nullptr;
 
 #ifdef MOZ_WEBSPEECH
   mSpeechSynthesis = nullptr;
 #endif
 
 #if defined(MOZ_WIDGET_ANDROID)
   mOrientationChangeObserver = nullptr;
@@ -1503,17 +1500,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
 
   tmp->TraverseHostObjectURIs(cb);
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -1581,17 +1577,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
 
   tmp->UnlinkHostObjectURIs();
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
 
   // Here the IdleRequest list would've been unlinked, but we rely on
   // that IdleRequest objects have been traced and will remove
@@ -1796,19 +1791,17 @@ nsGlobalWindowInner::EnsureClientSource(
   //       principal.  We do this in docshell, but as mentioned we aren't
   //       smart enough to handle all cases yet.  For example, a
   //       window.open() with new URL should inherit the controller from
   //       the opener, but we probably don't handle that yet.
   if (!mClientSource) {
     mClientSource = ClientManager::CreateSource(ClientType::Window,
                                                 EventTargetFor(TaskCategory::Other),
                                                 mDoc->NodePrincipal());
-    if (NS_WARN_IF(!mClientSource)) {
-      return NS_ERROR_FAILURE;
-    }
+    MOZ_DIAGNOSTIC_ASSERT(mClientSource);
     newClientSource = true;
   }
 
   // The load may have started controlling the Client as well.  If
   // so, mark it as controlled immediately here.  The actor may
   // or may not have been notified by the parent side about being
   // controlled yet.
   if (loadInfo) {
@@ -1828,19 +1821,17 @@ nsGlobalWindowInner::EnsureClientSource(
     //  https://github.com/w3c/ServiceWorker/issues/1232
     //
     else if (mClientSource->GetController().isSome()) {
       mClientSource.reset();
       mClientSource =
         ClientManager::CreateSource(ClientType::Window,
                                     EventTargetFor(TaskCategory::Other),
                                     mDoc->NodePrincipal());
-      if (NS_WARN_IF(!mClientSource)) {
-        return NS_ERROR_FAILURE;
-      }
+      MOZ_DIAGNOSTIC_ASSERT(mClientSource);
       newClientSource = true;
     }
   }
 
   // Its possible that we got a client just after being frozen in
   // the bfcache.  In that case freeze the client immediately.
   if (newClientSource && IsFrozen()) {
     mClientSource->Freeze();
@@ -2584,31 +2575,16 @@ nsGlobalWindowInner::GetContent(JSContex
                                 JS::MutableHandle<JSObject*> aRetval,
                                 CallerType aCallerType,
                                 ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
                             (aCx, aRetval, aCallerType, aError), aError, );
 }
 
-MozSelfSupport*
-nsGlobalWindowInner::GetMozSelfSupport(ErrorResult& aError)
-{
-  if (mMozSelfSupport) {
-    return mMozSelfSupport;
-  }
-
-  // We're called from JS and want to use out existing JSContext (and,
-  // importantly, its compartment!) here.
-  AutoJSContext cx;
-  GlobalObject global(cx, FastGetGlobalJSObject());
-  mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError);
-  return mMozSelfSupport;
-}
-
 BarProp*
 nsGlobalWindowInner::GetMenubar(ErrorResult& aError)
 {
   if (!mMenubar) {
     mMenubar = new MenubarProp(this);
   }
 
   return mMenubar;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -107,17 +107,16 @@ class Function;
 class Gamepad;
 enum class ImageBitmapFormat : uint8_t;
 class IdleRequest;
 class IdleRequestCallback;
 class IncrementalRunnable;
 class IntlUtils;
 class Location;
 class MediaQueryList;
-class MozSelfSupport;
 class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
 class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
@@ -884,18 +883,16 @@ public:
   void Home(nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
   bool Find(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
             bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
             bool aShowDialog, mozilla::ErrorResult& aError);
   uint64_t GetMozPaintCount(mozilla::ErrorResult& aError);
 
   bool ShouldResistFingerprinting();
 
-  mozilla::dom::MozSelfSupport* GetMozSelfSupport(mozilla::ErrorResult& aError);
-
   already_AddRefed<nsPIDOMWindowOuter>
   OpenDialog(JSContext* aCx,
              const nsAString& aUrl,
              const nsAString& aName,
              const nsAString& aOptions,
              const mozilla::dom::Sequence<JS::Value>& aExtraArgument,
              mozilla::ErrorResult& aError);
   nsresult UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason) override;
@@ -1321,18 +1318,16 @@ protected:
   RefPtr<mozilla::dom::Worklet> mAudioWorklet;
   RefPtr<mozilla::dom::Worklet> mPaintWorklet;
   // We need to store an nsISupports pointer to this object because the
   // mozilla::dom::External class doesn't exist on b2g and using the type
   // forward declared here means that ~nsGlobalWindow wouldn't compile because
   // it wouldn't see the ~External function's declaration.
   nsCOMPtr<nsISupports>         mExternal;
 
-  RefPtr<mozilla::dom::MozSelfSupport> mMozSelfSupport;
-
   RefPtr<mozilla::dom::Storage> mLocalStorage;
   RefPtr<mozilla::dom::Storage> mSessionStorage;
 
   RefPtr<mozilla::EventListenerManager> mListenerManager;
   RefPtr<mozilla::dom::Location> mLocation;
   RefPtr<nsHistory>           mHistory;
   RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
 
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -230,17 +230,16 @@
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/IntlUtils.h"
-#include "mozilla/dom/MozSelfSupportBinding.h"
 #include "mozilla/dom/PopStateEvent.h"
 #include "mozilla/dom/PopupBlockedEvent.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsITabChild.h"
 #include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/NavigatorBinding.h"
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -105,17 +105,16 @@ class Function;
 class Gamepad;
 enum class ImageBitmapFormat : uint8_t;
 class IdleRequest;
 class IdleRequestCallback;
 class IncrementalRunnable;
 class IntlUtils;
 class Location;
 class MediaQueryList;
-class MozSelfSupport;
 class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
 class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
--- a/dom/clients/manager/ClientChannelHelper.cpp
+++ b/dom/clients/manager/ClientChannelHelper.cpp
@@ -115,16 +115,17 @@ class ClientChannelHelper final : public
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Create the new ClientSource.  This should only happen for window
       // Clients since support cross-origin redirects are blocked by the
       // same-origin security policy.
       reservedClient.reset();
       reservedClient = ClientManager::CreateSource(ClientType::Window,
                                                    mEventTarget, principal);
+      MOZ_DIAGNOSTIC_ASSERT(reservedClient);
 
       newLoadInfo->GiveReservedClientSource(Move(reservedClient));
     }
 
     // Normally we keep the controller across channel redirects, but we must
     // clear it when a non-subresource load redirects.  Only do this for real
     // redirects, however.
     //
@@ -223,17 +224,17 @@ AddClientChannelHelper(nsIChannel* aChan
   if (initialClientInfo.isNothing() && reservedClientInfo.isNothing()) {
     // Wait to reserve the client until we are reasonably sure this method
     // will succeed.  We should only follow this path for window clients.
     // Workers should always provide a reserved ClientInfo since their
     // ClientSource object is owned by a different thread.
     reservedClient = ClientManager::CreateSource(ClientType::Window,
                                                  aEventTarget,
                                                  channelPrincipal);
-    NS_ENSURE_TRUE(reservedClient, NS_ERROR_FAILURE);
+    MOZ_DIAGNOSTIC_ASSERT(reservedClient);
   }
 
   RefPtr<ClientChannelHelper> helper =
     new ClientChannelHelper(outerCallbacks, aEventTarget);
 
   // Only set the callbacks helper if we are able to reserve the client
   // successfully.
   rv = aChannel->SetNotificationCallbacks(helper);
--- a/dom/clients/manager/ClientManager.cpp
+++ b/dom/clients/manager/ClientManager.cpp
@@ -98,46 +98,58 @@ ClientManager::Shutdown()
 
 UniquePtr<ClientSource>
 ClientManager::CreateSourceInternal(ClientType aType,
                                     nsISerialEventTarget* aEventTarget,
                                     const PrincipalInfo& aPrincipal)
 {
   NS_ASSERT_OWNINGTHREAD(ClientManager);
 
-  if (IsShutdown()) {
-    return nullptr;
-  }
-
   nsID id;
   nsresult rv = nsContentUtils::GenerateUUIDInPlace(id);
+  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
+    // If we can't even get a UUID, at least make sure not to use a garbage
+    // value.  Instead return a shutdown ClientSource with a zero'd id.
+    // This should be exceptionally rare, if it happens at all.
+    id.Clear();
+    ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
+    UniquePtr<ClientSource> source(new ClientSource(this, aEventTarget, args));
+    source->Shutdown();
+    return Move(source);
   }
 
   ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
   UniquePtr<ClientSource> source(new ClientSource(this, aEventTarget, args));
+
+  if (IsShutdown()) {
+    source->Shutdown();
+    return Move(source);
+  }
+
   source->Activate(GetActor());
 
   return Move(source);
 }
 
 already_AddRefed<ClientHandle>
 ClientManager::CreateHandleInternal(const ClientInfo& aClientInfo,
                                     nsISerialEventTarget* aSerialEventTarget)
 {
   NS_ASSERT_OWNINGTHREAD(ClientManager);
   MOZ_DIAGNOSTIC_ASSERT(aSerialEventTarget);
 
+  RefPtr<ClientHandle> handle = new ClientHandle(this, aSerialEventTarget,
+                                                 aClientInfo);
+
   if (IsShutdown()) {
-    return nullptr;
+    handle->Shutdown();
+    return handle.forget();
   }
 
-  RefPtr<ClientHandle> handle = new ClientHandle(this, aSerialEventTarget,
-                                                 aClientInfo);
   handle->Activate(GetActor());
 
   return handle.forget();
 }
 
 already_AddRefed<ClientOpPromise>
 ClientManager::StartOp(const ClientOpConstructorArgs& aArgs,
                        nsISerialEventTarget* aSerialEventTarget)
@@ -215,17 +227,17 @@ ClientManager::CreateSource(ClientType a
                             nsIPrincipal* aPrincipal)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPrincipal);
 
   PrincipalInfo principalInfo;
   nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
+    MOZ_CRASH("ClientManager::CreateSource() cannot serialize bad principal");
   }
 
   RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
   return mgr->CreateSourceInternal(aType, aEventTarget, principalInfo);
 }
 
 // static
 UniquePtr<ClientSource>
--- a/dom/clients/manager/ClientManagerService.cpp
+++ b/dom/clients/manager/ClientManagerService.cpp
@@ -19,16 +19,17 @@ namespace dom {
 
 using mozilla::ipc::AssertIsOnBackgroundThread;
 using mozilla::ipc::ContentPrincipalInfo;
 using mozilla::ipc::PrincipalInfo;
 
 namespace {
 
 ClientManagerService* sClientManagerServiceInstance = nullptr;
+bool sClientManagerServiceShutdownRegistered = false;
 
 bool
 MatchPrincipalInfo(const PrincipalInfo& aLeft, const PrincipalInfo& aRight)
 {
   if (aLeft.type() != aRight.type()) {
     return false;
   }
 
@@ -141,45 +142,56 @@ OnShutdown()
 
 } // anonymous namespace
 
 ClientManagerService::ClientManagerService()
   : mShutdown(false)
 {
   AssertIsOnBackgroundThread();
 
-  // While the ClientManagerService will be gracefully terminated as windows
-  // and workers are naturally killed, this can cause us to do extra work
-  // relatively late in the shutdown process.  To avoid this we eagerly begin
-  // shutdown at the first sign it has begun.  Since we handle normal shutdown
-  // gracefully we don't really need to block anything here.  We just begin
-  // destroying our IPC actors immediately.
-  OnShutdown()->Then(GetCurrentThreadSerialEventTarget(), __func__,
-    [] () {
-      RefPtr<ClientManagerService> svc = ClientManagerService::GetInstance();
-      if (svc) {
-        svc->Shutdown();
-      }
-    });
+  // Only register one shutdown handler at a time.  If a previous service
+  // instance did this, but shutdown has not come, then we can avoid
+  // doing it again.
+  if (!sClientManagerServiceShutdownRegistered) {
+    sClientManagerServiceShutdownRegistered = true;
+
+    // While the ClientManagerService will be gracefully terminated as windows
+    // and workers are naturally killed, this can cause us to do extra work
+    // relatively late in the shutdown process.  To avoid this we eagerly begin
+    // shutdown at the first sign it has begun.  Since we handle normal shutdown
+    // gracefully we don't really need to block anything here.  We just begin
+    // destroying our IPC actors immediately.
+    OnShutdown()->Then(GetCurrentThreadSerialEventTarget(), __func__,
+      [] () {
+        // Look up the latest service instance, if it exists.  This may
+        // be different from the instance that registered the shutdown
+        // handler.
+        RefPtr<ClientManagerService> svc = ClientManagerService::GetInstance();
+        if (svc) {
+          svc->Shutdown();
+        }
+      });
+  }
 }
 
 ClientManagerService::~ClientManagerService()
 {
   AssertIsOnBackgroundThread();
   MOZ_DIAGNOSTIC_ASSERT(mSourceTable.Count() == 0);
   MOZ_DIAGNOSTIC_ASSERT(mManagerList.IsEmpty());
 
   MOZ_DIAGNOSTIC_ASSERT(sClientManagerServiceInstance == this);
   sClientManagerServiceInstance = nullptr;
 }
 
 void
 ClientManagerService::Shutdown()
 {
   AssertIsOnBackgroundThread();
+  MOZ_DIAGNOSTIC_ASSERT(sClientManagerServiceShutdownRegistered);
 
   // If many ClientManagerService are created and destroyed quickly we can
   // in theory get more than one shutdown listener calling us.
   if (mShutdown) {
     return;
   }
   mShutdown = true;
 
--- a/dom/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -177,16 +177,20 @@ ClientSource::GetInnerWindow() const
 }
 
 void
 ClientSource::WorkerExecutionReady(WorkerPrivate* aWorkerPrivate)
 {
   MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
   aWorkerPrivate->AssertIsOnWorkerThread();
 
+  if (IsShutdown()) {
+    return;
+  }
+
   // Its safe to store the WorkerPrivate* here because the ClientSource
   // is explicitly destroyed by WorkerPrivate before exiting its run loop.
   MOZ_DIAGNOSTIC_ASSERT(mOwner.is<Nothing>());
   mOwner = AsVariant(aWorkerPrivate);
 
   ClientSourceExecutionReadyArgs args(
     aWorkerPrivate->GetLocationInfo().mHref,
     FrameType::None);
@@ -197,16 +201,20 @@ ClientSource::WorkerExecutionReady(Worke
 nsresult
 ClientSource::WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(aInnerWindow);
   MOZ_DIAGNOSTIC_ASSERT(aInnerWindow->IsCurrentInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(aInnerWindow->HasActiveDocument());
 
+  if (IsShutdown()) {
+    return NS_OK;
+  }
+
   nsIDocument* doc = aInnerWindow->GetExtantDoc();
   if (NS_WARN_IF(!doc)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // Don't use nsAutoCString here since IPC requires a full nsCString anyway.
   nsCString spec;
 
@@ -248,16 +256,20 @@ ClientSource::WindowExecutionReady(nsPID
 }
 
 nsresult
 ClientSource::DocShellExecutionReady(nsIDocShell* aDocShell)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(aDocShell);
 
+  if (IsShutdown()) {
+    return NS_OK;
+  }
+
   nsPIDOMWindowOuter* outer = aDocShell->GetWindow();
   if (NS_WARN_IF(!outer)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // TODO: dedupe this with WindowExecutionReady
   FrameType frameType = FrameType::Top_level;
   if (!outer->IsTopLevelWindow()) {
@@ -301,19 +313,25 @@ ClientSource::Info() const
   return mClientInfo;
 }
 
 void
 ClientSource::WorkerSyncPing(WorkerPrivate* aWorkerPrivate)
 {
   NS_ASSERT_OWNINGTHREAD(ClientSource);
   MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
+
+  if (IsShutdown()) {
+    return;
+  }
+
   MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate == mManager->GetWorkerPrivate());
   aWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_DIAGNOSTIC_ASSERT(GetActor());
+
   GetActor()->SendWorkerSyncPing();
 }
 
 void
 ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
 {
   NS_ASSERT_OWNINGTHREAD(ClientSource);
 
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -259,37 +259,16 @@ BuildTransactionHashes(const nsCString& 
     MOZ_LOG(gU2FLog, LogLevel::Debug,
             ("dom::U2FManager::Client Data Hash (base64): %s",
               NS_ConvertUTF16toUTF8(base64).get()));
   }
 
   return NS_OK;
 }
 
-template<typename T, typename C>
-static void
-ExecuteCallback(T& aResp, Maybe<nsMainThreadPtrHandle<C>>& aCb)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  if (aCb.isNothing()) {
-    return;
-  }
-
-  // reset callback earlier to allow reentry from callback.
-  nsMainThreadPtrHandle<C> callback(aCb.ref());
-  aCb.reset();
-  MOZ_ASSERT(aCb.isNothing());
-  MOZ_ASSERT(!!callback);
-
-  ErrorResult error;
-  callback->Call(aResp, error);
-  NS_WARNING_ASSERTION(!error.Failed(), "dom::U2F::Promise callback failed");
-  error.SuppressException(); // Useful exceptions already emitted
-}
-
 /***********************************************************************
  * U2F JavaScript API Implementation
  **********************************************************************/
 
 U2F::~U2F()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -297,19 +276,16 @@ U2F::~U2F()
     RejectTransaction(NS_ERROR_ABORT);
   }
 
   if (mChild) {
     RefPtr<WebAuthnTransactionChild> c;
     mChild.swap(c);
     c->Disconnect();
   }
-
-  mRegisterCallback.reset();
-  mSignCallback.reset();
 }
 
 void
 U2F::Init(ErrorResult& aRv)
 {
   MOZ_ASSERT(mParent);
 
   nsCOMPtr<nsIDocument> doc = mParent->GetDoc();
@@ -332,45 +308,64 @@ U2F::Init(ErrorResult& aRv)
 }
 
 /* virtual */ JSObject*
 U2F::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return U2FBinding::Wrap(aCx, this, aGivenProto);
 }
 
+template<typename T, typename C>
+void
+U2F::ExecuteCallback(T& aResp, nsMainThreadPtrHandle<C>& aCb)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aCb);
+
+  // Assert that mTransaction was cleared before before we were called to allow
+  // reentrancy from microtask checkpoints.
+  MOZ_ASSERT(mTransaction.isNothing());
+
+  ErrorResult error;
+  aCb->Call(aResp, error);
+  NS_WARNING_ASSERTION(!error.Failed(), "dom::U2F::Promise callback failed");
+  error.SuppressException(); // Useful exceptions already emitted
+}
+
 void
 U2F::Register(const nsAString& aAppId,
               const Sequence<RegisterRequest>& aRegisterRequests,
               const Sequence<RegisteredKey>& aRegisteredKeys,
               U2FRegisterCallback& aCallback,
               const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
               ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome()) {
     CancelTransaction(NS_ERROR_ABORT);
   }
 
-  MOZ_ASSERT(mRegisterCallback.isNothing());
-  mRegisterCallback = Some(nsMainThreadPtrHandle<U2FRegisterCallback>(
-                        new nsMainThreadPtrHolder<U2FRegisterCallback>(
-                            "U2F::Register::callback", &aCallback)));
+  nsMainThreadPtrHandle<U2FRegisterCallback> callback(
+    new nsMainThreadPtrHolder<U2FRegisterCallback>("U2F::Register::callback",
+                                                   &aCallback));
 
-  uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
+  // Ensure we have a callback.
+  if (NS_WARN_IF(!callback)) {
+    return;
+  }
 
   // Evaluate the AppID
   nsString adjustedAppId;
   adjustedAppId.Assign(aAppId);
   ErrorCode appIdResult = EvaluateAppID(mParent, mOrigin, adjustedAppId);
   if (appIdResult != ErrorCode::OK) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(appIdResult));
-    ExecuteCallback(response, mRegisterCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   // Produce the AppParam from the current AppID
   nsCString cAppId = NS_ConvertUTF16toUTF8(adjustedAppId);
 
   nsAutoString clientDataJSON;
 
@@ -387,76 +382,83 @@ U2F::Register(const nsAString& aAppId,
       continue;
     }
   }
 
   // Did we not get a valid RegisterRequest? Abort.
   if (clientDataJSON.IsEmpty()) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
-    ExecuteCallback(response, mRegisterCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   // Build the exclusion list, if any
   nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
   RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
                                        excludeList);
 
   auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
 
   CryptoBuffer rpIdHash, clientDataHash;
   if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
                                        rpIdHash, clientDataHash))) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
-    ExecuteCallback(response, mRegisterCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   if (!MaybeCreateBackgroundActor()) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
-    ExecuteCallback(response, mRegisterCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   ListenForVisibilityEvents();
 
   // Always blank for U2F
   nsTArray<WebAuthnExtension> extensions;
 
   // Default values for U2F.
   WebAuthnAuthenticatorSelection authSelection(false /* requireResidentKey */,
                                                false /* requireUserVerification */,
                                                false /* requirePlatformAttachment */);
 
+  uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
+
   WebAuthnMakeCredentialInfo info(rpIdHash,
                                   clientDataHash,
                                   adjustedTimeoutMillis,
                                   excludeList,
                                   extensions,
                                   authSelection);
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(U2FTransaction(clientData));
+  mTransaction = Some(U2FTransaction(clientData, Move(AsVariant(callback))));
   mChild->SendRequestRegister(mTransaction.ref().mId, info);
 }
 
 void
 U2F::FinishMakeCredential(const uint64_t& aTransactionId,
                           nsTArray<uint8_t>& aRegBuffer)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Check for a valid transaction.
   if (mTransaction.isNothing() || mTransaction.ref().mId != aTransactionId) {
     return;
   }
 
+  if (NS_WARN_IF(!mTransaction.ref().HasRegisterCallback())) {
+    RejectTransaction(NS_ERROR_ABORT);
+    return;
+  }
+
   CryptoBuffer clientDataBuf;
   if (NS_WARN_IF(!clientDataBuf.Assign(mTransaction.ref().mClientData))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   CryptoBuffer regBuf;
   if (NS_WARN_IF(!regBuf.Assign(aRegBuffer))) {
@@ -477,116 +479,129 @@ U2F::FinishMakeCredential(const uint64_t
 
   // Assemble a response object to return
   RegisterResponse response;
   response.mVersion.Construct(kRequiredU2FVersion);
   response.mClientData.Construct(clientDataBase64);
   response.mRegistrationData.Construct(registrationDataBase64);
   response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OK));
 
-  ExecuteCallback(response, mRegisterCallback);
+  // Keep the callback pointer alive.
+  nsMainThreadPtrHandle<U2FRegisterCallback> callback(
+    mTransaction.ref().GetRegisterCallback());
+
   ClearTransaction();
+  ExecuteCallback(response, callback);
 }
 
 void
 U2F::Sign(const nsAString& aAppId,
           const nsAString& aChallenge,
           const Sequence<RegisteredKey>& aRegisteredKeys,
           U2FSignCallback& aCallback,
           const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
           ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransaction.isSome()) {
     CancelTransaction(NS_ERROR_ABORT);
   }
 
-  MOZ_ASSERT(mSignCallback.isNothing());
-  mSignCallback = Some(nsMainThreadPtrHandle<U2FSignCallback>(
-                    new nsMainThreadPtrHolder<U2FSignCallback>(
-                        "U2F::Sign::callback", &aCallback)));
+  nsMainThreadPtrHandle<U2FSignCallback> callback(
+    new nsMainThreadPtrHolder<U2FSignCallback>("U2F::Sign::callback",
+                                               &aCallback));
 
-  uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
+  // Ensure we have a callback.
+  if (NS_WARN_IF(!callback)) {
+    return;
+  }
 
   // Evaluate the AppID
   nsString adjustedAppId;
   adjustedAppId.Assign(aAppId);
   ErrorCode appIdResult = EvaluateAppID(mParent, mOrigin, adjustedAppId);
   if (appIdResult != ErrorCode::OK) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(appIdResult));
-    ExecuteCallback(response, mSignCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   // Produce the AppParam from the current AppID
   nsCString cAppId = NS_ConvertUTF16toUTF8(adjustedAppId);
 
   nsAutoString clientDataJSON;
   nsresult rv = AssembleClientData(mOrigin, kGetAssertion, aChallenge,
                                    clientDataJSON);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
-    ExecuteCallback(response, mSignCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   // Build the key list, if any
   nsTArray<WebAuthnScopedCredentialDescriptor> permittedList;
   RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
                                        permittedList);
 
   auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
 
   CryptoBuffer rpIdHash, clientDataHash;
   if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
                                        rpIdHash, clientDataHash))) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
-    ExecuteCallback(response, mSignCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   if (!MaybeCreateBackgroundActor()) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OTHER_ERROR));
-    ExecuteCallback(response, mSignCallback);
+    ExecuteCallback(response, callback);
     return;
   }
 
   ListenForVisibilityEvents();
 
   // Always blank for U2F
   nsTArray<WebAuthnExtension> extensions;
 
+  uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
+
   WebAuthnGetAssertionInfo info(rpIdHash,
                                 clientDataHash,
                                 adjustedTimeoutMillis,
                                 permittedList,
                                 extensions);
 
   MOZ_ASSERT(mTransaction.isNothing());
-  mTransaction = Some(U2FTransaction(clientData));
+  mTransaction = Some(U2FTransaction(clientData, Move(AsVariant(callback))));
   mChild->SendRequestSign(mTransaction.ref().mId, info);
 }
 
 void
 U2F::FinishGetAssertion(const uint64_t& aTransactionId,
                         nsTArray<uint8_t>& aCredentialId,
                         nsTArray<uint8_t>& aSigBuffer)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Check for a valid transaction.
   if (mTransaction.isNothing() || mTransaction.ref().mId != aTransactionId) {
     return;
   }
 
+  if (NS_WARN_IF(!mTransaction.ref().HasSignCallback())) {
+    RejectTransaction(NS_ERROR_ABORT);
+    return;
+  }
+
   CryptoBuffer clientDataBuf;
   if (NS_WARN_IF(!clientDataBuf.Assign(mTransaction.ref().mClientData))) {
     RejectTransaction(NS_ERROR_ABORT);
     return;
   }
 
   CryptoBuffer credBuf;
   if (NS_WARN_IF(!credBuf.Assign(aCredentialId))) {
@@ -615,50 +630,62 @@ U2F::FinishGetAssertion(const uint64_t& 
   }
 
   SignResponse response;
   response.mKeyHandle.Construct(keyHandleBase64);
   response.mClientData.Construct(clientDataBase64);
   response.mSignatureData.Construct(signatureDataBase64);
   response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::OK));
 
-  ExecuteCallback(response, mSignCallback);
+  // Keep the callback pointer alive.
+  nsMainThreadPtrHandle<U2FSignCallback> callback(
+    mTransaction.ref().GetSignCallback());
+
   ClearTransaction();
+  ExecuteCallback(response, callback);
 }
 
 void
 U2F::ClearTransaction()
 {
   if (!NS_WARN_IF(mTransaction.isNothing())) {
     StopListeningForVisibilityEvents();
   }
 
   mTransaction.reset();
 }
 
 void
 U2F::RejectTransaction(const nsresult& aError)
 {
-  if (!NS_WARN_IF(mTransaction.isNothing())) {
-    ErrorCode code = ConvertNSResultToErrorCode(aError);
-
-    if (mRegisterCallback.isSome()) {
-      RegisterResponse response;
-      response.mErrorCode.Construct(static_cast<uint32_t>(code));
-      ExecuteCallback(response, mRegisterCallback);
-    }
-
-    if (mSignCallback.isSome()) {
-      SignResponse response;
-      response.mErrorCode.Construct(static_cast<uint32_t>(code));
-      ExecuteCallback(response, mSignCallback);
-    }
+  if (NS_WARN_IF(mTransaction.isNothing())) {
+    return;
   }
 
-  ClearTransaction();
+  StopListeningForVisibilityEvents();
+
+  // Clear out mTransaction before calling ExecuteCallback() below to allow
+  // reentrancy from microtask checkpoints.
+  Maybe<U2FTransaction> maybeTransaction(Move(mTransaction));
+  MOZ_ASSERT(mTransaction.isNothing() && maybeTransaction.isSome());
+
+  U2FTransaction& transaction = maybeTransaction.ref();
+  ErrorCode code = ConvertNSResultToErrorCode(aError);
+
+  if (transaction.HasRegisterCallback()) {
+    RegisterResponse response;
+    response.mErrorCode.Construct(static_cast<uint32_t>(code));
+    ExecuteCallback(response, transaction.GetRegisterCallback());
+  }
+
+  if (transaction.HasSignCallback()) {
+    SignResponse response;
+    response.mErrorCode.Construct(static_cast<uint32_t>(code));
+    ExecuteCallback(response, transaction.GetSignCallback());
+  }
 }
 
 void
 U2F::CancelTransaction(const nsresult& aError)
 {
   if (!NS_WARN_IF(!mChild || mTransaction.isNothing())) {
     mChild->SendRequestCancel(mTransaction.ref().mId);
   }
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -26,27 +26,51 @@ class U2FRegisterCallback;
 class U2FSignCallback;
 
 // Defined in U2FBinding.h by the U2F.webidl; their use requires a JSContext.
 struct RegisterRequest;
 struct RegisteredKey;
 
 class U2FTransaction
 {
+  typedef Variant<nsMainThreadPtrHandle<U2FRegisterCallback>,
+                  nsMainThreadPtrHandle<U2FSignCallback>> U2FCallback;
+
 public:
-  explicit U2FTransaction(const nsCString& aClientData)
+  explicit U2FTransaction(const nsCString& aClientData,
+                          const U2FCallback&& aCallback)
     : mClientData(aClientData)
+    , mCallback(Move(aCallback))
     , mId(NextId())
   {
     MOZ_ASSERT(mId > 0);
   }
 
+  bool HasRegisterCallback() {
+    return mCallback.is<nsMainThreadPtrHandle<U2FRegisterCallback>>();
+  }
+
+  auto& GetRegisterCallback() {
+    return mCallback.as<nsMainThreadPtrHandle<U2FRegisterCallback>>();
+  }
+
+  bool HasSignCallback() {
+    return mCallback.is<nsMainThreadPtrHandle<U2FSignCallback>>();
+  }
+
+  auto& GetSignCallback() {
+    return mCallback.as<nsMainThreadPtrHandle<U2FSignCallback>>();
+  }
+
   // Client data used to assemble reply objects.
   nsCString mClientData;
 
+  // The callback passed to the API.
+  U2FCallback mCallback;
+
   // Unique transaction id.
   uint64_t mId;
 
 private:
   // Generates a unique id for new transactions. This doesn't have to be unique
   // forever, it's sufficient to differentiate between temporally close
   // transactions, where messages can intersect. Can overflow.
   static uint64_t NextId() {
@@ -112,27 +136,26 @@ public:
 protected:
   // Cancels the current transaction (by sending a Cancel message to the
   // parent) and rejects it by calling RejectTransaction().
   void CancelTransaction(const nsresult& aError) override;
 
 private:
   ~U2F();
 
+  template<typename T, typename C>
+  void ExecuteCallback(T& aResp, nsMainThreadPtrHandle<C>& aCb);
+
   // Clears all information we have about the current transaction.
   void ClearTransaction();
-  // Rejects the current transaction and calls ClearTransaction().
+  // Rejects the current transaction and clears it.
   void RejectTransaction(const nsresult& aError);
 
   nsString mOrigin;
 
-  // U2F API callbacks.
-  Maybe<nsMainThreadPtrHandle<U2FRegisterCallback>> mRegisterCallback;
-  Maybe<nsMainThreadPtrHandle<U2FSignCallback>> mSignCallback;
-
   // The current transaction, if any.
   Maybe<U2FTransaction> mTransaction;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2F_h
deleted file mode 100644
--- a/dom/webidl/MozSelfSupport.webidl
+++ /dev/null
@@ -1,77 +0,0 @@
-/* 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/. */
-
-/**
- * The MozSelfSupport interface allows external Mozilla support sites such as
- * FHR and SUMO to access data and control settings that are not otherwise
- * exposed to external content.
- *
- * At the moment, this is a ChromeOnly interface, but the plan is to allow
- * specific Mozilla domains to access it directly.
- */
-[ChromeOnly,
- JSImplementation="@mozilla.org/mozselfsupport;1",
- Constructor()]
-interface MozSelfSupport
-{
-  /**
-   * Controls whether uploading FHR data is allowed.
-   */
-  attribute boolean healthReportDataSubmissionEnabled;
-
-  /**
-   * Retrieve a list of the archived Telemetry pings.
-   * This contains objects with ping info, which are of the form:
-   * {
-   *   type: <string>, // The pings type, e.g. "main", "environment-change", ...
-   *   timestampCreated: <number>, // The time the ping was created (ms since unix epoch).
-   *   id: <string>, // The pings UUID.
-   * }
-   *
-   * @return Promise<sequence<Object>>
-   *         Resolved with the ping infos when the archived ping list has been built.
-   */
-  Promise<sequence<object>> getTelemetryPingList();
-
-  /**
-   * Retrieve an archived Telemetry ping by it's id.
-   * This will load the ping data async from the archive, possibly hitting the disk.
-   *
-   * @return Promise<Object>
-   *         Resolved with the ping data, see the Telemetry "main" ping documentation for the format.
-   */
-  Promise<object> getTelemetryPing(DOMString pingID);
-
-  /**
-   * Get the current Telemetry environment - see the Telemetry documentation for details on the format.
-   *
-   * @return Promise<Object>
-   *         Resolved with an object containing the Telemetry environment data.
-   */
-  Promise<object> getCurrentTelemetryEnvironment();
-
-  /**
-   * Get a Telemetry "main" ping containing the current session measurements.
-   *
-   * @return Promise<Object>
-   *         Resolved with the ping data, see the Telemetry "main" ping documentation for the format.
-   */
-  Promise<object> getCurrentTelemetrySubsessionPing();
-
-  /**
-   * Resets a named pref:
-   * - if there is a default value, then change the value back to default,
-   * - if there's no default value, then delete the pref,
-   * - no-op otherwise.
-   *
-   * @param DOMString
-   *        The name of the pref to reset.
-   */
-  void resetPref(DOMString name);
-
-  /**
-   * Resets original search engines, and resets the default one.
-   */
-  void resetSearchEngines();
-};
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -298,24 +298,16 @@ partial interface Window {
                                                  optional boolean showDialog = false);
 
   /**
    * Returns the number of times this document for this window has
    * been painted to the screen.
    */
   [Throws] readonly attribute unsigned long long mozPaintCount;
 
-  /**
-   * This property exists because static attributes don't yet work for
-   * JS-implemented WebIDL (see bugs 1058606 and 863952). With this hack, we
-   * can use `MozSelfSupport.something(...)`, which will continue to work
-   * after we ditch this property and switch to static attributes. See
-   */
-  [ChromeOnly, Throws] readonly attribute MozSelfSupport MozSelfSupport;
-
            attribute EventHandler ondevicemotion;
            attribute EventHandler ondeviceorientation;
            attribute EventHandler onabsolutedeviceorientation;
            attribute EventHandler ondeviceproximity;
            attribute EventHandler onuserproximity;
            attribute EventHandler ondevicelight;
 
   void                      dump(DOMString str);
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -209,19 +209,16 @@ with Files("*Record*"):
     BUG_COMPONENT = ("Core", "Audio/Video: Recording")
 
 with Files("Media*Track*"):
     BUG_COMPONENT = ("Core", "WebRTC: Audio/Video")
 
 with Files("Mouse*"):
     BUG_COMPONENT = ("Core", "DOM: Events")
 
-with Files("MozSelfSupport.webidl"):
-    BUG_COMPONENT = ("Firefox Health Report", "Client: Desktop")
-
 with Files("MozTimeManager.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
 
 with Files("MutationEvent.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Events")
 
 with Files("NativeOSFileInternals.webidl"):
     BUG_COMPONENT = ("Toolkit", "OS.File")
@@ -688,17 +685,16 @@ WEBIDL_FILES = [
     'MenuBoxObject.webidl',
     'MessageChannel.webidl',
     'MessageEvent.webidl',
     'MessagePort.webidl',
     'MimeType.webidl',
     'MimeTypeArray.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
-    'MozSelfSupport.webidl',
     'MozStorageAsyncStatementParams.webidl',
     'MozStorageStatementParams.webidl',
     'MozStorageStatementRow.webidl',
     'MozTimeManager.webidl',
     'MutationEvent.webidl',
     'MutationObserver.webidl',
     'NamedNodeMap.webidl',
     'NativeOSFileInternals.webidl',
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -2371,19 +2371,17 @@ ServiceWorkerManager::StartControllingAD
   ServiceWorkerInfo* activeWorker = aRegistration->GetActive();
   nsPIDOMWindowInner* innerWindow = aDoc->GetInnerWindow();
   if (activeWorker && innerWindow) {
     Maybe<ClientInfo> clientInfo = innerWindow->GetClientInfo();
     if (clientInfo.isSome()) {
       RefPtr<ClientHandle> clientHandle =
         ClientManager::CreateHandle(clientInfo.ref(),
                                     SystemGroup::EventTargetFor(TaskCategory::Other));
-      if (clientHandle) {
-        ref = Move(clientHandle->Control(activeWorker->Descriptor()));
-      }
+      ref = Move(clientHandle->Control(activeWorker->Descriptor()));
     }
   }
 
   Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
   return Move(ref);
 }
 
 void
@@ -2719,19 +2717,17 @@ ServiceWorkerManager::DispatchFetchEvent
 
       if (clientInfo.isSome()) {
         // First, attempt to mark the reserved client controlled directly.  This
         // will update the controlled status in the ClientManagerService in the
         // parent.  It will also eventually propagate back to the ClientSource.
         RefPtr<ClientHandle> clientHandle =
           ClientManager::CreateHandle(clientInfo.ref(),
                                       SystemGroup::EventTargetFor(TaskCategory::Other));
-        if (clientHandle) {
-          clientHandle->Control(serviceWorker->Descriptor());
-        }
+        clientHandle->Control(serviceWorker->Descriptor());
       }
 
       // But we also note the reserved state on the LoadInfo.  This allows the
       // ClientSource to be updated immediately after the nsIChannel starts.
       // This is necessary to have the correct controller in place for immediate
       // follow-on requests.
       loadInfo->SetController(serviceWorker->Descriptor());
     }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5327,19 +5327,17 @@ WorkerPrivate::EnsureClientSource()
       type = ClientType::Serviceworker;
       break;
     default:
       MOZ_CRASH("unknown worker type!");
   }
 
   mClientSource = ClientManager::CreateSource(type, mWorkerHybridEventTarget,
                                               GetPrincipalInfo());
-  if (!mClientSource) {
-    return false;
-  }
+  MOZ_DIAGNOSTIC_ASSERT(mClientSource);
 
   if (mFrozen) {
     mClientSource->Freeze();
   }
 
   // Shortly after the client is reserved we will try loading the main script
   // for the worker.  This may get intercepted by the ServiceWorkerManager
   // which will then try to create a ClientHandle.  Its actually possible for
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-52460
+52463
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -5790,17 +5790,17 @@ IPA
 IPO/SM
 IQ/M
 IRA/SM
 IRC
 IRS/M
 ISBN
 ISIS
 ISO/M
-ISP
+ISP/SM
 ISS
 IT
 IUD
 IV/SM
 IVF
 Ia
 Iaccoca/M
 Iago/M
@@ -25839,16 +25839,17 @@ faze/GDS
 fazed/U
 faïence/M
 fealty/M
 fear/MDGS
 fearful/YP
 fearfulness/M
 fearless/PY
 fearlessness/M
+fearmonger/SMG
 fearsome
 feasibility/M
 feasible/IU
 feasibly
 feast/SMDRZG
 feaster/M
 feat/MS
 feather/SGMD
@@ -40304,17 +40305,17 @@ preoperative
 preordain/GDS
 preowned
 prep/MS
 prepackage/DSG
 prepacked
 prepaid
 preparation/SM
 preparatory
-prepare/GDS
+prepare/GDSRZ
 prepared/UP
 preparedness/UM
 prepay/GSL
 prepayment/MS
 preponderance/SM
 preponderant/Y
 preponderate/GDS
 preposition/SM
@@ -40856,16 +40857,17 @@ prude/MS
 prudence/M
 prudent/Y
 prudential/Y
 prudery/M
 prudish/YP
 prudishness/M
 prune/MZGDRS
 pruner/M
+pruno
 prurience/M
 prurient/Y
 pry/ZTGDRSM
 précis/MDG
 psalm/MS
 psalmist/SM
 psaltery/SM
 psephologist/S
@@ -49284,16 +49286,17 @@ treasurer/M
 treasury/SM
 treat/AGSMD
 treatable
 treated/U
 treatise/SM
 treatment/MS
 treaty/SM
 treble/MGDS
+trebuchet/S
 tree/MDS
 treeing
 treeless
 treelike
 treeline
 treetop/SM
 trefoil/SM
 trek/MS
--- a/gfx/layers/PaintThread.cpp
+++ b/gfx/layers/PaintThread.cpp
@@ -386,20 +386,17 @@ PaintThread::AsyncPaintTiledContents(Com
     clear.ClearBuffer();
   }
 
   DrawTarget* target = aState->mTargetTiled;
   DrawTargetCapture* capture = aState->mCapture;
 
   // Draw all the things into the actual dest target.
   target->DrawCapturedDT(capture, Matrix());
-
-  if (!mDrawTargetsToFlush.Contains(target)) {
-    mDrawTargetsToFlush.AppendElement(target);
-  }
+  target->Flush();
 
   if (gfxPrefs::LayersOMTPReleaseCaptureOnMainThread()) {
     // This should ensure the capture drawtarget, which may hold on to UnscaledFont objects,
     // gets destroyed on the main thread (See bug 1404742). This assumes (unflushed) target
     // DrawTargets do not themselves hold on to UnscaledFonts.
     NS_ReleaseOnMainThreadSystemGroup("CapturePaintState::DrawTargetCapture", aState->mCapture.forget());
   }
 
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -982,16 +982,18 @@ extern void gecko_profiler_unregister_th
 extern void gfx_critical_error(const char *aMsg);
 
 extern void gfx_critical_note(const char *aMsg);
 
 extern bool gfx_use_wrench();
 
 extern const char *gfx_wr_resource_path_override();
 
+extern bool is_glcontext_angle(void *aGlcontextPtr);
+
 extern bool is_glcontext_egl(void *aGlcontextPtr);
 
 extern bool is_in_compositor_thread();
 
 extern bool is_in_main_thread();
 
 extern bool is_in_render_thread();
 
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -312,58 +312,66 @@ RequestedModuleObject::create(JSContext*
 
 ///////////////////////////////////////////////////////////////////////////
 // IndirectBindingMap
 
 IndirectBindingMap::Binding::Binding(ModuleEnvironmentObject* environment, Shape* shape)
   : environment(environment), shape(shape)
 {}
 
-IndirectBindingMap::IndirectBindingMap(Zone* zone)
-  : map_(ZoneAllocPolicy(zone))
-{
-}
-
-bool
-IndirectBindingMap::init()
-{
-    return map_.init();
-}
-
 void
 IndirectBindingMap::trace(JSTracer* trc)
 {
-    for (Map::Enum e(map_); !e.empty(); e.popFront()) {
+    if (!map_)
+        return;
+
+    for (Map::Enum e(*map_); !e.empty(); e.popFront()) {
         Binding& b = e.front().value();
         TraceEdge(trc, &b.environment, "module bindings environment");
         TraceEdge(trc, &b.shape, "module bindings shape");
         jsid bindingName = e.front().key();
         TraceManuallyBarrieredEdge(trc, &bindingName, "module bindings binding name");
         MOZ_ASSERT(bindingName == e.front().key());
     }
 }
 
 bool
 IndirectBindingMap::put(JSContext* cx, HandleId name,
                         HandleModuleEnvironmentObject environment, HandleId localName)
 {
+    // This object might have been allocated on the background parsing thread in
+    // different zone to the final module. Lazily allocate the map so we don't
+    // have to switch its zone when merging compartments.
+    if (!map_) {
+        MOZ_ASSERT(!cx->zone()->group()->createdForHelperThread());
+        map_.emplace(cx->zone());
+        if (!map_->init()) {
+            map_.reset();
+            ReportOutOfMemory(cx);
+            return false;
+        }
+    }
+
     RootedShape shape(cx, environment->lookup(cx, localName));
     MOZ_ASSERT(shape);
-    if (!map_.put(name, Binding(environment, shape))) {
+    if (!map_->put(name, Binding(environment, shape))) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     return true;
 }
 
 bool
 IndirectBindingMap::lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const
 {
-    auto ptr = map_.lookup(name);
+    if (!map_)
+        return false;
+
+    auto ptr = map_->lookup(name);
     if (!ptr)
         return false;
 
     const Binding& binding = ptr->value();
     MOZ_ASSERT(binding.environment);
     MOZ_ASSERT(!binding.environment->inDictionaryMode());
     MOZ_ASSERT(binding.environment->containsPure(binding.shape));
     *envOut = binding.environment;
@@ -754,20 +762,19 @@ ModuleObject::create(JSContext* cx)
     RootedObject proto(cx, cx->global()->getModulePrototype());
     RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
     if (!obj)
         return nullptr;
 
     RootedModuleObject self(cx, &obj->as<ModuleObject>());
 
     Zone* zone = cx->zone();
-    IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
-    if (!bindings || !bindings->init()) {
+    IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>();
+    if (!bindings) {
         ReportOutOfMemory(cx);
-        js_delete<IndirectBindingMap>(bindings);
         return nullptr;
     }
 
     self->initReservedSlot(ImportBindingsSlot, PrivateValue(bindings));
 
     FunctionDeclarationVector* funDecls = zone->new_<FunctionDeclarationVector>(zone);
     if (!funDecls) {
         ReportOutOfMemory(cx);
@@ -1100,18 +1107,18 @@ ModuleObject::execute(JSContext* cx, Han
 
 /* static */ ModuleNamespaceObject*
 ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
 {
     MOZ_ASSERT(!self->namespace_());
     MOZ_ASSERT(exports->is<ArrayObject>());
 
     Zone* zone = cx->zone();
-    auto bindings = zone->make_unique<IndirectBindingMap>(zone);
-    if (!bindings || !bindings->init()) {
+    auto bindings = zone->make_unique<IndirectBindingMap>();
+    if (!bindings) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
     auto ns = ModuleNamespaceObject::create(cx, self, exports, Move(bindings));
     if (!ns)
         return nullptr;
 
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -2,16 +2,18 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef builtin_ModuleObject_h
 #define builtin_ModuleObject_h
 
+#include "mozilla/Maybe.h"
+
 #include "jsapi.h"
 #include "jsatom.h"
 
 #include "builtin/SelfHostingDefines.h"
 #include "js/GCVector.h"
 #include "js/Id.h"
 #include "js/UniquePtr.h"
 #include "vm/NativeObject.h"
@@ -123,51 +125,51 @@ class RequestedModuleObject : public Nat
 };
 
 typedef Rooted<RequestedModuleObject*> RootedRequestedModuleObject;
 typedef Handle<RequestedModuleObject*> HandleRequestedModuleObject;
 
 class IndirectBindingMap
 {
   public:
-    explicit IndirectBindingMap(Zone* zone);
-    bool init();
-
     void trace(JSTracer* trc);
 
     bool put(JSContext* cx, HandleId name,
              HandleModuleEnvironmentObject environment, HandleId localName);
 
     size_t count() const {
-        return map_.count();
+        return map_ ? map_->count() : 0;
     }
 
     bool has(jsid name) const {
-        return map_.has(name);
+        return map_ ? map_->has(name) : false;
     }
 
     bool lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const;
 
     template <typename Func>
     void forEachExportedName(Func func) const {
-        for (auto r = map_.all(); !r.empty(); r.popFront())
+        if (!map_)
+            return;
+
+        for (auto r = map_->all(); !r.empty(); r.popFront())
             func(r.front().key());
     }
 
   private:
     struct Binding
     {
         Binding(ModuleEnvironmentObject* environment, Shape* shape);
         HeapPtr<ModuleEnvironmentObject*> environment;
         HeapPtr<Shape*> shape;
     };
 
     typedef HashMap<jsid, Binding, DefaultHasher<jsid>, ZoneAllocPolicy> Map;
 
-    Map map_;
+    mozilla::Maybe<Map> map_;
 };
 
 class ModuleNamespaceObject : public ProxyObject
 {
   public:
     enum ModuleNamespaceSlot
     {
         ExportsSlot = 0,
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1372258.js
@@ -0,0 +1,28 @@
+if (helperThreadCount() == 0)
+    quit();
+
+// Overwrite built-in parseModule with off-thread module parser.
+function parseModule(source) {
+    offThreadCompileModule(source);
+    return finishOffThreadModule();
+}
+
+// Test case derived from: js/src/jit-test/tests/modules/many-imports.js
+
+// Test importing an import many times.
+
+load(libdir + "dummyModuleResolveHook.js");
+
+const count = 1024;
+
+let a = moduleRepo['a'] = parseModule("export let a = 1;");
+
+let s = "";
+for (let i = 0; i < count; i++) {
+    s += "import { a as i" + i + " } from 'a';\n";
+    s += "assertEq(i" + i + ", 1);\n";
+}
+let b = moduleRepo['b'] = parseModule(s);
+
+b.declarationInstantiation();
+b.evaluation();
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1924,18 +1924,21 @@ TryAttachFunCallStub(JSContext* cx, ICCa
     return true;
 }
 
 // Check if target is a native SIMD operation which returns a SIMD type.
 // If so, set res to a template object matching the SIMD type produced and return true.
 static bool
 GetTemplateObjectForSimd(JSContext* cx, JSFunction* target, MutableHandleObject res)
 {
+    if (!target->hasJitInfo())
+        return false;
+
     const JSJitInfo* jitInfo = target->jitInfo();
-    if (!jitInfo || jitInfo->type() != JSJitInfo::InlinableNative)
+    if (jitInfo->type() != JSJitInfo::InlinableNative)
         return false;
 
     // Check if this is a native inlinable SIMD operation.
     SimdType ctrlType;
     switch (jitInfo->inlinableNative) {
       case InlinableNative::SimdInt8x16:   ctrlType = SimdType::Int8x16;   break;
       case InlinableNative::SimdUint8x16:  ctrlType = SimdType::Uint8x16;  break;
       case InlinableNative::SimdInt16x8:   ctrlType = SimdType::Int16x8;   break;
@@ -2365,21 +2368,20 @@ TryAttachCallStub(JSContext* cx, ICCall_
                 return false;
             if (skipAttach) {
                 *handled = true;
                 return true;
             }
             MOZ_ASSERT_IF(templateObject, !templateObject->group()->maybePreliminaryObjects());
         }
 
-        bool ignoresReturnValue = false;
-        if (op == JSOP_CALL_IGNORES_RV && fun->isNative()) {
-            const JSJitInfo* jitInfo = fun->jitInfo();
-            ignoresReturnValue = jitInfo && jitInfo->type() == JSJitInfo::IgnoresReturnValueNative;
-        }
+        bool ignoresReturnValue = op == JSOP_CALL_IGNORES_RV &&
+                                  fun->isNative() &&
+                                  fun->hasJitInfo() &&
+                                  fun->jitInfo()->type() == JSJitInfo::IgnoresReturnValueNative;
 
         JitSpew(JitSpew_BaselineIC, "  Generating Call_Native stub (fun=%p, cons=%s, spread=%s)",
                 fun.get(), constructing ? "yes" : "no", isSpread ? "yes" : "no");
         ICCall_Native::Compiler compiler(cx, typeMonitorFallback->firstMonitorStub(),
                                          fun, templateObject, constructing, ignoresReturnValue,
                                          isSpread, script->pcToOffset(pc));
         ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
         if (!newStub)
@@ -3549,16 +3551,17 @@ ICCall_Native::Compiler::generateStubCod
 
 #ifdef JS_SIMULATOR
     // The simulator requires VM calls to be redirected to a special swi
     // instruction to handle them, so we store the redirected pointer in the
     // stub and use that instead of the original one.
     masm.callWithABI(Address(ICStubReg, ICCall_Native::offsetOfNative()));
 #else
     if (ignoresReturnValue_) {
+        MOZ_ASSERT(callee_->hasJitInfo());
         masm.loadPtr(Address(callee, JSFunction::offsetOfJitInfo()), callee);
         masm.callWithABI(Address(callee, JSJitInfo::offsetOfIgnoresReturnValueNative()));
     } else {
         masm.callWithABI(Address(callee, JSFunction::offsetOfNative()));
     }
 #endif
 
     // Test for failure.
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -342,17 +342,17 @@ IsCacheableGetPropCallNative(JSObject* o
     if (!getter.isNative())
         return false;
 
     if (getter.isClassConstructor())
         return false;
 
     // Check for a getter that has jitinfo and whose jitinfo says it's
     // OK with both inner and outer objects.
-    if (getter.jitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
+    if (getter.hasJitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
         return true;
 
     // For getters that need the WindowProxy (instead of the Window) as this
     // object, don't cache if obj is the Window, since our cache will pass that
     // instead of the WindowProxy.
     return !IsWindow(obj);
 }
 
@@ -844,17 +844,17 @@ GetPropIRGenerator::tryAttachWindowProxy
       case CanAttachCallGetter: {
         if (!IsCacheableGetPropCallNative(windowObj, holder, shape))
             return false;
 
         // Make sure the native getter is okay with the IC passing the Window
         // instead of the WindowProxy as |this| value.
         JSFunction* callee = &shape->getterObject()->as<JSFunction>();
         MOZ_ASSERT(callee->isNative());
-        if (!callee->jitInfo() || callee->jitInfo()->needsOuterizedThisObject())
+        if (!callee->hasJitInfo() || callee->jitInfo()->needsOuterizedThisObject())
             return false;
 
         // If a |super| access, it is not worth the complexity to attach an IC.
         if (isSuper())
             return false;
 
         // Guard the incoming object is a WindowProxy and inline a getter call based
         // on the Window object.
@@ -3160,17 +3160,17 @@ IsCacheableSetPropCallNative(JSObject* o
 
     JSFunction& setter = shape->setterObject()->as<JSFunction>();
     if (!setter.isNative())
         return false;
 
     if (setter.isClassConstructor())
         return false;
 
-    if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
+    if (setter.hasJitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
         return true;
 
     return !IsWindow(obj);
 }
 
 static bool
 IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
                                bool* isTemporarilyUnoptimizable = nullptr)
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4048,19 +4048,19 @@ CodeGenerator::visitCallNative(LCallNati
     emitTracelogStartEvent(TraceLogger_Call);
 
     // Construct and execute call.
     masm.setupUnalignedABICall(tempReg);
     masm.passABIArg(argContextReg);
     masm.passABIArg(argUintNReg);
     masm.passABIArg(argVpReg);
     JSNative native = target->native();
-    if (call->ignoresReturnValue()) {
+    if (call->ignoresReturnValue() && target->hasJitInfo()) {
         const JSJitInfo* jitInfo = target->jitInfo();
-        if (jitInfo && jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
+        if (jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
             native = jitInfo->ignoresReturnValueMethod;
     }
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, native), MoveOp::GENERAL,
                      CheckUnsafeCallWithABI::DontCheckHasExitFrame);
 
     emitTracelogStopEvent(TraceLogger_Call);
 
     // Test for failure.
@@ -4105,17 +4105,17 @@ LoadDOMPrivate(MacroAssembler& masm, Reg
 }
 
 void
 CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
 {
     WrappedFunction* target = call->getSingleTarget();
     MOZ_ASSERT(target);
     MOZ_ASSERT(target->isNative());
-    MOZ_ASSERT(target->jitInfo());
+    MOZ_ASSERT(target->hasJitInfo());
     MOZ_ASSERT(call->mir()->isCallDOMNative());
 
     int callargslot = call->argslot();
     int unusedStack = StackOffsetOfPassedArg(callargslot);
 
     // Registers used for callWithABI() argument-passing.
     const Register argJSContext = ToRegister(call->getArgJSContext());
     const Register argObj       = ToRegister(call->getArgObj());
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3745,26 +3745,26 @@ IonBuilder::inlineScriptedCall(CallInfo&
     if (callInfo.constructing()) {
         MDefinition* thisDefn = createThis(target, callInfo.fun(), callInfo.getNewTarget());
         if (!thisDefn)
             return abort(AbortReason::Alloc);
         callInfo.setThis(thisDefn);
     }
 
     // Capture formals in the outer resume point.
-    MOZ_TRY(callInfo.pushFormals(this, current));
+    MOZ_TRY(callInfo.pushCallStack(this, current));
 
     MResumePoint* outerResumePoint =
         MResumePoint::New(alloc(), current, pc, MResumePoint::Outer);
     if (!outerResumePoint)
         return abort(AbortReason::Alloc);
     current->setOuterResumePoint(outerResumePoint);
 
     // Pop formals again, except leave |fun| on stack for duration of call.
-    callInfo.popFormals(current);
+    callInfo.popCallStack(current);
     current->push(callInfo.fun());
 
     JSScript* calleeScript = target->nonLazyScript();
     BaselineInspector inspector(calleeScript);
 
     // Improve type information of |this| when not set.
     if (callInfo.constructing() &&
         !callInfo.thisArg()->resultTypeSet())
@@ -4411,17 +4411,17 @@ IonBuilder::inlineGenericFallback(JSFunc
     MBasicBlock* fallbackBlock;
     MOZ_TRY_VAR(fallbackBlock, newBlock(dispatchBlock, pc));
     graph().addBlock(fallbackBlock);
 
     // Create a new CallInfo to track modified state within this block.
     CallInfo fallbackInfo(alloc(), pc, callInfo.constructing(), callInfo.ignoresReturnValue());
     if (!fallbackInfo.init(callInfo))
         return abort(AbortReason::Alloc);
-    fallbackInfo.popFormals(fallbackBlock);
+    fallbackInfo.popCallStack(fallbackBlock);
 
     // Generate an MCall, which uses stateful |current|.
     MOZ_TRY(setCurrentAndSpecializePhis(fallbackBlock));
     MOZ_TRY(makeCall(target, fallbackInfo));
 
     // Pass return block to caller as |current|.
     return Ok();
 }
@@ -4468,17 +4468,17 @@ IonBuilder::inlineObjectGroupFallback(Ca
     dispatchBlock->add(undefined);
     dispatchBlock->rewriteAtDepth(-int(callInfo.numFormals()), undefined);
 
     // Construct a block that does nothing but remove formals from the stack.
     // This is effectively changing the entry resume point of the later fallback block.
     MBasicBlock* prepBlock;
     MOZ_TRY_VAR(prepBlock, newBlock(dispatchBlock, pc));
     graph().addBlock(prepBlock);
-    fallbackInfo.popFormals(prepBlock);
+    fallbackInfo.popCallStack(prepBlock);
 
     // Construct a block into which the MGetPropertyCache can be moved.
     // This is subtle: the pc and resume point are those of the MGetPropertyCache!
     InlinePropertyTable* propTable = cache->propTable();
     MResumePoint* priorResumePoint = propTable->takePriorResumePoint();
     MOZ_ASSERT(propTable->pc() != nullptr);
     MOZ_ASSERT(priorResumePoint != nullptr);
     MBasicBlock* getPropBlock;
@@ -4531,17 +4531,17 @@ IonBuilder::inlineCalls(CallInfo& callIn
     MOZ_ASSERT(IsIonInlinablePC(pc));
     MOZ_ASSERT(choiceSet.length() == targets.length());
     MOZ_ASSERT_IF(!maybeCache, targets.length() >= 2);
     MOZ_ASSERT_IF(maybeCache, targets.length() >= 1);
     MOZ_ASSERT_IF(maybeCache, maybeCache->value()->type() == MIRType::Object);
 
     MBasicBlock* dispatchBlock = current;
     callInfo.setImplicitlyUsedUnchecked();
-    MOZ_TRY(callInfo.pushFormals(this, dispatchBlock));
+    MOZ_TRY(callInfo.pushCallStack(this, dispatchBlock));
 
     // Patch any InlinePropertyTable to only contain functions that are
     // inlineable. The InlinePropertyTable will also be patched at the end to
     // exclude native functions that vetoed inlining.
     if (maybeCache) {
         InlinePropertyTable* propTable = maybeCache->propTable();
         propTable->trimToTargets(targets);
         if (propTable->numEntries() == 0)
@@ -4564,17 +4564,17 @@ IonBuilder::inlineCalls(CallInfo& callIn
     jsbytecode* postCall = GetNextPc(pc);
     MBasicBlock* returnBlock;
     MOZ_TRY_VAR(returnBlock, newBlock(stackDepth, postCall));
     graph().addBlock(returnBlock);
     returnBlock->setCallerResumePoint(callerResumePoint_);
 
     // Set up stack, used to manually create a post-call resume point.
     returnBlock->inheritSlots(dispatchBlock);
-    callInfo.popFormals(returnBlock);
+    callInfo.popCallStack(returnBlock);
 
     MPhi* retPhi = MPhi::New(alloc());
     returnBlock->addPhi(retPhi);
     returnBlock->push(retPhi);
 
     // Create a resume point from current stack state.
     if (!returnBlock->initEntrySlots(alloc()))
         return abort(AbortReason::Alloc);
@@ -4627,17 +4627,17 @@ IonBuilder::inlineCalls(CallInfo& callIn
         int funIndex = inlineBlock->entryResumePoint()->stackDepth() - callInfo.numFormals();
         inlineBlock->entryResumePoint()->replaceOperand(funIndex, funcDef);
         inlineBlock->rewriteSlot(funIndex, funcDef);
 
         // Create a new CallInfo to track modified state within the inline block.
         CallInfo inlineInfo(alloc(), pc, callInfo.constructing(), callInfo.ignoresReturnValue());
         if (!inlineInfo.init(callInfo))
             return abort(AbortReason::Alloc);
-        inlineInfo.popFormals(inlineBlock);
+        inlineInfo.popCallStack(inlineBlock);
         inlineInfo.setFun(funcDef);
 
         if (maybeCache) {
             // Assign the 'this' value a TypeSet specialized to the groups that
             // can generate this inlining target.
             MOZ_ASSERT(callInfo.thisArg() == maybeCache->value());
             TemporaryTypeSet* thisTypes =
                 maybeCache->propTable()->buildTypeSetForFunction(alloc(), target);
@@ -5260,16 +5260,30 @@ IonBuilder::jsop_funapplyarray(uint32_t 
     current->push(apply);
     MOZ_TRY(resumeAfter(apply));
 
     TemporaryTypeSet* types = bytecodeTypes(pc);
     return pushTypeBarrier(apply, types, BarrierKind::TypeSet);
 }
 
 AbortReasonOr<Ok>
+CallInfo::savePriorCallStack(MIRGenerator* mir, MBasicBlock* current, size_t peekDepth)
+{
+    MOZ_ASSERT(priorArgs_.empty());
+    if (!priorArgs_.reserve(peekDepth))
+        return mir->abort(AbortReason::Alloc);
+    while (peekDepth) {
+        priorArgs_.infallibleAppend(current->peek(0 - int32_t(peekDepth)));
+        peekDepth--;
+    }
+    return Ok();
+}
+
+
+AbortReasonOr<Ok>
 IonBuilder::jsop_funapplyarguments(uint32_t argc)
 {
     // Stack for JSOP_FUNAPPLY:
     // 1:      Vp
     // 2:      This
     // argc+1: JSFunction*, the 'f' in |f.call()|, in |this| position.
     // argc+2: The native 'apply' function.
 
@@ -5314,16 +5328,17 @@ IonBuilder::jsop_funapplyarguments(uint3
     // When inlining we have the arguments the function gets called with
     // and can optimize even more, by just calling the functions with the args.
     // We also try this path when doing the definite properties analysis, as we
     // can inline the apply() target and don't care about the actual arguments
     // that were passed in.
 
     CallInfo callInfo(alloc(), pc, /* constructing = */ false,
                       /* ignoresReturnValue = */ BytecodeIsPopped(pc));
+    MOZ_TRY(callInfo.savePriorCallStack(this, current, 4));
 
     // Vp
     MDefinition* vp = current->pop();
     vp->setImplicitlyUsedUnchecked();
 
     // Arguments
     if (inliningDepth_) {
         if (!callInfo.setArgs(inlineCallInfo_->argv()))
@@ -5415,17 +5430,17 @@ IonBuilder::jsop_call(uint32_t argc, boo
     }
 
     return makeCall(target, callInfo);
 }
 
 AbortReasonOr<bool>
 IonBuilder::testShouldDOMCall(TypeSet* inTypes, JSFunction* func, JSJitInfo::OpType opType)
 {
-    if (!func->isNative() || !func->jitInfo())
+    if (!func->isNative() || !func->hasJitInfo())
         return false;
 
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassHasProtoAtDepth instanceChecker =
         compartment->runtime()->DOMcallbacks()->instanceClassMatchesProto;
 
@@ -7186,17 +7201,17 @@ IonBuilder::addTypeBarrier(MDefinition* 
         return constant(NullValue());
 
     return barrier;
 }
 
 AbortReasonOr<Ok>
 IonBuilder::pushDOMTypeBarrier(MInstruction* ins, TemporaryTypeSet* observed, JSFunction* func)
 {
-    MOZ_ASSERT(func && func->isNative() && func->jitInfo());
+    MOZ_ASSERT(func && func->isNative() && func->hasJitInfo());
 
     const JSJitInfo* jitinfo = func->jitInfo();
     bool barrier = DOMCallNeedsBarrier(jitinfo, observed);
     // Need to be a bit careful: if jitinfo->returnType is JSVAL_TYPE_DOUBLE but
     // types->getKnownMIRType() is MIRType::Int32, then don't unconditionally
     // unbox as a double.  Instead, go ahead and barrier on having an int type,
     // since we know we need a barrier anyway due to the type mismatch.  This is
     // the only situation in which TI actually has more information about the
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -1187,31 +1187,35 @@ class IonBuilder
 };
 
 class CallInfo
 {
     MDefinition* fun_;
     MDefinition* thisArg_;
     MDefinition* newTargetArg_;
     MDefinitionVector args_;
+    // If non-empty, this corresponds to the stack prior any implicit inlining
+    // such as before JSOP_FUNAPPLY.
+    MDefinitionVector priorArgs_;
 
     bool constructing_:1;
 
     // True if the caller does not use the return value.
     bool ignoresReturnValue_:1;
 
     bool setter_:1;
     bool apply_:1;
 
   public:
     CallInfo(TempAllocator& alloc, jsbytecode* pc, bool constructing, bool ignoresReturnValue)
       : fun_(nullptr),
         thisArg_(nullptr),
         newTargetArg_(nullptr),
         args_(alloc),
+        priorArgs_(alloc),
         constructing_(constructing),
         ignoresReturnValue_(ignoresReturnValue),
         setter_(false),
         apply_(JSOp(*pc) == JSOP_FUNAPPLY)
     { }
 
     MOZ_MUST_USE bool init(CallInfo& callInfo) {
         MOZ_ASSERT(constructing_ == callInfo.constructing());
@@ -1245,21 +1249,40 @@ class CallInfo
 
         // Get |this| and |fun|
         setThis(current->pop());
         setFun(current->pop());
 
         return true;
     }
 
-    void popFormals(MBasicBlock* current) {
+    // Before doing any pop to the stack, capture whatever flows into the
+    // instruction, such that we can restore it later.
+    AbortReasonOr<Ok> savePriorCallStack(MIRGenerator* mir, MBasicBlock* current, size_t peekDepth);
+
+    void popPriorCallStack(MBasicBlock* current) {
+        if (priorArgs_.empty())
+            popCallStack(current);
+        else
+            current->popn(priorArgs_.length());
+    }
+
+    AbortReasonOr<Ok> pushPriorCallStack(MIRGenerator* mir, MBasicBlock* current) {
+        if (priorArgs_.empty())
+            return pushCallStack(mir, current);
+        for (MDefinition* def : priorArgs_)
+            current->push(def);
+        return Ok();
+    }
+
+    void popCallStack(MBasicBlock* current) {
         current->popn(numFormals());
     }
 
-    AbortReasonOr<Ok> pushFormals(MIRGenerator* mir, MBasicBlock* current) {
+    AbortReasonOr<Ok> pushCallStack(MIRGenerator* mir, MBasicBlock* current) {
         // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY.
         if (apply_) {
             uint32_t depth = current->stackDepth() + numFormals();
             if (depth > current->nslots()) {
                 if (!current->increaseSlots(depth - current->nslots()))
                     return mir->abort(AbortReason::Alloc);
             }
         }
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -50,17 +50,17 @@ IonBuilder::inlineNativeCall(CallInfo& c
 {
     MOZ_ASSERT(target->isNative());
 
     if (!optimizationInfo().inlineNative()) {
         trackOptimizationOutcome(TrackedOutcome::CantInlineDisabledIon);
         return InliningStatus_NotInlined;
     }
 
-    if (!target->jitInfo() || target->jitInfo()->type() != JSJitInfo::InlinableNative) {
+    if (!target->hasJitInfo() || target->jitInfo()->type() != JSJitInfo::InlinableNative) {
         // Reaching here means we tried to inline a native for which there is no
         // Ion specialization.
         trackOptimizationOutcome(TrackedOutcome::CantInlineNativeNoSpecialization);
         return InliningStatus_NotInlined;
     }
 
     // Default failure reason is observing an unsupported type.
     trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadType);
@@ -841,17 +841,17 @@ IonBuilder::inlineArrayPush(CallInfo& ca
         truncate->setRecoveredOnBailout();
 
         current->add(elements);
         current->add(length);
         current->add(truncate);
 
         // Restore the stack, such that resume points are created with the stack
         // as it was before the call.
-        MOZ_TRY(callInfo.pushFormals(this, current));
+        MOZ_TRY(callInfo.pushPriorCallStack(this, current));
     }
 
     MInstruction* ins = nullptr;
     for (uint32_t i = 0; i < callInfo.argc(); i++) {
         MDefinition* value = callInfo.getArg(i);
         if (toDouble) {
             MInstruction* valueDouble = MToDouble::New(alloc(), value);
             current->add(valueDouble);
@@ -874,17 +874,17 @@ IonBuilder::inlineArrayPush(CallInfo& ca
             MOZ_TRY(resumeAt(ins, pc));
             ins->resumePoint()->addStore(alloc(), truncate, lastRp);
             lastRp = ins->resumePoint();
         }
     }
 
     if (callInfo.argc() > 1) {
         // Fix the stack to represent the state after the call execution.
-        callInfo.popFormals(current);
+        callInfo.popPriorCallStack(current);
     }
     current->push(ins);
 
     if (callInfo.argc() > 1) {
         ins = MNop::New(alloc());
         current->add(ins);
     }
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2154,22 +2154,20 @@ MCallDOMNative::congruentTo(const MDefin
     MOZ_ASSERT(call->isMovable());
 
     return true;
 }
 
 const JSJitInfo*
 MCallDOMNative::getJitInfo() const
 {
-    MOZ_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
-
-    const JSJitInfo* jitInfo = getSingleTarget()->jitInfo();
-    MOZ_ASSERT(jitInfo);
-
-    return jitInfo;
+    MOZ_ASSERT(getSingleTarget() &&
+               getSingleTarget()->isNative() &&
+               getSingleTarget()->hasJitInfo());
+    return getSingleTarget()->jitInfo();
 }
 
 MDefinition*
 MStringLength::foldsTo(TempAllocator& alloc)
 {
     if (type() == MIRType::Int32 && string()->isConstant()) {
         JSAtom* atom = &string()->toConstant()->toString()->asAtom();
         return MConstant::New(alloc, Int32Value(atom->length()));
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4142,17 +4142,16 @@ class MInitElemGetterSetter
     MInitElemGetterSetter(MDefinition* obj, MDefinition* id, MDefinition* value)
       : MTernaryInstruction(classOpcode, obj, id, value)
     { }
 
   public:
     INSTRUCTION_HEADER(InitElemGetterSetter)
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, object), (1, idValue), (2, value))
-
 };
 
 // WrappedFunction wraps a JSFunction so it can safely be used off-thread.
 // In particular, a function's flags can be modified on the active thread as
 // functions are relazified and delazified, so we must be careful not to access
 // these flags off-thread.
 class WrappedFunction : public TempObject
 {
@@ -4169,16 +4168,17 @@ class WrappedFunction : public TempObjec
     bool isNative() const { return isNative_; }
     bool isConstructor() const { return isConstructor_; }
     bool isClassConstructor() const { return isClassConstructor_; }
     bool isSelfHostedBuiltin() const { return isSelfHostedBuiltin_; }
 
     // fun->native() and fun->jitInfo() can safely be called off-thread: these
     // fields never change.
     JSNative native() const { return fun_->native(); }
+    bool hasJitInfo() const { return fun_->hasJitInfo(); }
     const JSJitInfo* jitInfo() const { return fun_->jitInfo(); }
 
     JSFunction* rawJSFunction() const { return fun_; }
 
     bool appendRoots(MRootList& roots) const {
         return roots.append(fun_);
     }
 };
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -466,30 +466,30 @@ MacroAssembler::branchTwoByteString(Regi
                  Imm32(JSString::LATIN1_CHARS_BIT), label);
 }
 
 void
 MacroAssembler::branchIfFunctionHasNoScript(Register fun, Label* label)
 {
     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     // perform an aligned 32-bit load and adjust the bitmask accordingly.
-    MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
-    MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
+    static_assert(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0,
+                  "The code in this function and the ones below must change");
+    static_assert(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2,
+                  "The code in this function and the ones below must change");
     Address address(fun, JSFunction::offsetOfNargs());
     int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
     branchTest32(Assembler::Zero, address, Imm32(bit), label);
 }
 
 void
 MacroAssembler::branchIfInterpreted(Register fun, Label* label)
 {
     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     // perform an aligned 32-bit load and adjust the bitmask accordingly.
-    MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
-    MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
     Address address(fun, JSFunction::offsetOfNargs());
     int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
     branchTest32(Assembler::NonZero, address, Imm32(bit), label);
 }
 
 void
 MacroAssembler::branchIfObjectEmulatesUndefined(Register objReg, Register scratch,
                                                 Label* slowCheck, Label* label)
--- a/js/src/jit/x86-shared/Architecture-x86-shared.h
+++ b/js/src/jit/x86-shared/Architecture-x86-shared.h
@@ -233,23 +233,21 @@ class FloatRegisters {
 
     static const Encoding Invalid = X86Encoding::invalid_xmm;
 
 #if defined(JS_CODEGEN_X86)
     static const uint32_t Total = 8 * NumTypes;
     static const uint32_t TotalPhys = 8;
     static const uint32_t Allocatable = 7;
     typedef uint32_t SetType;
-
 #elif defined(JS_CODEGEN_X64)
     static const uint32_t Total = 16 * NumTypes;
     static const uint32_t TotalPhys = 16;
     static const uint32_t Allocatable = 15;
     typedef uint64_t SetType;
-
 #endif
 
     static_assert(sizeof(SetType) * 8 >= Total,
                   "SetType should be large enough to enumerate all registers.");
 
     // Magic values which are used to duplicate a mask of physical register for
     // a specific type of register. A multiplication is used to copy and shift
     // the bits of the physical register mask.
@@ -280,17 +278,16 @@ class FloatRegisters {
         ( (1 << X86Encoding::xmm0) |
           (1 << X86Encoding::xmm1) |
           (1 << X86Encoding::xmm2) |
           (1 << X86Encoding::xmm3) |
           (1 << X86Encoding::xmm4) |
           (1 << X86Encoding::xmm5)
         ) * SpreadScalar
         | AllPhysMask * SpreadVector;
-
 #else
     static const SetType VolatileMask =
         AllMask;
 #endif
 
     static const SetType NonVolatileMask = AllMask & ~VolatileMask;
     static const SetType WrapperMask = VolatileMask;
     static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -72,17 +72,16 @@ class ABIArgGenerator
     uint32_t stackOffset_;
     ABIArg current_;
 
   public:
     ABIArgGenerator();
     ABIArg next(MIRType argType);
     ABIArg& current() { return current_; }
     uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
-
 };
 
 // These registers may be volatile or nonvolatile.
 static constexpr Register ABINonArgReg0 = eax;
 static constexpr Register ABINonArgReg1 = ebx;
 static constexpr Register ABINonArgReg2 = ecx;
 
 // These registers may be volatile or nonvolatile.
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2229,17 +2229,17 @@ js::CloneAsmJSModuleFunction(JSContext* 
     MOZ_ASSERT(cx->compartment() == fun->compartment());
 
     JSFunction* clone = NewFunctionClone(cx, fun, GenericObject, AllocKind::FUNCTION_EXTENDED,
                                          /* proto = */ nullptr);
     if (!clone)
         return nullptr;
 
     MOZ_ASSERT(fun->native() == InstantiateAsmJS);
-    MOZ_ASSERT(!fun->jitInfo());
+    MOZ_ASSERT(!fun->hasJitInfo());
     clone->initNative(InstantiateAsmJS, nullptr);
 
     clone->setGroup(fun->group());
     return clone;
 }
 
 JSFunction*
 js::CloneSelfHostingIntrinsic(JSContext* cx, HandleFunction fun)
@@ -2249,17 +2249,17 @@ js::CloneSelfHostingIntrinsic(JSContext*
     MOZ_ASSERT(!fun->isExtended());
     MOZ_ASSERT(cx->compartment() != fun->compartment());
 
     JSFunction* clone = NewFunctionClone(cx, fun, SingletonObject, AllocKind::FUNCTION,
                                          /* proto = */ nullptr);
     if (!clone)
         return nullptr;
 
-    clone->initNative(fun->native(), fun->jitInfo());
+    clone->initNative(fun->native(), fun->hasJitInfo() ? fun->jitInfo() : nullptr);
     return clone;
 }
 
 /*
  * Return an atom for use as the name of a builtin method with the given
  * property id.
  *
  * Function names are always strings. If id is the well-known @@iterator
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -53,16 +53,17 @@ class JSFunction : public js::NativeObje
         FunctionKindLimit
     };
 
     enum Flags {
         INTERPRETED      = 0x0001,  /* function has a JSScript and environment. */
         CONSTRUCTOR      = 0x0002,  /* function that can be called as a constructor */
         EXTENDED         = 0x0004,  /* structure is FunctionExtended */
         BOUND_FUN        = 0x0008,  /* function was created with Function.prototype.bind. */
+        WASM_OPTIMIZED   = 0x0010,  /* asm.js/wasm function that has a jit entry */
         HAS_GUESSED_ATOM = 0x0020,  /* function had no explicit name, but a
                                        name was guessed for it anyway */
         HAS_BOUND_FUNCTION_NAME_PREFIX = 0x0020, /* bound functions reuse the HAS_GUESSED_ATOM
                                                     flag to track if atom_ already contains the
                                                     "bound " function name prefix */
         LAMBDA           = 0x0040,  /* function comes from a FunctionExpression, ArrowFunction, or
                                        Function() call (not a FunctionDeclaration or nonstandard
                                        function-statement) */
@@ -85,17 +86,19 @@ class JSFunction : public js::NativeObje
         GETTER_KIND = Getter << FUNCTION_KIND_SHIFT,
         SETTER_KIND = Setter << FUNCTION_KIND_SHIFT,
 
         /* Derived Flags values for convenience: */
         NATIVE_FUN = 0,
         NATIVE_CTOR = NATIVE_FUN | CONSTRUCTOR,
         NATIVE_CLASS_CTOR = NATIVE_FUN | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND,
         ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
+        ASMJS_OPT_CTOR = ASMJS_CTOR | WASM_OPTIMIZED,
         ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
+        WASM_FUN = NATIVE_FUN | WASM_OPTIMIZED,
         INTERPRETED_METHOD = INTERPRETED | METHOD_KIND,
         INTERPRETED_METHOD_GENERATOR_OR_ASYNC = INTERPRETED | METHOD_KIND,
         INTERPRETED_CLASS_CONSTRUCTOR = INTERPRETED | CLASSCONSTRUCTOR_KIND | CONSTRUCTOR,
         INTERPRETED_GETTER = INTERPRETED | GETTER_KIND,
         INTERPRETED_SETTER = INTERPRETED | SETTER_KIND,
         INTERPRETED_LAMBDA = INTERPRETED | LAMBDA | CONSTRUCTOR,
         INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND,
         INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC = INTERPRETED | LAMBDA,
@@ -126,16 +129,21 @@ class JSFunction : public js::NativeObje
         struct {
             JSObject* env_;            /* environment for new activations */
             union {
                 JSScript* script_;     /* interpreted bytecode descriptor or
                                           null; use the accessor! */
                 js::LazyScript* lazy_; /* lazily compiled script, or nullptr */
             } s;
         } scripted;
+        class {
+            friend class JSFunction;
+            js::Native native_; // The native for interpreter wasm calls.
+            void* jitEntry_;    // A pointer to a fast jit->wasm table entry.
+        } wasm;
     } u;
     js::GCPtrAtom atom_; /* name for diagnostics and decompiling */
 
   public:
     /* Call objects must be created for each invocation of this function. */
     bool needsCallObject() const {
         MOZ_ASSERT(!isInterpretedLazy());
 
@@ -180,16 +188,23 @@ class JSFunction : public js::NativeObje
     /* A function can be classified as either native (C++) or interpreted (JS): */
     bool isInterpreted()            const { return flags() & (INTERPRETED | INTERPRETED_LAZY); }
     bool isNative()                 const { return !isInterpreted(); }
 
     bool isConstructor()            const { return flags() & CONSTRUCTOR; }
 
     /* Possible attributes of a native function: */
     bool isAsmJSNative()            const { return kind() == AsmJS; }
+    bool isWasmOptimized()          const { return (flags() & WASM_OPTIMIZED); }
+    bool isBuiltinNative()          const { return isNative() && !isAsmJSNative() && !isWasmOptimized(); }
+
+    // May be called from the JIT with the jitEntry_ field.
+    bool isNativeWithJitEntry()     const { return isNative() && isWasmOptimized(); }
+    // Must be called from the JIT with the native_ field.
+    bool isNativeWithCppEntry()     const { return isNative() && !isWasmOptimized(); }
 
     /* Possible attributes of an interpreted function: */
     bool isBoundFunction()          const { return flags() & BOUND_FUN; }
     bool hasCompileTimeName()       const { return flags() & HAS_COMPILE_TIME_NAME; }
     bool hasGuessedAtom()           const {
         static_assert(HAS_GUESSED_ATOM == HAS_BOUND_FUNCTION_NAME_PREFIX,
                       "HAS_GUESSED_ATOM is unused for bound functions");
         return (flags() & (HAS_GUESSED_ATOM | BOUND_FUN)) == HAS_GUESSED_ATOM;
@@ -230,17 +245,17 @@ class JSFunction : public js::NativeObje
         if (!hasScript())
             return false;
 
         return nonLazyScript()->hasBaselineScript() || nonLazyScript()->hasIonScript();
     }
 
     /* Compound attributes: */
     bool isBuiltin() const {
-        return (isNative() && !isAsmJSNative()) || isSelfHostedBuiltin();
+        return isBuiltinNative() || isSelfHostedBuiltin();
     }
 
     bool isNamedLambda() const {
         return isLambda() && displayAtom() && !hasCompileTimeName() && !hasGuessedAtom();
     }
 
     bool hasLexicalThis() const {
         return isArrow();
@@ -564,37 +579,56 @@ class JSFunction : public js::NativeObje
         return u.native.func_;
     }
 
     JSNative maybeNative() const {
         return isInterpreted() ? nullptr : native();
     }
 
     void initNative(js::Native native, const JSJitInfo* jitinfo) {
+        MOZ_ASSERT(isNativeWithCppEntry());
         MOZ_ASSERT(native);
         u.native.func_ = native;
         u.native.jitinfo_ = jitinfo;
     }
-
+    bool hasJitInfo() const {
+        return isNativeWithCppEntry() && u.native.jitinfo_;
+    }
     const JSJitInfo* jitInfo() const {
-        MOZ_ASSERT(isNative());
+        MOZ_ASSERT(hasJitInfo());
         return u.native.jitinfo_;
     }
+    void setJitInfo(const JSJitInfo* data) {
+        MOZ_ASSERT(isNativeWithCppEntry());
+        u.native.jitinfo_ = data;
+    }
 
-    void setJitInfo(const JSJitInfo* data) {
-        MOZ_ASSERT(isNative());
-        u.native.jitinfo_ = data;
+    void initWasmNative(js::Native native) {
+        MOZ_ASSERT(isNativeWithJitEntry());
+        MOZ_ASSERT(native);
+        u.wasm.native_ = native;
+        u.wasm.jitEntry_ = nullptr;
+    }
+    void setWasmJitEntry(void* entry) {
+        MOZ_ASSERT(isNativeWithJitEntry());
+        MOZ_ASSERT(entry);
+        MOZ_ASSERT(!u.wasm.jitEntry_);
+        u.wasm.jitEntry_ = entry;
     }
 
     bool isDerivedClassConstructor();
 
     static unsigned offsetOfNative() {
+        static_assert(offsetof(U, native.func_) == offsetof(U, wasm.native_),
+                      "native.func_ must be at the same offset as wasm.native_");
         return offsetof(JSFunction, u.native.func_);
     }
     static unsigned offsetOfScript() {
+        static_assert(offsetof(U, scripted.s.script_) == offsetof(U, wasm.jitEntry_),
+                      "scripted.s.script_ must be at the same offset as wasm.jitEntry_");
         return offsetof(JSFunction, u.scripted.s.script_);
     }
     static unsigned offsetOfNativeOrEnv() {
         static_assert(offsetof(U, native.func_) == offsetof(U, scripted.env_),
                       "U.native.func_ must be at the same offset as U.scripted.env_");
         return offsetOfNative();
     }
     static unsigned offsetOfScriptOrLazyScript() {
@@ -698,35 +732,36 @@ NewFunctionWithProto(JSContext* cx, JSNa
                      HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                      NewObjectKind newKind = GenericObject);
 
 // Allocate a new function backed by a JSNative.  Note that by default this
 // creates a singleton object.
 inline JSFunction*
 NewNativeFunction(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
                   gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
-                  NewObjectKind newKind = SingletonObject)
+                  NewObjectKind newKind = SingletonObject,
+                  JSFunction::Flags flags = JSFunction::NATIVE_FUN)
 {
     MOZ_ASSERT(native);
-    return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
-                                nullptr, atom, nullptr, allocKind, newKind);
+    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr, allocKind,
+                                newKind);
 }
 
 // Allocate a new constructor backed by a JSNative.  Note that by default this
 // creates a singleton object.
 inline JSFunction*
 NewNativeConstructor(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
                      gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                      NewObjectKind newKind = SingletonObject,
                      JSFunction::Flags flags = JSFunction::NATIVE_CTOR)
 {
     MOZ_ASSERT(native);
     MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
-    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
-                                nullptr, allocKind, newKind);
+    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr, allocKind,
+                                newKind);
 }
 
 // Allocate a new scripted function.  If enclosingEnv is null, the
 // global will be used.  In all cases the parent of the resulting object will be
 // the global.
 extern JSFunction*
 NewScriptedFunction(JSContext* cx, unsigned nargs, JSFunction::Flags flags,
                     HandleAtom atom, HandleObject proto = nullptr,
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1372,18 +1372,18 @@ InitializePropertiesFromCompatibleNative
         // Get an in-order list of the shapes in the src object.
         Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
         for (Shape::Range<NoGC> r(src->lastProperty()); !r.empty(); r.popFront()) {
             if (!shapes.append(&r.front()))
                 return false;
         }
         Reverse(shapes.begin(), shapes.end());
 
-        for (Shape* shape : shapes) {
-            Rooted<StackShape> child(cx, StackShape(shape));
+        for (Shape* shapeToClone : shapes) {
+            Rooted<StackShape> child(cx, StackShape(shapeToClone));
             shape = cx->zone()->propertyTree().getChild(cx, shape, child);
             if (!shape)
                 return false;
         }
     }
     size_t span = shape->slotSpan();
     if (!dst->setLastProperty(cx, shape))
         return false;
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -460,19 +460,19 @@ js::InternalCallOrConstruct(JSContext* c
     if (construct != CONSTRUCT && fun->isClassConstructor()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CALL_CLASS_CONSTRUCTOR);
         return false;
     }
 
     if (fun->isNative()) {
         MOZ_ASSERT_IF(construct, !fun->isConstructor());
         JSNative native = fun->native();
-        if (!construct && args.ignoresReturnValue()) {
+        if (!construct && args.ignoresReturnValue() && fun->hasJitInfo()) {
             const JSJitInfo* jitInfo = fun->jitInfo();
-            if (jitInfo && jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
+            if (jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
                 native = jitInfo->ignoresReturnValueMethod;
         }
         return CallJSNative(cx, native, args);
     }
 
     if (!JSFunction::getOrCreateScript(cx, fun))
         return false;
 
@@ -506,17 +506,17 @@ InternalCall(JSContext* cx, const AnyInv
 
     if (args.thisv().isObject()) {
         // We must call the thisValue hook in case we are not called from the
         // interpreter, where a prior bytecode has computed an appropriate
         // |this| already.  But don't do that if fval is a DOM function.
         HandleValue fval = args.calleev();
         if (!fval.isObject() || !fval.toObject().is<JSFunction>() ||
             !fval.toObject().as<JSFunction>().isNative() ||
-            !fval.toObject().as<JSFunction>().jitInfo() ||
+            !fval.toObject().as<JSFunction>().hasJitInfo() ||
             fval.toObject().as<JSFunction>().jitInfo()->needsOuterizedThisObject())
         {
             JSObject* thisObj = &args.thisv().toObject();
             args.mutableThisv().set(GetThisValue(thisObj));
         }
     }
 
     return InternalCallOrConstruct(cx, args, NO_CONSTRUCT);
--- a/js/src/wasm/WasmBuiltins.cpp
+++ b/js/src/wasm/WasmBuiltins.cpp
@@ -959,17 +959,17 @@ ToBuiltinABIFunctionType(const Sig& sig)
     return Some(ABIFunctionType(abiType));
 }
 
 void*
 wasm::MaybeGetBuiltinThunk(HandleFunction f, const Sig& sig, JSContext* cx)
 {
     MOZ_ASSERT(builtinThunks);
 
-    if (!f->isNative() || !f->jitInfo() || f->jitInfo()->type() != JSJitInfo::InlinableNative)
+    if (!f->isNative() || !f->hasJitInfo() || f->jitInfo()->type() != JSJitInfo::InlinableNative)
         return nullptr;
 
     Maybe<ABIFunctionType> abiType = ToBuiltinABIFunctionType(sig);
     if (!abiType)
         return nullptr;
 
     TypedNative typedNative(f->jitInfo()->inlinableNative, *abiType);
 
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -601,16 +601,18 @@ struct nsGridContainerFrame::GridItemInf
                                                : NS_STYLE_ALIGN_SELF_END;
     }
     *aBaselineOffset = mBaselineOffset[aAxis];
     return aAlign;
   }
 
   // Return true if we should apply Automatic Minimum Size to this item.
   // https://drafts.csswg.org/css-grid/#min-size-auto
+  // @note the caller should also check that the item spans at least one track
+  // that has a min track sizing function that is 'auto' before applying it.
   bool ShouldApplyAutoMinSize(WritingMode aContainerWM,
                               LogicalAxis aContainerAxis,
                               nscoord aPercentageBasis) const
   {
     const auto pos = mFrame->StylePosition();
     const auto& size = aContainerAxis == eLogicalAxisInline ?
       pos->ISize(aContainerWM) : pos->BSize(aContainerWM);
     // NOTE: if we have a definite or 'max-content' size then our automatic
@@ -660,16 +662,22 @@ nsGridContainerFrame::GridItemInfo::Dump
     auto state = mState[aAxis];
     if (!state) {
       return;
     }
     printf("%s", aMsg);
     if (state & ItemState::eIsFlexing) {
       printf("flexing ");
     }
+    if (state & ItemState::eApplyAutoMinSize) {
+      printf("auto-min-size ");
+    }
+    if (state & ItemState::eClampMarginBoxMinSize) {
+      printf("clamp ");
+    }
     if (state & ItemState::eFirstBaseline) {
       printf("first baseline %s-alignment ",
              (state & ItemState::eSelfBaseline) ? "self" : "content");
     }
     if (state & ItemState::eLastBaseline) {
       printf("last baseline %s-alignment ",
              (state & ItemState::eSelfBaseline) ? "self" : "content");
     }
@@ -1087,25 +1095,19 @@ struct nsGridContainerFrame::Tracks
   }
 
   void Initialize(const TrackSizingFunctions& aFunctions,
                   const nsStyleCoord&         aGridGap,
                   uint32_t                    aNumTracks,
                   nscoord                     aContentBoxSize);
 
   /**
-   * Return true if aRange spans at least one track with an intrinsic sizing
-   * function and does not span any tracks with a <flex> max-sizing function.
-   * @param aRange the span of tracks to check
-   * @param aState will be set to the union of the state bits of all the spanned
-   *               tracks, unless a flex track is found - then it only contains
-   *               the union of the tracks up to and including the flex track.
+   * Return the union of the state bits for the tracks in aRange.
    */
-  bool HasIntrinsicButNoFlexSizingInRange(const LineRange&      aRange,
-                                          TrackSize::StateBits* aState) const;
+   TrackSize::StateBits StateBitsForRange(const LineRange& aRange) const;
 
   // Some data we collect for aligning baseline-aligned items.
   struct ItemBaselineData
   {
     uint32_t mBaselineTrack;
     nscoord mBaseline;
     nscoord mSize;
     GridItemInfo* mGridItem;
@@ -3750,52 +3752,48 @@ nsGridContainerFrame::Tracks::CalculateS
     if (freeSpace != NS_UNCONSTRAINEDSIZE) {
       freeSpace -= SumOfGridGaps();
     }
     DistributeFreeSpace(freeSpace);
     StretchFlexibleTracks(aState, aGridItems, aFunctions, freeSpace);
   }
 }
 
-bool
-nsGridContainerFrame::Tracks::HasIntrinsicButNoFlexSizingInRange(
-  const LineRange&      aRange,
-  TrackSize::StateBits* aState) const
+TrackSize::StateBits
+nsGridContainerFrame::Tracks::StateBitsForRange(const LineRange& aRange) const
 {
   MOZ_ASSERT(!aRange.IsAuto(), "must have a definite range");
+  TrackSize::StateBits state = TrackSize::StateBits(0);
   const uint32_t start = aRange.mStart;
   const uint32_t end = aRange.mEnd;
-  const TrackSize::StateBits selector =
-    TrackSize::eIntrinsicMinSizing | TrackSize::eIntrinsicMaxSizing;
-  bool foundIntrinsic = false;
   for (uint32_t i = start; i < end; ++i) {
-    TrackSize::StateBits state = mSizes[i].mState;
-    *aState |= state;
-    if (state & TrackSize::eFlexMaxSizing) {
-      return false;
-    }
-    if (state & selector) {
-      foundIntrinsic = true;
-    }
-  }
-  return foundIntrinsic;
+    state |= mSizes[i].mState;
+  }
+  return state;
 }
 
 bool
 nsGridContainerFrame::Tracks::ResolveIntrinsicSizeStep1(
   GridReflowInput&            aState,
   const TrackSizingFunctions& aFunctions,
   nscoord                     aPercentageBasis,
   SizingConstraint            aConstraint,
   const LineRange&            aRange,
   const GridItemInfo&         aGridItem)
 {
   CachedIntrinsicSizes cache;
   TrackSize& sz = mSizes[aRange.mStart];
   WritingMode wm = aState.mWM;
+
+  // Check if we need to apply "Automatic Minimum Size" and cache it.
+  if ((sz.mState & TrackSize::eAutoMinSizing) &&
+      aGridItem.ShouldApplyAutoMinSize(wm, mAxis, aPercentageBasis)) {
+    aGridItem.mState[mAxis] |= ItemState::eApplyAutoMinSize;
+  }
+
   // Calculate data for "Automatic Minimum Size" clamping, if needed.
   bool needed = ((sz.mState & TrackSize::eIntrinsicMinSizing) ||
                  aConstraint == SizingConstraint::eNoConstraint) &&
                 (aGridItem.mState[mAxis] & ItemState::eApplyAutoMinSize);
   if (needed && TrackSize::IsDefiniteMaxSizing(sz.mState)) {
     if (sz.mState & TrackSize::eIntrinsicMinSizing) {
       auto maxCoord = aFunctions.MaxSizingFor(aRange.mStart);
       cache.mMinSizeClamp = maxCoord.ComputeCoordPercentCalc(aPercentageBasis);
@@ -4192,36 +4190,41 @@ nsGridContainerFrame::Tracks::ResolveInt
   // Setup track selector for step 2.3:
   const auto maxContentMinSelector =
     aConstraint == SizingConstraint::eMaxContent ?
     (TrackSize::eMaxContentMinSizing | TrackSize::eAutoMinSizing) :
     TrackSize::eMaxContentMinSizing;
   iter.Reset();
   for (; !iter.AtEnd(); iter.Next()) {
     auto& gridItem = aGridItems[iter.ItemIndex()];
-
-    // Check if we need to apply "Automatic Minimum Size" and cache it.
-    MOZ_ASSERT(!(gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize),
-               "Why is eApplyAutoMinSize set already?");
-    if (gridItem.ShouldApplyAutoMinSize(wm, mAxis, aPercentageBasis)) {
-      gridItem.mState[mAxis] |= ItemState::eApplyAutoMinSize;
-    }
-
+    MOZ_ASSERT(!(gridItem.mState[mAxis] &
+                 (ItemState::eApplyAutoMinSize | ItemState::eIsFlexing |
+                  ItemState::eClampMarginBoxMinSize)),
+               "Why are any of these bits set already?");
     const GridArea& area = gridItem.mArea;
     const LineRange& lineRange = area.*aRange;
     uint32_t span = lineRange.Extent();
     if (span == 1) {
       // Step 1. Size tracks to fit non-spanning items.
       if (ResolveIntrinsicSizeStep1(aState, aFunctions, aPercentageBasis,
                                     aConstraint, lineRange, gridItem)) {
         gridItem.mState[mAxis] |= ItemState::eIsFlexing;
       }
     } else {
-      TrackSize::StateBits state = TrackSize::StateBits(0);
-      if (HasIntrinsicButNoFlexSizingInRange(lineRange, &state)) {
+      TrackSize::StateBits state = StateBitsForRange(lineRange);
+
+      // Check if we need to apply "Automatic Minimum Size" and cache it.
+      if ((state & TrackSize::eAutoMinSizing) &&
+          gridItem.ShouldApplyAutoMinSize(wm, mAxis, aPercentageBasis)) {
+        gridItem.mState[mAxis] |= ItemState::eApplyAutoMinSize;
+      }
+
+      if ((state & (TrackSize::eIntrinsicMinSizing |
+                    TrackSize::eIntrinsicMaxSizing)) &&
+          !(state & TrackSize::eFlexMaxSizing)) {
         // Collect data for Step 2.
         maxSpan = std::max(maxSpan, span);
         if (span >= stateBitsPerSpan.Length()) {
           uint32_t len = 2 * span;
           stateBitsPerSpan.SetCapacity(len);
           for (uint32_t i = stateBitsPerSpan.Length(); i < len; ++i) {
             stateBitsPerSpan.AppendElement(TrackSize::StateBits(0));
           }
--- a/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-003-ref.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-003-ref.html
@@ -26,41 +26,41 @@ span {
   min-height:0;
 }
 </style>
 </head>
 <body>
 
 <div class="grid">
   <span>a</span>
-  <span style="width:28px">IAmReallyWideAndTheBorderShouldSurroundMe</span>
+  <span style="width:-moz-max-content">IAmReallyWideAndTheBorderShouldSurroundMe</span>
 </div>
 
 <pre>The border shouldn't shrink-wrap the wide text below, due to definite "width" values:</pre>
 <div class="grid">
   <span>a</span>
   <span style="width: 130%">IAmReallyWideButIHaveADefiniteWidthSoIOverflow</span>
   <span>c</span>
   <span style="width: 50px">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span>
   <span style="width: 20px">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span><span></span>
   <span style="width: 20px; grid-column:span 2;">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span>
 </div>
 
 <pre>Now the same tests for 'height':</pre>
 
 <div class="grid" style="margin-bottom:50px;">
   <span>a</span>
-  <span style="font-size:72px;width:28px;height:28px">IAmReallyTall</span>
+  <span style="font-size:72px;width:-moz-max-content;height:-moz-max-content">IAmReallyTall</span>
   <span>c</span>
   <span>d</span>
 </div>
 
-The border shouldn't shrink-wrap the wide text below, due to definite "height" values:
+The border shouldn't shrink-wrap the text vertically below, due to definite "height" values:
 <div class="grid">
   <span>a</span>
-  <span style="font-size:72px; height:10%;width:28px">IAmReallyTall</span>
+  <span style="font-size:72px; height:10%;width:-moz-max-content">IAmReallyTall</span>
   <span>c</span>
-  <span style="font-size:72px; height:10px;width:28px">SameHere</span>
-  <span style="font-size:72px; height:40px;width:28px">SameHere</span>
+  <span style="font-size:72px; height:10px;width:-moz-max-content">SameHere</span>
+  <span style="font-size:72px; height:40px;width:-moz-max-content">SameHere</span>
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-003.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-003.html
@@ -48,17 +48,17 @@ span {
 
 <div class="grid" style="margin-bottom:50px;">
   <span>a</span>
   <span style="font-size:72px">IAmReallyTall</span>
   <span>c</span>
   <span>d</span>
 </div>
 
-The border shouldn't shrink-wrap the wide text below, due to definite "height" values:
+The border shouldn't shrink-wrap the text vertically below, due to definite "height" values:
 <div class="grid">
   <span>a</span>
   <span style="font-size:72px; height:10%">IAmReallyTall</span>
   <span>c</span>
   <span style="font-size:72px; height:10px">SameHere</span>
   <span style="font-size:72px; height:40px">SameHere</span>
 </div>
 
--- a/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-004-ref.html
+++ b/layout/reftests/css-grid/grid-auto-min-sizing-intrinsic-004-ref.html
@@ -35,41 +35,41 @@ pre {
   float: left;
 }
 </style>
 </head>
 <body>
 
 <div class="grid" style="margin-left:0">
   <span>a</span>
-  <span style="height:28px">IAmReallyWideAndTheBorderShouldSurroundMe</span>
+  <span style="height:-moz-max-content">IAmReallyWideAndTheBorderShouldSurroundMe</span>
 </div>
 
 <pre>The border shouldn't shrink-wrap the wide text below, due to definite "height" values:</pre>
 <div class="grid">
   <span>a</span>
   <span style="height: 130%;">IAmReallyWideButIHaveADefiniteHeightSoIOverflow</span>
   <span>c</span>
   <span style="height: 50px">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span>
   <span style="height: 20px">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span><span></span>
   <span style="height: 20px; grid-column:span 2;">SameHereeeeeeeeeeeeeeeeeeeeeeeeeeee</span>
 </div>
 
 <pre>Now the same tests for 'width':</pre>
 
 <div class="grid" style="margin-bottom:50px;">
   <span>a</span>
-  <span style="font-size:72px;height:28px;width:28px">IAmReallyTall</span>
+  <span style="font-size:72px;height:-moz-max-content;width:-moz-max-content">IAmReallyTall</span>
   <span>c</span>
   <span>d</span>
 </div>
 
 <pre>The border shouldn't shrink-wrap the wide text below, due to definite "width" values:</pre>
 <div class="grid">
   <span>a</span>
-  <span style="font-size:72px; width:10%;height:28px">IAmReallyTall</span>
+  <span style="font-size:72px; width:10%;height:-moz-max-content">IAmReallyTall</span>
   <span>c</span>
-  <span style="font-size:72px; width:10px;height:28px">SameHere</span>
-  <span style="font-size:72px; width:40px;height:28px">SameHere</span>
+  <span style="font-size:72px; width:10px;height:-moz-max-content">SameHere</span>
+  <span style="font-size:72px; width:40px;height:-moz-max-content">SameHere</span>
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-001-ref.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-001-ref.html
@@ -27,23 +27,23 @@ body,html { color:black; background:whit
   height: 40px;
 }
 
 .definite {
   grid-template-columns: repeat(2,15px);
   grid-template-rows:    repeat(2,10px);
 }
 .min {
+  grid-template-columns: repeat(2,minmax(max-content, 15px));
+  grid-template-rows:    repeat(2,minmax(max-content, 10px));
+}
+.max {
   grid-template-columns: repeat(2,minmax(min-content, 15px));
   grid-template-rows:    repeat(2,minmax(min-content, 10px));
 }
-.max {
-  grid-template-columns: repeat(2,minmax(max-content, 15px));
-  grid-template-rows:    repeat(2,minmax(max-content, 10px));
-}
 
 .larger .grid {
   grid-template-columns: repeat(2,minmax(auto, 25px));
   grid-template-rows:    repeat(2,minmax(auto, 28px));
 }
 .larger .definite {
   grid-template-columns: repeat(2,25px);
   grid-template-rows:    repeat(2,28px);
@@ -87,31 +87,23 @@ body,html { color:black; background:whit
 span {
   grid-area: 1 / 1;
   font-size: 48px;
   background: grey;
   background-clip: content-box;
   border: 1px solid;
   padding: 1px 3px 5px 7px;
   margin: 3px 5px 7px 1px;
-  width: 0;
-  height: 0;
 }
 .span2 {
   grid-area: 1 / 1 / span 2 / span 2;
-  width: 13px;
-  height: 3px;
 }
 .grid.max span {
   width:20px;
 }
-.larger .grid span {
-  width: 7px;
-  height: 10px;
-}
 .larger .grid .span2 {
   font-size: 32px;
   width: 20px;
   height: 32px;
 }
 .stretch.larger .grid .span2 {
   width: 33px;
   height: 39px;
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-002-ref.html
@@ -27,40 +27,40 @@ body,html { color:black; background:whit
   height: 40px;
 }
 
 .definite {
   grid-template-columns: repeat(2,15px);
   grid-template-rows:    repeat(2,10px);
 }
 .min {
+  grid-template-columns: repeat(2,minmax(max-content, 15px));
+  grid-template-rows:    repeat(2,minmax(max-content, 10px));
+}
+.max {
   grid-template-columns: repeat(2,minmax(min-content, 15px));
   grid-template-rows:    repeat(2,minmax(min-content, 10px));
 }
-.max {
-  grid-template-columns: repeat(2,minmax(max-content, 15px));
-  grid-template-rows:    repeat(2,minmax(max-content, 10px));
-}
 
 .larger .grid {
   grid-template-columns: repeat(2,minmax(auto, 25px));
   grid-template-rows:    repeat(2,minmax(auto, 28px));
 }
 .larger .definite {
   grid-template-columns: repeat(2,25px);
   grid-template-rows:    repeat(2,28px);
 }
 .larger .min {
+  grid-template-columns: repeat(2,minmax(max-content, 25px));
+  grid-template-rows:    repeat(2,minmax(max-content, 28px));
+}
+.larger .max {
   grid-template-columns: repeat(2,minmax(min-content, 25px));
   grid-template-rows:    repeat(2,minmax(min-content, 28px));
 }
-.larger .max {
-  grid-template-columns: repeat(2,minmax(max-content, 25px));
-  grid-template-rows:    repeat(2,minmax(max-content, 28px));
-}
 
 .stretch .grid {
   align-items: stretch;
   justify-items: stretch;
 }
 .grid.a.max {
   height:61px;
 }
@@ -72,27 +72,19 @@ span {
   writing-mode: vertical-rl;
   grid-area: 1 / 1;
   font-size: 48px;
   background: grey;
   background-clip: content-box;
   border: 1px solid;
   padding: 1px 3px 5px 7px;
   margin: 3px 5px 7px 1px;
-  width: 0;
-  height: 0;
 }
 .span2 {
   grid-area: 1 / 1 / span 2 / span 2;
-  width: 13px;
-  height: 3px;
-}
-.larger .grid span {
-  width: 7px;
-  height: 10px;
 }
 .larger .grid .span2 {
   font-size: 32px;
   width: 20px;
   height: 32px;
 }
 .stretch.larger .grid .span2 {
   width: 33px;
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-003-ref.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-003-ref.html
@@ -73,18 +73,18 @@ body,html { color:black; background:whit
 .larger .grid.a2 {
   width:51px;
 }
 img {
   grid-area: 1 / 1;
   border: 1px solid;
   padding: 1px 3px 5px 7px;
   margin: 3px 5px 7px 1px;
-  width: 0;
-  height: 0;
+  min-width: 0;
+  min-height: 0;
 }
 .span2 {
   grid-area: 1 / 1 / span 2 / span 2;
 }
 
 x {
   grid-area: 1 / 1;
   min-width: 0;
@@ -151,74 +151,74 @@ document.body.appendChild(wrap);
 
 </script>
 
 
 <script>
 var imgSizes =
 [
   ['0px', '0px'],
-  ['0px', '0px'],
+  ['20px', '32px'],
   ['2px', '3px'],
-  ['2px', '3px'],
-  ['0px', '0px'],
+  ['20px', '32px'],
   ['0px', '0px'],
-  ['2px', '3px'],
-  ['2px', '3px'],
-  ['0px', '0px'],
-  ['2px', '3px'],
-  ['0px', '0px'],
+  ['20px', '32px'],
   ['2px', '3px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
-  ['6px', '10px'],
-  ['6px', '10px'],
   ['20px', '32px'],
   ['20px', '32px'],
-  ['6px', '10px'],
-  ['6px', '10px'],
+  ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['6px', '10px'],
   ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
   ['6px', '10px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
   ['0px', '0px'],
   ['0px', '0px'],
   ['13px', '3px'],
   ['13px', '3px'],
   ['0px', '0px'],
   ['0px', '0px'],
   ['13px', '3px'],
   ['13px', '3px'],
-  ['0px', '0px'],
-  ['13px', '3px'],
-  ['0px', '0px'],
-  ['13px', '3px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
+  ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['20px', '32px'],
   ['7px', '10px'],
   ['7px', '10px'],
   ['33px', '39px'],
   ['33px', '39px'],
   ['7px', '10px'],
   ['7px', '10px'],
   ['22px', '32px'],
   ['33px', '39px'],
-  ['7px', '10px'],
+  ['20px', '32px'],
   ['33px', '39px'],
-  ['7px', '10px'],
+  ['20px', '32px'],
   ['22px', '32px'],
   ['20px', '32px'],
   ['33px', '39px'],
   ['20px', '32px'],
   ['22px', '32px'],
 ];
 var imgs = document.querySelectorAll('img');
 for (var i = 0; i < imgs.length; ++i) {
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-003.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-003.html
@@ -29,40 +29,40 @@ body,html { color:black; background:whit
   height: 40px;
 }
 
 .definite {
   grid-template-columns: repeat(2,15px);
   grid-template-rows:    repeat(2,10px);
 }
 .min {
+  grid-template-columns: repeat(2,minmax(max-content, 15px));
+  grid-template-rows:    repeat(2,minmax(max-content, 10px));
+}
+.max {
   grid-template-columns: repeat(2,minmax(min-content, 15px));
   grid-template-rows:    repeat(2,minmax(min-content, 10px));
 }
-.max {
-  grid-template-columns: repeat(2,minmax(max-content, 15px));
-  grid-template-rows:    repeat(2,minmax(max-content, 10px));
-}
 
 .larger .grid {
   grid-template-columns: repeat(2,minmax(auto, 25px));
   grid-template-rows:    repeat(2,minmax(auto, 28px));
 }
 .larger .definite {
   grid-template-columns: repeat(2,25px);
   grid-template-rows:    repeat(2,28px);
 }
 .larger .min {
+  grid-template-columns: repeat(2,minmax(max-content, 25px));
+  grid-template-rows:    repeat(2,minmax(max-content, 28px));
+}
+.larger .max {
   grid-template-columns: repeat(2,minmax(min-content, 25px));
   grid-template-rows:    repeat(2,minmax(min-content, 28px));
 }
-.larger .max {
-  grid-template-columns: repeat(2,minmax(max-content, 25px));
-  grid-template-rows:    repeat(2,minmax(max-content, 28px));
-}
 
 .stretch .grid {
   align-items: stretch;
   justify-items: stretch;
 }
 
 img {
   grid-area: 1 / 1;
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-005-ref.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-005-ref.html
@@ -69,41 +69,22 @@ span {
   background-clip: content-box;
   border: 1px solid;
   padding: 1px 3px 5px 7px;
   margin: 0;
 }
 .span2 {
   grid-area: 1 / 1 / span 2 / span 2;
 }
+
 .larger .grid .span2 {
-  font-size: 32px;
-}
-
-.larger .grid span {
-  align-self:center;
-  justify-self:center;
-}
-.larger .grid .span2 {
-  font-size: 32px;
+  font-size: 16px;
   width: 20px;
   height: 32px;
 }
-.stretch.larger .grid .span2 {
-  align-self:center;
-  justify-self:center;
-}
-.stretch.larger .grid.sz .span2 {
-  align-self:center;
-  justify-self:center;
-}
-.stretch.larger .grid.definite .span2 {
-  align-self:center;
-  justify-self:center;
-}
 
 x {
   grid-area: 1 / 1;
   min-width: 0;
   min-height: 0;
   align-self: stretch;
   justify-self: stretch;
   background: cyan;
@@ -112,63 +93,73 @@ c {
   display: block;
   width: 20px;
   height: 32px;
 }
 
 br {
   clear: both;
 }
+
+.larger .center > span {
+  justify-self: center;
+  align-self: center;
+}
+.larger .ml4 > span {
+  margin-left: 4px;
+}
   </style>
 </head>
 <body>
 
 <div id="tests">
 <div class="grid"><x></x><span><c>X</c></span></div>
 <div class="grid definite"><x></x><span><c>X</c></span></div>
-<div class="grid"><x></x><span class="span2"><c>X</c></span></div>
-<div class="grid definite"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid center"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid center definite"><x></x><span class="span2"><c>X</c></span></div>
 
 <div class="grid sz"><x></x><span><c>X</c></span></div>
 <div class="grid sz definite"><x></x><span><c>X</c></span></div>
-<div class="grid sz"><x></x><span class="span2"><c>X</c></span></div>
-<div class="grid sz definite"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid ml4 sz"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid center sz definite"><x></x><span class="span2"><c>X</c></span></div>
 
 <br>
 
 <div class="grid min"><x></x><span><c>X</c></span></div>
-<div class="grid min"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid center min"><x></x><span class="span2"><c>X</c></span></div>
 <div class="grid sz min"><x></x><span><c>X</c></span></div>
-<div class="grid sz min"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid ml4 sz min"><x></x><span class="span2"><c>X</c></span></div>
 
 <div class="grid max"><x></x><span><c>X</c></span></div>
-<div class="grid max"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid center max"><x></x><span class="span2"><c>X</c></span></div>
 <div class="grid sz max"><x></x><span><c>X</c></span></div>
-<div class="grid sz max"><x></x><span class="span2"><c>X</c></span></div>
+<div class="grid ml4 sz max"><x></x><span class="span2"><c>X</c></span></div>
 
 <br>
 
 </div>
 
 <script>
 var tests = document.getElementById('tests');
 
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'larger';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
 
+/* TODO: sort out https://bugs.chromium.org/p/chromium/issues/detail?id=789927 first
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'stretch';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
 
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'stretch larger';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
+*/
 
 </script>
 
 </body></html>
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-005.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-005.html
@@ -72,17 +72,17 @@ span {
   border: 1px solid;
   padding: 1px 3px 5px 7px;
   margin: auto;
 }
 .span2 {
   grid-area: 1 / 1 / span 2 / span 2;
 }
 .larger .grid .span2 {
-  font-size: 32px;
+  font-size: 16px;
 }
 
 x {
   grid-area: 1 / 1;
   min-width: 0;
   min-height: 0;
   align-self: stretch;
   justify-self: stretch;
@@ -132,23 +132,25 @@ br {
 var tests = document.getElementById('tests');
 
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'larger';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
 
+/* TODO: sort out https://bugs.chromium.org/p/chromium/issues/detail?id=789927 first
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'stretch';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
 
 var n = tests.cloneNode(true);
 var wrap = document.createElement('div');
 wrap.className = 'stretch larger';
 wrap.appendChild(n);
 document.body.appendChild(wrap);
+*/
 
 </script>
 
 </body></html>
--- a/layout/reftests/css-grid/grid-item-auto-min-size-clamp-007-ref.html
+++ b/layout/reftests/css-grid/grid-item-auto-min-size-clamp-007-ref.html
@@ -18,23 +18,21 @@ body,html { color:black; background:whit
   grid-template-rows: repeat(2,20px);
   align-items: start;
   justify-items: start;
   border: 1px dashed;
   margin-right: 16px;
   margin-bottom: 14px;
 }
 .c-auto { grid-template-columns: 15px; width: 15px; }
-.c-min { grid-template-columns: 15px; width: 15px; }
-.c-max { grid-template-columns: 15px; width: 15px; }
 .c-1530 { grid-template-columns: 15px; width: 30px; }
 .c-30 { grid-template-columns: 30px; width: 30px; }
 .r-auto { grid-template-rows: 15px; height: 15px; }
-.r-min { grid-template-rows: 15px; height: 15px; }
-.r-max { grid-template-rows: 15px; height: 15px; }
+.r-min { grid-template-rows: 40px; height: 40px; }
+.r-max { grid-template-rows: 40px; height: 40px; }
 span {
   grid-area: 1 / 1;
   font-size: 48px;
   background: grey;
 }
 y {
   position: absolute;
   grid-area: 2 / 1 / 3 / 2;
@@ -50,38 +48,39 @@ y {
 }
 br { clear: both; }
 
 x { display:block; width:30px; height:40px; }
 span { width:15px; }
 .r span { width:20px; }
 .grid.c-30 span, .r.grid.c-30 span { width:30px; }
 .r span { height:15px; }
+.r.r-min span, .r.r-max span { height:40px; }
   </style>
 </head>
 <body>
 
 <div class="grid c-1530"><y></y><span><x>X</x></span></div>
 <div class="grid c-auto"><y></y><span><x>X</x></span></div>
 <div class="grid c-30"><y style="width:30px"></y><span><x>X</x></span></div>
 <div class="grid c-1530"><y></y><span><x>X</x></span></div>
 <div class="grid c-1530"><y></y><span><x>X</x></span></div>
 
 <br>
 
-<div class="grid c-min"><y></y><span><x>X</x></span></div>
-<div class="grid c-min"><y></y><span><x>X</x></span></div>
-<div class="grid c-30" style="width:30px"><y style="width:30px"></y><span><x>X</x></span></div>
-<div class="grid c-min"><y></y><span><x>X</x></span></div>
-<div class="grid c-min"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
 
 <br>
 
 <div class="grid c-30"><y></y><span><x>X</x></span></div>
-<div class="grid c-max"><y></y><span><x>X</x></span></div>
+<div class="grid c-30"><y></y><span><x>X</x></span></div>
 <div class="grid c-30"><y></y><span><x>X</x></span></div>
 <div class="grid c-30"><y></y><span><x>X</x></span></div>
 <div class="grid c-30"><y></y><span><x>X</x></span></div>
 
 <br>
 
 <div class="grid r r-auto"><y></y><span><x>X</x></span></div>
 <div class="grid r r-auto"><y></y><span><x>X</x></span></div>
@@ -102,55 +101,55 @@ span { width:15px; }
 <div class="grid r r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r r-max"><y></y><span><x>X</x></span></div>
 
 <br>
 
-<div class="grid r c-min r-auto"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-auto"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-auto"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-auto"><y></y><span><x>X</x></span></div>
-
-<br>
-
-<div class="grid r c-min r-min"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-min"><y></y><span><x>X</x></span></div>
-<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-min"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-min"><y></y><span><x>X</x></span></div>
-
-<br>
-
-<div class="grid r c-min r-max"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-max"><y></y><span><x>X</x></span></div>
-<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-max"><y></y><span><x>X</x></span></div>
-<div class="grid r c-min r-max"><y></y><span><x>X</x></span></div>
-
-<br>
-
 <div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
-<div class="grid r c-max r-auto"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
 
 <br>
 
 <div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
-<div class="grid r c-max r-min"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
 
 <br>
 
 <div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
-<div class="grid r c-max r-max"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
+
+<br>
+
+<div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-auto"><y></y><span><x>X</x></span></div>
+
+<br>
+
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-min"><y></y><span><x>X</x></span></div>
+
+<br>
+
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
+<div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
 <div class="grid r c-30 r-max"><y></y><span><x>X</x></span></div>
 
 </body></html>
--- a/layout/reftests/css-grid/grid-item-button-001-ref.html
+++ b/layout/reftests/css-grid/grid-item-button-001-ref.html
@@ -4,30 +4,42 @@
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html><head>
   <meta charset="utf-8">
   <title>Reference: stretching/clamping button item</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1314206">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+* { font:16px/1 monospace; }
 
+.grid2 {
+  display: grid;
+  float: left;
+  grid: auto-flow auto / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
+  grid-gap: 5px;
+  margin-bottom:20px;
+  margin-right:20px;
+  border:1px solid;
+}
 .grid {
   display: block;
   float: left;
   margin-bottom:20px;
   margin-right:20px;
   border:1px solid;
   line-height: 0;
 }
 button {
   border: 1px solid;
   padding: 0;
   margin: 0;
-  vertical-align:top;
+  vertical-align: top;
+  box-sizing: border-box;
+  min-width: 0;
 }
 button:nth-child(1n) { background: blue; }
 button:nth-child(2n) { background: grey; }
 button:nth-child(3n) { background: tan; }
 button:nth-child(4n) { background: silver; }
 .sz > button {
   width:20px; height:10px;
 }
@@ -39,51 +51,56 @@ button:nth-child(4n) { background: silve
 }
 .sz.t2 > button {
   width:10px; height:20px;
 }
 a30 {
   display: inline-block;
   height: 0;
   width: 30px;
-  margin-left: 5px;
-  text-align: right;
+  direction: rtl;
+}
+a10 {
+  display: inline-block;
+  height: 0;
+  width: 10px;
+  direction: rtl;
 }
 .rel > button {
   position:absolute;
 }
   </style>
 </head>
 <body>
 
 <div class="grid sz">
-<button>AB</button><button style="margin-left:-5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:15px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:-5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:15px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button></div>
+<button>&nbsp;&nbsp;</button><button style="margin-left:-5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:15px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:-5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:15px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button></div>
 
 <div class="grid sz t2">
-<button>AB</button><button style="margin-left:5px">AB</button><button style="margin-left:25px">AB</button><button style="margin-left:25px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:25px">AB</button><button style="margin-left:25px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button></div>
+<button>&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:25px">&nbsp;&nbsp;</button><button style="margin-left:25px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:25px">&nbsp;&nbsp;</button><button style="margin-left:25px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button></div>
 
-<div class="grid" style="width:215px">
-<button style="width:10px">AB</button><button style="width:30px;margin-left:5px">AB</button><button style="width:10px;margin-left:5px">AB</button><a30><button style="background:silver">AB</button></a30><button style="width:10px;margin-left:5px">AB</button><button style="width:30px;margin-left:5px">AB</button><button style="width:10px;margin-left:5px">AB</button><a30><button style="background:silver;">AB</button></a30></div>
+<div class="grid2" style="width:215px">
+<button style="width:10px">&nbsp;&nbsp;</button><button style="width:30px">&nbsp;&nbsp;</button><a10><button style="background:tan">&nbsp;&nbsp;</button></a10><a30><button style="background:silver">&nbsp;&nbsp;</button></a30><button style="width:10px">&nbsp;&nbsp;</button><button style="width:30px">&nbsp;&nbsp;</button><a10><button>&nbsp;&nbsp;</button></a10><a30><button style="background:silver;">&nbsp;&nbsp;</button></a30></div>
 
 <div class="grid">
-<button>AB</button><button>AB</button><br><button style="background:tan">AB</button><button style="background:silver">AB</button></div>
+<button>&nbsp;&nbsp;</button><button>&nbsp;&nbsp;</button><br><button style="background:tan">&nbsp;&nbsp;</button><button style="background:silver">&nbsp;&nbsp;</button></div>
 
 <div class="grid rel" style="width:100px; height:100px; position:relative">
-<button style="top:0;width:50px;height:50px">AB</button><button style="top:0;right:0;height:50px">&nbsp;&nbsp;</button><button style="bottom:0;width:50px;">AB</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
+<button style="top:0;width:50px;height:50px">&nbsp;&nbsp;</button><button style="top:0;right:0;height:50px">&nbsp;&nbsp;</button><button style="bottom:0;width:50px;">&nbsp;&nbsp;</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
 
 <div class="grid rel" style="height:40px; position:relative">
-<button style="left:0;top:0;height:20px">AB</button><button style="top:0;right:0;height:20px">AB</button><button style="left:0;bottom:0;">AB</button><button style="bottom:0;right:0">AB</button><button style="position:static;visibility:hidden">AB</button><button style="position:static;visibility:hidden">AB</button>
+<button style="left:0;top:0;height:20px">&nbsp;&nbsp;</button><button style="top:0;right:0;height:20px">&nbsp;&nbsp;</button><button style="left:0;bottom:0;">&nbsp;&nbsp;</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button><button style="position:static;visibility:hidden">&nbsp;&nbsp;</button><button style="position:static;visibility:hidden">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid sz t2 mw">
-<button>AB</button><button>AB</button><button style="margin-left:15px">AB</button><button style="margin-left:20px">AB</button><button style="margin-left:5px">AB</button><button>AB</button><button style="margin-left:15px">AB</button><button style="margin-left:20px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:5px">AB</button></div>
+<button>&nbsp;&nbsp;</button><button>&nbsp;&nbsp;</button><button style="margin-left:15px">&nbsp;&nbsp;</button><button style="margin-left:20px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button>&nbsp;&nbsp;</button><button style="margin-left:15px">&nbsp;&nbsp;</button><button style="margin-left:20px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button></div>
 
 <div class="grid mw40" style="width:215px">
-<button>AB</button><button style="margin-left:-25px">AB</button><button style="margin-left:-35px">AB</button><button style="margin-left:-5px">AB</button><button style="margin-left:5px">AB</button><button style="margin-left:-25px">AB</button><button style="margin-left:-35px">AB</button><button style="margin-left:-5px">AB</button></div>
+<button>&nbsp;&nbsp;</button><button style="margin-left:-25px">&nbsp;&nbsp;</button><button style="margin-left:-35px">&nbsp;&nbsp;</button><button style="margin-left:-5px">&nbsp;&nbsp;</button><button style="margin-left:5px">&nbsp;&nbsp;</button><button style="margin-left:-25px">&nbsp;&nbsp;</button><button style="margin-left:-35px">&nbsp;&nbsp;</button><button style="margin-left:-5px">&nbsp;&nbsp;</button></div>
 
 <div class="grid rel" style="width:100px; height:100px; position:relative">
-<button style="top:0;width:40px;height:40px">AB</button><button style="top:0;right:0;height:40px">&nbsp;&nbsp;</button><button style="bottom:0;width:40px;">AB</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
+<button style="top:0;width:40px;height:40px">&nbsp;&nbsp;</button><button style="top:0;right:0;height:40px">&nbsp;&nbsp;</button><button style="bottom:0;width:40px;">&nbsp;&nbsp;</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
 
 <div class="grid rel" style="width:100px; height:100px; position:relative">
-<button style="top:0;width:40px;height:40px">AB</button><button style="top:0;right:0;height:40px">&nbsp;&nbsp;</button><button style="bottom:0;width:40px;">AB</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
+<button style="top:0;width:40px;height:40px">&nbsp;&nbsp;</button><button style="top:0;right:0;height:40px">&nbsp;&nbsp;</button><button style="bottom:0;width:40px;">&nbsp;&nbsp;</button><button style="bottom:0;right:0">&nbsp;&nbsp;</button></div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-button-001.html
+++ b/layout/reftests/css-grid/grid-item-button-001.html
@@ -6,16 +6,17 @@
 <html><head>
   <meta charset="utf-8">
   <title>CSS Grid Test: stretching/clamping button item</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1314206">
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch">
   <link rel="match" href="grid-item-button-001-ref.html">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
+* { font:16px/1 monospace; }
 
 .grid {
   display: grid;
   float: left;
   grid: auto-flow auto / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
   grid-gap: 5px;
   margin-bottom:20px;
   margin-right:20px;
@@ -50,111 +51,111 @@ button:nth-child(4n) { background: silve
 .jend { justify-self: end; }
 .aend { align-self: end; }
 .end { justify-self: end; align-self: end; }
   </style>
 </head>
 <body>
 
 <div class="grid sz">
-<button>AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
-<button class="end">AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid sz t2">
-<button>AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
-<button class="end">AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid">
-<button>AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid" style="grid: auto/auto auto; grid-gap: 0;">
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid" style="grid: 50px 50px/50px 50px; grid-gap: 0;">
-<button>AB</button>
+<button>&nbsp;&nbsp;</button>
 <button class="jend">&nbsp;&nbsp;</button>
-<button class="aend">AB</button>
+<button class="aend">&nbsp;&nbsp;</button>
 <button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid" style="grid: minmax(auto,20px) 20px/auto auto; grid-gap: 0;">
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid sz t2 mw">
-<button>AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
-<button class="end">AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid mw40">
-<button>AB</button>
-<button>AB</button>
-<button class="jend">AB</button>
-<button class="jend">AB</button>
-<button class="aend">AB</button>
-<button class="aend">AB</button>
-<button class="end">AB</button>
-<button class="end">AB</button>
+<button>&nbsp;&nbsp;</button>
+<button>&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="jend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="aend">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
+<button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid max40" style="grid:50px 50px/50px 50px; grid-gap: 0;">
-<button>AB</button>
+<button>&nbsp;&nbsp;</button>
 <button class="jend">&nbsp;&nbsp;</button>
-<button class="aend">AB</button>
+<button class="aend">&nbsp;&nbsp;</button>
 <button class="end">&nbsp;&nbsp;</button>
 </div>
 
 <div class="grid max40" style="grid:50px 50px/50px 50px; place-items:stretch; grid-gap: 0;">
-<button>AB</button>
+<button>&nbsp;&nbsp;</button>
 <button class="jend">&nbsp;&nbsp;</button>
-<button class="aend">AB</button>
+<button class="aend">&nbsp;&nbsp;</button>
 <button class="end">&nbsp;&nbsp;</button>
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-canvas-001-ref.html
+++ b/layout/reftests/css-grid/grid-item-canvas-001-ref.html
@@ -33,18 +33,25 @@ canvas {
 <body>
 
 <div class="block sz">
 <canvas></canvas><canvas style="margin-left:-5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:15px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:-5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:15px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas></div>
 
 <div class="block sz t2">
 <canvas></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:25px"></canvas><canvas style="margin-left:25px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:25px"></canvas><canvas style="margin-left:25px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas><canvas style="margin-left:5px"></canvas></div>
 
-<div class="block" style="height:150px; width:215px">
-<canvas style="width:10px;height:5px;"></canvas><canvas style="width:30px;height:15px;margin-left:5px"></canvas><canvas style="width:10px;height:5px;margin-left:5px"></canvas><canvas style="width:30px;height:15px;margin-left:5px"></canvas><canvas style="width:10px;height:5px;vertical-align:bottom;margin-top:145px;margin-left:5px"></canvas><canvas style="width:30px;height:15px;vertical-align:bottom;margin-top:135px;margin-left:5px"></canvas><canvas style="width:10px;height:5px;vertical-align:bottom;margin-top:145px;margin-left:5px"></canvas><canvas style="width:30px;height:15px;vertical-align:bottom;margin-top:135px;margin-left:5px"></canvas></div>
+<br clear=all>
+<br clear=all>
+
+<div class="block" style="height:150px; width:215px; white-space:pre">
+<canvas style="width:195px; height:150px; background:black"></canvas><canvas style="width:220px; height:150px; background:tan"></canvas></div>
+
 
 <div class="block" style="height:300px; width:600px"><canvas style="width:300px;height:150px"></canvas><canvas style="width:300px;height:150px"></canvas><canvas style="width:300px;height:150px"></canvas><canvas style="width:300px;height:150px"></canvas></div>
 
-<div class="block" style="height:60px; width:600px">
-<canvas style="height:30px"></canvas><canvas style="height:30px;margin-left:480px"></canvas><canvas style="height:30px"></canvas><canvas style="height:30px;margin-left:480px"></canvas></div>
+<br clear=all>
+<br clear=all>
+
+<div class="block" style="height:60px; width:600px; white-space:pre">
+<span style="display:inline-block; height:60px; margin-top:-90px"><canvas style="background:tan; vertical-align:bottom"></canvas><canvas style="background:black; vertical-align:bottom"></canvas></span></div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-canvas-001.html
+++ b/layout/reftests/css-grid/grid-item-canvas-001.html
@@ -62,16 +62,19 @@ canvas:nth-child(4n) { background: black
 <canvas class="end"></canvas>
 <canvas class="end"></canvas>
 <canvas></canvas>
 <canvas class="jend"></canvas>
 <canvas class="aend"></canvas>
 <canvas class="end"></canvas>
 </div>
 
+<br clear=all>
+<br clear=all>
+
 <div class="grid">
 <canvas></canvas>
 <canvas></canvas>
 <canvas class="jend"></canvas>
 <canvas class="jend"></canvas>
 <canvas class="aend"></canvas>
 <canvas class="aend"></canvas>
 <canvas class="end"></canvas>
@@ -80,16 +83,19 @@ canvas:nth-child(4n) { background: black
 
 <div class="grid" style="grid: auto/auto auto; grid-gap: 0;">
 <canvas></canvas>
 <canvas class="jend"></canvas>
 <canvas class="aend"></canvas>
 <canvas class="end"></canvas>
 </div>
 
+<br clear=all>
+<br clear=all>
+
 <div class="grid" style="grid: minmax(auto,30px) 30px/auto auto; grid-gap: 0">
 <canvas></canvas>
 <canvas class="jend"></canvas>
 <canvas class="aend"></canvas>
 <canvas class="end"></canvas>
 </div>
 
 </body>
--- a/layout/reftests/css-grid/grid-item-input-stretch-001-ref.html
+++ b/layout/reftests/css-grid/grid-item-input-stretch-001-ref.html
@@ -52,30 +52,30 @@ input {
 <div class="grid"><input class="hma10 je" style="height:20px"></div>
 <div class="grid"><input class="hmaa jc" style="height:20px"></div>
 <div class="grid"><input class="vr hma10 je" style="height:20px"></div>
 <div class="grid"><input class="vr hmaa jc" style="height:20px"></div>
 <div class="grid"><input class="vr je" style="width:198px; height:28px"></div>
 
 <div class="grid"><input class="vma10 ae" style="width:190px"></div>
 <div class="grid"><input class="vmaa ac" style="width:190px"></div>
-<div class="grid"><input class="vr vma10" style="width:190px; height:25px"></div>
-<div class="grid"><input class="vr vmaa ac" style="width:190px; height:28px"></div>
-<div class="grid"><input class="vr p vma10" style="width:182px; height:17px"></div>
-<div class="grid"><input class="vr p vmaa ac" style="width:182px; height:20px"></div>
+<div class="grid"><input class="vr vma10" style="width:190px;"></div>
+<div class="grid"><input class="vr vmaa" style="width:190px;"></div>
+<div class="grid"><input class="vr p vma10" style="width:182px;"></div>
+<div class="grid"><input class="vr p vmaa" style="width:182px;"></div>
 
 <div class="grid"><input class="mxw m" style="height:20px"></div>
 <div class="grid"><input class="mxw hma10 je" style="height:20px"></div>
 <div class="grid"><input class="mxw hmaa jc" style="height:20px"></div>
 <div class="grid"><input class="mxw vr hma10 je" style="width:10px; height:20px"></div>
 <div class="grid"><input class="mxw vr" style="height:28px"></div>
 
 <div class="grid"><input class="mxh m je" style="width:190px"></div>
 <div class="grid"><input class="mxh hma10 je"></div>
 <div class="grid"><input class="mxh hmaa jc"></div>
 <div class="grid"><input class="mxh vr hmaa jc" style="width:10px"></div>
 <div class="grid"><input class="mxh vr" style="width:198px"></div>
 
-<div class="grid" style="grid:2px/2px; padding:0;"><input style="width:0;height:0"></div>
-<div class="grid" style="grid:2px/2px; padding:0;"><input style="width:0;height:0"></div>
+<div class="grid" style="grid:auto/auto; padding:0;"><input></div>
+<div class="grid" style="grid:auto/auto; padding:0;"><input></div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-002-ref.html
@@ -39,44 +39,44 @@ x { width:32px; height:2px; background:c
 <div style="height:32px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:32px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w4" style="grid:8px 10px 8px / repeat(7, 4px); grid-column-gap:32px; ">
+<div class="grid w4" style="grid:8px 10px 8px / repeat(7, 4px); grid-column-gap:32px; width:292px">
 <div style="height:8px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:8px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w4" style="grid:32px 10px 32px / repeat(7, 4px); grid-column-gap:32px; ">
+<div class="grid w4" style="grid:32px 10px 32px / repeat(7, 4px); grid-column-gap:32px; width:292px">
 <div style="height:32px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:32px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w8" style="grid:repeat(3, 4px) / repeat(7, 8px); grid-gap:8px; ">
+<div class="grid w8" style="grid:4px 10px 4px 2px 2px / repeat(7, 8px); grid-gap:8px; width:152px">
 <div style="height:4px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:4px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid" style="grid:repeat(3, 8px) / repeat(7, 32px); grid-gap:16px; ">
+<div class="grid" style="grid:8px 10px 8px 2px 2px / repeat(7, 32px); grid-gap:16px; ">
 <div style="height:4px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:4px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-002.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-002.html
@@ -20,62 +20,62 @@ x { width:32px; height:2px; background:c
 .w24 > x { width:24px; }
 .w8  > x { width:8px; }
 .w4  > x { width:4px; }
 
   </style>
 </head>
 <body>
 
-<div class="grid" style="grid:24px 10px 24px / repeat(7, 32px); grid-column-gap: 10px;">
+<div class="grid" style="grid: minmax(auto, 24px) minmax(auto, 10px) minmax(auto, 24px) / repeat(7, minmax(auto, 32px)); grid-column-gap: 10px;">
 <div style="height:24px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:24px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w24" style="grid:32px 10px 32px / repeat(7, 24px); grid-column-gap: 10px;">
+<div class="grid w24" style="grid: minmax(auto, 32px) minmax(auto, 10px) minmax(auto, 32px) / repeat(7, minmax(auto, 24px)); grid-column-gap: 10px;">
 <div style="height:32px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:32px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w4" style="grid:8px 10px 8px / repeat(7, 4px); grid-column-gap:32px; ">
+<div class="grid w4" style="grid: minmax(auto, 8px) minmax(auto, 10px) minmax(auto, 8px) / repeat(7, minmax(auto, 4px)); grid-column-gap:32px; ">
 <div style="height:8px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:8px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w4" style="grid:32px 10px 32px / repeat(7, 4px); grid-column-gap:32px; ">
+<div class="grid w4" style="grid: minmax(auto, 32px) minmax(auto, 10px) minmax(auto, 32px) / repeat(7, minmax(auto, 4px)); grid-column-gap:32px; ">
 <div style="height:32px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:32px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid w8" style="grid:repeat(3, 4px) / repeat(7, 8px); grid-gap:8px; ">
+<div class="grid w8" style="grid: repeat(3, minmax(auto, 4px)) / repeat(7, minmax(auto, 8px)); grid-gap:8px; ">
 <div style="height:4px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:4px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
-<div class="grid" style="grid:repeat(3, 8px) / repeat(7, 32px); grid-gap:16px; ">
+<div class="grid" style="grid: repeat(3, minmax(auto, 8px)) / repeat(7, minmax(auto, 32px)); grid-gap:16px; ">
 <div style="height:4px; width:2px; background:cyan; grid-row:1"></div>
 <div style="height:10px; grid-row:2; grid-column: span 7"></div>
 <div style="height:4px; grid-row:3"></div>
 <x style="grid-row:4"></x>
 </div>
 
 <br>
 
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-003-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-003-ref.html
@@ -17,17 +17,19 @@
 }
 .r { grid: 4px / 32px; }
 
 .start {align-self:start; justify-self:start}
 .na {align-self:start; justify-self:start}
 .sa {align-self:start; justify-self:start}
 .an {align-self:start; justify-self:start}
 .as {align-self:start; justify-self:start}
-.w20 { width: 20px min-width: 0px; }
+.w20 { width: 20px; min-width: 0px; }
+.w16 { width: 16px; }
+.w10 { width: 10px; }
 .mw20 { min-width: 20px }
 .mw0 { min-width: 0px }
 
 .h20 { height: 20px; min-height: 0px; }
 .mh20 { min-height: 20px }
 .mh0 { min-height: 0px }
 
   </style>
@@ -37,109 +39,109 @@
 <div class="grid r"><img></div>
 <div class="grid r"><img class="start"></div>
 <div class="grid r"><img class="sa"></div>
 <div class="grid r"><img class="sa mxw10"></div>
 <div class="grid r"><img class="na"></div>
 <div class="grid r"><img class="na mxw2"></div>
 
 <pre><!--min-height:20px--></pre>
-<div class="grid r"><img class="mh20"></div>
-<div class="grid r"><img class="mh20 mxw10"></div>
-<div class="grid r"><img class="start mh20"></div>
-<div class="grid r"><img class="start mh20 mxw10"></div>
-<div class="grid r"><img class="sa mh20"></div>
-<div class="grid r"><img class="sa mh20 mxw10"></div>
-<div class="grid r"><img class="na mh20"></div>
-<div class="grid r"><img class="na mh20 mxw10"></div>
+<div class="grid r mh20"><img class="mh20"></div>
+<div class="grid r mh20"><img class="mh20 mxw10"></div>
+<div class="grid r mh20"><img class="start mh20"></div>
+<div class="grid r mh20"><img class="start mh20 mxw10"></div>
+<div class="grid r mh20"><img class="sa mh20"></div>
+<div class="grid r mh20"><img class="sa mh20 mxw10"></div>
+<div class="grid r mh20"><img class="na mh20"></div>
+<div class="grid r mh20"><img class="na mh20 mxw10"></div>
 
 <pre><!--min-height:0--></pre>
 <div class="grid r"><img class="mh0"></div>
 <div class="grid r"><img class="mh0 mxw10"></div>
 <div class="grid r"><img class="start mh0"></div>
 <div class="grid r"><img class="start mh0 mxw10"></div>
 <div class="grid r"><img class="sa mh0"></div>
 <div class="grid r"><img class="sa mh0 mxw10"></div>
 <div class="grid r"><img class="na mh0"></div>
 <div class="grid r"><img class="na mh0 mxw2"></div>
 
 <pre><!----></pre>
 
-<div class="grid"><img></div>
+<div class="grid w16"><img></div>
 <div class="grid"><img class="mxw2"></div>
-<div class="grid"><img class="start"></div>
+<div class="grid w16"><img class="start"></div>
 <div class="grid"><img class="start mxw2"></div>
-<div class="grid"><img class="sa"></div>
+<div class="grid w16"><img class="sa"></div>
 <div class="grid"><img class="sa mxw2"></div>
-<div class="grid"><img class="na"></div>
+<div class="grid w16"><img class="na"></div>
 <div class="grid"><img class="na mxw2"></div>
 
 <pre><!--min-width:20px--></pre>
-<div class="grid"><img class="mw20"></div>
-<div class="grid"><img class="mw20 mxh10"></div>
-<div class="grid"><img class="start mw20"></div>
-<div class="grid"><img class="start mw20 mxh10"></div>
-<div class="grid"><img class="sa mw20"></div>
-<div class="grid"><img class="sa mw20 mxh10"></div>
-<div class="grid"><img class="na mw20"></div>
-<div class="grid"><img class="na mw20 mxh10"></div>
+<div class="grid mw20"><img class="mw20"></div>
+<div class="grid mw20"><img class="mw20 mxh10"></div>
+<div class="grid mw20"><img class="start mw20"></div>
+<div class="grid mw20"><img class="start mw20 mxh10"></div>
+<div class="grid mw20"><img class="sa mw20"></div>
+<div class="grid mw20"><img class="sa mw20 mxh10"></div>
+<div class="grid mw20"><img class="na mw20"></div>
+<div class="grid mw20"><img class="na mw20 mxh10"></div>
 
 <pre><!--min-width:0--></pre>
-<div class="grid"><img class="mw0"></div>
-<div class="grid"><img class="mw0 mxh10"></div>
-<div class="grid"><img class="start mw0"></div>
-<div class="grid"><img class="start mw0 mxh10"></div>
-<div class="grid"><img class="sa mw0"></div>
-<div class="grid"><img class="sa mw0 mxh10"></div>
-<div class="grid"><img class="na mw0"></div>
-<div class="grid"><img class="na mw0 mxh10"></div>
+<div class="grid w16"><img class="mw0"></div>
+<div class="grid w10"><img class="mw0 mxh10"></div>
+<div class="grid w16"><img class="start mw0"></div>
+<div class="grid w10"><img class="start mw0 mxh10"></div>
+<div class="grid w16"><img class="sa mw0"></div>
+<div class="grid w10"><img class="sa mw0 mxh10"></div>
+<div class="grid w16"><img class="na mw0"></div>
+<div class="grid w10"><img class="na mw0 mxh10"></div>
 
 <pre><!--width:20px--></pre>
 
 <div class="grid r"><img class="w20"></div>
 <div class="grid r"><img class="w20 mxh10"></div>
 <div class="grid r"><img class="start w20"></div>
 <div class="grid r"><img class="start w20 mxh10"></div>
 <div class="grid r"><img class="sa w20"></div>
 <div class="grid r"><img class="sa w20 mxh2"></div>
 <div class="grid r"><img class="na w20"></div>
 <div class="grid r"><img class="na w20 mxh2"></div>
 
 <pre><!--width:20px--></pre>
 
-<div class="grid"><img class="start w20"></div>
-<div class="grid"><img class="start w20 mxh10"></div>
-<div class="grid"><img class="start w20"></div>
-<div class="grid"><img class="start w20 mxh10"></div>
-<div class="grid"><img class="sa w20"></div>
-<div class="grid"><img class="sa w20 mxh10"></div>
-<div class="grid"><img class="na w20"></div>
-<div class="grid"><img class="na w20 mxh10"></div>
+<div class="grid mw20"><img class="start w20"></div>
+<div class="grid mw20"><img class="start w20 mxh10"></div>
+<div class="grid mw20"><img class="start w20"></div>
+<div class="grid mw20"><img class="start w20 mxh10"></div>
+<div class="grid mw20"><img class="sa w20"></div>
+<div class="grid mw20"><img class="sa w20 mxh10"></div>
+<div class="grid mw20"><img class="na w20"></div>
+<div class="grid mw20"><img class="na w20 mxh10"></div>
 
 <pre><!--height:20px--></pre>
 
-<div class="grid r"><img class="h20"></div>
-<div class="grid r"><img class="h20 mxw10"></div>
-<div class="grid r"><img class="start h20"></div>
-<div class="grid r"><img class="start h20 mxw10"></div>
-<div class="grid r"><img class="as h20"></div>
-<div class="grid r"><img class="as h20 mxw10"></div>
-<div class="grid r"><img class="an h20"></div>
-<div class="grid r"><img class="an h20 mxw10"></div>
+<div class="grid r mh20"><img class="h20"></div>
+<div class="grid r mh20"><img class="h20 mxw10"></div>
+<div class="grid r mh20"><img class="start h20"></div>
+<div class="grid r mh20"><img class="start h20 mxw10"></div>
+<div class="grid r mh20"><img class="as h20"></div>
+<div class="grid r mh20"><img class="as h20 mxw10"></div>
+<div class="grid r mh20"><img class="an h20"></div>
+<div class="grid r mh20"><img class="an h20 mxw10"></div>
 
 <pre><!--height:20px--></pre>
 
-<div class="grid"><img class="h20"></div>
+<div class="grid mw20"><img class="h20"></div>
 <div class="grid"><img class="h20 mxw2"></div>
-<div class="grid"><img class="start h20"></div>
-<div class="grid"><img class="start h20 mxw10"></div>
-<div class="grid"><img class="as h20"></div>
+<div class="grid mw20"><img class="start h20"></div>
+<div class="grid w10"><img class="start h20 mxw10"></div>
+<div class="grid mw20"><img class="as h20"></div>
 <div class="grid"><img class="as h20 mxw2"></div>
-<div class="grid"><img class="an h20"></div>
-<div class="grid"><img class="an h20 mxw10"></div>
+<div class="grid mw20"><img class="an h20"></div>
+<div class="grid w10"><img class="an h20 mxw10"></div>
 
 <script>
 var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAEElEQVQoz2NgGAWjYBTAAAADEAABaJFtwwAAAABJRU5ErkJggg%3D%3D";
 var imgs = document.querySelectorAll('img');
 var imgSizes =
 [
   ['4px', '4px'],
   ['4px', '4px'],
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-003.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-003.html
@@ -9,20 +9,20 @@
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-normal">
   <link rel="match" href="grid-item-intrinsic-ratio-normal-003-ref.html">
   <style type="text/css">
 * { vertical-align: bottom; }
 .grid {
   display: inline-grid;
   border: 3px solid grey;
-  grid: 32px / 4px;
+  grid: minmax(auto, 32px) / minmax(auto, 4px);
   margin-right:20px;
 }
-.r { grid: 4px / 32px; }
+.r { grid: minmax(auto, 4px) / minmax(auto, 32px); }
 
 button {
   border: 1px solid;
   padding: 0;
   margin: 0;
   background: lightgrey;
 }
 
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-004-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-004-ref.html
@@ -86,47 +86,47 @@ img {
 <img class="aend">
 <img class="end">
 </div>
 
 <script>
 var url = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="0px"><circle cx="50%" cy="50%" r="50%" fill="pink"/></svg>'
 var imgSizes =
 [
-  ['8px', '20px'],
+  ['16px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
-  ['8px', '20px'],
+  ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-005-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-normal-005-ref.html
@@ -86,48 +86,48 @@ img {
 <img class="aend">
 <img class="end">
 </div>
 
 <script>
 var url = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="0px" height="16px"><circle cx="50%" cy="50%" r="50%" fill="pink"/></svg>'
 var imgSizes =
 [
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-004-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-004-ref.html
@@ -23,34 +23,34 @@ body,html { color:black; background:whit
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="height:96px; width:20px">
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="height:96px; width:4px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: 8px / 20px; width:24px">
 <img src="support/lime-24x2.png" style="width:20px; height:8px">
 </div>
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="width:100px; height:8px">
 </div>
 
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:start; height:24px; width:10px">
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="align-self:start; height:24px; width:4px">
 </div>
 
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:24px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: 8px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:10px; height:8px">
 </div>
 
 <br>
 
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
 </div>
@@ -59,58 +59,58 @@ body,html { color:black; background:whit
 </div>
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
 </div>
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
 </div>
 
-<div class="grid" style="grid: 4px / 10px">
+<div class="grid" style="grid: 4px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start unsafe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start safe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:end unsafe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 80px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:end safe; width:10px; height:4px">
 </div>
 
 <br>
 
 <div class="vertical-tests">
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="height:96px; width:20px">
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="height:96px; width:4px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: 8px / 20px; width:24px">
 <img src="support/lime-24x2.png" style="width:20px; height:8px">
 </div>
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="width:100px; height:8px">
 </div>
 
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:start; height:24px; width:10px">
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="align-self:start; height:24px; width:4px">
 </div>
 
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:24px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: 8px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:10px; height:8px">
 </div>
 
 <br>
 
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
 </div>
@@ -119,25 +119,25 @@ body,html { color:black; background:whit
 </div>
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
 </div>
 <div class="grid" style="grid: 96px / 10px">
 <img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
 </div>
 
-<div class="grid" style="grid: 4px / 10px">
+<div class="grid" style="grid: 4px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start unsafe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start safe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:end unsafe; width:10px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
+<div class="grid" style="grid: 4px / 10px; margin-left: 80px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:end safe; width:10px; height:4px">
 </div>
 
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-004.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-004.html
@@ -18,128 +18,128 @@ body,html { color:black; background:whit
   place-items: stretch stretch;
 }
 .vertical-tests img { writing-mode: vertical-rl; }
 .vertical-tests div { vertical-align:bottom }
   </style>
 </head>
 <body>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png">
 </div>
 
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="justify-self:start">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start">
 </div>
 
 <br>
 
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start safe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start unsafe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:end safe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:end unsafe;">
 </div>
 
-<div class="grid" style="grid: 4px / 10px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start safe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
 <img src="support/lime-24x2.png" style="justify-self:start unsafe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
 <img src="support/lime-24x2.png" style="justify-self:end safe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 80px">
 <img src="support/lime-24x2.png" style="justify-self:end unsafe">
 </div>
 
 <br>
 
 <div class="vertical-tests">
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png">
 </div>
 
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="justify-self:start">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start">
 </div>
 
 <br>
 
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start safe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:start unsafe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:end safe;">
 </div>
-<div class="grid" style="grid: 96px / 10px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
 <img src="support/lime-2x24.png" style="align-self:end unsafe;">
 </div>
 
-<div class="grid" style="grid: 4px / 10px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start safe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
 <img src="support/lime-24x2.png" style="justify-self:start unsafe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
 <img src="support/lime-24x2.png" style="justify-self:end safe">
 </div>
-<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 80px">
 <img src="support/lime-24x2.png" style="justify-self:end unsafe">
 </div>
 
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-005-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-005-ref.html
@@ -12,16 +12,20 @@ body,html { color:black; background:whit
 
 .grid {
   display: inline-grid;
   border: 1px solid;
   margin: 5px;
   align-items: start;
   justify-items: start;
 }
+img {
+  min-width: 0;
+  min-height: 0;
+}
 .vertical-tests div { vertical-align:bottom }
   </style>
 </head>
 <body>
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="width:4px; height:96px">
 </div>
@@ -41,47 +45,49 @@ body,html { color:black; background:whit
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="align-self:start; height:12px; width:4px">
 </div>
 
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:24px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: 8px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:10px; height:8px">
 </div>
 
 <br>
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="width:20px; height:96px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: 96px / 4px; width:6px">
 <img src="support/lime-2x24.png" style="width:6px; height:96px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: 8px / 20px; width:24px">
 <img src="support/lime-24x2.png" style="width:20px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: 8px / 100px; width:120px; height:10px">
 <img src="support/lime-24x2.png" style="width:100px; height:10px">
 </div>
 
-<div class="grid" style="grid: 48px / 6px">
+<div class="grid" style="grid: 48px / 6px; width:7px; height:80px">
 <img src="support/lime-2x24.png" style="align-self:start; width:6px; height:80px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<!--
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 6px)">
 <img src="support/lime-2x24.png" style="align-self:start; width:4px; height:72px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
-<img src="support/lime-24x2.png" style="justify-self:start; width:98px; height:calc(2px * (98 / 24))">
+<div class="grid" style="grid: 4px / 100px">
+<img src="support/lime-24x2.png" style="justify-self:start; width:72px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px">
+-->
+<div class="grid" style="grid: 4px / 10px; width:72px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:72px; height:4px">
 </div>
 
 <br>
 
 <div class="vertical-tests">
 
 <div class="grid" style="grid: 96px / 20px">
@@ -103,46 +109,48 @@ body,html { color:black; background:whit
 </div>
 <div class="grid" style="grid: 96px / 4px">
 <img src="support/lime-2x24.png" style="align-self:start; height:12px; width:4px">
 </div>
 
 <div class="grid" style="grid: 8px / 100px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:24px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: 8px / 10px; width:24px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:10px; height:8px">
 </div>
 
 <br>
 
 <div class="grid" style="grid: 96px / 20px">
 <img src="support/lime-2x24.png" style="width:20px; height:96px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: 96px / 4px; width:6px">
 <img src="support/lime-2x24.png" style="width:6px; height:96px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: 8px / 20px; width:24px">
 <img src="support/lime-24x2.png" style="width:20px; height:8px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: 8px / 100px; width:120px; height:10px">
 <img src="support/lime-24x2.png" style="width:100px; height:10px">
 </div>
 
-<div class="grid" style="grid: 48px / 6px">
+<div class="grid" style="grid: 48px / 6px; width:7px; height:80px">
 <img src="support/lime-2x24.png" style="align-self:start; width:6px; height:80px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<!--
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 6px)">
 <img src="support/lime-2x24.png" style="align-self:start; width:4px; height:72px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
-<img src="support/lime-24x2.png" style="justify-self:start; width:98px; height:calc(2px * (98 / 24))">
+<div class="grid" style="grid: 4px / 100px">
+<img src="support/lime-24x2.png" style="justify-self:start; width:72px; height:4px">
 </div>
-<div class="grid" style="grid: 4px / 10px">
+-->
+<div class="grid" style="grid: 4px / 10px; width:72px">
 <img src="support/lime-24x2.png" style="justify-self:start; width:72px; height:4px">
 </div>
 
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-005.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-005.html
@@ -19,132 +19,136 @@ body,html { color:black; background:whit
   place-items: stretch;
 }
 .vertical-tests img { writing-mode: vertical-rl; }
 .vertical-tests div { vertical-align:bottom }
   </style>
 </head>
 <body>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="max-width:4px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="max-height:12px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png" style="max-width:12px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="max-height:6px">
 </div>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="align-self:start; max-height:48px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start; max-height:12px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="justify-self:start; max-width:48px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start; max-width:48px">
 </div>
 
 <br>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="min-width:10px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="min-width:6px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png" style="min-height:2px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="min-height:10px">
 </div>
 
-<div class="grid" style="grid: 48px / 6px">
+<div class="grid" style="grid: minmax(auto, 48px) / minmax(auto, 6px)">
 <img src="support/lime-2x24.png" style="align-self:start; min-height:80px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<!--
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start; min-height:72px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
-<img src="support/lime-24x2.png" style="justify-self:start; min-width:98px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 100px)">
+<img src="support/lime-24x2.png" style="justify-self:start; min-width:72px">
 </div>
-<div class="grid" style="grid: 4px / 10px">
+-->
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start; min-width:72px">
 </div>
 
 <br>
 
 <div class="vertical-tests">
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="max-width:4px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="max-height:12px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png" style="max-width:12px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="max-height:6px">
 </div>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="align-self:start; max-height:48px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start; max-height:12px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="justify-self:start; max-width:48px">
 </div>
-<div class="grid" style="grid: 8px / 10px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start; max-width:48px">
 </div>
 
 <br>
 
-<div class="grid" style="grid: 96px / 20px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 20px)">
 <img src="support/lime-2x24.png" style="min-width:10px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="min-width:6px">
 </div>
 
-<div class="grid" style="grid: 8px / 20px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 20px)">
 <img src="support/lime-24x2.png" style="min-height:2px">
 </div>
-<div class="grid" style="grid: 8px / 100px">
+<div class="grid" style="grid: minmax(auto, 8px) / minmax(auto, 100px)">
 <img src="support/lime-24x2.png" style="min-height:10px">
 </div>
 
-<div class="grid" style="grid: 48px / 6px">
+<div class="grid" style="grid: minmax(auto, 48px) / minmax(auto, 6px)">
 <img src="support/lime-2x24.png" style="align-self:start; min-height:80px">
 </div>
-<div class="grid" style="grid: 96px / 4px">
+<!--
+<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 4px)">
 <img src="support/lime-2x24.png" style="align-self:start; min-height:72px">
 </div>
 
-<div class="grid" style="grid: 8px / 100px">
-<img src="support/lime-24x2.png" style="justify-self:start; min-width:98px">
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 100px)">
+<img src="support/lime-24x2.png" style="justify-self:start; min-width:72px">
 </div>
-<div class="grid" style="grid: 4px / 10px">
+-->
+<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
 <img src="support/lime-24x2.png" style="justify-self:start; min-width:72px">
 </div>
 
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-006-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-006-ref.html
@@ -8,17 +8,17 @@
   <title>Reference: 'stretch' of image with zero ratio</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315857">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
 
 .grid {
   display: grid;
   float: left;
-  grid: auto-flow auto / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
+  grid: auto-flow auto / 10px 30px 10px 30px 10px 30px 10px 30px 26px 26px 26px 26px;
   grid-gap: 5px;
   border:1px solid;
   align-items: stretch;
   justify-items: stretch;
 }
 img:nth-child(1n) { background: blue; }
 img:nth-child(2n) { background: grey; }
 img:nth-child(3n) { background: tan; }
@@ -59,17 +59,17 @@ img {
 <img class="end">
 <img class="end">
 <img>
 <img class="jend">
 <img class="aend">
 <img class="end">
 </div>
 
-<div class="grid">
+<div class="grid" style="grid-template-columns: 10px 30px 10px 30px 10px 30px 10px 30px 26px 16px">
 <img>
 <img>
 <img class="jend">
 <img class="jend">
 <img class="aend">
 <img class="aend">
 <img class="end">
 <img class="end">
@@ -96,48 +96,48 @@ var imgSizes =
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
-  ['16px', '20px'],
+  ['24px', '20px'],
   ['16px', '20px'],
-  ['16px', '20px'],
+  ['24px', '20px'],
   ['16px', '20px'],
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
-  ['16px', '20px'],
+  ['24px', '20px'],
   ['16px', '20px'],
-  ['16px', '20px'],
+  ['24px', '20px'],
   ['16px', '20px'],
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
   ['8px', '20px'],
   ['28px', '20px'],
   ['8px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
   ['16px', '20px'],
-  ['16px', '20px'],
+  ['16px', '20px']
 ];
 var imgs = document.querySelectorAll('img');
 for (var i = 0; i < imgs.length; ++i) {
   var img = imgs[i];
   img.style.width = imgSizes[i][0];
   img.style.height = imgSizes[i][1];
   img.src = url;
 }
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-006.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-006.html
@@ -10,17 +10,17 @@
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch">
   <link rel="match" href="grid-item-intrinsic-ratio-stretch-006-ref.html">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
 
 .grid {
   display: grid;
   float: left;
-  grid: auto-flow auto / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
+  grid: auto-flow auto / minmax(auto, 10px)  minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) auto auto auto auto;
   grid-gap: 5px;
   border:1px solid;
   align-items: stretch;
   justify-items: stretch;
 }
 img:nth-child(1n) { background: blue; }
 img:nth-child(2n) { background: grey; }
 img:nth-child(3n) { background: tan; }
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-007-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-007-ref.html
@@ -8,17 +8,17 @@
   <title>Reference: 'stretch' of image with zero ratio</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315857">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
 
 .grid {
   display: grid;
   float: left;
-  grid: auto-flow 10px / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
+  grid: auto-flow 18px / 22px 30px 22px 30px 22px 30px 22px 30px 22px 22px 22px 22px;
   grid-gap: 5px;
   border:1px solid;
 }
 img:nth-child(1n) { background: blue; }
 img:nth-child(2n) { background: grey; }
 img:nth-child(3n) { background: tan; }
 img:nth-child(4n) { background: black; }
 img {
@@ -57,17 +57,17 @@ img {
 <img class="end">
 <img class="end">
 <img>
 <img class="jend">
 <img class="aend">
 <img class="end">
 </div>
 
-<div class="grid">
+<div class="grid" style="grid-template-columns: 22px 30px 22px 30px 22px 30px 22px 30px 15px">
 <img>
 <img>
 <img class="jend">
 <img class="jend">
 <img class="aend">
 <img class="aend">
 <img class="end">
 <img class="end">
@@ -86,48 +86,48 @@ img {
 <img class="aend">
 <img class="end">
 </div>
 
 <script>
 var url = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="0px" height="16px"><circle cx="50%" cy="50%" r="50%" fill="pink"/></svg>'
 var imgSizes =
 [
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
-  ['20px', '8px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
+  ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
   ['20px', '16px'],
--- a/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-007.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-ratio-stretch-007.html
@@ -10,17 +10,17 @@
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch">
   <link rel="match" href="grid-item-intrinsic-ratio-stretch-007-ref.html">
   <style type="text/css">
 body,html { color:black; background:white; font:16px/1 monospace; padding:0; margin:0; }
 
 .grid {
   display: grid;
   float: left;
-  grid: auto-flow 10px / 10px 30px 10px 30px 10px 30px 10px 30px auto auto auto auto;
+  grid: auto-flow auto / minmax(auto, 10px)  minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) minmax(auto, 10px) minmax(auto, 30px) auto auto auto auto;
   grid-gap: 5px;
   border:1px solid;
 }
 img:nth-child(1n) { background: blue; }
 img:nth-child(2n) { background: grey; }
 img:nth-child(3n) { background: tan; }
 img:nth-child(4n) { background: black; }
 img {
--- a/layout/reftests/css-grid/grid-item-intrinsic-size-normal-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-size-normal-002-ref.html
@@ -21,129 +21,133 @@
 
 iframe {
   border: 1px solid;
   padding: 0;
   margin: 0;
   background: lightgrey;
 }
 
-.w20 { width: 20px min-width: 0px; }
+.w20 { width: 20px; min-width: 0px; }
+.w22 { width: 22px; }
 .mw20 { min-width: 20px }
 .mw0 { min-width: 0px }
+.wi { width:302px }
 
 .h20 { height: 20px; min-height: 0px; }
+.h22 { height: 22px; min-height: 0px; }
+.h32 { height: 32px; min-height: 0px; }
 .mh20 { min-height: 20px }
 .mh0 { min-height: 0px }
 
   </style>
 </head>
 <body>
 
-<div class="grid r"><iframe></iframe></div>
-<div class="grid r"><iframe class="start"></iframe></div>
-<div class="grid r"><iframe class="sa"></iframe></div>
+<div class="grid r wi"><iframe></iframe></div>
+<div class="grid r wi"><iframe class="start"></iframe></div>
+<div class="grid r wi"><iframe class="sa"></iframe></div>
 <div class="grid r"><iframe class="sa mxw10"></iframe></div>
-<div class="grid r"><iframe class="na"></iframe></div>
+<div class="grid r wi"><iframe class="na"></iframe></div>
 <div class="grid r"><iframe class="na mxw2"></iframe></div>
 
 <pre><!--min-height:20px--></pre>
-<div class="grid r" style="margin-right:0"><iframe class="mh20"></iframe></div>
-<div class="grid r"><iframe class="mh20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="start mh20"></iframe></div>
-<div class="grid r"><iframe class="start mh20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="sa mh20"></iframe></div>
-<div class="grid r"><iframe class="sa mh20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="na mh20"></iframe></div>
-<div class="grid r"><iframe class="na mh20 mxw10"></iframe></div>
+<div class="grid h22 r wi" style="margin-right:0"><iframe class="h20"></iframe></div>
+<div class="grid h22 r"><iframe class="mh20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="start mh20"></iframe></div>
+<div class="grid h22 r"><iframe class="start mh20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="sa mh20"></iframe></div>
+<div class="grid h22 r"><iframe class="sa mh20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="na mh20"></iframe></div>
+<div class="grid h22 r"><iframe class="na mh20 mxw10"></iframe></div>
 
 <pre><!--min-height:0--></pre>
-<div class="grid r"><iframe class="mh0"></iframe></div>
+<div class="grid r wi"><iframe class="mh0"></iframe></div>
 <div class="grid r"><iframe class="mh0 mxw10"></iframe></div>
-<div class="grid r"><iframe class="start mh0"></iframe></div>
+<div class="grid r wi"><iframe class="start mh0"></iframe></div>
 <div class="grid r"><iframe class="start mh0 mxw10"></iframe></div>
-<div class="grid r"><iframe class="sa mh0"></iframe></div>
+<div class="grid r wi"><iframe class="sa mh0"></iframe></div>
 <div class="grid r"><iframe class="sa mh0 mxw10"></iframe></div>
-<div class="grid r"><iframe class="na mh0"></iframe></div>
+<div class="grid r wi"><iframe class="na mh0"></iframe></div>
 <div class="grid r"><iframe class="na mh0 mxw2"></iframe></div>
 
 <pre><!----></pre>
 
-<div class="grid"><iframe></iframe></div>
+<div class="grid wi"><iframe></iframe></div>
 <div class="grid"><iframe class="mxw2"></iframe></div>
-<div class="grid"><iframe class="start"></iframe></div>
+<div class="grid wi"><iframe class="start"></iframe></div>
 <div class="grid"><iframe class="start mxw2"></iframe></div>
-<div class="grid"><iframe class="sa"></iframe></div>
+<div class="grid wi"><iframe class="sa"></iframe></div>
 <div class="grid"><iframe class="sa mxw2"></iframe></div>
-<div class="grid"><iframe class="na"></iframe></div>
+<div class="grid wi"><iframe class="na"></iframe></div>
 <div class="grid"><iframe class="na mxw2"></iframe></div>
 
 <pre><!--min-width:20px--></pre>
-<div class="grid"><iframe class="mw20"></iframe></div>
-<div class="grid"><iframe class="mw20 mxh10"></iframe></div>
-<div class="grid"><iframe class="start mw20"></iframe></div>
-<div class="grid" style="margin-top:5px"><iframe class="start mw20 mxh10"></iframe></div>
-<div class="grid" style="margin-top:10px"><iframe class="sa mw20"></iframe></div>
-<div class="grid" style="margin-top:25px"><iframe class="sa mw20 mxh10"></iframe></div>
-<div class="grid"><iframe class="na mw20"></iframe></div>
-<div class="grid" style="margin-top:5px"><iframe class="na mw20 mxh10 mxw10"></iframe></div>
+<div class="grid wi"><iframe class="mw20"></iframe></div>
+<div class="grid wi"><iframe class="mw20 mxh10"></iframe></div>
+<div class="grid wi"><iframe class="start mw20"></iframe></div>
+<div class="grid wi" style="margin-top:5px"><iframe class="start mw20 mxh10"></iframe></div>
+<div class="grid wi" style="margin-top:10px"><iframe class="sa mw20"></iframe></div>
+<div class="grid wi" style="margin-top:25px"><iframe class="sa mw20 mxh10"></iframe></div>
+<div class="grid wi"><iframe class="na mw20"></iframe></div>
+<div class="grid w22" style="margin-top:5px"><iframe class="na mw20 mxh10 mxw10"></iframe></div>
 
 <pre><!--min-width:0--></pre>
-<div class="grid"><iframe class="mw0"></iframe></div>
-<div class="grid"><iframe class="mw0 mxh10"></iframe></div>
-<div class="grid"><iframe class="start mw0"></iframe></div>
-<div class="grid" style="margin-top:5px"><iframe class="start mw0 mxh10"></iframe></div>
-<div class="grid" style="margin-top:10px"><iframe class="sa mw0"></iframe></div>
-<div class="grid" style="margin-top:25px"><iframe class="sa mw0 mxh10 mxw10"></iframe></div>
-<div class="grid"><iframe class="na mw0 mxw10"></iframe></div>
-<div class="grid" style="margin-top:5px"><iframe class="na mw0 mxh10"></iframe></div>
+<div class="grid wi"><iframe class="mw0"></iframe></div>
+<div class="grid wi"><iframe class="mw0 mxh10"></iframe></div>
+<div class="grid wi"><iframe class="start mw0"></iframe></div>
+<div class="grid wi" style="margin-top:5px"><iframe class="start mw0 mxh10"></iframe></div>
+<div class="grid wi" style="margin-top:10px"><iframe class="sa mw0"></iframe></div>
+<div class="grid " style="margin-top:25px; width:12px"><iframe class="sa mw0 mxh10 mxw10"></iframe></div>
+<div class="grid " style="width:12px"><iframe class="na mw0 mxw10"></iframe></div>
+<div class="grid wi" style="margin-top:5px"><iframe class="na mw0 mxh10"></iframe></div>
 
 <pre><!--width:20px--></pre>
 
 <div class="grid r"><iframe class="w20"></iframe></div>
 <div class="grid r"><iframe class="w20 mxh10"></iframe></div>
 <div class="grid r"><iframe class="start w20"></iframe></div>
 <div class="grid r"><iframe class="start w20 mxh10"></iframe></div>
 <div class="grid r"><iframe class="sa w20"></iframe></div>
 <div class="grid r"><iframe class="sa w20 mxh2"></iframe></div>
 <div class="grid r"><iframe class="na w20"></iframe></div>
 <div class="grid r"><iframe class="na w20 mxh2"></iframe></div>
 
 <pre><!--width:20px--></pre>
 
-<div class="grid"><iframe class="start w20"></iframe></div>
-<div class="grid"><iframe class="start w20 mxh10"></iframe></div>
-<div class="grid"><iframe class="start w20"></iframe></div>
-<div class="grid"><iframe class="start w20 mxh10"></iframe></div>
-<div class="grid"><iframe class="sa w20"></iframe></div>
-<div class="grid"><iframe class="sa w20 mxh10"></iframe></div>
-<div class="grid"><iframe class="na w20"></iframe></div>
-<div class="grid"><iframe class="na w20 mxh10"></iframe></div>
+<div class="grid w22"><iframe class="start w20"></iframe></div>
+<div class="grid w22"><iframe class="start w20 mxh10"></iframe></div>
+<div class="grid w22"><iframe class="start w20"></iframe></div>
+<div class="grid w22"><iframe class="start w20 mxh10"></iframe></div>
+<div class="grid w22"><iframe class="sa w20"></iframe></div>
+<div class="grid w22"><iframe class="sa w20 mxh10"></iframe></div>
+<div class="grid w22"><iframe class="na w20"></iframe></div>
+<div class="grid w22"><iframe class="na w20 mxh10"></iframe></div>
 
 <pre><!--height:20px--></pre>
 
-<div class="grid r"><iframe class="h20"></iframe></div>
-<div class="grid r"><iframe class="h20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="start h20"></iframe></div>
-<div class="grid r"><iframe class="start h20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="as h20"></iframe></div>
-<div class="grid r"><iframe class="as h20 mxw10"></iframe></div>
-<div class="grid r"><iframe class="an h20"></iframe></div>
-<div class="grid r"><iframe class="an h20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="h20"></iframe></div>
+<div class="grid h22 r"><iframe class="h20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="start h20"></iframe></div>
+<div class="grid h22 r"><iframe class="start h20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="as h20"></iframe></div>
+<div class="grid h22 r"><iframe class="as h20 mxw10"></iframe></div>
+<div class="grid h22 r wi"><iframe class="an h20"></iframe></div>
+<div class="grid h22 r"><iframe class="an h20 mxw10"></iframe></div>
 
 <pre><!--height:20px--></pre>
 
-<div class="grid"><iframe class="h20"></iframe></div>
-<div class="grid"><iframe class="h20 mxw2"></iframe></div>
-<div class="grid"><iframe class="start h20"></iframe></div>
-<div class="grid"><iframe class="start h20 mxw10"></iframe></div>
-<div class="grid"><iframe class="as h20"></iframe></div>
-<div class="grid"><iframe class="as h20 mxw2"></iframe></div>
-<div class="grid"><iframe class="an h20"></iframe></div>
-<div class="grid"><iframe class="an h20 mxw10"></iframe></div>
+<div class="grid h32 wi"><iframe class="h20"></iframe></div>
+<div class="grid h32"><iframe class="h20 mxw2"></iframe></div>
+<div class="grid h32 wi"><iframe class="start h20"></iframe></div>
+<div class="grid h32" style="width:12px"><iframe class="start h20 mxw10"></iframe></div>
+<div class="grid h32 wi"><iframe class="as h20"></iframe></div>
+<div class="grid h32"><iframe class="as h20 mxw2"></iframe></div>
+<div class="grid h32 wi"><iframe class="an h20"></iframe></div>
+<div class="grid h32" style="width:12px"><iframe class="an h20 mxw10"></iframe></div>
 
 <script>
 var iframeSizes =
 [
   ['30px', '2px'],
   ['30px', '2px'],
   ['30px', '2px'],
   ['10px', '2px'],
--- a/layout/reftests/css-grid/grid-item-intrinsic-size-normal-002.html
+++ b/layout/reftests/css-grid/grid-item-intrinsic-size-normal-002.html
@@ -9,20 +9,20 @@
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-normal">
   <link rel="match" href="grid-item-intrinsic-ratio-normal-003-ref.html">
   <style type="text/css">
 * { vertical-align: top; }
 .grid {
   display: inline-grid;
   border: 3px solid grey;
-  grid: 32px / 4px;
+  grid: minmax(auto, 32px) / minmax(auto, 4px);
   margin-right:20px;
 }
-.r { grid: 4px / 32px; }
+.r { grid: minmax(auto, 4px) / minmax(auto, 32px); }
 
 iframe {
   border: 1px solid;
   padding: 0;
   margin: 0;
   background: lightgrey;
 }
 
--- a/layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html
+++ b/layout/reftests/css-grid/grid-item-overflow-stretch-006-ref.html
@@ -29,18 +29,18 @@ body,html { color:black; background:whit
 x { display:block; width:110px; height:5px; background:grey; }
 .h .grid x { width:5px; height:110px; }
 
 br { clear:both; }
   </style>
 </head>
 <body>
 
-<div class="grid"><span class=""><x></x></span></div>
-<div class="grid"><span class="m"><x></x></span></div>
+<div class="grid"><span class="" style="width:78px"><x></x></span></div>
+<div class="grid"><span class="m" style="width:68px"><x></x></span></div>
 <div class="grid"><span class="ma" style="margin-left:5px"><x></x></span></div>
 
 <br>
 
 <div class="h">
 
 <div class="grid"><span class="" style="flex:1"><x></x></span></div>
 <div class="grid"><span class="m" style="flex:1"><x></x></span></div>
--- a/layout/reftests/css-grid/grid-item-table-stretch-002-ref.html
+++ b/layout/reftests/css-grid/grid-item-table-stretch-002-ref.html
@@ -11,18 +11,19 @@
 * { vertical-align: bottom; }
 .grid {
   display: inline-grid;
   border: 3px solid grey;
   grid: 32px / 4px;
   margin-right:20px;
   align-items: start;
   justify-items: start;
+  width: 18px;
 }
-.r { grid: 4px / 32px; }
+.r { grid: 4px / 32px; width: 32px;}
 
 table {
   border: 1px solid;
   padding: 0;
   margin: 0;
   background: lightgrey;
 }
 caption { border: 1px dashed blue; }
@@ -30,16 +31,17 @@ caption { justify-self: stretch; } /* XX
 x { display:block; width:16px; height:16px; }
 t { display:block; width:6px; height:6px; }
 
 .w20 { width: 20px }
 .mxw2 { width: 2px }
 .mxw10 { width: 10px }
 .mw20 { width: 20px }
 .wfill { width:32px }
+.w6 { width: 6px }
 
 .h20 { height: 20px }
 .mxh10 { height: 10px }
 .mxh2 { height: 2px }
 .mh20 { height: 20px }
 .h16 { height: 16px } /* XXX to workaround bug 307866 */
 .h8 { height: 8px } /* XXX to workaround bug 307866 */
 .w8 { width: 8px } /* XXX to workaround bug 307866 */
@@ -90,103 +92,103 @@ t { display:block; width:6px; height:6px
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="sa w8 mh0 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="na mh0"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="na mh0 mxw2"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="wfill as mh0"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="wfill an mh0"><caption><x></x></caption><td><t></t></td></table></div>
 
 <pre><!----></pre>
 
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill mxw2"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill mxw2"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="end"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="end mxw2"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill sa"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill sa mxw2"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill na"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill na mxw2"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as mxw2"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an mxw2"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as mxw2"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="an"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="an mxw2"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--min-width:20px--></pre>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="end mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="end h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill sa mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="sa mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill na mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="na mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an mw20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="hfill mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="end mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="end h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="hfill sa mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="sa mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="hfill na mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="na mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="as mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="as h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="an mw20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="an h8 mw20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--min-width:0--></pre>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill mw0"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill mw0"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="mw0 mxh10"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="end mw0"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="end h8 mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill sa mw0"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="sa mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="hfill na mw0"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="na mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as mw0"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as h8 mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an mw0"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an h8 mw0 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as mw0"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as h8 mw0 mxh10"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="an mw0"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="an h8 mw0 mxh10"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--width:20px--></pre>
 
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="w20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="h8 w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="h8 end w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="sa w20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="na w20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="as w20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="an w20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="an w20 mxh2"><caption><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--width:20px--></pre>
 
-<div class="grid"><table cellpadding=0 cellspacing=0 class="end w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h8 end w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="end w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h8 end w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill sa w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="sa w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="hfill na w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="na w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h8 as w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an w20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h8 an w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="end w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="h8 end w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="end w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="h8 end w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="hfill sa w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="sa w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="hfill na w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="na w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="as w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="h8 as w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="an w20"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid mw20"><table cellpadding=0 cellspacing=0 class="h8 an w20 mxh10"><caption><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--height:20px--></pre>
 
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="wfill h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="end h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="w8 end h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="wfill as h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="as h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="wfill an h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid r"><table cellpadding=0 cellspacing=0 class="an h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 
 <pre><!--height:20px--></pre>
 
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="h20 mxw2"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="h20"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="h20 mxw2"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="end h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="w8 end h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="sa h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="sa h20 mxw2"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="na h20"><caption><x></x></caption><td><t></t></td></table></div>
 <div class="grid"><table cellpadding=0 cellspacing=0 class="w8 na h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as h20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="as h20 mxw2"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="an h20"><caption><x></x></caption><td><t></t></td></table></div>
-<div class="grid"><table cellpadding=0 cellspacing=0 class="w8 an h20 mxw10"><caption><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as h20"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="as h20 mxw2"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="an h20"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
+<div class="grid"><table cellpadding=0 cellspacing=0 class="w8 an h20 mxw10"><caption class="w6"><x></x></caption><td><t></t></td></table></div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-item-table-stretch-002.html
+++ b/layout/reftests/css-grid/grid-item-table-stretch-002.html
@@ -9,20 +9,20 @@
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1316051">
   <link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-justify-self-normal">
   <link rel="match" href="grid-item-table-stretch-002-ref.html">
   <style type="text/css">
 * { vertical-align: bottom; }
 .grid {
   display: inline-grid;
   border: 3px solid grey;
-  grid: 32px / 4px;
+  grid: minmax(auto,32px) / minmax(auto,4px);
   margin-right:20px;
 }
-.r { grid: 4px / 32px; }
+.r { grid: minmax(auto,4px) / minmax(auto,32px); }
 
 table {
   border: 1px solid;
   padding: 0;
   margin: 0;
   background: lightgrey;
 }
 caption { border: 1px dashed blue; }
--- a/layout/reftests/css-grid/grid-track-fit-content-sizing-001-ref.html
+++ b/layout/reftests/css-grid/grid-track-fit-content-sizing-001-ref.html
@@ -59,21 +59,22 @@ y {
 .w7 .c2 { grid-template-columns: 80px 0 minmax(0px, 1fr); }
 .w7 .c3 { grid-template-columns: 80px 80px minmax(0px, 1fr); }
 .w7 .c4 { grid-template-columns: 0px 100px minmax(0px, 1fr); }
 
 .w8 .c1 { grid-template-columns: 50px minmax(100px, 1fr); }
 .w8 .c2 { grid-template-columns: 50px 0 minmax(100px, 1fr); }
 .w8 .c3 { grid-template-columns: 56px 56px minmax(0, 1fr); }
 .w8 .c4 { grid-template-columns: 0px 100px minmax(100px, 1fr); }
+.w8 .c5 { grid-template-columns: 0px 40px 100px; }
 
 .w9 .c1 { grid-template-columns: 50px minmax(100px, 1fr); }
 .w9 .c2 { grid-template-columns: 50px 0 minmax(100px, 1fr); }
 .w9 .c3 { grid-template-columns: 32px 32px minmax(0, 1fr); }
-.w9 .c4 { grid-template-columns: 0px 100px minmax(100px, 1fr); }
+.w9 .c4 { grid-template-columns: 0px 100px 100px; }
 
 .wA .c1 { grid-template-columns: 50px minmax(100px, 1fr); }
 .wA .c2 { grid-template-columns: 50px 0 minmax(100px, 1fr); }
 .wA .c3 { grid-template-columns: 25px 25px minmax(0, 1fr); }
 .wA .c4 { grid-template-columns: 0px 100px minmax(100px, 1fr); }
 
 .wB .c1 { grid-template-columns: 50px minmax(100px, 1fr); }
 .wB .c2 { grid-template-columns: 50px 0 minmax(100px, 1fr); }
@@ -141,38 +142,38 @@ y {
 <div class="grid c7"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 </div>
 
 <div class="w8" style="width:142px">
 <div class="grid c1"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c2"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c3"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c4"><span><a></a><a></a><a></a><a></a></span><y></y></div>
-<div class="grid c5"><span><a></a><a></a><a></a><a></a></span><y></y></div>
+<div class="grid c5"><span style="width:50px"><a></a><a></a><a></a><a></a></span><y></y></div>
 </div>
 
 <div class="w9" style="width:82px">
 <div class="grid c1"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c2"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c3"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c4"><span><a></a><a></a><a></a><a></a></span><y></y></div>
-<div class="grid c5"><span><a></a><a></a><a></a><a></a></span><y></y></div>
+<div class="grid c5"><span style="width:50px"><a></a><a></a><a></a><a></a></span><y></y></div>
 </div>
 
 <div class="wA" style="width:22px">
 <div class="grid c1"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c2"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c3"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c4"><span><a></a><a></a><a></a><a></a></span><y></y></div>
-<div class="grid c5"><span><a></a><a></a><a></a><a></a></span><y></y></div>
+<div class="grid c5"><span style="width:50px"><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c6"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 </div>
 
 <div class="wB" style="width:2px">
 <div class="grid c1"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c2"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c3"><span><a></a><a></a><a></a><a></a></span><y></y></div>
 <div class="grid c4"><span><a></a><a></a><a></a><a></a></span><y></y></div>
-<div class="grid c5"><span><a></a><a></a><a></a><a></a></span><y></y></div>
+<div class="grid c5"><span style="width:50px"><a></a><a></a><a></a><a></a></span><y></y></div>
 </div>
 
 </body>
 </html>
--- a/layout/reftests/css-grid/reftest.list
+++ b/layout/reftests/css-grid/reftest.list
@@ -107,19 +107,19 @@ skip-if(Android) == grid-auto-min-sizing
 == grid-item-intrinsic-ratio-normal-003.html grid-item-intrinsic-ratio-normal-003-ref.html
 == grid-item-intrinsic-ratio-normal-004.html grid-item-intrinsic-ratio-normal-004-ref.html
 == grid-item-intrinsic-ratio-normal-005.html grid-item-intrinsic-ratio-normal-005-ref.html
 == grid-item-intrinsic-size-normal-001.html grid-item-intrinsic-size-normal-001-ref.html
 == grid-item-intrinsic-size-normal-002.html grid-item-intrinsic-size-normal-002-ref.html
 == grid-item-auto-min-size-clamp-001.html grid-item-auto-min-size-clamp-001-ref.html
 == grid-item-auto-min-size-clamp-002.html grid-item-auto-min-size-clamp-002-ref.html
 == grid-item-auto-min-size-clamp-003.html grid-item-auto-min-size-clamp-003-ref.html
-== grid-item-auto-min-size-clamp-004.html grid-item-auto-min-size-clamp-004-ref.html
+# == grid-item-auto-min-size-clamp-004.html grid-item-auto-min-size-clamp-004-ref.html # bug 1421976
 == grid-item-auto-min-size-clamp-005.html grid-item-auto-min-size-clamp-005-ref.html
-== grid-item-auto-min-size-clamp-006.html grid-item-auto-min-size-clamp-006-ref.html
+# == grid-item-auto-min-size-clamp-006.html grid-item-auto-min-size-clamp-006-ref.html # bug 1421976
 == grid-item-auto-min-size-clamp-007.html grid-item-auto-min-size-clamp-007-ref.html
 == grid-item-overflow-stretch-001.html grid-item-overflow-stretch-001-ref.html
 == grid-item-overflow-stretch-002.html grid-item-overflow-stretch-002-ref.html
 == grid-item-overflow-stretch-003.html grid-item-overflow-stretch-003-ref.html
 == grid-item-overflow-stretch-004.html grid-item-overflow-stretch-004-ref.html
 == grid-item-overflow-stretch-005.html grid-item-overflow-stretch-005-ref.html
 == grid-item-overflow-stretch-006.html grid-item-overflow-stretch-006-ref.html
 == grid-item-canvas-001.html grid-item-canvas-001-ref.html
--- a/layout/xul/nsMenuBarListener.cpp
+++ b/layout/xul/nsMenuBarListener.cpp
@@ -308,17 +308,17 @@ nsMenuBarListener::KeyPress(nsIDOMEvent*
         // The F10 key just went down by itself or with ctrl pressed.
         // In Windows, both of these activate the menu bar.
         mMenuBarFrame->SetActiveByKeyboard();
         ToggleMenuActiveState();
 
         if (mMenuBarFrame->IsActive()) {
 #ifdef MOZ_WIDGET_GTK
           // In GTK, this also opens the first menu.
-          mMenuBarFrame->GetCurrentMenuItem()->OpenMenu(true);
+          mMenuBarFrame->GetCurrentMenuItem()->OpenMenu(false);
 #endif
           aKeyEvent->StopPropagation();
           aKeyEvent->PreventDefault();
         }
       }
 
       return NS_OK;
     }
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -2188,29 +2188,44 @@ nsXULPopupManager::HandleKeyboardNavigat
   else
     return false;
 
   nsNavigationDirection theDirection;
   NS_ASSERTION(aKeyCode >= nsIDOMKeyEvent::DOM_VK_END &&
                  aKeyCode <= nsIDOMKeyEvent::DOM_VK_DOWN, "Illegal key code");
   theDirection = NS_DIRECTION_FROM_KEY_CODE(itemFrame, aKeyCode);
 
+  bool selectFirstItem = true;
+#ifdef MOZ_WIDGET_GTK
+  nsMenuFrame* currentItem = nullptr;
+  if (item && mActiveMenuBar && NS_DIRECTION_IS_INLINE(theDirection)) {
+    currentItem = item->Frame()->GetCurrentMenuItem();
+    // If nothing is selected in the menu and we have a menubar, let it
+    // handle the movement not to steal focus from it.
+    if (!currentItem) {
+      item = nullptr;
+    }
+  }
+  // On menu change, only select first item if an item is already selected.
+  selectFirstItem = currentItem != nullptr;
+#endif
+
   // if a popup is open, first check for navigation within the popup
   if (item && HandleKeyboardNavigationInPopup(item, theDirection))
     return true;
 
   // no popup handled the key, so check the active menubar, if any
   if (mActiveMenuBar) {
     nsMenuFrame* currentMenu = mActiveMenuBar->GetCurrentMenuItem();
 
     if (NS_DIRECTION_IS_INLINE(theDirection)) {
       nsMenuFrame* nextItem = (theDirection == eNavigationDirection_End) ?
                               GetNextMenuItem(mActiveMenuBar, currentMenu, false, true) :
                               GetPreviousMenuItem(mActiveMenuBar, currentMenu, false, true);
-      mActiveMenuBar->ChangeMenuItem(nextItem, true, true);
+      mActiveMenuBar->ChangeMenuItem(nextItem, selectFirstItem, true);
       return true;
     }
     else if (NS_DIRECTION_IS_BLOCK(theDirection)) {
       // Open the menu and select its first item.
       if (currentMenu) {
         nsCOMPtr<nsIContent> content = currentMenu->GetContent();
         ShowMenu(content, true, false);
       }
--- a/memory/mozalloc/mozalloc.h
+++ b/memory/mozalloc/mozalloc.h
@@ -123,17 +123,21 @@ MOZ_END_EXTERN_C
 #else
 #  define MOZALLOC_EXPORT_NEW
 #endif
 
 #if defined(_MSC_VER)
 /*
  * Suppress build warning spam (bug 578546).
  */
+#if _MSC_VER < 1912
 #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+#else
+#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
+#endif
 #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
 #elif __cplusplus >= 201103
 /*
  * C++11 has deprecated exception-specifications in favour of |noexcept|.
  */
 #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS noexcept(true)
 #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS noexcept(false)
 #else
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2200,26 +2200,35 @@ pref("network.auth.subresource-img-cross
 //
 // This preference has no effect when the browser is set to "Never Remember History",
 // in that case default credentials will always be used.
 pref("network.auth.private-browsing-sso", false);
 
 // Control how throttling of http responses works - number of ms that each
 // suspend and resume period lasts (prefs named appropriately)
 pref("network.http.throttle.enable", true);
+pref("network.http.throttle.version", 1);
+
+// V1 prefs
 pref("network.http.throttle.suspend-for", 900);
 pref("network.http.throttle.resume-for", 100);
+
+// V2 prefs
+pref("network.http.throttle.read-limit-bytes", 8000);
+pref("network.http.throttle.read-interval-ms", 500);
+
+// Common prefs
 // Delay we resume throttled background responses after the last unthrottled
 // response has finished.  Prevents resuming too soon during an active page load
 // at which sub-resource reqeusts quickly come and go.
-pref("network.http.throttle.resume-background-in", 1000);
+pref("network.http.throttle.hold-time-ms", 800);
 // After the last transaction activation or last data chunk response we only
 // throttle for this period of time.  This prevents comet and unresponsive
 // http requests to engage long-standing throttling.
-pref("network.http.throttle.time-window", 3000);
+pref("network.http.throttle.max-time-ms", 500);
 
 // Give higher priority to requests resulting from a user interaction event
 // like click-to-play, image fancy-box zoom, navigation.
 pref("network.http.on_click_priority", true);
 
 // Some requests during a page load are marked as "tail", mainly trackers, but not only.
 // This pref controls whether such requests are put to the tail, behind other requests
 // emerging during page loading process.
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -111,20 +111,23 @@ nsHttpConnectionMgr::InsertTransactionSo
 nsHttpConnectionMgr::nsHttpConnectionMgr()
     : mReentrantMonitor("nsHttpConnectionMgr.mReentrantMonitor")
     , mMaxUrgentExcessiveConns(0)
     , mMaxConns(0)
     , mMaxPersistConnsPerHost(0)
     , mMaxPersistConnsPerProxy(0)
     , mMaxRequestDelay(0)
     , mThrottleEnabled(false)
+    , mThrottleVersion(2)
     , mThrottleSuspendFor(0)
     , mThrottleResumeFor(0)
-    , mThrottleResumeIn(0)
-    , mThrottleTimeWindow(0)
+    , mThrottleReadLimit(0)
+    , mThrottleReadInterval(0)
+    , mThrottleHoldTime(0)
+    , mThrottleMaxTime(0)
     , mIsShuttingDown(false)
     , mNumActiveConns(0)
     , mNumIdleConns(0)
     , mNumSpdyActiveConns(0)
     , mNumHalfOpenConns(0)
     , mTimeOfNextWakeUp(UINT64_MAX)
     , mPruningNoTraffic(false)
     , mTimeoutTickArmed(false)
@@ -169,37 +172,43 @@ nsHttpConnectionMgr::EnsureSocketThreadT
 
 nsresult
 nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
                           uint16_t maxConns,
                           uint16_t maxPersistConnsPerHost,
                           uint16_t maxPersistConnsPerProxy,
                           uint16_t maxRequestDelay,
                           bool throttleEnabled,
+                          uint32_t throttleVersion,
                           uint32_t throttleSuspendFor,
                           uint32_t throttleResumeFor,
-                          uint32_t throttleResumeIn,
-                          uint32_t throttleTimeWindow)
+                          uint32_t throttleReadLimit,
+                          uint32_t throttleReadInterval,
+                          uint32_t throttleHoldTime,
+                          uint32_t throttleMaxTime)
 {
     LOG(("nsHttpConnectionMgr::Init\n"));
 
     {
         ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
         mMaxUrgentExcessiveConns = maxUrgentExcessiveConns;
         mMaxConns = maxConns;
         mMaxPersistConnsPerHost = maxPersistConnsPerHost;
         mMaxPersistConnsPerProxy = maxPersistConnsPerProxy;
         mMaxRequestDelay = maxRequestDelay;
 
         mThrottleEnabled = throttleEnabled;
+        mThrottleVersion = throttleVersion;
         mThrottleSuspendFor = throttleSuspendFor;
         mThrottleResumeFor = throttleResumeFor;
-        mThrottleResumeIn = throttleResumeIn;
-        mThrottleTimeWindow = TimeDuration::FromMilliseconds(throttleTimeWindow);
+        mThrottleReadLimit = throttleReadLimit;
+        mThrottleReadInterval = throttleReadInterval;
+        mThrottleHoldTime = throttleHoldTime;
+        mThrottleMaxTime = TimeDuration::FromMilliseconds(throttleMaxTime);
 
         mIsShuttingDown = false;
     }
 
     return EnsureSocketThreadTarget();
 }
 
 class BoolWrapper : public ARefBase
@@ -2827,21 +2836,27 @@ nsHttpConnectionMgr::OnMsgUpdateParam(in
         SetThrottlingEnabled(!!value);
         break;
     case THROTTLING_SUSPEND_FOR:
         mThrottleSuspendFor = value;
         break;
     case THROTTLING_RESUME_FOR:
         mThrottleResumeFor = value;
         break;
-    case THROTTLING_RESUME_IN:
-        mThrottleResumeIn = value;
+    case THROTTLING_READ_LIMIT:
+        mThrottleReadLimit = value;
+        break;
+    case THROTTLING_READ_INTERVAL:
+        mThrottleReadInterval = value;
         break;
-    case THROTTLING_TIME_WINDOW:
-        mThrottleTimeWindow = TimeDuration::FromMilliseconds(value);
+    case THROTTLING_HOLD_TIME:
+        mThrottleHoldTime = value;
+        break;
+    case THROTTLING_MAX_TIME:
+        mThrottleMaxTime = TimeDuration::FromMilliseconds(value);
         break;
     default:
         NS_NOTREACHED("unexpected parameter name");
     }
 }
 
 // nsHttpConnectionMgr::nsConnectionEntry
 nsHttpConnectionMgr::nsConnectionEntry::~nsConnectionEntry()
@@ -2947,17 +2962,17 @@ bool nsHttpConnectionMgr::InThrottlingTi
 }
 
 void nsHttpConnectionMgr::TouchThrottlingTimeWindow(bool aEnsureTicker)
 {
     LOG(("nsHttpConnectionMgr::TouchThrottlingTimeWindow"));
 
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
-    mThrottlingWindowEndsAt = TimeStamp::NowLoRes() + mThrottleTimeWindow;
+    mThrottlingWindowEndsAt = TimeStamp::NowLoRes() + mThrottleMaxTime;
 
     if (!mThrottleTicker && 
         MOZ_LIKELY(aEnsureTicker) && MOZ_LIKELY(mThrottleEnabled)) {
         EnsureThrottleTickerIfNeeded();
     }
 }
 
 void nsHttpConnectionMgr::LogActiveTransactions(char operation)
@@ -3086,21 +3101,23 @@ nsHttpConnectionMgr::RemoveActiveTransac
         // Nothing active globally, just get rid of the timer completely and we are done.
         MOZ_ASSERT(!mActiveTabUnthrottledTransactionsExist);
         MOZ_ASSERT(!mActiveTabTransactionsExist);
 
         DestroyThrottleTicker();
         return;
     }
 
-    if (!mThrottlingInhibitsReading) {
-        // There is then nothing to wake up.  Affected transactions will not be put
-        // to sleep automatically on next tick.
-        LOG(("  reading not currently inhibited"));
-        return;
+    if (mThrottleVersion == 1) {
+        if (!mThrottlingInhibitsReading) {
+            // There is then nothing to wake up.  Affected transactions will not be put
+            // to sleep automatically on next tick.
+            LOG(("  reading not currently inhibited"));
+            return;
+        }
     }
 
     if (mActiveTabUnthrottledTransactionsExist) {
         // There are still unthrottled transactions for the active tab, hence the state
         // is unaffected and we don't need to do anything (nothing to wake).
         LOG(("  there are unthrottled for the active tab"));
         return;
     }
@@ -3135,92 +3152,118 @@ nsHttpConnectionMgr::RemoveActiveTransac
     LOG(("  not resuming anything"));
 }
 
 void
 nsHttpConnectionMgr::UpdateActiveTransaction(nsHttpTransaction * aTrans)
 {
     LOG(("nsHttpConnectionMgr::UpdateActiveTransaction ENTER t=%p", aTrans));
 
-    AddActiveTransaction(aTrans);
+    // First remove then add.  In case of a download that is the only active
+    // transaction and has just been marked as download (goes unthrottled to
+    // throttled), adding first would cause it to be throttled for first few
+    // milliseconds - becuause it would appear as if there were both throttled
+    // and unthrottled transactions at the time.
 
     Maybe<bool> reversed;
     reversed.emplace(!aTrans->EligibleForThrottling());
     RemoveActiveTransaction(aTrans, reversed);
 
+    AddActiveTransaction(aTrans);
+
     LOG(("nsHttpConnectionMgr::UpdateActiveTransaction EXIT t=%p", aTrans));
 }
 
 bool
-nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans)
+nsHttpConnectionMgr::ShouldThrottle(nsHttpTransaction * aTrans)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
-    if (!mThrottlingInhibitsReading || !mThrottleEnabled) {
-        return false;
+    LOG(("nsHttpConnectionMgr::ShouldThrottle trans=%p", aTrans));
+
+    if (mThrottleVersion == 1) {
+        if (!mThrottlingInhibitsReading || !mThrottleEnabled) {
+            return false;
+        }
+    } else {
+        if (!mThrottleEnabled) {
+            return false;
+        }
     }
 
     uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
     bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
     bool throttled = aTrans->EligibleForThrottling();
 
     bool stop = [=]() {
         if (mActiveTabTransactionsExist) {
             if (!tabId) {
                 // Chrome initiated and unidentified transactions just respect
                 // their throttle flag, when something for the active tab is happening.
                 // This also includes downloads.
+                LOG(("  active tab loads, trans is tab-less, throttled=%d", throttled));
                 return throttled;
             }
             if (!forActiveTab) {
                 // This is a background tab request, we want them to always throttle
                 // when there are transactions running for the ative tab.
+                LOG(("  active tab loads, trans not of the active tab"));
                 return true;
             }
 
             if (mActiveTabUnthrottledTransactionsExist) {
                 // Unthrottled transactions for the active tab take precedence
+                LOG(("  active tab loads unthrottled, trans throttled=%d", throttled));
                 return throttled;
             }
 
+            LOG(("  trans for active tab, don't throttle"));
             return false;
         }
 
         MOZ_ASSERT(!forActiveTab);
 
-        if (mDelayedResumeReadTimer) {
-            // If this timer exists, background transactions are scheduled to be woken
-            // after a delay, hence leave them asleep.
-            return true;
-        }
-
         if (!mActiveTransactions[false].IsEmpty()) {
             // This means there are unthrottled active transactions for background tabs.
             // If we are here, there can't be any transactions for the active tab.
             // (If there is no transaction for a tab id, there is no entry for it in
             // the hashtable.)
+            LOG(("  backround tab(s) load unthrottled, trans throttled=%d", throttled));
             return throttled;
         }
 
         // There are only unthrottled transactions for background tabs: don't throttle.
+        LOG(("  backround tab(s) load throttled, don't throttle"));
         return false;
     }();
 
     if (forActiveTab && !stop) {
-        // This active-tab transaction is allowed to read even though 
-        // we are in the middle of "stop reading" interval.  Hence, 
+        // This is an active-tab transaction and is allowed to read.  Hence,
         // prolong the throttle time window to make sure all 'lower-decks' 
         // transactions will actually throttle.
         TouchThrottlingTimeWindow();
         return false;
     }
 
-    // Only stop reading when in the 3 seconds throttle time window.
-    // This window is prolonged (restarted) by a call to TouchThrottlingTimeWindow.
-    return stop && InThrottlingTimeWindow();
+    // Only stop reading when in the configured throttle max-time (aka time window).
+    // This window is prolonged (restarted) by a call to TouchThrottlingTimeWindow
+    // called on new transaction activation or on receive of response bytes of an
+    // active tab transaction.
+    bool inWindow = InThrottlingTimeWindow();
+
+    LOG(("  stop=%d, in-window=%d, delayed-bck-timer=%d",
+         stop, inWindow, !!mDelayedResumeReadTimer));
+
+    if (!forActiveTab) {
+        // If the delayed background resume timer exists, background transactions are
+        // scheduled to be woken after a delay, hence leave them throttled.
+        inWindow = inWindow || mDelayedResumeReadTimer;
+    }
+
+    return stop && inWindow;
 }
 
 bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
 {
     nsConnectionEntry *ent = mCT.GetWeak(connInfo->HashKey());
     if (!ent) {
       // No entry, no pressure.
       return false;
@@ -3271,22 +3314,26 @@ nsHttpConnectionMgr::EnsureThrottleTicke
     // There is a new demand to throttle, hence unschedule delayed resume
     // of background throttled transastions.
     CancelDelayedResumeBackgroundThrottledTransactions();
 
     if (mThrottleTicker) {
         return;
     }
 
-    MOZ_ASSERT(!mThrottlingInhibitsReading);
-
     mThrottleTicker = NS_NewTimer();
     if (mThrottleTicker) {
-        mThrottleTicker->Init(this, mThrottleSuspendFor, nsITimer::TYPE_ONE_SHOT);
-        mThrottlingInhibitsReading = true;
+        if (mThrottleVersion == 1) {
+            MOZ_ASSERT(!mThrottlingInhibitsReading);
+
+            mThrottleTicker->Init(this, mThrottleSuspendFor, nsITimer::TYPE_ONE_SHOT);
+            mThrottlingInhibitsReading = true;
+        } else {
+            mThrottleTicker->Init(this, mThrottleReadInterval, nsITimer::TYPE_ONE_SHOT);
+        }
     }
 
     LogActiveTransactions('^');
 }
 
 void
 nsHttpConnectionMgr::DestroyThrottleTicker()
 {
@@ -3299,64 +3346,98 @@ nsHttpConnectionMgr::DestroyThrottleTick
 
     if (!mThrottleTicker) {
         return;
     }
 
     LOG(("nsHttpConnectionMgr::DestroyThrottleTicker"));
     mThrottleTicker->Cancel();
     mThrottleTicker = nullptr;
-    mThrottlingInhibitsReading = false;
+
+    if (mThrottleVersion == 1) {
+        mThrottlingInhibitsReading = false;
+    }
 
     LogActiveTransactions('v');
 }
 
 void
 nsHttpConnectionMgr::ThrottlerTick()
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
-    mThrottlingInhibitsReading = !mThrottlingInhibitsReading;
-
-    LOG(("nsHttpConnectionMgr::ThrottlerTick inhibit=%d", mThrottlingInhibitsReading));
-
-    // If there are only background transactions to be woken after a delay, keep
-    // the ticker so that we woke them only for the resume-for interval and then
-    // throttle them again until the background-resume delay passes.
-    if (!mThrottlingInhibitsReading &&
-        !mDelayedResumeReadTimer &&
-        (!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
-        LOG(("  last tick"));
-        mThrottleTicker = nullptr;
-    }
-
-    if (mThrottlingInhibitsReading) {
-        if (mThrottleTicker) {
-            mThrottleTicker->Init(this, mThrottleSuspendFor, nsITimer::TYPE_ONE_SHOT);
+    if (mThrottleVersion == 1) {
+        mThrottlingInhibitsReading = !mThrottlingInhibitsReading;
+
+        LOG(("nsHttpConnectionMgr::ThrottlerTick inhibit=%d", mThrottlingInhibitsReading));
+
+        // If there are only background transactions to be woken after a delay, keep
+        // the ticker so that we woke them only for the resume-for interval and then
+        // throttle them again until the background-resume delay passes.
+        if (!mThrottlingInhibitsReading &&
+            !mDelayedResumeReadTimer &&
+            (!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
+            LOG(("  last tick"));
+            mThrottleTicker = nullptr;
+        }
+
+        if (mThrottlingInhibitsReading) {
+            if (mThrottleTicker) {
+                mThrottleTicker->Init(this, mThrottleSuspendFor, nsITimer::TYPE_ONE_SHOT);
+            }
+        } else {
+            if (mThrottleTicker) {
+                mThrottleTicker->Init(this, mThrottleResumeFor, nsITimer::TYPE_ONE_SHOT);
+            }
+
+            ResumeReadOf(mActiveTransactions[false], true);
+            ResumeReadOf(mActiveTransactions[true]);
         }
     } else {
+        LOG(("nsHttpConnectionMgr::ThrottlerTick"));
+
+        // If there are only background transactions to be woken after a delay, keep
+        // the ticker so that we still keep the low read limit for that time.
+        if (!mDelayedResumeReadTimer &&
+            (!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
+            LOG(("  last tick"));
+            mThrottleTicker = nullptr;
+        }
+
         if (mThrottleTicker) {
-            mThrottleTicker->Init(this, mThrottleResumeFor, nsITimer::TYPE_ONE_SHOT);
+            mThrottleTicker->Init(this, mThrottleReadInterval, nsITimer::TYPE_ONE_SHOT);
         }
 
         ResumeReadOf(mActiveTransactions[false], true);
         ResumeReadOf(mActiveTransactions[true]);
     }
 }
 
 void
 nsHttpConnectionMgr::DelayedResumeBackgroundThrottledTransactions()
 {
-    if (mDelayedResumeReadTimer) {
-        return;
+    MOZ_ASSERT(OnSocketThread(), "not on socket thread");
+
+    if (mThrottleVersion == 1) {
+        if (mDelayedResumeReadTimer) {
+            return;
+        }
+    } else {
+        // If the mThrottleTicker doesn't exist, there is nothing currently
+        // being throttled.  Hence, don't invoke the hold time interval.
+        // This is called also when a single download transaction becomes
+        // marked as throttleable.  We would otherwise block it unnecessarily.
+        if (mDelayedResumeReadTimer || !mThrottleTicker) {
+            return;
+        }
     }
 
     LOG(("nsHttpConnectionMgr::DelayedResumeBackgroundThrottledTransactions"));
     NS_NewTimerWithObserver(getter_AddRefs(mDelayedResumeReadTimer),
-                            this, mThrottleResumeIn, nsITimer::TYPE_ONE_SHOT);
+                            this, mThrottleHoldTime, nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 nsHttpConnectionMgr::CancelDelayedResumeBackgroundThrottledTransactions()
 {
     if (!mDelayedResumeReadTimer) {
         return;
     }
@@ -3459,42 +3540,39 @@ nsHttpConnectionMgr::OnMsgUpdateCurrentT
     uint64_t winId = static_cast<UINT64Wrapper*>(param)->GetValue();
 
     if (mCurrentTopLevelOuterContentWindowId == winId) {
         // duplicate notification
         return;
     }
 
     bool activeTabWasLoading = mActiveTabTransactionsExist;
-    bool activeTabIdChanged = mCurrentTopLevelOuterContentWindowId != winId;
 
     uint64_t previousWindowId = mCurrentTopLevelOuterContentWindowId;
     mCurrentTopLevelOuterContentWindowId = winId;
 
     if (gHttpHandler->ActiveTabPriority()) {
         NotifyConnectionOfWindowIdChange(previousWindowId);
     }
 
     LOG(("nsHttpConnectionMgr::OnMsgUpdateCurrentTopLevelOuterContentWindowId"
          " id=%" PRIx64 "\n",
          mCurrentTopLevelOuterContentWindowId));
 
     nsTArray<RefPtr<nsHttpTransaction>> *transactions = nullptr;
 
-    if (activeTabIdChanged) {
-        // Update the "Exists" caches and resume any transactions that now deserve it,
-        // changing the active tab changes the conditions for throttling.
-        transactions = mActiveTransactions[false].Get(mCurrentTopLevelOuterContentWindowId);
-        mActiveTabUnthrottledTransactionsExist = !!transactions;
-
-        if (!mActiveTabUnthrottledTransactionsExist) {
-            transactions = mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId);
-        }
-        mActiveTabTransactionsExist = !!transactions;
-    }
+    // Update the "Exists" caches and resume any transactions that now deserve it,
+    // changing the active tab changes the conditions for throttling.
+    transactions = mActiveTransactions[false].Get(mCurrentTopLevelOuterContentWindowId);
+    mActiveTabUnthrottledTransactionsExist = !!transactions;
+
+    if (!mActiveTabUnthrottledTransactionsExist) {
+        transactions = mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId);
+    }
+    mActiveTabTransactionsExist = !!transactions;
 
     if (transactions) {
         // This means there are some transactions for this newly activated tab, resume them
         // but anything else.
         LOG(("  resuming newly activated tab transactions"));
         ResumeReadOf(transactions);
         return;
     }
@@ -3508,18 +3586,18 @@ nsHttpConnectionMgr::OnMsgUpdateCurrentT
 
     if (!mActiveTransactions[false].IsEmpty()) {
         LOG(("  resuming unthrottled background transactions"));
         ResumeReadOf(mActiveTransactions[false]);
         return;
     }
 
     if (!mActiveTransactions[true].IsEmpty()) {
-        LOG(("  delayed resuming throttled background transactions"));
-        DelayedResumeBackgroundThrottledTransactions();
+        LOG(("  resuming throttled background transactions"));
+        ResumeReadOf(mActiveTransactions[true]);
         return;
     }
 
     DestroyThrottleTicker();
 }
 
 void
 nsHttpConnectionMgr::TimeoutTick()
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -55,36 +55,41 @@ public:
         MAX_URGENT_START_Q,
         MAX_CONNECTIONS,
         MAX_PERSISTENT_CONNECTIONS_PER_HOST,
         MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
         MAX_REQUEST_DELAY,
         THROTTLING_ENABLED,
         THROTTLING_SUSPEND_FOR,
         THROTTLING_RESUME_FOR,
-        THROTTLING_RESUME_IN,
-        THROTTLING_TIME_WINDOW
+        THROTTLING_READ_LIMIT,
+        THROTTLING_READ_INTERVAL,
+        THROTTLING_HOLD_TIME,
+        THROTTLING_MAX_TIME
     };
 
     //-------------------------------------------------------------------------
     // NOTE: functions below may only be called on the main thread.
     //-------------------------------------------------------------------------
 
     nsHttpConnectionMgr();
 
     MOZ_MUST_USE nsresult Init(uint16_t maxUrgentExcessiveConns,
                                uint16_t maxConnections,
                                uint16_t maxPersistentConnectionsPerHost,
                                uint16_t maxPersistentConnectionsPerProxy,
                                uint16_t maxRequestDelay,
                                bool throttleEnabled,
+                               uint32_t throttleVersion,
                                uint32_t throttleSuspendFor,
                                uint32_t throttleResumeFor,
-                               uint32_t throttleResumeIn,
-                               uint32_t throttleTimeWindow);
+                               uint32_t throttleReadLimit,
+                               uint32_t throttleReadInterval,
+                               uint32_t throttleHoldTime,
+                               uint32_t throttleMaxTime);
     MOZ_MUST_USE nsresult Shutdown();
 
     //-------------------------------------------------------------------------
     // NOTE: functions below may be called on any thread.
     //-------------------------------------------------------------------------
 
     // Schedules next pruning of dead connection to happen after
     // given time.
@@ -220,29 +225,29 @@ public:
 
     // tracks and untracks active transactions according their throttle status
     void AddActiveTransaction(nsHttpTransaction* aTrans);
     void RemoveActiveTransaction(nsHttpTransaction* aTrans,
                                  Maybe<bool> const& aOverride = Nothing());
     void UpdateActiveTransaction(nsHttpTransaction* aTrans);
 
     // called by nsHttpTransaction::WriteSegments.  decides whether the transaction
-    // should stop reading data based on: the throttling ticker status, overall
-    // status of all active transactions regarding active tab and respective
-    // throttling state.
-    bool ShouldStopReading(nsHttpTransaction* aTrans);
+    // should limit reading its reponse data.  There are various conditions this
+    // methods evaluates.  If called by an active-tab non-throttled transaction,
+    // the throttling window time will be prolonged.
+    bool ShouldThrottle(nsHttpTransaction* aTrans);
 
-    // prolongs the throttling time window to now + the window preferred size
+    // prolongs the throttling time window to now + the window preferred delay.
     // called when:
     // - any transaction is activated
     // - or when a currently unthrottled transaction for the active window receives data
     void TouchThrottlingTimeWindow(bool aEnsureTicker = true);
 
     // return true iff the connection has pending transactions for the active tab.
-    // it's mainly used to disallow throttling (stop reading) of a response
+    // it's mainly used to disallow throttling (limit reading) of a response
     // belonging to the same conn info to free up a connection ASAP.
     // NOTE: relatively expensive to call, there are two hashtable lookups.
     bool IsConnEntryUnderPressure(nsHttpConnectionInfo*);
 
     uint64_t CurrentTopLevelOuterContentWindowId()
     {
         return mCurrentTopLevelOuterContentWindowId;
     }
@@ -526,20 +531,23 @@ private:
 
     // connection limits
     uint16_t mMaxUrgentExcessiveConns;
     uint16_t mMaxConns;
     uint16_t mMaxPersistConnsPerHost;
     uint16_t mMaxPersistConnsPerProxy;
     uint16_t mMaxRequestDelay; // in seconds
     bool mThrottleEnabled;
+    uint32_t mThrottleVersion;
     uint32_t mThrottleSuspendFor;
     uint32_t mThrottleResumeFor;
-    uint32_t mThrottleResumeIn;
-    TimeDuration mThrottleTimeWindow;
+    uint32_t mThrottleReadLimit;
+    uint32_t mThrottleReadInterval;
+    uint32_t mThrottleHoldTime;
+    TimeDuration mThrottleMaxTime;
     Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
 
     //-------------------------------------------------------------------------
     // NOTE: these members are only accessed on the socket transport thread
     //-------------------------------------------------------------------------
 
     MOZ_MUST_USE bool ProcessPendingQForEntry(nsConnectionEntry *,
                                               bool considerAll);
@@ -712,32 +720,40 @@ private:
     bool InThrottlingTimeWindow();
 
     // Two hashtalbes keeping track of active transactions regarding window id and throttling.
     // Used by the throttling algorithm to obtain number of transactions for the active tab
     // and for inactive tabs according their throttle status.
     // mActiveTransactions[0] are all unthrottled transactions, mActiveTransactions[1] throttled.
     nsClassHashtable<nsUint64HashKey, nsTArray<RefPtr<nsHttpTransaction>>> mActiveTransactions[2];
 
+    // V1 specific
     // Whether we are inside the "stop reading" interval, altered by the throttle ticker
     bool mThrottlingInhibitsReading;
 
     TimeStamp mThrottlingWindowEndsAt;
 
     // ticker for the 'stop reading'/'resume reading' signal
     nsCOMPtr<nsITimer> mThrottleTicker;
     // Checks if the combination of active transactions requires the ticker.
     bool IsThrottleTickerNeeded();
     // The method also unschedules the delayed resume of background tabs timer
     // if the ticker was about to be scheduled.
     void EnsureThrottleTickerIfNeeded();
+    // V1:
     // Drops also the mThrottlingInhibitsReading flag.  Immediate or delayed resume
     // of currently throttled transactions is not affected by this method.
+    // V2:
+    // Immediate or delayed resume of currently throttled transactions is not
+    // affected by this method.
     void DestroyThrottleTicker();
+    // V1:
     // Handler for the ticker: alters the mThrottlingInhibitsReading flag.
+    // V2:
+    // Handler for the ticker: calls ResumeReading() for all throttled transactions.
     void ThrottlerTick();
 
     // mechanism to delay immediate resume of background tabs and chrome initiated
     // throttled transactions after the last transaction blocking their unthrottle
     // has been removed.  Needs to be delayed because during a page load there is
     // a number of intervals when there is no transaction that would cause throttling.
     // Hence, throttling of long standing responses, like downloads, would be mostly
     // ineffective if resumed during every such interval.
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -206,20 +206,23 @@ nsHttpHandler::nsHttpHandler()
     , mMaxRequestDelay(10)
     , mIdleSynTimeout(250)
     , mH2MandatorySuiteEnabled(false)
     , mMaxUrgentExcessiveConns(3)
     , mMaxConnections(24)
     , mMaxPersistentConnectionsPerServer(2)
     , mMaxPersistentConnectionsPerProxy(4)
     , mThrottleEnabled(true)
+    , mThrottleVersion(2)
     , mThrottleSuspendFor(3000)
     , mThrottleResumeFor(200)
-    , mThrottleResumeIn(400)
-    , mThrottleTimeWindow(3000)
+    , mThrottleReadLimit(8000)
+    , mThrottleReadInterval(500)
+    , mThrottleHoldTime(600)
+    , mThrottleMaxTime(3000)
     , mUrgentStartEnabled(true)
     , mTailBlockingEnabled(true)
     , mTailDelayQuantum(600)
     , mTailDelayQuantumAfterDCL(100)
     , mTailDelayMax(6000)
     , mRedirectionLimit(10)
     , mPhishyUserPassLength(1)
     , mQoSBits(0x00)
@@ -608,20 +611,23 @@ nsHttpHandler::InitConnectionMgr()
     }
 
     rv = mConnMgr->Init(mMaxUrgentExcessiveConns,
                         mMaxConnections,
                         mMaxPersistentConnectionsPerServer,
                         mMaxPersistentConnectionsPerProxy,
                         mMaxRequestDelay,
                         mThrottleEnabled,
+                        mThrottleVersion,
                         mThrottleSuspendFor,
                         mThrottleResumeFor,
-                        mThrottleResumeIn,
-                        mThrottleTimeWindow);
+                        mThrottleReadLimit,
+                        mThrottleReadInterval,
+                        mThrottleHoldTime,
+                        mThrottleMaxTime);
     return rv;
 }
 
 nsresult
 nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecure)
 {
     nsresult rv;
 
@@ -1634,16 +1640,21 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
     if (PREF_CHANGED(HTTP_PREF("throttle.enable"))) {
         rv = prefs->GetBoolPref(HTTP_PREF("throttle.enable"), &mThrottleEnabled);
         if (NS_SUCCEEDED(rv) && mConnMgr) {
             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_ENABLED,
                                             static_cast<int32_t>(mThrottleEnabled));
         }
     }
 
+    if (PREF_CHANGED(HTTP_PREF("throttle.version"))) {
+        rv = prefs->GetIntPref(HTTP_PREF("throttle.version"), &val);
+        mThrottleVersion = (uint32_t)clamped(val, 1, 2);
+    }
+
     if (PREF_CHANGED(HTTP_PREF("throttle.suspend-for"))) {
         rv = prefs->GetIntPref(HTTP_PREF("throttle.suspend-for"), &val);
         mThrottleSuspendFor = (uint32_t)clamped(val, 0, 120000);
         if (NS_SUCCEEDED(rv) && mConnMgr) {
             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_SUSPEND_FOR,
                                             mThrottleSuspendFor);
         }
     }
@@ -1652,31 +1663,49 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
         rv = prefs->GetIntPref(HTTP_PREF("throttle.resume-for"), &val);
         mThrottleResumeFor = (uint32_t)clamped(val, 0, 120000);
         if (NS_SUCCEEDED(rv) && mConnMgr) {
             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_RESUME_FOR,
                                             mThrottleResumeFor);
         }
     }
 
-    if (PREF_CHANGED(HTTP_PREF("throttle.resume-background-in"))) {
-        rv = prefs->GetIntPref(HTTP_PREF("throttle.resume-background-in"), &val);
-        mThrottleResumeIn = (uint32_t)clamped(val, 0, 120000);
+    if (PREF_CHANGED(HTTP_PREF("throttle.read-limit-bytes"))) {
+        rv = prefs->GetIntPref(HTTP_PREF("throttle.read-limit-bytes"), &val);
+        mThrottleReadLimit = (uint32_t)clamped(val, 0, 500000);
         if (NS_SUCCEEDED(rv) && mConnMgr) {
-            Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_RESUME_IN,
-                                            mThrottleResumeIn);
+            Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_READ_LIMIT,
+                                            mThrottleReadLimit);
         }
     }
 
-    if (PREF_CHANGED(HTTP_PREF("throttle.time-window"))) {
-      rv = prefs->GetIntPref(HTTP_PREF("throttle.time-window"), &val);
-      mThrottleTimeWindow = (uint32_t)clamped(val, 0, 120000);
+    if (PREF_CHANGED(HTTP_PREF("throttle.read-interval-ms"))) {
+        rv = prefs->GetIntPref(HTTP_PREF("throttle.read-interval-ms"), &val);
+        mThrottleReadInterval = (uint32_t)clamped(val, 0, 120000);
+        if (NS_SUCCEEDED(rv) && mConnMgr) {
+            Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_READ_INTERVAL,
+                                            mThrottleReadInterval);
+        }
+    }
+
+    if (PREF_CHANGED(HTTP_PREF("throttle.hold-time-ms"))) {
+        rv = prefs->GetIntPref(HTTP_PREF("throttle.hold-time-ms"), &val);
+        mThrottleHoldTime = (uint32_t)clamped(val, 0, 120000);
+        if (NS_SUCCEEDED(rv) && mConnMgr) {
+            Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_HOLD_TIME,
+                                            mThrottleHoldTime);
+        }
+    }
+
+    if (PREF_CHANGED(HTTP_PREF("throttle.max-time-ms"))) {
+      rv = prefs->GetIntPref(HTTP_PREF("throttle.max-time-ms"), &val);
+      mThrottleMaxTime = (uint32_t)clamped(val, 0, 120000);
       if (NS_SUCCEEDED(rv) && mConnMgr) {
-        Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_TIME_WINDOW,
-                                        mThrottleTimeWindow);
+        Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_MAX_TIME,
+                                        mThrottleMaxTime);
       }
     }
 
     if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) {
         Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
     }
 
     if (PREF_CHANGED(HTTP_PREF("tailing.enabled"))) {
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -140,16 +140,18 @@ public:
     bool           PromptTempRedirect()      { return mPromptTempRedirect; }
     bool           IsUrgentStartEnabled() { return mUrgentStartEnabled; }
     bool           IsTailBlockingEnabled() { return mTailBlockingEnabled; }
     uint32_t       TailBlockingDelayQuantum(bool aAfterDOMContentLoaded) {
       return aAfterDOMContentLoaded ? mTailDelayQuantumAfterDCL : mTailDelayQuantum;
     }
     uint32_t       TailBlockingDelayMax() { return mTailDelayMax; }
 
+    uint32_t       ThrottlingReadLimit() { return mThrottleVersion == 1 ? 0 : mThrottleReadLimit; }
+
     // TCP Keepalive configuration values.
 
     // Returns true if TCP keepalive should be enabled for short-lived conns.
     bool TCPKeepaliveEnabledForShortLivedConns() {
       return mTCPKeepaliveShortLivedEnabled;
     }
     // Return time (secs) that a connection is consider short lived (for TCP
     // keepalive purposes). After this time, the connection is long-lived.
@@ -479,20 +481,23 @@ private:
 
     bool     mH2MandatorySuiteEnabled;
     uint16_t mMaxUrgentExcessiveConns;
     uint16_t mMaxConnections;
     uint8_t  mMaxPersistentConnectionsPerServer;
     uint8_t  mMaxPersistentConnectionsPerProxy;
 
     bool mThrottleEnabled;
+    uint32_t mThrottleVersion;
     uint32_t mThrottleSuspendFor;
     uint32_t mThrottleResumeFor;
-    uint32_t mThrottleResumeIn;
-    uint32_t mThrottleTimeWindow;
+    uint32_t mThrottleReadLimit;
+    uint32_t mThrottleReadInterval;
+    uint32_t mThrottleHoldTime;
+    uint32_t mThrottleMaxTime;
 
     bool mUrgentStartEnabled;
     bool mTailBlockingEnabled;
     uint32_t mTailDelayQuantum;
     uint32_t mTailDelayQuantumAfterDCL;
     uint32_t mTailDelayMax;
 
     uint8_t  mRedirectionLimit;
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -99,16 +99,17 @@ nsHttpTransaction::nsHttpTransaction()
     , mChunkedDecoder(nullptr)
     , mStatus(NS_OK)
     , mPriority(0)
     , mRestartCount(0)
     , mCaps(0)
     , mHttpVersion(NS_HTTP_VERSION_UNKNOWN)
     , mHttpResponseCode(0)
     , mCurrentHttpResponseHeaderSize(0)
+    , mThrottlingReadAllowance(THROTTLE_NO_LIMIT)
     , mCapsToClear(0)
     , mResponseIsComplete(false)
     , mReadingStopped(false)
     , mClosed(false)
     , mConnected(false)
     , mActivated(false)
     , mActivatedAsH2(false)
     , mHaveStatusLine(false)
@@ -161,16 +162,21 @@ void nsHttpTransaction::ResumeReading()
 
     if (!mReadingStopped) {
         return;
     }
 
     LOG(("nsHttpTransaction::ResumeReading %p", this));
 
     mReadingStopped = false;
+
+    // This with either reengage the limit when still throttled in WriteSegments or
+    // simply reset to allow unlimeted reading again.
+    mThrottlingReadAllowance = THROTTLE_NO_LIMIT;
+
     if (mConnection) {
         nsresult rv = mConnection->ResumeRecv();
         if (NS_FAILED(rv)) {
             LOG(("  resume failed with rv=%" PRIx32, static_cast<uint32_t>(rv)));
         }
     }
 }
 
@@ -848,54 +854,58 @@ nsHttpTransaction::WritePipeSegment(nsIO
     //
     rv = trans->ProcessData(buf, *countWritten, countWritten);
     if (NS_FAILED(rv))
         trans->Close(rv);
 
     return rv; // failure code only stops WriteSegments; it is not propagated.
 }
 
-bool nsHttpTransaction::ShouldStopReading()
+bool nsHttpTransaction::ShouldThrottle()
 {
     if (mActivatedAsH2) {
         // Throttling feature is now disabled for http/2 transactions
         // because of bug 1367861.  The logic around mActivatedAsH2
         // will be removed when that is fixed.
         // 
-        // Calling ShouldStopReading on the manager just to make sure 
+        // Calling ShouldThrottle on the manager just to make sure
         // the throttling time window is correctly updated by this transaction.
-        Unused << gHttpHandler->ConnMgr()->ShouldStopReading(this);
+        Unused << gHttpHandler->ConnMgr()->ShouldThrottle(this);
         return false;
     }
 
     if (mClassOfService & nsIClassOfService::DontThrottle) {
         // We deliberately don't touch the throttling window here since
         // DontThrottle requests are expected to be long-standing media
         // streams and would just unnecessarily block running downloads.
         // If we want to ballance bandwidth for media responses against
         // running downloads, we need to find something smarter like 
         // changing the suspend/resume throttling intervals at-runtime.
         return false;
     }
 
-    if (!gHttpHandler->ConnMgr()->ShouldStopReading(this)) {
+    if (!gHttpHandler->ConnMgr()->ShouldThrottle(this)) {
         // We are not obligated to throttle
         return false;
     }
 
     if (mContentRead < 16000) {
         // Let the first bytes go, it may also well be all the content we get
-        LOG(("nsHttpTransaction::ShouldStopReading too few content (%" PRIi64 ") this=%p", mContentRead, this));
+        LOG(("nsHttpTransaction::ShouldThrottle too few content (%" PRIi64 ") this=%p", mContentRead, this));
         return false;
     }
 
-    if (gHttpHandler->ConnMgr()->IsConnEntryUnderPressure(mConnInfo)) {
-        LOG(("nsHttpTransaction::ShouldStopReading entry pressure this=%p", this));
+    if (!(mClassOfService & nsIClassOfService::Throttleable) &&
+        gHttpHandler->ConnMgr()->IsConnEntryUnderPressure(mConnInfo)) {
+        LOG(("nsHttpTransaction::ShouldThrottle entry pressure this=%p", this));
         // This is expensive to check (two hashtable lookups) but may help
         // freeing connections for active tab transactions.
+        // Checking this only for transactions that are not explicitly marked
+        // as throttleable because trackers and (specially) downloads should
+        // keep throttling even under pressure.
         return false;
     }
 
     return true;
 }
 
 nsresult
 nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
@@ -904,17 +914,26 @@ nsHttpTransaction::WriteSegments(nsAHttp
     LOG(("nsHttpTransaction::WriteSegments %p", this));
 
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
     if (mTransactionDone) {
         return NS_SUCCEEDED(mStatus) ? NS_BASE_STREAM_CLOSED : mStatus;
     }
 
-    if (ShouldStopReading()) {
+    if (ShouldThrottle()) {
+        if (mThrottlingReadAllowance == THROTTLE_NO_LIMIT) { // no limit set
+            // V1: ThrottlingReadLimit() returns 0
+            mThrottlingReadAllowance = gHttpHandler->ThrottlingReadLimit();
+        }
+    } else {
+        mThrottlingReadAllowance = THROTTLE_NO_LIMIT; // don't limit
+    }
+
+    if (mThrottlingReadAllowance == 0) { // depleted
         if (gHttpHandler->ConnMgr()->CurrentTopLevelOuterContentWindowId() !=
             mTopLevelOuterContentWindowId) {
             nsHttp::NotifyActiveTabLoadOptimization();
         }
 
         // Must remember that we have to call ResumeRecv() on our connection when
         // called back by the conn manager to resume reading.
         LOG(("nsHttpTransaction::WriteSegments %p response throttled", this));
@@ -932,16 +951,22 @@ nsHttpTransaction::WriteSegments(nsAHttp
     uint32_t * vtable = (uint32_t *) mPipeOut.get();
     MOZ_DIAGNOSTIC_ASSERT(*vtable != 0);
 #endif // WIN32
 
     if (!mPipeOut) {
         return NS_ERROR_UNEXPECTED;
     }
 
+    if (mThrottlingReadAllowance > 0) {
+        LOG(("nsHttpTransaction::WriteSegments %p limiting read from %u to %d",
+             this, count, mThrottlingReadAllowance));
+        count = std::min(count, static_cast<uint32_t>(mThrottlingReadAllowance));
+    }
+
     nsresult rv = mPipeOut->WriteSegments(WritePipeSegment, this, count, countWritten);
 
     mWriter = nullptr;
 
     if (mForceRestart) {
         // The forceRestart condition was dealt with on the stack, but it did not
         // clear the flag because nsPipe in the writesegment stack clears out
         // return codes, so we need to use the flag here as a cue to return ERETARGETED
@@ -958,16 +983,19 @@ nsHttpTransaction::WriteSegments(nsAHttp
         Unused << gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target));
         if (target) {
             mPipeOut->AsyncWait(this, 0, 0, target);
             mWaitingOnPipeOut = true;
         } else {
             NS_ERROR("no socket thread event target");
             rv = NS_ERROR_UNEXPECTED;
         }
+    } else if (mThrottlingReadAllowance > 0 && NS_SUCCEEDED(rv)) {
+        MOZ_ASSERT(count >= *countWritten);
+        mThrottlingReadAllowance -= *countWritten;
     }
 
     return rv;
 }
 
 void
 nsHttpTransaction::Close(nsresult reason)
 {
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -224,17 +224,17 @@ private:
     // If such is found in any of them, NS_HTTP_STICKY_CONNECTION is set in mCaps.
     // We need the sticky flag be set early to keep the connection from very start
     // of the authentication process.
     void CheckForStickyAuthScheme();
     void CheckForStickyAuthSchemeAt(nsHttpAtom const& header);
 
     // Called from WriteSegments.  Checks for conditions whether to throttle reading
     // the content.  When this returns true, WriteSegments returns WOULD_BLOCK.
-    bool ShouldStopReading();
+    bool ShouldThrottle();
 
 private:
     class UpdateSecurityCallbacks : public Runnable
     {
       public:
         UpdateSecurityCallbacks(nsHttpTransaction* aTrans,
                                 nsIInterfaceRequestor* aCallbacks)
           : Runnable("net::nsHttpTransaction::UpdateSecurityCallbacks")
@@ -306,16 +306,29 @@ private:
     uint16_t                        mRestartCount;        // the number of times this transaction has been restarted
     uint32_t                        mCaps;
 
     nsHttpVersion                   mHttpVersion;
     uint16_t                        mHttpResponseCode;
 
     uint32_t                        mCurrentHttpResponseHeaderSize;
 
+    int32_t const THROTTLE_NO_LIMIT = -1;
+    // This can have 3 possible values:
+    // * THROTTLE_NO_LIMIT - this means the transaction is not in any way limited
+    //                       to read the response, this is the default
+    // * a positive number - a limit is set because the transaction is obligated
+    //                       to throttle the response read, this is decresed with
+    //                       every piece of data the transaction receives
+    // * zero - when the transaction depletes the limit for reading, this makes it
+    //          stop reading and return WOULD_BLOCK from WriteSegments; transaction
+    //          then waits for a call of ResumeReading that resets this member back
+    //          to THROTTLE_NO_LIMIT
+    int32_t                         mThrottlingReadAllowance;
+
     // mCapsToClear holds flags that should be cleared in mCaps, e.g. unset
     // NS_HTTP_REFRESH_DNS when DNS refresh request has completed to avoid
     // redundant requests on the network. The member itself is atomic, but
     // access to it from the networking thread may happen either before or
     // after the main thread modifies it. To deal with raciness, only unsetting
     // bitfields should be allowed: 'lost races' will thus err on the
     // conservative side, e.g. by going ahead with a 2nd DNS refresh.
     Atomic<uint32_t>                mCapsToClear;
--- a/old-configure.in
+++ b/old-configure.in
@@ -1034,16 +1034,18 @@ case "$target" in
             CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"
             # jemalloc uses __declspec(allocator) as a profiler hint,
             # which clang-cl doesn't understand.
             CXXFLAGS="$CXXFLAGS -Wno-ignored-attributes"
         fi
         # make 'foo == bar;' error out
         CFLAGS="$CFLAGS -we4553"
         CXXFLAGS="$CXXFLAGS -we4553"
+        # Silence VS2017 15.5+ TR1 deprecation warnings hit by older gtest versions
+        CXXFLAGS="$CXXFLAGS -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib secur32.lib"
         MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
         WARNINGS_AS_ERRORS='-WX'
         MOZ_OPTIMIZE_FLAGS='-O1 -Oi'
         MOZ_FIX_LINK_PATHS=
         LDFLAGS="$LDFLAGS -LARGEADDRESSAWARE -NXCOMPAT"
         if test -z "$DEVELOPER_OPTIONS"; then
             LDFLAGS="$LDFLAGS -RELEASE"
--- a/testing/runtimes/mochitest-browser-chrome-e10s.runtimes.json
+++ b/testing/runtimes/mochitest-browser-chrome-e10s.runtimes.json
@@ -810,17 +810,16 @@
     "browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js": 2484,
     "browser/modules/test/browser/browser_UsageTelemetry_private_and_restore.js": 2818,
     "browser/modules/test/browser/browser_UsageTelemetry_searchbar.js": 8194,
     "browser/modules/test/browser/browser_UsageTelemetry_urlbar.js": 8847,
     "browser/modules/test/browser_BrowserUITelemetry_buckets.js": 4394,
     "browser/modules/test/browser_ContentSearch.js": 6354,
     "browser/modules/test/browser_NetworkPrioritizer.js": 7917,
     "browser/modules/test/browser_PermissionUI.js": 5119,
-    "browser/modules/test/browser_SelfSupportBackend.js": 5739,
     "browser/modules/test/browser_UnsubmittedCrashHandler.js": 2991,
     "browser/modules/test/browser_UsageTelemetry.js": 12884,
     "browser/modules/test/browser_UsageTelemetry_content.js": 3978,
     "browser/modules/test/browser_UsageTelemetry_private_and_restore.js": 2645,
     "browser/modules/test/browser_UsageTelemetry_searchbar.js": 4426,
     "browser/modules/test/browser_UsageTelemetry_urlbar.js": 6733,
     "caps/tests/mochitest/browser_checkloaduri.js": 3104,
     "docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js": 4212,
--- a/testing/runtimes/mochitest-browser-chrome.runtimes.json
+++ b/testing/runtimes/mochitest-browser-chrome.runtimes.json
@@ -737,17 +737,16 @@
     "browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js": 1892,
     "browser/modules/test/browser/browser_UsageTelemetry_private_and_restore.js": 2310,
     "browser/modules/test/browser/browser_UsageTelemetry_searchbar.js": 5740,
     "browser/modules/test/browser/browser_UsageTelemetry_urlbar.js": 6699,
     "browser/modules/test/browser_BrowserUITelemetry_buckets.js": 4374,
     "browser/modules/test/browser_ContentSearch.js": 5221,
     "browser/modules/test/browser_NetworkPrioritizer.js": 4005,
     "browser/modules/test/browser_PermissionUI.js": 4020,
-    "browser/modules/test/browser_SelfSupportBackend.js": 5724,
     "browser/modules/test/browser_UnsubmittedCrashHandler.js": 2842,
     "browser/modules/test/browser_UsageTelemetry.js": 9979,
     "browser/modules/test/browser_UsageTelemetry_content.js": 3073,
     "browser/modules/test/browser_UsageTelemetry_content_aboutHome.js": 1812,
     "browser/modules/test/browser_UsageTelemetry_private_and_restore.js": 2215,
     "browser/modules/test/browser_UsageTelemetry_searchbar.js": 3575,
     "browser/modules/test/browser_UsageTelemetry_urlbar.js": 5256,
     "docshell/test/browser/browser_bug1347823.js": 4094,
@@ -1015,9 +1014,9 @@
     "toolkit/mozapps/update/tests/browser/browser_updatesBackgroundWindow.js": 1819,
     "toolkit/mozapps/update/tests/browser/browser_updatesBackgroundWindowFailures.js": 3440,
     "toolkit/mozapps/update/tests/browser/browser_updatesCompleteAndPartialPatchesWithBadSizes.js": 2769,
     "toolkit/mozapps/update/tests/browser/browser_updatesCompletePatchWithBadCompleteSize.js": 2115,
     "toolkit/mozapps/update/tests/browser/browser_updatesDownloadFailures.js": 2872,
     "toolkit/mozapps/update/tests/browser/browser_updatesPartialPatchWithBadPartialSize.js": 1852,
     "uriloader/exthandler/tests/mochitest/browser_web_protocol_handlers.js": 2437
   }
-}
\ No newline at end of file
+}
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-007.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-007.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-009.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-009.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-017.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-017.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-025.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-025.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-027.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-027.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/alignment/grid-alignment-implies-size-change-035.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[grid-alignment-implies-size-change-035.html]
-  type: testharness
-  [.before 1]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-012.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[grid-minimum-size-grid-items-012.html]
-  type: reftest
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-013.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[grid-minimum-size-grid-items-013.html]
-  type: reftest
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-grid/grid-items/grid-minimum-size-grid-items-014.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[grid-minimum-size-grid-items-014.html]
-  type: reftest
-  expected: FAIL
--- a/testing/web-platform/tests/dom/events/Event-subclasses-constructors.html
+++ b/testing/web-platform/tests/dom/events/Event-subclasses-constructors.html
@@ -16,27 +16,45 @@ function assert_props(iface, event, defa
                   "The value of the " + property + " property should be " +
                   format_value(value));
   });
   if ("parent" in expected[iface]) {
     assert_props(expected[iface].parent, event, defaults);
   }
 }
 
+// Class declarations don't go on the global by default, so put it there ourselves:
+
+self.SubclassedEvent = class SubclassedEvent extends Event {
+  constructor(name, props) {
+    super(name, props);
+    if (props && typeof(props) == "object" && "customProp" in props) {
+      this.customProp = props.customProp;
+    } else {
+      this.customProp = 5;
+    }
+  }
+
+  get fixedProp() {
+    return 17;
+  }
+}
+
 var EventModifierInit = [
   ["ctrlKey", false, true],
   ["shiftKey", false, true],
   ["altKey", false, true],
   ["metaKey", false, true],
 ];
 var expected = {
   "Event": {
     "properties": [
       ["bubbles", false, true],
       ["cancelable", false, true],
+      ["isTrusted", false, false],
     ],
   },
 
   "UIEvent": {
     "parent": "Event",
     "properties": [
       ["view", null, window],
       ["detail", 0, 7],
@@ -88,16 +106,24 @@ var expected = {
   },
 
   "CompositionEvent": {
     "parent": "UIEvent",
     "properties": [
       ["data", "", "string"],
     ],
   },
+
+  "SubclassedEvent": {
+    "parent": "Event",
+    "properties": [
+      ["customProp", 5, 8],
+      ["fixedProp", 17, 17],
+    ],
+  },
 };
 
 Object.keys(expected).forEach(function(iface) {
   test(function() {
     var event = new self[iface]("type");
     assert_props(iface, event, true);
   }, iface + " constructor (no argument)");
 
--- a/toolkit/components/telemetry/docs/concepts/submission.rst
+++ b/toolkit/components/telemetry/docs/concepts/submission.rst
@@ -6,17 +6,17 @@ Submission
 
 Pings are submitted via a common API on ``TelemetryController``.
 If a ping fails to successfully submit to the server immediately (e.g. because
 of missing internet connection), Telemetry will store it on disk and retry to
 send it until the maximum ping age is exceeded (14 days).
 
 .. note::
 
-  The :doc:`main pings <../data/main-ping>` are kept locally even after successful submission to enable the HealthReport and SelfSupport features. They will be deleted after their retention period of 180 days.
+  The :doc:`main pings <../data/main-ping>` are kept locally even after successful submission to enable the HealthReport feature. They will be deleted after their retention period of 180 days.
 
 Submission logic
 ================
 
 Sending of pending pings starts as soon as the delayed startup is finished. They are sent in batches, newest-first, with up
 to 10 persisted pings per batch plus all unpersisted pings.
 The send logic then waits for each batch to complete.
 
--- a/toolkit/content/tests/widgets/window_menubar.xul
+++ b/toolkit/content/tests/widgets/window_menubar.xul
@@ -90,24 +90,24 @@ window.opener.SimpleTest.waitForFocus(fu
 }, window);
 
 // On Linux, the first menu opens when F10 is pressed, but on other platforms
 // the menubar is focused but no menu is opened. This means that different events
 // fire.
 function pressF10Events()
 {
   return navigator.platform.indexOf("Linux") >= 0 ?
-    [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup"] :
+    [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu", "popupshowing filepopup", "popupshown filepopup"] :
     [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ];
 }
 
 function closeAfterF10Events(extraInactive)
 {
   if (navigator.platform.indexOf("Linux") >= 0) {
-    var events = [ "popuphiding filepopup", "popuphidden filepopup", "DOMMenuItemInactive item1",
+    var events = [ "popuphiding filepopup", "popuphidden filepopup",
                    "DOMMenuInactive filepopup", "DOMMenuBarInactive menubar",
                    "DOMMenuItemInactive filemenu" ];
     if (extraInactive)
       events.push("DOMMenuItemInactive filemenu");
     return events;
   }
 
   return [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ];
@@ -474,19 +474,19 @@ var popupTests = [
   // pressing cursor left then down should open a menu
   testname: "cursor down on menu",
   events: (navigator.platform.indexOf("Linux") >= 0) ?
             [  "DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
                // This is in a different order than the
                // "accelerator on active menubar" because menus opened from a
                // shortcut key are fired asynchronously
                "popuphiding filepopup", "popuphidden filepopup",
-               "popupshowing helppopup", "DOMMenuItemInactive item1",
-               "DOMMenuItemActive item2", "DOMMenuItemInactive item2",
-               "DOMMenuInactive filepopup", "DOMMenuItemActive contents",
+               "popupshowing helppopup",
+               "DOMMenuItemActive item1", "DOMMenuItemInactive item1",
+               "DOMMenuInactive filepopup",
                "popupshown helppopup" ] :
             [ "popupshowing helppopup", "DOMMenuItemInactive filemenu",
               "DOMMenuItemActive helpmenu",
               // This is in a different order than the
               // "accelerator on active menubar" because menus opened from a
               // shortcut key are fired asynchronously
               "DOMMenuItemActive contents", "popupshown helppopup" ],
   test: function() { sendKey("LEFT"); sendKey("DOWN"); },
@@ -494,17 +494,19 @@ var popupTests = [
     is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
   }
 },
 {
   // pressing a letter that doesn't correspond to an accelerator. The menu
   // should not close because there is more than one item corresponding to
   // that letter
   testname: "menuitem with no accelerator",
-  events: [ "DOMMenuItemInactive contents", "DOMMenuItemActive one" ],
+  events: (navigator.platform.indexOf("Linux") >= 0) ?
+           [ "DOMMenuItemActive one" ] :
+           [ "DOMMenuItemInactive contents", "DOMMenuItemActive one" ],
   test: function() { sendChar("o"); },
   result: function(testname) { checkOpen("helpmenu", testname); }
 },
 {
   // pressing the letter again should select the next one that starts with
   // that letter
   testname: "menuitem with no accelerator again",
   events: [ "DOMMenuItemInactive one", "DOMMenuItemActive only" ],
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
@@ -29,17 +29,16 @@ module.exports = {
     // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/InternalError
     "InternalError": true,
     "KeyEvent": false,
     "MatchGlob": false,
     "MatchPattern": false,
     "MatchPatternSet": false,
     "MenuBoxObject": false,
     // Specific to Firefox (Chrome code only).
-    "MozSelfSupport": false,
     "SharedArrayBuffer": false,
     "SimpleGestureEvent": false,
     // Note: StopIteration will likely be removed as part of removing legacy
     // generators, see bug 968038.
     "StopIteration": false,
     "StructuredCloneHolder": false,
     "WebAssembly": false,
     "WebExtensionContentScript": false,
--- a/widget/windows/nsAppShell.cpp
+++ b/widget/windows/nsAppShell.cpp
@@ -179,25 +179,25 @@ UiaHookProc(int aCode, WPARAM aWParam, L
   if (aCode < 0) {
     return ::CallNextHookEx(nullptr, aCode, aWParam, aLParam);
   }
 
   auto cwp = reinterpret_cast<CWPSTRUCT*>(aLParam);
   if (gUiaMsg && cwp->message == gUiaMsg) {
     Maybe<bool> shouldCallNextHook =
       a11y::Compatibility::OnUIAMessage(cwp->wParam, cwp->lParam);
-    if (shouldCallNextHook.isSome()) {
-      // We've got an instantiator, disconnect this hook
-      if (::UnhookWindowsHookEx(gUiaHook)) {
-        gUiaHook = nullptr;
-      }
 
-      if (!shouldCallNextHook.value()) {
-        return 0;
-      }
+    // Unconditionally remove the hook, as UIA detection is too expensive to
+    // leave running for every single request.
+    if (::UnhookWindowsHookEx(gUiaHook)) {
+      gUiaHook = nullptr;
+    }
+
+    if (shouldCallNextHook.isSome() && !shouldCallNextHook.value()) {
+      return 0;
     }
   }
 
   return ::CallNextHookEx(nullptr, aCode, aWParam, aLParam);
 }
 
 static void
 InitUIADetection()