Merge central to autoland. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Thu, 21 Jun 2018 04:18:03 +0300
changeset 479927 9e214df80589d11213cdd0db69794b29063baec8
parent 479867 2731368a39e57a7fda79ebe8b33a9251a327fe5d (current diff)
parent 479926 d231a32316809f8c9efa43ed6f74484ff552c115 (diff)
child 479928 714db494a627748b0b3c8588fb5b782924c246e7
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge central to autoland. a=merge
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/color.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/counters.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_box.mako.rs
servo/components/style/properties/longhand/inherited_svg.mako.rs
servo/components/style/properties/longhand/inherited_table.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/inherited_ui.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/properties/longhand/margin.mako.rs
servo/components/style/properties/longhand/outline.mako.rs
servo/components/style/properties/longhand/padding.mako.rs
servo/components/style/properties/longhand/position.mako.rs
servo/components/style/properties/longhand/svg.mako.rs
servo/components/style/properties/longhand/table.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/properties/longhand/ui.mako.rs
servo/components/style/properties/longhand/xul.mako.rs
servo/components/style/properties/shorthand/background.mako.rs
servo/components/style/properties/shorthand/border.mako.rs
servo/components/style/properties/shorthand/box.mako.rs
servo/components/style/properties/shorthand/column.mako.rs
servo/components/style/properties/shorthand/font.mako.rs
servo/components/style/properties/shorthand/inherited_svg.mako.rs
servo/components/style/properties/shorthand/inherited_text.mako.rs
servo/components/style/properties/shorthand/list.mako.rs
servo/components/style/properties/shorthand/margin.mako.rs
servo/components/style/properties/shorthand/mask.mako.rs
servo/components/style/properties/shorthand/outline.mako.rs
servo/components/style/properties/shorthand/padding.mako.rs
servo/components/style/properties/shorthand/position.mako.rs
servo/components/style/properties/shorthand/serialize.mako.rs
servo/components/style/properties/shorthand/text.mako.rs
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/clear-site-data/navigation.https.html.ini
--- a/.hgignore
+++ b/.hgignore
@@ -3,16 +3,19 @@
 # Filenames that should be ignored wherever they appear
 ~$
 \.py(c|o)$
 (?i)(^|/)TAGS$
 (^|/)ID$
 (^|/)\.DS_Store$
 \.pdb
 \.egg-info
+\.gcda
+\.gcno
+\.gcov
 
 # Vim swap files.
 ^\.sw.$
 .[^/]*\.sw.$
 
 # Emacs directory variable files.
 \.dir-locals\.el
 
--- a/browser/base/content/test/sanitize/browser_sanitize-timespans.js
+++ b/browser/base/content/test/sanitize/browser_sanitize-timespans.js
@@ -448,17 +448,18 @@ async function setupHistory() {
   addPlace("http://2hour.com/", "Less than 2 hours ago", now_uSec - 90 * kUsecPerMin);
   addPlace("http://2hour10minutes.com/", "2 hours 10 minutes ago", now_uSec - 130 * kUsecPerMin);
   addPlace("http://4hour.com/", "Less than 4 hours ago", now_uSec - 180 * kUsecPerMin);
   addPlace("http://4hour10minutes.com/", "4 hours 10 minutesago", now_uSec - 250 * kUsecPerMin);
 
   let today = new Date();
   today.setHours(0);
   today.setMinutes(0);
-  today.setSeconds(1);
+  today.setSeconds(0);
+  today.setMilliseconds(1);
   addPlace("http://today.com/", "Today", today.getTime() * 1000);
 
   let lastYear = new Date();
   lastYear.setFullYear(lastYear.getFullYear() - 1);
   addPlace("http://before-today.com/", "Before Today", lastYear.getTime() * 1000);
   await PlacesTestUtils.addVisits(places);
 }
 
@@ -559,17 +560,18 @@ async function setupFormHistory() {
 
   timestamp = now_uSec - 250 * kUsecPerMin;
   results = await searchEntries(["guid"], { fieldname: "4hour10minutes" });
   await update({ op: "update", firstUsed: timestamp, guid: results[0].guid });
 
   let today = new Date();
   today.setHours(0);
   today.setMinutes(0);
-  today.setSeconds(1);
+  today.setSeconds(0);
+  today.setMilliseconds(1);
   timestamp = today.getTime() * 1000;
   results = await searchEntries(["guid"], { fieldname: "today" });
   await update({ op: "update", firstUsed: timestamp, guid: results[0].guid });
 
   let lastYear = new Date();
   lastYear.setFullYear(lastYear.getFullYear() - 1);
   timestamp = lastYear.getTime() * 1000;
   results = await searchEntries(["guid"], { fieldname: "b4today" });
@@ -650,17 +652,18 @@ async function setupDownloads() {
   download.startTime = new Date(now_mSec - 250 * kMsecPerMin), // 250 minutes ago
   download.canceled = true;
   await publicList.add(download);
 
   // Add "today" download
   let today = new Date();
   today.setHours(0);
   today.setMinutes(0);
-  today.setSeconds(1);
+  today.setSeconds(0);
+  today.setMilliseconds(1);
 
   download = await Downloads.createDownload({
     source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
     target: "fakefile-today"
   });
   download.startTime = today, // 12:00:01 AM this morning
   download.canceled = true;
   await publicList.add(download);
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -122,20 +122,20 @@ var Policies = {
     }
   },
 
   "Cookies": {
     onBeforeUIStartup(manager, param) {
       addAllowDenyPermissions("cookie", param.Allow, param.Block);
 
       if (param.Block) {
-        const hosts = param.Block.map(uri => uri.host).sort().join("\n");
+        const hosts = param.Block.map(url => url.hostname).sort().join("\n");
         runOncePerModification("clearCookiesForBlockedHosts", hosts, () => {
           for (let blocked of param.Block) {
-            Services.cookies.removeCookiesWithOriginAttributes("{}", blocked.host);
+            Services.cookies.removeCookiesWithOriginAttributes("{}", blocked.hostname);
           }
         });
       }
 
       if (param.Default !== undefined ||
           param.AcceptThirdParty !== undefined ||
           param.Locked) {
         const ACCEPT_COOKIES = 0;
@@ -503,19 +503,19 @@ var Policies = {
     }
   },
 
   "Homepage": {
     onBeforeUIStartup(manager, param) {
       // |homepages| will be a string containing a pipe-separated ('|') list of
       // URLs because that is what the "Home page" section of about:preferences
       // (and therefore what the pref |browser.startup.homepage|) accepts.
-      let homepages = param.URL.spec;
+      let homepages = param.URL.href;
       if (param.Additional && param.Additional.length > 0) {
-        homepages += "|" + param.Additional.map(url => url.spec).join("|");
+        homepages += "|" + param.Additional.map(url => url.href).join("|");
       }
       if (param.Locked) {
         setAndLockPref("browser.startup.homepage", homepages);
         setAndLockPref("browser.startup.page", 1);
         setAndLockPref("pref.browser.homepage.disable_button.current_page", true);
         setAndLockPref("pref.browser.homepage.disable_button.bookmark_page", true);
         setAndLockPref("pref.browser.homepage.disable_button.restore_default", true);
       } else {
@@ -558,24 +558,24 @@ var Policies = {
   "OfferToSaveLogins": {
     onBeforeUIStartup(manager, param) {
       setAndLockPref("signon.rememberSignons", param);
     }
   },
 
   "OverrideFirstRunPage": {
     onProfileAfterChange(manager, param) {
-      let url = param ? param.spec : "";
+      let url = param ? param.href : "";
       setAndLockPref("startup.homepage_welcome_url", url);
     }
   },
 
   "OverridePostUpdatePage": {
     onProfileAfterChange(manager, param) {
-      let url = param ? param.spec : "";
+      let url = param ? param.href : "";
       setAndLockPref("startup.homepage_override_url", url);
       // The pref startup.homepage_override_url is only used
       // as a fallback when the update.xml file hasn't provided
       // a specific post-update URL.
       manager.disallowFeature("postUpdateCustomPage");
     }
   },
 
@@ -852,28 +852,28 @@ function setDefaultPermission(policyName
  *        The list of URLs to be set as DENY_ACTION for the chosen permission.
  */
 function addAllowDenyPermissions(permissionName, allowList, blockList) {
   allowList = allowList || [];
   blockList = blockList || [];
 
   for (let origin of allowList) {
     try {
-      Services.perms.add(origin,
+      Services.perms.add(Services.io.newURI(origin.href),
                          permissionName,
                          Ci.nsIPermissionManager.ALLOW_ACTION,
                          Ci.nsIPermissionManager.EXPIRE_POLICY);
     } catch (ex) {
       log.error(`Added by default for ${permissionName} permission in the permission
-      manager - ${origin.spec}`);
+      manager - ${origin.href}`);
     }
   }
 
   for (let origin of blockList) {
-    Services.perms.add(origin,
+    Services.perms.add(Services.io.newURI(origin.href),
                        permissionName,
                        Ci.nsIPermissionManager.DENY_ACTION,
                        Ci.nsIPermissionManager.EXPIRE_POLICY);
   }
 }
 
 /**
  * runOnce
--- a/browser/components/enterprisepolicies/helpers/BookmarksPolicies.jsm
+++ b/browser/components/enterprisepolicies/helpers/BookmarksPolicies.jsm
@@ -3,43 +3,43 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 /*
  * A Bookmark object received through the policy engine will be an
  * object with the following properties:
  *
- * - URL (nsIURI)
+ * - URL (URL)
  *   (required) The URL for this bookmark
  *
  * - Title (string)
  *   (required) The title for this bookmark
  *
  * - Placement (string)
  *   (optional) Either "toolbar" or "menu". If missing or invalid,
  *   "toolbar" will be used
  *
  * - Folder (string)
  *   (optional) The name of the folder to put this bookmark into.
  *   If present, a folder with this name will be created in the
  *   chosen placement above, and the bookmark will be created there.
  *   If missing, the bookmark will be created directly into the
  *   chosen placement.
  *
- * - Favicon (nsIURI)
+ * - Favicon (URL)
  *   (optional) An http:, https: or data: URL with the favicon.
  *   If possible, we recommend against using this property, in order
  *   to keep the json file small.
  *   If a favicon is not provided through the policy, it will be loaded
  *   naturally after the user first visits the bookmark.
  *
  *
  * Note: The Policy Engine automatically converts the strings given to
- * the URL and favicon properties into a nsIURI object.
+ * the URL and favicon properties into a URL object.
  *
  * The schema for this object is defined in policies-schema.json.
  */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 ChromeUtils.defineModuleGetter(this, "PlacesUtils",
@@ -104,17 +104,17 @@ async function calculateLists(specifiedB
   // --------- STEP 1 ---------
   // Build two Maps (one with the existing bookmarks, another with
   // the specified bookmarks), to make iteration quicker.
 
   // LIST A
   // MAP of url (string) -> bookmarks objects from the Policy Engine
   let specifiedBookmarksMap = new Map();
   for (let bookmark of specifiedBookmarks) {
-    specifiedBookmarksMap.set(bookmark.URL.spec, bookmark);
+    specifiedBookmarksMap.set(bookmark.URL.href, bookmark);
   }
 
   // LIST B
   // MAP of url (string) -> bookmarks objects from Places
   let existingBookmarksMap = new Map();
   await PlacesUtils.bookmarks.fetch(
     { guidPrefix: BookmarksPolicies.BOOKMARK_GUID_PREFIX },
     (bookmark) => existingBookmarksMap.set(bookmark.url.href, bookmark)
@@ -188,60 +188,60 @@ async function calculateLists(specifiedB
   };
 }
 
 async function insertBookmark(bookmark) {
   let parentGuid = await getParentGuid(bookmark.Placement,
                                        bookmark.Folder);
 
   await PlacesUtils.bookmarks.insert({
-    url: bookmark.URL,
+    url: Services.io.newURI(bookmark.URL.href),
     title: bookmark.Title,
     guid: generateGuidWithPrefix(BookmarksPolicies.BOOKMARK_GUID_PREFIX),
     parentGuid,
   });
 
   if (bookmark.Favicon) {
     await setFaviconForBookmark(bookmark).catch(
       () => log.error(`Error setting favicon for ${bookmark.Title}`));
   }
 }
 
 async function setFaviconForBookmark(bookmark) {
   let faviconURI;
   let nullPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
 
-  switch (bookmark.Favicon.scheme) {
-    case "data":
+  switch (bookmark.Favicon.protocol) {
+    case "data:":
       // data urls must first call replaceFaviconDataFromDataURL, using a
       // fake URL. Later, it's needed to call setAndFetchFaviconForPage
       // with the same URL.
-      faviconURI = Services.io.newURI("fake-favicon-uri:" + bookmark.URL.spec);
+      faviconURI = Services.io.newURI("fake-favicon-uri:" + bookmark.URL.href);
 
       PlacesUtils.favicons.replaceFaviconDataFromDataURL(
         faviconURI,
-        bookmark.Favicon.spec,
+        bookmark.Favicon.href,
         0, /* max expiration length */
         nullPrincipal
       );
       break;
 
-    case "http":
-    case "https":
-      faviconURI = bookmark.Favicon;
+    case "http:":
+    case "https:":
+      faviconURI = Services.io.newURI(bookmark.Favicon.href);
       break;
 
     default:
       log.error(`Bad URL given for favicon on bookmark "${bookmark.Title}"`);
       return Promise.resolve();
   }
 
   return new Promise(resolve => {
     PlacesUtils.favicons.setAndFetchFaviconForPage(
-      bookmark.URL,
+      Services.io.newURI(bookmark.URL.href),
       faviconURI,
       false, /* forceReload */
       PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
       resolve,
       nullPrincipal
     );
   });
 }
--- a/browser/components/enterprisepolicies/helpers/ProxyPolicies.jsm
+++ b/browser/components/enterprisepolicies/helpers/ProxyPolicies.jsm
@@ -35,17 +35,17 @@ var EXPORTED_SYMBOLS = [ "ProxyPolicies"
 
 var ProxyPolicies = {
   configureProxySettings(param, setPref) {
     if (param.Mode) {
       setPref("network.proxy.type", PROXY_TYPES_MAP.get(param.Mode));
     }
 
     if (param.AutoConfigURL) {
-      setPref("network.proxy.autoconfig_url", param.AutoConfigURL.spec);
+      setPref("network.proxy.autoconfig_url", param.AutoConfigURL.href);
     }
 
     if (param.UseProxyForDNS !== undefined) {
       setPref("network.proxy.socks_remote_dns", param.UseProxyForDNS);
     }
 
     if (param.AutoLogin !== undefined) {
       setPref("signon.autologin.proxy", param.AutoLogin);
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_bookmarks.js
@@ -10,17 +10,17 @@ ChromeUtils.import("resource://gre/modul
 const FAVICON_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=";
 
 const { BookmarksPolicies } = ChromeUtils.import("resource:///modules/policies/BookmarksPolicies.jsm", {});
 
 let CURRENT_POLICY;
 
 const BASE_POLICY = {
   "policies": {
-    "display_bookmarks_toolbar": true,
+    "DisplayBookmarksToolbar": true,
     "Bookmarks": [
       {
         "Title": "Bookmark 1",
         "URL": "https://bookmark1.example.com/",
         "Favicon": FAVICON_DATA
       },
       {
         "Title": "Bookmark 2",
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_proxy.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_proxy.js
@@ -11,19 +11,19 @@ add_task(async function test_proxy_modes
   let { ProxyPolicies, PROXY_TYPES_MAP } = ChromeUtils.import("resource:///modules/policies/ProxyPolicies.jsm", {});
 
   for (let [mode, expectedValue] of PROXY_TYPES_MAP) {
     ProxyPolicies.configureProxySettings({Mode: mode}, (_, value) => {
       is(value, expectedValue, "Correct proxy mode");
     });
   }
 
-  let autoconfigURL = Services.io.newURI("data:text/plain,test");
+  let autoconfigURL = new URL("data:text/plain,test");
   ProxyPolicies.configureProxySettings({AutoConfigURL: autoconfigURL}, (_, value) => {
-    is(value, autoconfigURL.spec, "AutoconfigURL correctly set");
+    is(value, autoconfigURL.href, "AutoconfigURL correctly set");
   });
 });
 
 add_task(async function test_proxy_boolean_settings() {
   // Tests that both false and true values are correctly set and locked
   await setupPolicyEngineWithJson({
     "policies": {
       "Proxy": {
--- a/browser/modules/Sanitizer.jsm
+++ b/browser/modules/Sanitizer.jsm
@@ -201,16 +201,17 @@ var Sanitizer = {
       case Sanitizer.TIMESPAN_4HOURS :
         startDate = endDate - 14400000000; // 4*60*60*1000000
         break;
       case Sanitizer.TIMESPAN_TODAY :
         var d = new Date(); // Start with today
         d.setHours(0); // zero us back to midnight...
         d.setMinutes(0);
         d.setSeconds(0);
+        d.setMilliseconds(0);
         startDate = d.valueOf() * 1000; // convert to epoch usec
         break;
       case Sanitizer.TIMESPAN_24HOURS :
         startDate = endDate - 86400000000; // 24*60*60*1000000
         break;
       default:
         throw "Invalid time span for clear private data: " + ts;
     }
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -2907,16 +2907,37 @@ exports.CSS_PROPERTIES = {
       "cursor",
       "pointer-events",
       "-moz-user-input",
       "-moz-user-modify",
       "-moz-user-focus",
       "caret-color",
       "scrollbar-face-color",
       "scrollbar-track-color",
+      "text-anchor",
+      "color-interpolation",
+      "color-interpolation-filters",
+      "fill",
+      "fill-opacity",
+      "fill-rule",
+      "shape-rendering",
+      "stroke",
+      "stroke-width",
+      "stroke-linecap",
+      "stroke-linejoin",
+      "stroke-miterlimit",
+      "stroke-opacity",
+      "stroke-dasharray",
+      "stroke-dashoffset",
+      "clip-rule",
+      "marker-start",
+      "marker-mid",
+      "marker-end",
+      "paint-order",
+      "-moz-context-properties",
       "list-style-position",
       "list-style-type",
       "list-style-image",
       "quotes",
       "-moz-image-region",
       "margin-top",
       "margin-right",
       "margin-bottom",
@@ -2976,37 +2997,16 @@ exports.CSS_PROPERTIES = {
       "text-decoration-line",
       "text-decoration-style",
       "text-decoration-color",
       "initial-letter",
       "ime-mode",
       "-moz-user-select",
       "-moz-window-dragging",
       "-moz-force-broken-image-icon",
-      "text-anchor",
-      "color-interpolation",
-      "color-interpolation-filters",
-      "fill",
-      "fill-opacity",
-      "fill-rule",
-      "shape-rendering",
-      "stroke",
-      "stroke-width",
-      "stroke-linecap",
-      "stroke-linejoin",
-      "stroke-miterlimit",
-      "stroke-opacity",
-      "stroke-dasharray",
-      "stroke-dashoffset",
-      "clip-rule",
-      "marker-start",
-      "marker-mid",
-      "marker-end",
-      "paint-order",
-      "-moz-context-properties",
       "dominant-baseline",
       "vector-effect",
       "stop-color",
       "stop-opacity",
       "flood-color",
       "flood-opacity",
       "lighting-color",
       "mask-type",
--- a/devtools/shared/heapsnapshot/AutoMemMap.h
+++ b/devtools/shared/heapsnapshot/AutoMemMap.h
@@ -40,17 +40,18 @@ class MOZ_RAII AutoMemMap
   PRFileMap*   fileMap;
   void*        addr;
 
   AutoMemMap(const AutoMemMap& aOther) = delete;
   void operator=(const AutoMemMap& aOther) = delete;
 
 public:
   explicit AutoMemMap(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
-      : fd(nullptr)
+      : fileInfo()
+      , fd(nullptr)
       , fileMap(nullptr)
       , addr(nullptr)
   {
       MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   };
   ~AutoMemMap();
 
   // Initialize this AutoMemMap.
--- a/devtools/shared/heapsnapshot/HeapSnapshot.cpp
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.cpp
@@ -1354,17 +1354,19 @@ class MOZ_STACK_CLASS HeapSnapshotHandle
 public:
   // For telemetry.
   uint32_t nodeCount;
   uint32_t edgeCount;
 
   HeapSnapshotHandler(CoreDumpWriter& writer,
                       JS::CompartmentSet* compartments)
     : writer(writer),
-      compartments(compartments)
+      compartments(compartments),
+      nodeCount(0),
+      edgeCount(0)
   { }
 
   // JS::ubi::BreadthFirst handler interface.
 
   class NodeData { };
   typedef JS::ubi::BreadthFirst<HeapSnapshotHandler> Traversal;
   bool operator() (Traversal& traversal,
                    JS::ubi::Node origin,
--- a/docshell/base/nsDefaultURIFixup.cpp
+++ b/docshell/base/nsDefaultURIFixup.cpp
@@ -128,32 +128,41 @@ HasUserPassword(const nsACString& aStrin
         return true;
       }
     }
   }
 
   return false;
 }
 
+// Assume that 1 tab is accidental, but more than 1 implies this is
+// supposed to be tab-separated content.
+static bool
+MaybeTabSeparatedContent(const nsCString& aStringURI)
+{
+  auto firstTab = aStringURI.FindChar('\t');
+  return firstTab != kNotFound && aStringURI.RFindChar('\t') != firstTab;
+}
+
 NS_IMETHODIMP
 nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
                                    uint32_t aFixupFlags,
                                    nsIInputStream** aPostData,
                                    nsIURIFixupInfo** aInfo)
 {
   NS_ENSURE_ARG(!aStringURI.IsEmpty());
 
   nsresult rv;
 
   nsAutoCString uriString(aStringURI);
 
   // Eliminate embedded newlines, which single-line text fields now allow:
   uriString.StripCRLF();
-  // Cleanup the empty spaces that might be on each end:
-  uriString.Trim(" ");
+  // Cleanup the empty spaces and tabs that might be on each end:
+  uriString.Trim(" \t");
 
   NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
 
   RefPtr<nsDefaultURIFixupInfo> info = new nsDefaultURIFixupInfo(uriString);
   NS_ADDREF(*aInfo = info);
 
   nsCOMPtr<nsIIOService> ioService =
     do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
@@ -355,22 +364,26 @@ nsDefaultURIFixup::GetFixupURIInfo(const
   if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("://"))) {
     uriString = StringTail(uriString, uriString.Length() - 3);
     inputHadDuffProtocol = true;
   } else if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("//"))) {
     uriString = StringTail(uriString, uriString.Length() - 2);
     inputHadDuffProtocol = true;
   }
 
-  // NB: this rv gets returned at the end of this method if we never
-  // do a keyword fixup after this (because the pref or the flags passed
-  // might not let us).
-  rv = FixupURIProtocol(uriString, info, getter_AddRefs(uriWithProtocol));
-  if (uriWithProtocol) {
-    info->mFixedURI = uriWithProtocol;
+  // Note: this rv gets returned at the end of this method if we don't fix up
+  // the protocol and don't do a keyword fixup after this (because the pref
+  // or the flags passed might not let us).
+  rv = NS_OK;
+  // Avoid fixing up content that looks like tab-separated values
+  if (!MaybeTabSeparatedContent(uriString)) {
+    rv = FixupURIProtocol(uriString, info, getter_AddRefs(uriWithProtocol));
+    if (uriWithProtocol) {
+      info->mFixedURI = uriWithProtocol;
+    }
   }
 
   // See if it is a keyword
   // Test whether keywords need to be fixed up
   if (sFixupKeywords && (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP) &&
       !inputHadDuffProtocol) {
     if (NS_SUCCEEDED(KeywordURIFixup(uriString, info, aPostData)) &&
         info->mPreferredURI) {
--- a/docshell/test/unit/test_nsDefaultURIFixup_info.js
+++ b/docshell/test/unit/test_nsDefaultURIFixup_info.js
@@ -488,16 +488,26 @@ var testcases = [ {
     fixedURI: "http://plonk:8080/",
     protocolChange: true,
   }, {
     input: "\u10E0\u10D4\u10D2\u10D8\u10E1\u10E2\u10E0\u10D0\u10EA\u10D8\u10D0.\u10D2\u10D4",
     fixedURI: "http://xn--lodaehvb5cdik4g.xn--node/",
     alternateURI: "http://www.xn--lodaehvb5cdik4g.xn--node/",
     protocolChange: true,
   },
+  {
+    input: " \t mozilla.org/\t \t ",
+    fixedURI: "http://mozilla.org/",
+    alternateURI: "http://www.mozilla.org/",
+    protocolChange: true,
+  },
+  {
+    input: " moz\ti\tlla.org ",
+    keywordLookup: true,
+  },
 ];
 
 if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
   testcases.push({
     input: "C:\\some\\file.txt",
     fixedURI: "file:///C:/some/file.txt",
     protocolChange: true,
   });
@@ -584,55 +594,58 @@ function do_single_test_run() {
         continue;
       }
 
       info("Checking \"" + testInput + "\" with flags " + flags +
            " (host lookup for single words: " + (gSingleWordHostLookup ? "yes" : "no") + ")");
 
       // Both APIs should then also be using the same spec.
       Assert.equal(!!fixupURIOnly, !!URIInfo.preferredURI);
-      if (fixupURIOnly)
-        Assert.equal(fixupURIOnly.spec, URIInfo.preferredURI.spec);
+      if (fixupURIOnly) {
+        Assert.equal(fixupURIOnly.spec, URIInfo.preferredURI.spec, "Fixed and preferred URI should match");
+      }
 
       let isFileURL = expectedFixedURI && expectedFixedURI.startsWith("file");
 
       // Check the fixedURI:
       let makeAlternativeURI = flags & urifixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI;
       if (makeAlternativeURI && alternativeURI != null) {
-        Assert.equal(URIInfo.fixedURI.spec, alternativeURI);
+        Assert.equal(URIInfo.fixedURI.spec, alternativeURI, "should have gotten alternate URI");
       } else {
-        Assert.equal(URIInfo.fixedURI && URIInfo.fixedURI.spec, expectedFixedURI);
+        Assert.equal(URIInfo.fixedURI && URIInfo.fixedURI.spec, expectedFixedURI, "should get correct fixed URI");
       }
 
       // Check booleans on input:
       let couldDoKeywordLookup = flags & urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
-      Assert.equal(!!URIInfo.keywordProviderName, couldDoKeywordLookup && expectKeywordLookup);
-      Assert.equal(URIInfo.fixupChangedProtocol, expectProtocolChange);
-      Assert.equal(URIInfo.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null);
+      Assert.equal(!!URIInfo.keywordProviderName, couldDoKeywordLookup && expectKeywordLookup, "keyword lookup as expected");
+      Assert.equal(URIInfo.fixupChangedProtocol, expectProtocolChange, "protocol change as expected");
+      Assert.equal(URIInfo.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null, "alternative URI as expected");
 
       // Check the preferred URI
       if (couldDoKeywordLookup) {
         if (expectKeywordLookup) {
           if (!inWhitelist) {
             let urlparamInput = encodeURIComponent(sanitize(testInput)).replace(/%20/g, "+");
             // If the input starts with `?`, then URIInfo.preferredURI.spec will omit it
             // In order to test this behaviour, remove `?` only if it is the first character
             if (urlparamInput.startsWith("%3F")) {
               urlparamInput = urlparamInput.replace("%3F", "");
             }
             let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
             let spec = URIInfo.preferredURI.spec.replace(/%27/g, "'");
-            Assert.equal(spec, searchURL);
+            Assert.equal(spec, searchURL, "should get correct search URI");
           } else {
-            Assert.equal(URIInfo.preferredURI, null);
+            Assert.equal(URIInfo.preferredURI, null, "not expecting a preferred URI");
           }
         } else {
-          Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec);
+          Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec, "fixed URI should match");
         }
       } else {
         // In these cases, we should never be doing a keyword lookup and
         // the fixed URI should be preferred:
-        Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec);
+        let prefURI = URIInfo.preferredURI && URIInfo.preferredURI.spec;
+        let fixedURI = URIInfo.fixedURI && URIInfo.fixedURI.spec;
+        Assert.equal(prefURI, fixedURI, "fixed URI should be same as expected");
       }
-      Assert.equal(sanitize(testInput), URIInfo.originalInput);
+      Assert.equal(sanitize(testInput), URIInfo.originalInput, "should mirror original input");
     }
   }
 }
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -75,16 +75,18 @@
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/Likely.h"
 #include "mozilla/ManualNAC.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/dom/Selection.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/TextEvents.h"
 #include "nsArrayUtils.h"
 #include "nsAString.h"
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsBindingManager.h"
 #include "nsCanvasFrame.h"
@@ -507,16 +509,51 @@ EventListenerManagerHashClearEntry(PLDHa
 {
   EventListenerManagerMapEntry *lm =
     static_cast<EventListenerManagerMapEntry *>(entry);
 
   // Let the EventListenerManagerMapEntry clean itself up...
   lm->~EventListenerManagerMapEntry();
 }
 
+static bool
+IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
+                            nsIChannel* aChannel,
+                            nsIURI* aURI)
+{
+  MOZ_ASSERT(!aWindow || !aChannel,
+             "A window and channel should not both be provided.");
+
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
+  if (!thirdPartyUtil) {
+    return false;
+  }
+
+  // In the absence of a window or channel, we assume that we are first-party.
+  bool thirdParty = false;
+
+  if (aWindow) {
+    Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
+                                                 aURI,
+                                                 &thirdParty);
+  }
+
+  if (aChannel) {
+    // Note, we must call IsThirdPartyChannel() here and not just try to
+    // use nsILoadInfo.isThirdPartyContext.  That nsILoadInfo property only
+    // indicates if the parent loading window is third party or not.  We
+    // want to check the channel URI against the loading principal as well.
+    Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
+                                                  nullptr,
+                                                  &thirdParty);
+  }
+
+  return thirdParty;
+}
+
 class SameOriginCheckerImpl final : public nsIChannelEventSink,
                                     public nsIInterfaceRequestor
 {
   ~SameOriginCheckerImpl() = default;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
@@ -8810,16 +8847,46 @@ nsContentUtils::GetCookieBehaviorForPrin
       // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
       // specific domain. As BEHAVIOR_LIMIT_FOREIGN isn't visible in our UI,
       // this is probably not an issue.
       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
       break;
   }
 }
 
+// static public
+bool
+nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
+                                              nsIChannel* aChannel,
+                                              nsIURI* aURI)
+{
+  if (!StaticPrefs::privacy_trackingprotection_storagerestriction_enabled()) {
+    return false;
+  }
+
+  // Let's check if this is a 3rd party context.
+  if (!IsThirdPartyWindowOrChannel(aWindow, aChannel, aURI)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIChannel> channel;
+
+  // aChannel and aWindow are mutually exclusive.
+  channel = aChannel;
+  if (aWindow) {
+    nsIDocument* document = aWindow->GetExtantDoc();
+    if (document) {
+      channel = document->GetChannel();
+    }
+  }
+
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
+  return httpChannel && httpChannel->GetIsTrackingResource();
+}
+
 // static, private
 nsContentUtils::StorageAccess
 nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
                                                    nsPIDOMWindowInner* aWindow,
                                                    nsIURI* aURI,
                                                    nsIChannel* aChannel)
 {
   MOZ_ASSERT(aPrincipal);
@@ -8827,16 +8894,20 @@ nsContentUtils::InternalStorageAllowedFo
   StorageAccess access = StorageAccess::eAllow;
 
   // We don't allow storage on the null principal, in general. Even if the
   // calling context is chrome.
   if (aPrincipal->GetIsNullPrincipal()) {
     return StorageAccess::eDeny;
   }
 
+  if (StorageDisabledByAntiTracking(aWindow, aChannel, aURI)) {
+    return StorageAccess::eDeny;
+  }
+
   if (aWindow) {
     // If the document is sandboxed, then it is not permitted to use storage
     nsIDocument* document = aWindow->GetExtantDoc();
     if (document && document->GetSandboxFlags() & SANDBOXED_ORIGIN) {
       return StorageAccess::eDeny;
     }
 
     // Check if we are in private browsing, and record that fact
@@ -8902,57 +8973,25 @@ nsContentUtils::InternalStorageAllowedFo
     }
   }
 
   // We don't want to prompt for every attempt to access permissions.
   if (behavior == nsICookieService::BEHAVIOR_REJECT) {
     return StorageAccess::eDeny;
   }
 
-  if (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
-      behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) {
-
-    // In the absence of a window or channel, we assume that we are first-party.
-    bool thirdParty = false;
-
-    MOZ_ASSERT(!aWindow || !aChannel,
-               "A window and channel should not both be provided.");
-
-    if (aWindow) {
-      nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-        do_GetService(THIRDPARTYUTIL_CONTRACTID);
-      MOZ_ASSERT(thirdPartyUtil);
-
-      Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
-                                                   aURI,
-                                                   &thirdParty);
-    }
-
-    if (aChannel) {
-      nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-        do_GetService(THIRDPARTYUTIL_CONTRACTID);
-      MOZ_ASSERT(thirdPartyUtil);
-
-      // Note, we must call IsThirdPartyChannel() here and not just try to
-      // use nsILoadInfo.isThirdPartyContext.  That nsILoadInfo property only
-      // indicates if the parent loading window is third party or not.  We
-      // want to check the channel URI against the loading principal as well.
-      Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
-                                                    nullptr,
-                                                    &thirdParty);
-    }
-
-    if (thirdParty) {
-      // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
-      // simply rejecting the request to use the storage. In the future, if we
-      // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
-      // for non-cookie storage types, this may change.
-
-      return StorageAccess::eDeny;
-    }
+  if ((behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
+       behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) &&
+      IsThirdPartyWindowOrChannel(aWindow, aChannel, aURI)) {
+    // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
+    // simply rejecting the request to use the storage. In the future, if we
+    // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
+    // for non-cookie storage types, this may change.
+
+    return StorageAccess::eDeny;
   }
 
   return access;
 }
 
 namespace {
 
 // We put StringBuilder in the anonymous namespace to prevent anything outside
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2950,16 +2950,24 @@ public:
   /*
    * Checks if storage for the given principal is permitted by the user's
    * preferences. The caller is assumed to not be a third-party iframe.
    * (if that is possible, the caller should use StorageAllowedForWindow)
    */
   static StorageAccess StorageAllowedForPrincipal(nsIPrincipal* aPrincipal);
 
   /*
+   * Returns true if this window/channel should disable storages because of the
+   * anti-tracking feature.
+   */
+  static bool StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
+                                            nsIChannel* aChannel,
+                                            nsIURI* aURI);
+
+  /*
    * Serializes a HTML nsINode into its markup representation.
    */
   static bool SerializeNodeToMarkup(nsINode* aRoot,
                                     bool aDescendentsOnly,
                                     nsAString& aOut);
 
   /*
    * Returns true iff the provided JSObject is a global, and its URI matches
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -936,16 +936,20 @@ nsGlobalWindowInner::nsGlobalWindowInner
       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
       if (os) {
         // Watch for online/offline status changes so we can fire events. Use
         // a strong reference.
         os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
                         false);
 
         os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC, false);
+
+        if (aOuterWindow->IsTopLevelWindow()) {
+          os->AddObserver(mObserver, "clear-site-data-reload-needed", false);
+        }
       }
 
       Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
 
       // Watch for storage notifications so we can fire storage events.
       RefPtr<StorageNotifierService> sns =
         StorageNotifierService::GetOrCreate();
       if (sns) {
@@ -1263,16 +1267,21 @@ nsGlobalWindowInner::FreeInnerObjects()
 
   DisconnectEventTargetObjects();
 
   if (mObserver) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
       os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC);
+
+      if (GetOuterWindowInternal() &&
+          GetOuterWindowInternal()->IsTopLevelWindow()) {
+        os->RemoveObserver(mObserver, "clear-site-data-reload-needed");
+      }
     }
 
     RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
     if (sns) {
      sns->Unregister(mObserver);
     }
 
     if (mIdleService) {
@@ -5813,16 +5822,23 @@ nsGlobalWindowInner::Observe(nsISupports
 
   if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
     if (mPerformance) {
       mPerformance->MemoryPressure();
     }
     return NS_OK;
   }
 
+  if (!nsCRT::strcmp(aTopic, "clear-site-data-reload-needed")) {
+    // The reload is propagated from the top-level window only.
+    NS_ConvertUTF16toUTF8 otherOrigin(aData);
+    PropagateClearSiteDataReload(otherOrigin);
+    return NS_OK;
+  }
+
   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
     mCurrentlyIdle = true;
     if (IsFrozen()) {
       // need to fire only one idle event while the window is frozen.
       mNotifyIdleObserversIdleOnThaw = true;
       mNotifyIdleObserversActiveOnThaw = false;
     } else if (IsCurrentInnerWindow()) {
       HandleIdleActiveEvent();
@@ -8048,16 +8064,49 @@ nsPIDOMWindowInner::MaybeCreateDoc()
     // Note that |document| here is the same thing as our mDoc, but we
     // don't have to explicitly set the member variable because the docshell
     // has already called SetNewDocument().
     nsCOMPtr<nsIDocument> document = docShell->GetDocument();
     Unused << document;
   }
 }
 
+void
+nsGlobalWindowInner::PropagateClearSiteDataReload(const nsACString& aOrigin)
+{
+  nsIPrincipal* principal = GetPrincipal();
+  if (!principal) {
+    return;
+  }
+
+  nsAutoCString origin;
+  nsresult rv = principal->GetOrigin(origin);
+  NS_ENSURE_SUCCESS_VOID(rv);
+
+  // If the URL of this window matches, let's refresh this window only.
+  // We don't need to traverse the DOM tree.
+  if (origin.Equals(aOrigin)) {
+    nsCOMPtr<nsIDocShell> docShell = GetDocShell();
+    nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
+    if (NS_WARN_IF(!webNav)) {
+      return;
+    }
+
+    // We don't need any special reload flags, because this notification is
+    // dispatched by Clear-Site-Data header, which should have already cleaned
+    // up all the needed data.
+    rv = webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
+    NS_ENSURE_SUCCESS_VOID(rv);
+
+    return;
+  }
+
+  CallOnChildren(&nsGlobalWindowInner::PropagateClearSiteDataReload, aOrigin);
+}
+
 mozilla::dom::DocGroup*
 nsPIDOMWindowInner::GetDocGroup() const
 {
   nsIDocument* doc = GetExtantDoc();
   if (doc) {
     return doc->GetDocGroup();
   }
   return nullptr;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -974,16 +974,18 @@ public:
   void GetInterface(JSContext* aCx, nsIJSID* aIID,
                     JS::MutableHandle<JS::Value> aRetval,
                     mozilla::ErrorResult& aError);
 
   already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
 
   bool ShouldReportForServiceWorkerScope(const nsAString& aScope);
 
+  void PropagateClearSiteDataReload(const nsACString& aOrigin);
+
   already_AddRefed<mozilla::dom::InstallTriggerImpl> GetInstallTrigger();
 
   void UpdateTopInnerWindow();
 
   virtual bool IsInSyncOperation() override
   {
     return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
   }
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/StaticPrefs.h"
 #include "nsContentUtils.h"
 
 #include "nsIBFCacheEntry.h"
 #include "nsIDocument.h"
 #include "nsISupportsPrimitives.h"
 
 #ifdef XP_WIN
 #undef PostMessage
@@ -294,22 +295,35 @@ BroadcastChannel::Constructor(const Glob
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
+
+    if (StaticPrefs::privacy_trackingprotection_storagerestriction_enabled() &&
+        nsContentUtils::StorageAllowedForWindow(window) !=
+          nsContentUtils::StorageAccess::eAllow) {
+      aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
+    }
   } else {
     JSContext* cx = aGlobal.Context();
 
     WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
     MOZ_ASSERT(workerPrivate);
 
+    if (StaticPrefs::privacy_trackingprotection_storagerestriction_enabled() &&
+        !workerPrivate->IsStorageAllowed()) {
+      aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return nullptr;
+    }
+
     RefPtr<StrongWorkerRef> workerRef =
       StrongWorkerRef::Create(workerPrivate, "BroadcastChannel",
                               [bc] () { bc->Shutdown(); });
     // We are already shutting down the worker. Let's return a non-active
     // object.
     if (NS_WARN_IF(!workerRef)) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1101,16 +1101,21 @@ nsHTMLDocument::GetCookie(nsAString& aCo
 
   // If the document's sandboxed origin flag is set, access to read cookies
   // is prohibited.
   if (mSandboxFlags & SANDBOXED_ORIGIN) {
     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
+  if (nsContentUtils::StorageDisabledByAntiTracking(GetInnerWindow(), nullptr,
+                                                    nullptr)) {
+    return;
+  }
+
   // If the document is a cookie-averse Document... return the empty string.
   if (IsCookieAverse()) {
     return;
   }
 
   // not having a cookie service isn't an error
   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
   if (service) {
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2585,16 +2585,28 @@ ContentChild::RecvUpdateAppLocales(nsTAr
 mozilla::ipc::IPCResult
 ContentChild::RecvUpdateRequestedLocales(nsTArray<nsCString>&& aRequestedLocales)
 {
   LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentChild::RecvClearSiteDataReloadNeeded(const nsString& aOrigin)
+{
+  // Rebroadcast "clear-site-data-reload-needed".
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->NotifyObservers(nullptr, "clear-site-data-reload-needed",
+                         aOrigin.get());
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 ContentChild::RecvAddPermission(const IPC::Permission& permission)
 {
   nsCOMPtr<nsIPermissionManager> permissionManagerIface =
     services::GetPermissionManager();
   nsPermissionManager* permissionManager =
     static_cast<nsPermissionManager*>(permissionManagerIface.get());
   MOZ_ASSERT(permissionManager,
          "We have no permissionManager in the Content process !");
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -400,16 +400,18 @@ public:
 
   virtual mozilla::ipc::IPCResult RecvUpdateDictionaryList(InfallibleTArray<nsString>&& aDictionaries) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateFontList(InfallibleTArray<SystemFontListEntry>&& aFontList) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateAppLocales(nsTArray<nsCString>&& aAppLocales) override;
   virtual mozilla::ipc::IPCResult RecvUpdateRequestedLocales(nsTArray<nsCString>&& aRequestedLocales) override;
 
+  virtual mozilla::ipc::IPCResult RecvClearSiteDataReloadNeeded(const nsString& aOrigin) override;
+
   virtual mozilla::ipc::IPCResult RecvAddPermission(const IPC::Permission& permission) override;
 
   virtual mozilla::ipc::IPCResult RecvFlushMemory(const nsString& reason) override;
 
   virtual mozilla::ipc::IPCResult RecvActivateA11y(const uint32_t& aMainChromeTid,
                                                    const uint32_t& aMsaaID) override;
   virtual mozilla::ipc::IPCResult RecvShutdownA11y() override;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -589,16 +589,17 @@ static const char* sObserverTopics[] = {
 #ifdef ACCESSIBILITY
   "a11y-init-or-shutdown",
 #endif
   "cacheservice:empty-cache",
   "intl:app-locales-changed",
   "intl:requested-locales-changed",
   "cookie-changed",
   "private-cookie-changed",
+  "clear-site-data-reload-needed",
 };
 
 // PreallocateProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateProcess()
 {
   RefPtr<ContentParent> process =
@@ -3007,16 +3008,19 @@ ContentParent::Observe(nsISupports* aSub
     nsCOMPtr<nsICookie> xpcCookie = do_QueryInterface(aSubject);
     NS_ASSERTION(xpcCookie, "couldn't get cookie");
     if (!nsCRT::strcmp(aData, u"deleted")) {
       cs->RemoveCookie(xpcCookie);
     } else if ((!nsCRT::strcmp(aData, u"added")) ||
                (!nsCRT::strcmp(aData, u"changed"))) {
       cs->AddCookie(xpcCookie);
     }
+  } else if (!strcmp(aTopic, "clear-site-data-reload-needed")) {
+    // Rebroadcast "clear-site-data-reload-needed".
+    Unused << SendClearSiteDataReloadNeeded(nsString(aData));
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ContentParent::GetInterface(const nsIID& aIID, void** aResult)
 {
   NS_ENSURE_ARG_POINTER(aResult);
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -450,16 +450,18 @@ child:
 
     async UpdateDictionaryList(nsString[] dictionaries);
 
     async UpdateFontList(SystemFontListEntry[] fontList);
 
     async UpdateAppLocales(nsCString[] appLocales);
     async UpdateRequestedLocales(nsCString[] requestedLocales);
 
+    async ClearSiteDataReloadNeeded(nsString origin);
+
     // nsIPermissionManager messages
     async AddPermission(Permission permission);
 
     async FlushMemory(nsString reason);
 
     async GarbageCollect();
     async CycleCollect();
     async UnlinkGhosts();
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -89,8 +89,10 @@ BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type.
 BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
 BlockSubresourceRedirectToData=Redirecting to insecure data: URI not allowed (Blocked loading of: “%1$S”)
 
 BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blocked loading of: “%1$S”)
 
 # LOCALIZATION NOTE (BrowserUpgradeInsecureDisplayRequest):
 # %1$S is the browser name "brandShortName"; %2$S is the URL of the upgraded request; %1$S is the upgraded scheme.
 BrowserUpgradeInsecureDisplayRequest = %1$S is upgrading an insecure display request ‘%2$S’ to use ‘%3$S’
+RunningClearSiteDataValue=Clear-Site-Data header forces the clean up of “%S” data.
+UnknownClearSiteDataValue=Clear-Site-Data header found. Unknown value “%S”.
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -108,18 +108,18 @@ static NPNetscapeFuncs sBrowserFuncs = {
   nullptr, // _write, unimplemented
   nullptr, // _destroystream, unimplemented
   _status,
   _useragent,
   _memalloc,
   _memfree,
   _memflush,
   _reloadplugins,
-  nullptr, // _getJavaEnv, unimplemented
-  nullptr, // _getJavaPeer, unimplemented
+  _getJavaEnv,
+  _getJavaPeer,
   _geturlnotify,
   _posturlnotify,
   _getvalue,
   _setvalue,
   _invalidaterect,
   _invalidateregion,
   _forceredraw,
   _getstringidentifier,
@@ -1698,16 +1698,24 @@ NPError
 }
 
 NPError
 _requestread(NPStream *pstream, NPByteRange *rangeList)
 {
   return NPERR_STREAM_NOT_SEEKABLE;
 }
 
+// Deprecated, only stubbed out
+void* /* OJI type: JRIEnv* */
+_getJavaEnv()
+{
+  NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
+  return nullptr;
+}
+
 const char *
 _useragent(NPP npp)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_useragent called from the wrong thread\n"));
     return nullptr;
   }
   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_UserAgent: npp=%p\n", (void*)npp));
@@ -1731,16 +1739,24 @@ void *
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN_memalloc called from the wrong thread\n"));
   }
   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_MemAlloc: size=%d\n", size));
   return moz_xmalloc(size);
 }
 
+// Deprecated, only stubbed out
+void* /* OJI type: jref */
+_getJavaPeer(NPP npp)
+{
+  NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
+  return nullptr;
+}
+
 void
 _pushpopupsenabledstate(NPP npp, NPBool enabled)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_pushpopupsenabledstate called from the wrong thread\n"));
     return;
   }
   nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
--- a/dom/plugins/base/nsNPAPIPlugin.h
+++ b/dom/plugins/base/nsNPAPIPlugin.h
@@ -274,16 +274,23 @@ void
 _forceredraw(NPP npp);
 
 const char*
 _useragent(NPP npp);
 
 void*
 _memalloc (uint32_t size);
 
+// Deprecated entry points for the old Java plugin.
+void* /* OJI type: JRIEnv* */
+_getJavaEnv();
+
+void* /* OJI type: jref */
+_getJavaPeer(NPP npp);
+
 void
 _urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
 
 NPError
 _initasyncsurface(NPP instance, NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface);
 
 NPError
 _finalizeasyncsurface(NPP instance, NPAsyncSurface *surface);
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -870,16 +870,24 @@ static void
 _forceredraw(NPP aNPP);
 
 static const char*
 _useragent(NPP aNPP);
 
 static void*
 _memalloc (uint32_t size);
 
+// Deprecated entry points for the old Java plugin.
+static void* /* OJI type: JRIEnv* */
+_getjavaenv(void);
+
+// Deprecated entry points for the old Java plugin.
+static void* /* OJI type: jref */
+_getjavapeer(NPP aNPP);
+
 static bool
 _invoke(NPP aNPP, NPObject* npobj, NPIdentifier method, const NPVariant *args,
         uint32_t argCount, NPVariant *result);
 
 static bool
 _invokedefault(NPP aNPP, NPObject* npobj, const NPVariant *args,
                uint32_t argCount, NPVariant *result);
 
@@ -974,18 +982,18 @@ const NPNetscapeFuncs PluginModuleChild:
     nullptr, // _write, unimplemented
     nullptr, // _destroystream, unimplemented
     mozilla::plugins::child::_status,
     mozilla::plugins::child::_useragent,
     mozilla::plugins::child::_memalloc,
     mozilla::plugins::child::_memfree,
     mozilla::plugins::child::_memflush,
     mozilla::plugins::child::_reloadplugins,
-    nullptr, // _getjavaenv, unimplemented
-    nullptr, // _getjavapeer, unimplemented
+    mozilla::plugins::child::_getjavaenv,
+    mozilla::plugins::child::_getjavapeer,
     mozilla::plugins::child::_geturlnotify,
     mozilla::plugins::child::_posturlnotify,
     mozilla::plugins::child::_getvalue,
     mozilla::plugins::child::_setvalue,
     mozilla::plugins::child::_invalidaterect,
     mozilla::plugins::child::_invalidateregion,
     mozilla::plugins::child::_forceredraw,
     PluginModuleChild::NPN_GetStringIdentifier,
@@ -1291,16 +1299,31 @@ const char*
 
 void*
 _memalloc(uint32_t aSize)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     return moz_xmalloc(aSize);
 }
 
+// Deprecated entry points for the old Java plugin.
+void* /* OJI type: JRIEnv* */
+_getjavaenv(void)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    return 0;
+}
+
+void* /* OJI type: jref */
+_getjavapeer(NPP aNPP)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    return 0;
+}
+
 bool
 _invoke(NPP aNPP,
         NPObject* aNPObj,
         NPIdentifier aMethod,
         const NPVariant* aArgs,
         uint32_t aArgCount,
         NPVariant* aResult)
 {
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -175,30 +175,36 @@ nsContentSecurityManager::CheckFTPSubres
     return NS_OK;
   }
 
   nsContentPolicyType type = loadInfo->GetExternalContentPolicyType();
   if (type == nsIContentPolicy::TYPE_DOCUMENT) {
     return NS_OK;
   }
 
+  // Allow the system principal to load everything. This is meant to
+  // temporarily fix downloads and pdf.js.
+  nsIPrincipal* triggeringPrincipal = loadInfo->TriggeringPrincipal();
+  if (nsContentUtils::IsSystemPrincipal(triggeringPrincipal)) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
   if (!uri) {
     return NS_OK;
   }
 
   bool isFtpURI = (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtpURI)) && isFtpURI);
   if (!isFtpURI) {
     return NS_OK;
   }
 
   // Allow loading FTP subresources in FTP documents, like XML.
-  nsIPrincipal* triggeringPrincipal = loadInfo->TriggeringPrincipal();
   nsCOMPtr<nsIURI> triggeringURI;
   triggeringPrincipal->GetURI(getter_AddRefs(triggeringURI));
   if (triggeringURI && nsContentUtils::SchemeIs(triggeringURI, "ftp")) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocument> doc;
   if (nsINode* node = loadInfo->LoadingNode()) {
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -303,19 +303,17 @@ LoadContextOptions(const char* aPrefName
                 .setIon(GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion")))
                 .setNativeRegExp(GetWorkerPref<bool>(NS_LITERAL_CSTRING("native_regexp")))
                 .setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack")))
                 .setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror")))
 #ifdef FUZZING
                 .setFuzzing(GetWorkerPref<bool>(NS_LITERAL_CSTRING("fuzzing.enabled")))
 #endif
                 .setStreams(GetWorkerPref<bool>(NS_LITERAL_CSTRING("streams")))
-                .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")))
-                .setArrayProtoValues(GetWorkerPref<bool>(
-                      NS_LITERAL_CSTRING("array_prototype_values")));
+                .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")));
 
   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   if (xr) {
     bool safeMode = false;
     xr->GetInSafeMode(&safeMode);
     if (safeMode) {
       contextOptions.disableOptionsForSafeMode();
     }
--- a/gfx/layers/wr/ClipManager.cpp
+++ b/gfx/layers/wr/ClipManager.cpp
@@ -86,17 +86,17 @@ void
 ClipManager::PushOverrideForASR(const ActiveScrolledRoot* aASR,
                                 const Maybe<wr::WrClipId>& aClipId)
 {
   layers::FrameMetrics::ViewID viewId = aASR
       ? aASR->GetViewId() : layers::FrameMetrics::NULL_SCROLL_ID;
   Maybe<wr::WrClipId> scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
   MOZ_ASSERT(scrollId.isSome());
 
-  CLIP_LOG("Pushing override %" PRIu64 " -> %s\n", scrollId->id,
+  CLIP_LOG("Pushing override %zu -> %s\n", scrollId->id,
       aClipId ? Stringify(aClipId->id).c_str() : "(none)");
   auto it = mASROverride.insert({ *scrollId, std::stack<Maybe<wr::WrClipId>>() });
   it.first->second.push(aClipId);
 
   // Start a new cache
   mCacheStack.emplace();
 }
 
@@ -109,17 +109,17 @@ ClipManager::PopOverrideForASR(const Act
   layers::FrameMetrics::ViewID viewId = aASR
       ? aASR->GetViewId() : layers::FrameMetrics::NULL_SCROLL_ID;
   Maybe<wr::WrClipId> scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
   MOZ_ASSERT(scrollId.isSome());
 
   auto it = mASROverride.find(*scrollId);
   MOZ_ASSERT(it != mASROverride.end());
   MOZ_ASSERT(!(it->second.empty()));
-  CLIP_LOG("Popping override %" PRIu64 " -> %s\n", scrollId->id,
+  CLIP_LOG("Popping override %zu -> %s\n", scrollId->id,
       it->second.top() ? Stringify(it->second.top()->id).c_str() : "(none)");
   it->second.pop();
   if (it->second.empty()) {
     mASROverride.erase(it);
   }
 }
 
 Maybe<wr::WrClipId>
@@ -128,17 +128,17 @@ ClipManager::ClipIdAfterOverride(const M
   if (!aClipId) {
     return Nothing();
   }
   auto it = mASROverride.find(*aClipId);
   if (it == mASROverride.end()) {
     return aClipId;
   }
   MOZ_ASSERT(!it->second.empty());
-  CLIP_LOG("Overriding %" PRIu64 " with %s\n", aClipId->id,
+  CLIP_LOG("Overriding %zu with %s\n", aClipId->id,
       it->second.top() ? Stringify(it->second.top()->id).c_str() : "(none)");
   return it->second.top();
 }
 
 void
 ClipManager::BeginItem(nsDisplayItem* aItem,
                        const StackingContextHelper& aStackingContext)
 {
@@ -304,17 +304,17 @@ ClipManager::DefineClipChain(const Displ
   // Iterate through the clips in the current item's clip chain, define them
   // in WR, and put their IDs into |clipIds|.
   for (const DisplayItemClipChain* chain = aChain; chain; chain = chain->mParent) {
     ClipIdMap& cache = mCacheStack.top();
     auto it = cache.find(chain);
     if (it != cache.end()) {
       // Found it in the currently-active cache, so just use the id we have for
       // it.
-      CLIP_LOG("cache[%p] => %" PRIu64 "\n", chain, it->second.id);
+      CLIP_LOG("cache[%p] => %zu\n", chain, it->second.id);
       clipIds.AppendElement(it->second);
       continue;
     }
     if (!chain->mClip.HasClip()) {
       // This item in the chain is a no-op, skip over it
       continue;
     }
 
@@ -334,17 +334,17 @@ ClipManager::DefineClipChain(const Displ
 
     // Define the clip
     Maybe<wr::WrClipId> parent = ClipIdAfterOverride(scrollId);
     wr::WrClipId clipId = mBuilder->DefineClip(
         parent,
         wr::ToRoundedLayoutRect(clip), &wrRoundedRects);
     clipIds.AppendElement(clipId);
     cache[chain] = clipId;
-    CLIP_LOG("cache[%p] <= %" PRIu64 "\n", chain, clipId.id);
+    CLIP_LOG("cache[%p] <= %zu\n", chain, clipId.id);
   }
 
   // Now find the parent display item's clipchain id
   Maybe<wr::WrClipChainId> parentChainId;
   if (!mItemClipStack.empty()) {
     parentChainId = mItemClipStack.top().mClipChainId;
   }
 
--- a/gfx/qcms/iccread.c
+++ b/gfx/qcms/iccread.c
@@ -509,16 +509,17 @@ static void read_nested_curveType(struct
 	uint32_t channel_offset = 0;
 	int i;
 	for (i = 0; i < num_channels; i++) {
 		uint32_t tag_len;
 
 		(*curveArray)[i] = read_curveType(src, curve_offset + channel_offset, &tag_len);
 		if (!(*curveArray)[i]) {
 			invalid_source(src, "invalid nested curveType curve");
+			break;
 		}
 
 		channel_offset += tag_len;
 		// 4 byte aligned
 		if ((tag_len % 4) != 0)
 			channel_offset += 4 - (tag_len % 4);
 	}
 
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -11,16 +11,18 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Blur.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/SystemGroup.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 #include "gfxUtils.h"
+#include <limits>
+#include <cmath>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 gfxAlphaBoxBlur::gfxAlphaBoxBlur()
   : mData(nullptr),
     mAccelerated(false)
 {
@@ -948,16 +950,26 @@ DrawMirroredMinBoxShadow(DrawTarget* aDe
 gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
                                const gfxRect& aRect,
                                const RectCornerRadii* aCornerRadii,
                                const gfxPoint& aBlurStdDev,
                                const Color& aShadowColor,
                                const gfxRect& aDirtyRect,
                                const gfxRect& aSkipRect)
 {
+  const double maxSize = (double)gfxPlatform::MaxTextureSize();
+  const double maxPos = (double)std::numeric_limits<std::int16_t>::max();
+  if (aRect.width > maxSize || aRect.height > maxSize ||
+      std::abs(aRect.x) > maxPos || std::abs(aRect.y) > maxPos) {
+    // The rectangle is huge, perhaps due to a very strong perspective or some other
+    // transform. We won't be able to blur something this big so give up now before
+    // overflowing or running into texture size limits later.
+    return;
+  }
+
   IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
   bool mirrorCorners = !aCornerRadii || aCornerRadii->AreRadiiSame();
 
   IntRect rect = RoundedToInt(ToRect(aRect));
   IntMargin blurMargin;
   IntMargin slice;
   IntSize minSize;
   RefPtr<SourceSurface> boxShadow = GetBlur(aDestinationCtx,
--- a/image/ImageCacheKey.cpp
+++ b/image/ImageCacheKey.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ImageCacheKey.h"
 
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Move.h"
+#include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsString.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ServiceWorkerManager.h"
 #include "nsIDocument.h"
 #include "nsPrintfCString.h"
 
@@ -37,17 +38,17 @@ BlobSerial(nsIURI* aURI)
 }
 
 ImageCacheKey::ImageCacheKey(nsIURI* aURI,
                              const OriginAttributes& aAttrs,
                              nsIDocument* aDocument,
                              nsresult& aRv)
   : mURI(aURI)
   , mOriginAttributes(aAttrs)
-  , mControlledDocument(GetControlledDocumentToken(aDocument))
+  , mControlledDocument(GetSpecialCaseDocumentToken(aDocument, aURI))
   , mHash(0)
   , mIsChrome(false)
 {
   if (SchemeIs("blob")) {
     mBlobSerial = BlobSerial(mURI);
   } else if (SchemeIs("chrome")) {
     mIsChrome = true;
   }
@@ -120,26 +121,35 @@ ImageCacheKey::operator==(const ImageCac
 bool
 ImageCacheKey::SchemeIs(const char* aScheme)
 {
   bool matches = false;
   return NS_SUCCEEDED(mURI->SchemeIs(aScheme, &matches)) && matches;
 }
 
 /* static */ void*
-ImageCacheKey::GetControlledDocumentToken(nsIDocument* aDocument)
+ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
 {
-  // For non-controlled documents, we just return null.  For controlled
-  // documents, we cast the pointer into a void* to avoid dereferencing
-  // it (since we only use it for comparisons), and return it.
+  // For controlled documents, we cast the pointer into a void* to avoid
+  // dereferencing it (since we only use it for comparisons).
   void* pointer = nullptr;
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (aDocument && swm) {
     ErrorResult rv;
     if (aDocument->GetController().isSome()) {
       pointer = aDocument;
     }
   }
+
+  // If this document has been marked as tracker, let's use its address to make
+  // a unique cache key.
+  if (!pointer && aDocument &&
+      nsContentUtils::StorageDisabledByAntiTracking(nullptr,
+                                                    aDocument->GetChannel(),
+                                                    aURI)) {
+    pointer = aDocument;
+  }
+
   return pointer;
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/ImageCacheKey.h
+++ b/image/ImageCacheKey.h
@@ -36,29 +36,35 @@ public:
                 nsIDocument* aDocument, nsresult& aRv);
 
   ImageCacheKey(const ImageCacheKey& aOther);
   ImageCacheKey(ImageCacheKey&& aOther);
 
   bool operator==(const ImageCacheKey& aOther) const;
   PLDHashNumber Hash() const { return mHash; }
 
-  /// A weak pointer to the URI. For logging only.
+  /// A weak pointer to the URI.
   nsIURI* URI() const { return mURI; }
 
+  const OriginAttributes& OriginAttributesRef() const { return mOriginAttributes; }
+
   /// Is this cache entry for a chrome image?
   bool IsChrome() const { return mIsChrome; }
 
   /// A token indicating which service worker controlled document this entry
   /// belongs to, if any.
   void* ControlledDocument() const { return mControlledDocument; }
 
 private:
   bool SchemeIs(const char* aScheme);
-  static void* GetControlledDocumentToken(nsIDocument* aDocument);
+
+  // For ServiceWorker and for anti-tracking we need to use the document as
+  // token for the key. All those exceptions are handled by this method.
+  static void* GetSpecialCaseDocumentToken(nsIDocument* aDocument,
+                                           nsIURI* aURI);
 
   nsCOMPtr<nsIURI> mURI;
   Maybe<uint64_t> mBlobSerial;
   nsCString mBlobRef;
   OriginAttributes mOriginAttributes;
   void* mControlledDocument;
   PLDHashNumber mHash;
   bool mIsChrome;
--- a/image/imgICache.idl
+++ b/image/imgICache.idl
@@ -3,21 +3,30 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface imgIRequest;
 interface nsIDocument;
+interface nsIPrincipal;
 interface nsIProperties;
 interface nsIURI;
 
 webidl Document;
 
+%{ C++
+namespace mozilla {
+class OriginAttributes;
+} // mozilla namespace
+%}
+
+[ptr] native OriginAttributesPtr(mozilla::OriginAttributes);
+
 /**
  * imgICache interface
  *
  * @author Stuart Parmenter <pavlov@netscape.com>
  * @version 0.1
  * @see imagelib2
  */
 [scriptable, builtinclass, uuid(bfdf23ff-378e-402e-8a6c-840f0c82b6c3)]
@@ -37,16 +46,24 @@ interface imgICache : nsISupports
    * @param uri The URI to remove.
    * @param doc The document to remove the cache entry for.
    * @throws NS_ERROR_NOT_AVAILABLE if \a uri was unable to be removed from
    * the cache.
    */
   [noscript] void removeEntry(in nsIURI uri, [optional] in Document doc);
 
   /**
+   * Evict images from the cache with the same origin and the same
+   * originAttributes of the passed principal.
+   *
+   * @param aPrincipal The principal
+   */
+  void removeEntriesFromPrincipal(in nsIPrincipal aPrincipal);
+
+  /**
    * Find Properties
    * Used to get properties such as 'type' and 'content-disposition'
    * 'type' is a nsISupportsCString containing the images' mime type such as
    * 'image/png'
    * 'content-disposition' will be a nsISupportsCString containing the header
    * If you call this before any data has been loaded from a URI, it will
    * succeed, but come back empty.
    *
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -1465,16 +1465,55 @@ imgLoader::ClearCache(bool chrome)
   if (chrome) {
     return ClearChromeImageCache();
   }
   return ClearImageCache();
 
 }
 
 NS_IMETHODIMP
+imgLoader::RemoveEntriesFromPrincipal(nsIPrincipal* aPrincipal)
+{
+  nsAutoString origin;
+  nsresult rv = nsContentUtils::GetUTFOrigin(aPrincipal, origin);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  AutoTArray<RefPtr<imgCacheEntry>, 128> entriesToBeRemoved;
+
+  imgCacheTable& cache = GetCache(nsContentUtils::IsSystemPrincipal(aPrincipal));
+  for (auto iter = cache.Iter(); !iter.Done(); iter.Next()) {
+    auto& key = iter.Key();
+
+    if (key.OriginAttributesRef() != BasePrincipal::Cast(aPrincipal)->OriginAttributesRef()) {
+       continue;
+    }
+
+    nsAutoString imageOrigin;
+    nsresult rv = nsContentUtils::GetUTFOrigin(key.URI(), imageOrigin);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      continue;
+    }
+
+    if (imageOrigin == origin) {
+      entriesToBeRemoved.AppendElement(iter.Data());
+    }
+  }
+
+  for (auto& entry : entriesToBeRemoved) {
+    if (!RemoveFromCache(entry)) {
+      NS_WARNING("Couldn't remove an entry from the cache in RemoveEntriesFromPrincipal()\n");
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 imgLoader::RemoveEntry(nsIURI* aURI,
                        nsIDocument* aDoc)
 {
   if (aURI) {
     OriginAttributes attrs;
     if (aDoc) {
       nsCOMPtr<nsIPrincipal> principal = aDoc->NodePrincipal();
       if (principal) {
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -257,21 +257,24 @@ EvalKernel(JSContext* cx, HandleValue v,
         esg.lookupInEvalCache(linearStr, callerScript, pc);
 
     if (!esg.foundScript()) {
         RootedScript maybeScript(cx);
         unsigned lineno;
         const char* filename;
         bool mutedErrors;
         uint32_t pcOffset;
-        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
-                                             &mutedErrors,
-                                             evalType == DIRECT_EVAL
-                                             ? CALLED_FROM_JSOP_EVAL
-                                             : NOT_CALLED_FROM_JSOP_EVAL);
+        if (evalType == DIRECT_EVAL) {
+            DescribeScriptedCallerForDirectEval(cx, callerScript, pc, &filename, &lineno,
+                                                &pcOffset, &mutedErrors);
+            maybeScript = callerScript;
+        } else {
+            DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
+                                                 &mutedErrors);
+        }
 
         const char* introducerFilename = filename;
         if (maybeScript && maybeScript->scriptSource()->introducerFilename())
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         RootedScope enclosing(cx);
         if (evalType == DIRECT_EVAL)
             enclosing = callerScript->innermostScope(pc);
@@ -339,39 +342,39 @@ js::DirectEvalStringFromIon(JSContext* c
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
     esg.lookupInEvalCache(linearStr, callerScript, pc);
 
     if (!esg.foundScript()) {
-        RootedScript maybeScript(cx);
         const char* filename;
         unsigned lineno;
         bool mutedErrors;
         uint32_t pcOffset;
-        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
-                                             &mutedErrors, CALLED_FROM_JSOP_EVAL);
+        DescribeScriptedCallerForDirectEval(cx, callerScript, pc, &filename, &lineno, &pcOffset,
+                                            &mutedErrors);
 
         const char* introducerFilename = filename;
-        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
-            introducerFilename = maybeScript->scriptSource()->introducerFilename();
+        if (callerScript->scriptSource()->introducerFilename())
+            introducerFilename = callerScript->scriptSource()->introducerFilename();
 
         RootedScope enclosing(cx, callerScript->innermostScope(pc));
 
         CompileOptions options(cx);
         options.setIsRunOnce(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
                .maybeMakeStrictMode(IsStrictEvalPC(pc));
 
         if (introducerFilename) {
             options.setFileAndLine(filename, 1);
-            options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
+            options.setIntroductionInfo(introducerFilename, "eval", lineno, callerScript,
+                                        pcOffset);
         } else {
             options.setFileAndLine("eval", 1);
             options.setIntroductionType("eval");
         }
 
         AutoStableStringChars linearChars(cx);
         if (!linearChars.initTwoByte(cx, linearStr))
             return false;
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1355,17 +1355,17 @@ CaptureFirstSubsumedFrame(JSContext* cx,
 
     RootedObject obj(cx, &args[0].toObject());
     obj = CheckedUnwrap(obj);
     if (!obj) {
         JS_ReportErrorASCII(cx, "Denied permission to object.");
         return false;
     }
 
-    JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->realm()->principals()));
+    JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->nonCCWRealm()->principals()));
     if (args.length() > 1)
         capture.as<JS::FirstSubsumedFrame>().ignoreSelfHosted = JS::ToBoolean(args[1]);
 
     JS::RootedObject capturedStack(cx);
     if (!JS::CaptureCurrentStack(cx, &capturedStack, std::move(capture)))
         return false;
 
     args.rval().setObjectOrNull(capturedStack);
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -334,23 +334,23 @@ static const uint32_t ReferenceSizes[] =
     sizeof(_type),
     JS_FOR_EACH_REFERENCE_TYPE_REPR(REFERENCE_SIZE) 0
 #undef REFERENCE_SIZE
 };
 
 uint32_t
 ReferenceTypeDescr::size(Type t)
 {
-    return ReferenceSizes[t];
+    return ReferenceSizes[uint32_t(t)];
 }
 
 uint32_t
 ReferenceTypeDescr::alignment(Type t)
 {
-    return ReferenceSizes[t];
+    return ReferenceSizes[uint32_t(t)];
 }
 
 /*static*/ const char*
 ReferenceTypeDescr::typeName(Type type)
 {
     switch (type) {
 #define NUMERIC_TYPE_TO_STRING(constant_, type_, name_) \
         case constant_: return #name_;
@@ -370,30 +370,30 @@ js::ReferenceTypeDescr::call(JSContext* 
 
     if (args.length() < 1) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                                   descr->typeName(), "0", "s");
         return false;
     }
 
     switch (descr->type()) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
         args.rval().set(args[0]);
         return true;
 
-      case ReferenceTypeDescr::TYPE_OBJECT:
+      case ReferenceType::TYPE_OBJECT:
       {
         RootedObject obj(cx, ToObject(cx, args[0]));
         if (!obj)
             return false;
         args.rval().setObject(*obj);
         return true;
       }
 
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
       {
         RootedString obj(cx, ToString<CanGC>(cx, args[0]));
         if (!obj)
             return false;
         args.rval().setString(&*obj);
         return true;
       }
     }
@@ -761,53 +761,74 @@ const JSFunctionSpec StructMetaTypeDescr
 const JSPropertySpec StructMetaTypeDescr::typedObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructMetaTypeDescr::typedObjectMethods[] = {
     JS_FS_END
 };
 
-JSObject*
+CheckedInt32
+StructMetaTypeDescr::Layout::addField(int32_t fieldAlignment, int32_t fieldSize)
+{
+    // Alignment of the struct is the max of the alignment of its fields.
+    structAlignment = js::Max(structAlignment, fieldAlignment);
+
+    // Align the pointer.
+    CheckedInt32 offset = RoundUpToAlignment(sizeSoFar, fieldAlignment);
+    if (!offset.isValid())
+        return offset;
+
+    // Allocate space.
+    sizeSoFar = offset + fieldSize;
+    if (!sizeSoFar.isValid())
+        return sizeSoFar;
+
+    return offset;
+}
+
+CheckedInt32
+StructMetaTypeDescr::Layout::addScalar(Scalar::Type type) {
+    return addField(ScalarTypeDescr::alignment(type),
+                    ScalarTypeDescr::size(type));
+}
+
+CheckedInt32
+StructMetaTypeDescr::Layout::addReference(ReferenceType type) {
+    return addField(ReferenceTypeDescr::alignment(type),
+                    ReferenceTypeDescr::size(type));
+}
+
+CheckedInt32
+StructMetaTypeDescr::Layout::close(int32_t *alignment) {
+    if (alignment)
+        *alignment = structAlignment;
+    return RoundUpToAlignment(sizeSoFar, structAlignment);
+}
+
+/* static */ JSObject*
 StructMetaTypeDescr::create(JSContext* cx,
                             HandleObject metaTypeDescr,
                             HandleObject fields)
 {
     // Obtain names of fields, which are the own properties of `fields`
     AutoIdVector ids(cx);
     if (!GetPropertyKeys(cx, fields, JSITER_OWNONLY | JSITER_SYMBOLS, &ids))
         return nullptr;
 
     // Iterate through each field. Collect values for the various
     // vectors below and also track total size and alignment. Be wary
     // of overflow!
-    StringBuffer stringBuffer(cx);     // Canonical string repr
-    AutoValueVector fieldNames(cx);    // Name of each field.
     AutoValueVector fieldTypeObjs(cx); // Type descriptor of each field.
-    AutoValueVector fieldOffsets(cx);  // Offset of each field field.
-    RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
-    RootedObject userFieldTypes(cx);   // User-exposed {f:descr} object.
-    CheckedInt32 sizeSoFar(0);         // Size of struct thus far.
-    uint32_t alignment = 1;            // Alignment of struct.
     bool opaque = false;               // Opacity of struct.
 
-    userFieldOffsets = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
-    if (!userFieldOffsets)
-        return nullptr;
-
-    userFieldTypes = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
-    if (!userFieldTypes)
-        return nullptr;
-
-    if (!stringBuffer.append("new StructType({"))
-        return nullptr;
-
     RootedValue fieldTypeVal(cx);
     RootedId id(cx);
     Rooted<TypeDescr*> fieldType(cx);
+
     for (unsigned int i = 0; i < ids.length(); i++) {
         id = ids[i];
 
         // Check that all the property names are non-numeric strings.
         uint32_t unused;
         if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&unused)) {
             RootedValue idValue(cx, IdToValue(id));
             ReportCannotConvertTo(cx, idValue, "StructType field name");
@@ -819,22 +840,69 @@ StructMetaTypeDescr::create(JSContext* c
         if (!GetProperty(cx, fields, fields, id, &fieldTypeVal))
             return nullptr;
         fieldType = ToObjectIf<TypeDescr>(fieldTypeVal);
         if (!fieldType) {
             ReportCannotConvertTo(cx, fieldTypeVal, "StructType field specifier");
             return nullptr;
         }
 
-        // Collect field name and type object
+        // Collect field type object
+        if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
+            return nullptr;
+
+        // Struct is opaque if any field is opaque
+        if (fieldType->opaque())
+            opaque = true;
+    }
+
+    RootedObject structTypePrototype(cx, GetPrototype(cx, metaTypeDescr));
+    if (!structTypePrototype)
+        return nullptr;
+
+    return createFromArrays(cx, structTypePrototype, opaque, ids, fieldTypeObjs);
+}
+
+/* static */ StructTypeDescr*
+StructMetaTypeDescr::createFromArrays(JSContext* cx,
+                                      HandleObject structTypePrototype,
+                                      bool opaque,
+                                      AutoIdVector& ids,
+                                      AutoValueVector& fieldTypeObjs)
+{
+    StringBuffer stringBuffer(cx);     // Canonical string repr
+    AutoValueVector fieldNames(cx);    // Name of each field.
+    AutoValueVector fieldOffsets(cx);  // Offset of each field field.
+    RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
+    RootedObject userFieldTypes(cx);   // User-exposed {f:descr} object.
+    Layout layout;                     // Field offsetter
+
+    userFieldOffsets = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
+    if (!userFieldOffsets)
+        return nullptr;
+
+    userFieldTypes = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
+    if (!userFieldTypes)
+        return nullptr;
+
+    if (!stringBuffer.append("new StructType({"))
+        return nullptr;
+
+    RootedId id(cx);
+    Rooted<TypeDescr*> fieldType(cx);
+
+    for (unsigned int i = 0; i < ids.length(); i++) {
+        id = ids[i];
+
+        // Collect field name
         RootedValue fieldName(cx, IdToValue(id));
         if (!fieldNames.append(fieldName))
             return nullptr;
-        if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
-            return nullptr;
+
+        fieldType = ToObjectIf<TypeDescr>(fieldTypeObjs[i]);
 
         // userFieldTypes[id] = typeObj
         if (!DefineDataProperty(cx, userFieldTypes, id, fieldTypeObjs[i],
                                 JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return nullptr;
         }
 
@@ -843,69 +911,50 @@ StructMetaTypeDescr::create(JSContext* c
             return nullptr;
         if (!stringBuffer.append(JSID_TO_ATOM(id)))
             return nullptr;
         if (!stringBuffer.append(": "))
             return nullptr;
         if (!stringBuffer.append(&fieldType->stringRepr()))
             return nullptr;
 
-        // Offset of this field is the current total size adjusted for
-        // the field's alignment.
-        CheckedInt32 offset = RoundUpToAlignment(sizeSoFar, fieldType->alignment());
+        CheckedInt32 offset = layout.addField(fieldType->alignment(), fieldType->size());
         if (!offset.isValid()) {
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
             return nullptr;
         }
         MOZ_ASSERT(offset.value() >= 0);
         if (!fieldOffsets.append(Int32Value(offset.value())))
             return nullptr;
 
         // userFieldOffsets[id] = offset
         RootedValue offsetValue(cx, Int32Value(offset.value()));
         if (!DefineDataProperty(cx, userFieldOffsets, id, offsetValue,
                                 JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return nullptr;
         }
-
-        // Add space for this field to the total struct size.
-        sizeSoFar = offset + fieldType->size();
-        if (!sizeSoFar.isValid()) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
-            return nullptr;
-        }
-
-        // Struct is opaque if any field is opaque
-        if (fieldType->opaque())
-            opaque = true;
-
-        // Alignment of the struct is the max of the alignment of its fields.
-        alignment = js::Max(alignment, fieldType->alignment());
     }
 
     // Complete string representation.
     if (!stringBuffer.append("})"))
         return nullptr;
 
     RootedAtom stringRepr(cx, stringBuffer.finishAtom());
     if (!stringRepr)
         return nullptr;
 
-    // Adjust the total size to be a multiple of the final alignment.
-    CheckedInt32 totalSize = RoundUpToAlignment(sizeSoFar, alignment);
+    int32_t alignment;
+    CheckedInt32 totalSize = layout.close(&alignment);
     if (!totalSize.isValid()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
         return nullptr;
     }
 
     // Now create the resulting type descriptor.
-    RootedObject structTypePrototype(cx, GetPrototype(cx, metaTypeDescr));
-    if (!structTypePrototype)
-        return nullptr;
 
     Rooted<StructTypeDescr*> descr(cx);
     descr = NewObjectWithGivenProto<StructTypeDescr>(cx, structTypePrototype, SingletonObject);
     if (!descr)
         return nullptr;
 
     descr->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(type::Struct));
     descr->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr));
@@ -1122,17 +1171,17 @@ DefineSimpleTypeDescr(JSContext* cx,
     if (!descr)
         return false;
 
     descr->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(T::Kind));
     descr->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(className));
     descr->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(T::alignment(type)));
     descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(AssertedCast<int32_t>(T::size(type))));
     descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(T::Opaque));
-    descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(type));
+    descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(int32_t(type)));
 
     if (!CreateUserSizeAndAlignmentProperties(cx, descr))
         return false;
 
     if (!JS_DefineFunctions(cx, descr, T::typeObjectMethods))
         return false;
 
     // Create the typed prototype for the scalar type. This winds up
@@ -2735,32 +2784,32 @@ class MemoryInitVisitor {
 };
 
 } // namespace
 
 void
 MemoryInitVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
 {
     switch (descr.type()) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
       {
         js::GCPtrValue* heapValue = reinterpret_cast<js::GCPtrValue*>(mem);
         heapValue->init(UndefinedValue());
         return;
       }
 
-      case ReferenceTypeDescr::TYPE_OBJECT:
+      case ReferenceType::TYPE_OBJECT:
       {
         js::GCPtrObject* objectPtr =
             reinterpret_cast<js::GCPtrObject*>(mem);
         objectPtr->init(nullptr);
         return;
       }
 
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
       {
         js::GCPtrString* stringPtr =
             reinterpret_cast<js::GCPtrString*>(mem);
         stringPtr->init(rt_->emptyString);
         return;
       }
     }
 
@@ -2805,31 +2854,31 @@ class MemoryTracingVisitor {
 };
 
 } // namespace
 
 void
 MemoryTracingVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
 {
     switch (descr.type()) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
       {
         GCPtrValue* heapValue = reinterpret_cast<js::GCPtrValue*>(mem);
         TraceEdge(trace_, heapValue, "reference-val");
         return;
       }
 
-      case ReferenceTypeDescr::TYPE_OBJECT:
+      case ReferenceType::TYPE_OBJECT:
       {
         GCPtrObject* objectPtr = reinterpret_cast<js::GCPtrObject*>(mem);
         TraceNullableEdge(trace_, objectPtr, "reference-obj");
         return;
       }
 
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
       {
         GCPtrString* stringPtr = reinterpret_cast<js::GCPtrString*>(mem);
         TraceNullableEdge(trace_, stringPtr, "reference-str");
         return;
       }
     }
 
     MOZ_CRASH("Invalid kind");
@@ -2859,19 +2908,19 @@ struct TraceListVisitor {
 
 } // namespace
 
 void
 TraceListVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
 {
     VectorType* offsets;
     switch (descr.type()) {
-      case ReferenceTypeDescr::TYPE_ANY: offsets = &valueOffsets; break;
-      case ReferenceTypeDescr::TYPE_OBJECT: offsets = &objectOffsets; break;
-      case ReferenceTypeDescr::TYPE_STRING: offsets = &stringOffsets; break;
+      case ReferenceType::TYPE_ANY: offsets = &valueOffsets; break;
+      case ReferenceType::TYPE_OBJECT: offsets = &objectOffsets; break;
+      case ReferenceType::TYPE_STRING: offsets = &stringOffsets; break;
       default: MOZ_CRASH("Invalid kind");
     }
 
     AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!offsets->append((uintptr_t) mem))
         oomUnsafe.crash("TraceListVisitor::visitReference");
 }
 
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.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_TypedObject_h
 #define builtin_TypedObject_h
 
+#include "mozilla/CheckedInt.h"
+
 #include "builtin/TypedObjectConstants.h"
 #include "gc/WeakMap.h"
 #include "js/Conversions.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/JSObject.h"
 #include "vm/ShapedObject.h"
 
 /*
@@ -281,53 +283,55 @@ class ScalarTypeDescr : public SimpleTyp
     macro_(Scalar::Float32, float,    float32)                  \
     macro_(Scalar::Float64, double,   float64)
 
 // Must be in same order as the enum ScalarTypeDescr::Type:
 #define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_)                    \
     JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)           \
     macro_(Scalar::Uint8Clamped, uint8_t, uint8Clamped)
 
+enum class ReferenceType {
+    TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
+    TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
+    TYPE_STRING = JS_REFERENCETYPEREPR_STRING
+};
+
 // Type for reference type constructors like `Any`, `String`, and
 // `Object`. All such type constructors share a common js::Class and
 // JSFunctionSpec. All these types are opaque.
 class ReferenceTypeDescr : public SimpleTypeDescr
 {
   public:
     // Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
-    enum Type {
-        TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
-        TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
-        TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
-    };
-    static const int32_t TYPE_MAX = TYPE_STRING + 1;
+    typedef ReferenceType Type;
     static const char* typeName(Type type);
 
+    static const int32_t TYPE_MAX = int32_t(ReferenceType::TYPE_STRING) + 1;
     static const type::Kind Kind = type::Reference;
     static const bool Opaque = true;
     static const Class class_;
     static uint32_t size(Type t);
     static uint32_t alignment(Type t);
     static const JSFunctionSpec typeObjectMethods[];
 
-    ReferenceTypeDescr::Type type() const {
-        return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
+    ReferenceType type() const {
+        return (ReferenceType) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
     }
 
     const char* typeName() const {
         return typeName(type());
     }
 
     static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
 };
 
 #define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
-    macro_(ReferenceTypeDescr::TYPE_ANY, GCPtrValue, Any) \
-    macro_(ReferenceTypeDescr::TYPE_OBJECT, GCPtrObject, Object) \
-    macro_(ReferenceTypeDescr::TYPE_STRING, GCPtrString, string)
+    macro_(ReferenceType::TYPE_ANY, GCPtrValue, Any) \
+    macro_(ReferenceType::TYPE_OBJECT, GCPtrObject, Object) \
+    macro_(ReferenceType::TYPE_STRING, GCPtrString, string)
 
 // Type descriptors whose instances are objects and hence which have
 // an associated `prototype` property.
 class ComplexTypeDescr : public TypeDescr
 {
   public:
     // Returns the prototype that instances of this type descriptor
     // will have.
@@ -430,29 +434,59 @@ class ArrayTypeDescr : public ComplexTyp
  */
 class StructMetaTypeDescr : public NativeObject
 {
   private:
     static JSObject* create(JSContext* cx, HandleObject structTypeGlobal,
                             HandleObject fields);
 
   public:
+    // The prototype cannot be null.
+    // The names in `ids` must all be non-numeric.
+    // The type objects in `fieldTypeObjs` must all be TypeDescr objects.
+    static StructTypeDescr* createFromArrays(JSContext* cx,
+                                             HandleObject structTypePrototype,
+                                             bool opaque,
+                                             AutoIdVector& ids,
+                                             AutoValueVector& fieldTypeObjs);
+
     // Properties and methods to be installed on StructType.prototype,
     // and hence inherited by all struct type objects:
     static const JSPropertySpec typeObjectProperties[];
     static const JSFunctionSpec typeObjectMethods[];
 
     // Properties and methods to be installed on StructType.prototype.prototype,
     // and hence inherited by all struct *typed* objects:
     static const JSPropertySpec typedObjectProperties[];
     static const JSFunctionSpec typedObjectMethods[];
 
     // This is the function that gets called when the user
     // does `new StructType(...)`. It produces a struct type object.
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
+
+    class Layout
+    {
+        // Can call addField() directly.
+        friend class StructMetaTypeDescr;
+
+        mozilla::CheckedInt32 sizeSoFar = 0;
+        int32_t structAlignment = 1;
+
+        mozilla::CheckedInt32 addField(int32_t fieldAlignment, int32_t fieldSize);
+
+      public:
+        // The field adders return the offset of the the field.
+        mozilla::CheckedInt32 addScalar(Scalar::Type type);
+        mozilla::CheckedInt32 addReference(ReferenceType type);
+
+        // The close method rounds up the structure size to the appropriate
+        // alignment and returns that size.  If `alignment` is not NULL then
+        // return the structure alignment through that pointer.
+        mozilla::CheckedInt32 close(int32_t* alignment = nullptr);
+    };
 };
 
 class StructTypeDescr : public ComplexTypeDescr
 {
   public:
     static const Class class_;
 
     // Returns the number of fields defined in this struct.
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -3,35 +3,41 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ds/LifoAlloc.h"
 
 #include "mozilla/MathAlgorithms.h"
 
+#include "ds/MemoryProtectionExceptionHandler.h"
+
+#ifdef LIFO_CHUNK_PROTECT
+# include "gc/Memory.h"
+#endif
+
 using namespace js;
 
 using mozilla::RoundUpPow2;
 using mozilla::tl::BitSize;
 
 namespace js {
 namespace detail {
 
 /* static */
 UniquePtr<BumpChunk>
-BumpChunk::newWithCapacity(size_t size)
+BumpChunk::newWithCapacity(size_t size, bool protect)
 {
     MOZ_ASSERT(RoundUpPow2(size) == size);
     MOZ_ASSERT(size >= sizeof(BumpChunk));
     void* mem = js_malloc(size);
     if (!mem)
         return nullptr;
 
-    UniquePtr<BumpChunk> result(new (mem) BumpChunk(size));
+    UniquePtr<BumpChunk> result(new (mem) BumpChunk(size, protect));
 
     // We assume that the alignment of LIFO_ALLOC_ALIGN is less than that of the
     // underlying memory allocator -- creating a new BumpChunk should always
     // satisfy the LIFO_ALLOC_ALIGN alignment constraint.
     MOZ_ASSERT(AlignPtr(result->begin()) == result->begin());
     return result;
 }
 
@@ -39,27 +45,119 @@ bool
 BumpChunk::canAlloc(size_t n)
 {
     uint8_t* aligned = AlignPtr(bump_);
     uint8_t* newBump = aligned + n;
     // bump_ <= newBump, is necessary to catch overflow.
     return bump_ <= newBump && newBump <= capacity_;
 }
 
+#ifdef LIFO_CHUNK_PROTECT
+
+static const uint8_t*
+AlignPtrUp(const uint8_t* ptr, uintptr_t align) {
+    MOZ_ASSERT(mozilla::IsPowerOfTwo(align));
+    uintptr_t uptr = uintptr_t(ptr);
+    uintptr_t diff = uptr & (align - 1);
+    diff = (align - diff) & (align - 1);
+    uptr = uptr + diff;
+    return (uint8_t*) uptr;
+}
+
+static const uint8_t*
+AlignPtrDown(const uint8_t* ptr, uintptr_t align) {
+    MOZ_ASSERT(mozilla::IsPowerOfTwo(align));
+    uintptr_t uptr = uintptr_t(ptr);
+    uptr = uptr & ~(align - 1);
+    return (uint8_t*) uptr;
+}
+
+void
+BumpChunk::setRWUntil(Loc loc) const
+{
+    if (!protect_)
+        return;
+
+    uintptr_t pageSize = gc::SystemPageSize();
+    // The allocated chunks might not be aligned on page boundaries. This code
+    // is used to ensure that we are changing the memory protection of pointers
+    // which are within the range of the BumpChunk, or that the range formed by
+    // [b .. e] is empty.
+    const uint8_t* b = base();
+    const uint8_t* e = capacity_;
+    b = AlignPtrUp(b, pageSize);
+    e = AlignPtrDown(e, pageSize);
+    if (e < b)
+        e = b;
+    // The mid-point is aligned to the next page, and clamp to the end-point to
+    // ensure that it remains in the [b .. e] range.
+    const uint8_t* m = nullptr;
+    switch (loc) {
+      case Loc::Header:
+        m = b;
+        break;
+      case Loc::Allocated:
+        m = begin();
+        break;
+      case Loc::Reserved:
+        m = end();
+        break;
+      case Loc::End:
+        m = e;
+        break;
+    }
+    m = AlignPtrUp(m, pageSize);
+    if (e < m)
+        m = e;
+
+    if (b < m)
+        gc::UnprotectPages(const_cast<uint8_t*>(b), m - b);
+    // Note: We could use no-access protection for everything after begin(), but
+    // we need to read capabilities for reading the bump_ / capacity_ fields
+    // from this function to unprotect the memory later.
+    if (m < e)
+        gc::MakePagesReadOnly(const_cast<uint8_t*>(m), e - m);
+}
+
+// The memory protection handler is catching memory accesses error on the
+// regions registered into it. These method, instead of registering sub-ranges
+// of the BumpChunk within setRWUntil, we just register the full BumpChunk
+// ranges, and let the MemoryProtectionExceptionHandler catch bad memory
+// accesses when it is being protected by setRWUntil.
+void
+BumpChunk::addMProtectHandler() const
+{
+    if (!protect_)
+        return;
+    js::MemoryProtectionExceptionHandler::addRegion(const_cast<uint8_t*>(base()), capacity_ - base());
+}
+
+void
+BumpChunk::removeMProtectHandler() const
+{
+    if (!protect_)
+        return;
+    js::MemoryProtectionExceptionHandler::removeRegion(const_cast<uint8_t*>(base()));
+}
+
+#endif
+
 } // namespace detail
 } // namespace js
 
 void
 LifoAlloc::freeAll()
 {
     while (!chunks_.empty()) {
+        chunks_.begin()->setRWUntil(Loc::End);
         BumpChunk bc = chunks_.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
     }
     while (!unused_.empty()) {
+        unused_.begin()->setRWUntil(Loc::End);
         BumpChunk bc = unused_.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
     }
 
     // Nb: maintaining curSize_ correctly isn't easy.  Fortunately, this is an
     // excellent sanity check.
     MOZ_ASSERT(curSize_ == 0);
 }
@@ -85,53 +183,64 @@ LifoAlloc::newChunkWithCapacity(size_t n
         }
 
         chunkSize = RoundUpPow2(allocSizeWithCanaries);
     } else {
         chunkSize = defaultChunkSize_;
     }
 
     // Create a new BumpChunk, and allocate space for it.
-    BumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
+    BumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize, protect_);
     if (!result)
         return nullptr;
     MOZ_ASSERT(result->computedSizeOfIncludingThis() == chunkSize);
     return result;
 }
 
 bool
 LifoAlloc::getOrCreateChunk(size_t n)
 {
+    // This function is adding a new BumpChunk in which all upcoming allocation
+    // would be made. Thus, we protect against out-of-bounds the last chunk in
+    // which we did our previous allocations.
+    if (!chunks_.empty())
+        chunks_.last()->setRWUntil(Loc::Reserved);
+
     // Look for existing unused BumpChunks to satisfy the request, and pick the
     // first one which is large enough, and move it into the list of used
     // chunks.
     if (!unused_.empty()) {
         if (unused_.begin()->canAlloc(n)) {
             chunks_.append(unused_.popFirst());
+            chunks_.last()->setRWUntil(Loc::End);
             return true;
         }
 
         BumpChunkList::Iterator e(unused_.end());
         for (BumpChunkList::Iterator i(unused_.begin()); i->next() != e.get(); ++i) {
             detail::BumpChunk* elem = i->next();
             MOZ_ASSERT(elem->empty());
             if (elem->canAlloc(n)) {
                 BumpChunkList temp = unused_.splitAfter(i.get());
                 chunks_.append(temp.popFirst());
                 unused_.appendAll(std::move(temp));
+                chunks_.last()->setRWUntil(Loc::End);
                 return true;
             }
         }
     }
 
     // Allocate a new BumpChunk with enough space for the next allocation.
     BumpChunk newChunk = newChunkWithCapacity(n);
     if (!newChunk)
         return false;
     size_t size = newChunk->computedSizeOfIncludingThis();
+    // The last chunk in which allocations are performed should be protected
+    // with setRWUntil(Loc::End), but this is not necessary here because any new
+    // allocation should be protected as RW already.
     chunks_.append(std::move(newChunk));
     incrementCurSize(size);
     return true;
 }
 
 void
 LifoAlloc::transferFrom(LifoAlloc* other)
 {
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -211,24 +211,31 @@ AlignPtr(uint8_t* orig) {
 // and the deallocation.
 //
 // This structure is only move-able, but not copyable.
 class BumpChunk : public SingleLinkedListElement<BumpChunk>
 {
   private:
     // Pointer to the last byte allocated in this chunk.
     uint8_t* bump_;
-    // Pointer to the last byte available in this chunk.
-    const uint8_t* capacity_;
+    // Pointer to the first byte after this chunk.
+    uint8_t* const capacity_;
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     // Magic number used to check against poisoned values.
-    const uintptr_t magic_;
-    static constexpr uintptr_t magicNumber =
-        sizeof(uintptr_t) == 4 ? uintptr_t(0x4c69666f) : uintptr_t(0x4c69666f42756d70);
+    const uintptr_t magic_ : 24;
+    static constexpr uintptr_t magicNumber = uintptr_t(0x4c6966);
+#endif
+
+#if defined(DEBUG) || defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
+# define LIFO_CHUNK_PROTECT 1
+    // Constant used to know if the current chunk should be protected. This is
+    // mainly use to prevent dead-lock in the MemoryProtectionExceptionHandler
+    // methods.
+    const uintptr_t protect_ : 1;
 #endif
 
     // Poison the memory with memset, in order to catch errors due to
     // use-after-free, with undefinedChunkMemory pattern, or to catch
     // use-before-init with uninitializedChunkMemory.
 #if defined(DEBUG)
 # define LIFO_HAVE_MEM_CHECKS 1
 
@@ -264,22 +271,25 @@ class BumpChunk : public SingleLinkedLis
         MOZ_DIAGNOSTIC_ASSERT(magic_ == magicNumber);
         MOZ_ASSERT(begin() <= end());
         MOZ_ASSERT(end() <= capacity_);
     }
 
     BumpChunk& operator=(const BumpChunk&) = delete;
     BumpChunk(const BumpChunk&) = delete;
 
-    explicit BumpChunk(uintptr_t capacity)
+    explicit BumpChunk(uintptr_t capacity, bool protect)
       : bump_(begin()),
         capacity_(base() + capacity)
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
       , magic_(magicNumber)
 #endif
+#ifdef LIFO_CHUNK_PROTECT
+      , protect_(protect ? 1 : 0)
+#endif
     {
         // We cannot bake this value inside the BumpChunk class, because
         // sizeof(BumpChunk) can only be computed after the closing brace of the
         // BumpChunk class, or within one of its methods. As a work-around, the
         // reservedSpace value is baked in, and we check that it indeed matches
         // with the space taken by the data of the BumpChunk class, and the
         // alignment of a pointer.
         MOZ_ASSERT(BumpChunk::reservedSpace == AlignBytes(sizeof(BumpChunk), LIFO_ALLOC_ALIGN),
@@ -287,16 +297,17 @@ class BumpChunk : public SingleLinkedLis
 
         assertInvariants();
 #if defined(LIFO_HAVE_MEM_CHECKS)
         // The memory is freshly allocated and marked as undefined by the
         // allocator of the BumpChunk. Instead, we mark this memory as
         // no-access, as it has not been allocated within the BumpChunk.
         LIFO_MAKE_MEM_NOACCESS(bump_, capacity_ - bump_);
 #endif
+        addMProtectHandler();
     }
 
     // Cast |this| into a uint8_t* pointer.
     //
     // Warning: Are you sure you do not want to use begin() instead?
     const uint8_t* base() const { return reinterpret_cast<const uint8_t*>(this); }
     uint8_t* base() { return reinterpret_cast<uint8_t*>(this); }
 
@@ -321,16 +332,17 @@ class BumpChunk : public SingleLinkedLis
             LIFO_MAKE_MEM_UNDEFINED(bump_, newBump - bump_);
 #endif
         bump_ = newBump;
     }
 
   public:
     ~BumpChunk() {
         release();
+        removeMProtectHandler();
     }
 
     // Space reserved for the BumpChunk internal data, and the alignment of the
     // first allocation content.  This can be used to ensure there is enough
     // space for the next allocation. (see LifoAlloc::newChunkWithCapacity)
     static constexpr size_t reservedSpace = 4 * sizeof(uintptr_t);
 
     // Returns true if this chunk contains no allocated content.
@@ -345,17 +357,20 @@ class BumpChunk : public SingleLinkedLis
     // LifoAlloc::Enum)
     const uint8_t* begin() const { return base() + reservedSpace; }
     uint8_t* begin() { return base() + reservedSpace; }
     uint8_t* end() const { return bump_; }
 
     // This function is the only way to allocate and construct a chunk. It
     // returns a UniquePtr to the newly allocated chunk.  The size given as
     // argument includes the space needed for the header of the chunk.
-    static UniquePtr<BumpChunk> newWithCapacity(size_t size);
+    //
+    // The protect boolean is used to indicate whether the Bumpchunk memory
+    // should be reported within the MemoryProtectionExceptionHandler.
+    static UniquePtr<BumpChunk> newWithCapacity(size_t size, bool protect);
 
     // Report allocation.
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return mallocSizeOf(this);
     }
 
     // Report allocation size.
     size_t computedSizeOfIncludingThis() const {
@@ -438,26 +453,65 @@ class BumpChunk : public SingleLinkedLis
         // Check for overflow.
         if (MOZ_UNLIKELY(newBump < bump_))
             return nullptr;
 
         MOZ_ASSERT(canAlloc(n)); // Ensure consistency between "can" and "try".
         setBump(newBump);
         return aligned;
     }
+
+    // These locations are approximated locations, with the base rounded up to
+    // the nearest page boundary.
+    enum class Loc {
+        // Refers to the inherited linked list, this includes any allocated any
+        // reserved bytes, from base() to capacity_.
+        //
+        // This is used when freezing a LifoAlloc, such as moving a LifoAlloc to
+        // another thread.
+        Header    = 0,
+        // Refers to the set of allocated and reserved bytes, from
+        // PageRoundup(begin()), to capacity_.
+        //
+        // This is used when a BumpChunk is moved to the list of unused chunks,
+        // as we want the header to remain mutable.
+        Allocated = 1,
+        // Refers to the set of reserved bytes, from PageRoundup(end()) to
+        // capacity_.
+        //
+        // This is used when a BumpChunk is no longer used for allocation, while
+        // containing live data. This should catch out-of-bound accesses within
+        // the LifoAlloc content.
+        Reserved  = 2,
+        // Refers to the end of the BumpChunk.
+        //
+        // This is used when a BumpChunk is used for doing allocation, as
+        // re-protecting at each setBump would be too costly.
+        End = 3
+    };
+#ifdef LIFO_CHUNK_PROTECT
+    void setRWUntil(Loc loc) const;
+    void addMProtectHandler() const;
+    void removeMProtectHandler() const;
+#else
+    void setRWUntil(Loc loc) const {}
+    void addMProtectHandler() const {}
+    void removeMProtectHandler() const {}
+#endif
 };
 
 } // namespace detail
 
 // LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
 //
 // Note: We leave BumpChunks latent in the set of unused chunks after they've
 // been released to avoid thrashing before a GC.
 class LifoAlloc
 {
+    using Loc = detail::BumpChunk::Loc;
     using BumpChunk = js::UniquePtr<detail::BumpChunk>;
     using BumpChunkList = detail::SingleLinkedList<detail::BumpChunk>;
 
     // List of chunks containing allocated data. In the common case, the last
     // chunk of this list is always used to perform the allocations. When the
     // allocation cannot be performed, we move a Chunk from the unused set to
     // the list of used chunks.
     BumpChunkList chunks_;
@@ -467,33 +521,40 @@ class LifoAlloc
 
     size_t      markCount;
     size_t      defaultChunkSize_;
     size_t      curSize_;
     size_t      peakSize_;
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     bool        fallibleScope_;
 #endif
+#ifdef LIFO_CHUNK_PROTECT
+    const bool  protect_;
+#endif
 
     void operator=(const LifoAlloc&) = delete;
     LifoAlloc(const LifoAlloc&) = delete;
 
     // Return a BumpChunk that can perform an allocation of at least size |n|.
     BumpChunk newChunkWithCapacity(size_t n);
 
     // Reuse or allocate a BumpChunk that can perform an allocation of at least
     // size |n|, if successful it is placed at the end the list of |chunks_|.
     MOZ_MUST_USE bool getOrCreateChunk(size_t n);
 
     void reset(size_t defaultChunkSize) {
         MOZ_ASSERT(mozilla::RoundUpPow2(defaultChunkSize) == defaultChunkSize);
-        while (!chunks_.empty())
+        while (!chunks_.empty()) {
+            chunks_.begin()->setRWUntil(Loc::End);
             chunks_.popFirst();
-        while (!unused_.empty())
+        }
+        while (!unused_.empty()) {
+            unused_.begin()->setRWUntil(Loc::End);
             unused_.popFirst();
+        }
         defaultChunkSize_ = defaultChunkSize;
         markCount = 0;
         curSize_ = 0;
     }
 
     // Append unused chunks to the end of this LifoAlloc.
     void appendUnused(BumpChunkList&& otherUnused) {
 #ifdef DEBUG
@@ -531,21 +592,24 @@ class LifoAlloc
 
         // Since we just created a large enough chunk, this can't fail.
         result = chunks_.last()->tryAlloc(n);
         MOZ_ASSERT(result);
         return result;
     }
 
   public:
-    explicit LifoAlloc(size_t defaultChunkSize)
+    explicit LifoAlloc(size_t defaultChunkSize, bool protect = true)
       : peakSize_(0)
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
       , fallibleScope_(true)
 #endif
+#ifdef LIFO_CHUNK_PROTECT
+      , protect_(protect)
+#endif
     {
         reset(defaultChunkSize);
     }
 
     // Steal allocated chunks from |other|.
     void steal(LifoAlloc* other) {
         MOZ_ASSERT(!other->markCount);
         MOZ_ASSERT(chunks_.empty());
@@ -636,16 +700,17 @@ class LifoAlloc
             if (total >= n)
                 return true;
         }
 
         BumpChunk newChunk = newChunkWithCapacity(n);
         if (!newChunk)
             return false;
         size_t size = newChunk->computedSizeOfIncludingThis();
+        newChunk->setRWUntil(Loc::Allocated);
         unused_.pushFront(std::move(newChunk));
         incrementCurSize(size);
         return true;
     }
 
     MOZ_ALWAYS_INLINE
     void setAsInfallibleByDefault() {
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
@@ -709,32 +774,59 @@ class LifoAlloc
         // Move the blocks which are after the mark to the set of unused chunks.
         BumpChunkList released;
         if (!mark.markedChunk())
             released = std::move(chunks_);
         else
             released = chunks_.splitAfter(mark.markedChunk());
 
         // Release the content of all the blocks which are after the marks.
-        for (detail::BumpChunk& bc : released)
+        for (detail::BumpChunk& bc : released) {
             bc.release();
+            bc.setRWUntil(Loc::Allocated);
+        }
         unused_.appendAll(std::move(released));
 
         // Release everything which follows the mark in the last chunk.
-        if (!chunks_.empty())
+        if (!chunks_.empty()) {
+            chunks_.last()->setRWUntil(Loc::End);
             chunks_.last()->release(mark);
+        }
     }
 
     void releaseAll() {
         MOZ_ASSERT(!markCount);
-        for (detail::BumpChunk& bc : chunks_)
+        for (detail::BumpChunk& bc : chunks_) {
             bc.release();
+            bc.setRWUntil(Loc::Allocated);
+        }
         unused_.appendAll(std::move(chunks_));
     }
 
+    // Protect the content of the LifoAlloc chunks.
+    void setReadOnly() {
+#ifdef LIFO_CHUNK_PROTECT
+        for (detail::BumpChunk& bc : chunks_)
+            bc.setRWUntil(Loc::Header);
+        for (detail::BumpChunk& bc : unused_)
+            bc.setRWUntil(Loc::Header);
+#endif
+    }
+    void setReadWrite() {
+#ifdef LIFO_CHUNK_PROTECT
+        BumpChunkList::Iterator e(chunks_.last());
+        for (BumpChunkList::Iterator i(chunks_.begin()); i != e; ++i)
+            i->setRWUntil(Loc::Reserved);
+        if (!chunks_.empty())
+            chunks_.last()->setRWUntil(Loc::End);
+        for (detail::BumpChunk& bc : unused_)
+            bc.setRWUntil(Loc::Allocated);
+#endif
+    }
+
     // Get the total "used" (occupied bytes) count for the arena chunks.
     size_t used() const {
         size_t accum = 0;
         for (const detail::BumpChunk& chunk : chunks_)
             accum += chunk.used();
         return accum;
     }
 
--- a/js/src/ds/MemoryProtectionExceptionHandler.cpp
+++ b/js/src/ds/MemoryProtectionExceptionHandler.cpp
@@ -60,17 +60,19 @@ class ProtectedRegionTree
 
     Mutex lock;
     LifoAlloc alloc;
     SplayTree<Region, Region> tree;
 
   public:
     ProtectedRegionTree()
       : lock(mutexid::ProtectedRegionTree),
-        alloc(4096),
+        // Here "false" is used to not use the memory protection mechanism of
+        // LifoAlloc in order to prevent dead-locks.
+        alloc(4096, false),
         tree(&alloc)
     {
         sProtectedRegionsInit = true;
     }
 
     ~ProtectedRegionTree() {
         // See Bug 1445619: Currently many users of the JS engine are leaking
         // the world, unfortunately LifoAlloc owned by JSRuntimes have
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -426,30 +426,44 @@ Zone::ownedByCurrentHelperThread()
 
 void Zone::releaseAtoms()
 {
     MOZ_ASSERT(hasKeptAtoms());
 
     keepAtomsCount--;
 
     if (!hasKeptAtoms() && purgeAtomsDeferred) {
-        atomCache().clearAndShrink();
         purgeAtomsDeferred = false;
+        purgeAtomCache();
     }
 }
 
 void
 Zone::purgeAtomCacheOrDefer()
 {
     if (hasKeptAtoms()) {
         purgeAtomsDeferred = true;
         return;
     }
 
+    purgeAtomCache();
+}
+
+void
+Zone::purgeAtomCache()
+{
+    MOZ_ASSERT(!hasKeptAtoms());
+    MOZ_ASSERT(!purgeAtomsDeferred);
+
     atomCache().clearAndShrink();
+
+    // Also purge the dtoa caches so that subsequent lookups populate atom
+    // cache too.
+    for (RealmsInZoneIter r(this); !r.done(); r.next())
+        r->dtoaCache.purge();
 }
 
 void
 Zone::traceAtomCache(JSTracer* trc)
 {
     MOZ_ASSERT(hasKeptAtoms());
     for (auto r = atomCache().all(); !r.empty(); r.popFront()) {
         JSAtom* atom = r.front().asPtrUnbarriered();
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -519,16 +519,17 @@ class Zone : public JS::shadow::Zone,
 
   public:
     js::SparseBitmap& markedAtoms() { return markedAtoms_.ref(); }
 
     js::AtomSet& atomCache() { return atomCache_.ref(); }
 
     void traceAtomCache(JSTracer* trc);
     void purgeAtomCacheOrDefer();
+    void purgeAtomCache();
 
     js::ExternalStringCache& externalStringCache() { return externalStringCache_.ref(); };
 
     js::FunctionToStringCache& functionToStringCache() { return functionToStringCache_.ref(); }
 
     // Track heap usage under this Zone.
     js::gc::HeapUsage usage;
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1468792.js
@@ -0,0 +1,18 @@
+// |jit-test| error: ReferenceError
+
+loadFile(`
+  gczeal(2,9);
+  evaluate(\`
+    reportCompare(expect, actual, summary);
+  \`);
+`);
+function loadFile(lfVarx) {
+    try {
+        evaluate(lfVarx);
+    } catch (lfVare) {}
+}
+eval("(function(){({6953421313:0})})")();
+function f() {
+    x[6953421313] = "a";
+}
+f();
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1238,28 +1238,28 @@ BaselineCacheIRCompiler::emitStoreUnboxe
 }
 
 bool
 BaselineCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
 {
     ObjOperandId objId = reader.objOperandId();
     Address offsetAddr = stubAddress(reader.stubOffset());
     TypedThingLayout layout = reader.typedThingLayout();
-    ReferenceTypeDescr::Type type = reader.referenceTypeDescrType();
+    ReferenceType type = reader.referenceTypeDescrType();
 
     // Allocate the fixed registers first. These need to be fixed for
     // callTypeUpdateIC.
     AutoScratchRegister scratch1(allocator, masm, R1.scratchReg());
     ValueOperand val = allocator.useFixedValueRegister(masm, reader.valOperandId(), R0);
 
     Register obj = allocator.useRegister(masm, objId);
     AutoScratchRegister scratch2(allocator, masm);
 
     // We don't need a type update IC if the property is always a string.
-    if (type != ReferenceTypeDescr::TYPE_STRING) {
+    if (type != ReferenceType::TYPE_STRING) {
         LiveGeneralRegisterSet saveRegs;
         saveRegs.add(obj);
         saveRegs.add(val);
         if (!callTypeUpdateIC(obj, val, scratch1, saveRegs))
             return false;
     }
 
     // Compute the address being written to.
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2213,17 +2213,17 @@ static const VMFunction MutateProtoInfo 
     FunctionInfo<MutateProtoFn>(MutatePrototype, "MutatePrototype");
 
 bool
 BaselineCompiler::emit_JSOP_MUTATEPROTO()
 {
     // Keep values on the stack for the decompiler.
     frame.syncStack(0);
 
-    masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
+    masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
 
     prepareVMCall();
 
     pushArg(R1);
     pushArg(R0.scratchReg());
 
     if (!callVM(MutateProtoInfo))
@@ -2696,17 +2696,17 @@ BaselineCompiler::emit_JSOP_STRICTDELPRO
 
 void
 BaselineCompiler::getEnvironmentCoordinateObject(Register reg)
 {
     EnvironmentCoordinate ec(pc);
 
     masm.loadPtr(frame.addressOfEnvironmentChain(), reg);
     for (unsigned i = ec.hops(); i; i--)
-        masm.extractObject(Address(reg, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
+        masm.unboxObject(Address(reg, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
 }
 
 Address
 BaselineCompiler::getEnvironmentCoordinateAddressFromObject(Register objReg, Register reg)
 {
     EnvironmentCoordinate ec(pc);
     Shape* shape = EnvironmentCoordinateToEnvironmentShape(script, pc);
 
@@ -2995,18 +2995,18 @@ BaselineCompiler::emitInitPropGetterSett
                JSOp(*pc) == JSOP_INITPROP_SETTER ||
                JSOp(*pc) == JSOP_INITHIDDENPROP_SETTER);
 
     // Keep values on the stack for the decompiler.
     frame.syncStack(0);
 
     prepareVMCall();
 
-    masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
-    masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
+    masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
+    masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
 
     pushArg(R0.scratchReg());
     pushArg(ImmGCPtr(script->getName(pc)));
     pushArg(R1.scratchReg());
     pushArg(ImmPtr(pc));
 
     if (!callVM(InitPropGetterSetterInfo))
         return false;
@@ -3052,23 +3052,23 @@ BaselineCompiler::emitInitElemGetterSett
                JSOp(*pc) == JSOP_INITHIDDENELEM_GETTER ||
                JSOp(*pc) == JSOP_INITELEM_SETTER ||
                JSOp(*pc) == JSOP_INITHIDDENELEM_SETTER);
 
     // Load index and value in R0 and R1, but keep values on the stack for the
     // decompiler.
     frame.syncStack(0);
     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
-    masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
+    masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
 
     prepareVMCall();
 
     pushArg(R1.scratchReg());
     pushArg(R0);
-    masm.extractObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
+    masm.unboxObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
     pushArg(R0.scratchReg());
     pushArg(ImmPtr(pc));
 
     if (!callVM(InitElemGetterSetterInfo))
         return false;
 
     frame.popn(2);
     return true;
--- a/js/src/jit/BaselineFrameInfo.h
+++ b/js/src/jit/BaselineFrameInfo.h
@@ -60,32 +60,32 @@ class StackValue
         EvalNewTargetSlot
 #ifdef DEBUG
         // In debug builds, assert Kind is initialized.
         , Uninitialized
 #endif
     };
 
   private:
-    Kind kind_;
+    MOZ_INIT_OUTSIDE_CTOR Kind kind_;
 
-    union Data {
+    MOZ_INIT_OUTSIDE_CTOR union Data {
         JS::Value constant;
         ValueOperand reg;
         uint32_t localSlot;
         uint32_t argSlot;
 
         // |constant| has a non-trivial constructor and therefore MUST be
         // placement-new'd into existence.
         MOZ_PUSH_DISABLE_NONTRIVIAL_UNION_WARNINGS
         Data() {}
         MOZ_POP_DISABLE_NONTRIVIAL_UNION_WARNINGS
     } data;
 
-    JSValueType knownType_;
+    MOZ_INIT_OUTSIDE_CTOR JSValueType knownType_;
 
   public:
     StackValue() {
         reset();
     }
 
     Kind kind() const {
         return kind_;
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -301,24 +301,24 @@ DoTypeUpdateFallback(JSContext* cx, Base
     // we want to include it in this property's type information.
     bool addType = true;
     if (MOZ_UNLIKELY(obj->is<TypedObject>()) && value.isNullOrUndefined()) {
         StructTypeDescr* structDescr = &obj->as<TypedObject>().typeDescr().as<StructTypeDescr>();
         size_t fieldIndex;
         MOZ_ALWAYS_TRUE(structDescr->fieldIndex(id, &fieldIndex));
 
         TypeDescr* fieldDescr = &structDescr->fieldDescr(fieldIndex);
-        ReferenceTypeDescr::Type type = fieldDescr->as<ReferenceTypeDescr>().type();
-        if (type == ReferenceTypeDescr::TYPE_ANY) {
+        ReferenceType type = fieldDescr->as<ReferenceTypeDescr>().type();
+        if (type == ReferenceType::TYPE_ANY) {
             // Ignore undefined values, which are included implicitly in type
             // information for this property.
             if (value.isUndefined())
                 addType = false;
         } else {
-            MOZ_ASSERT(type == ReferenceTypeDescr::TYPE_OBJECT);
+            MOZ_ASSERT(type == ReferenceType::TYPE_OBJECT);
 
             // Ignore null values being written here. Null is included
             // implicitly in type information for this property. Note that
             // non-object, non-null values are not possible here, these
             // should have been filtered out by the IR emitter.
             if (value.isNull())
                 addType = false;
         }
@@ -1371,17 +1371,17 @@ DoGetIntrinsicFallback(JSContext* cx, Ba
 
     RootedScript script(cx, frame->script());
     jsbytecode* pc = stub->icEntry()->pc(script);
     mozilla::DebugOnly<JSOp> op = JSOp(*pc);
     FallbackICSpew(cx, stub, "GetIntrinsic(%s)", CodeName[JSOp(*pc)]);
 
     MOZ_ASSERT(op == JSOP_GETINTRINSIC);
 
-    if (!GetIntrinsicOperation(cx, pc, res))
+    if (!GetIntrinsicOperation(cx, script, pc, res))
         return false;
 
     // An intrinsic operation will always produce the same result, so only
     // needs to be monitored once. Attach a stub to load the resulting constant
     // directly.
 
     TypeScript::Monitor(cx, script, pc, res);
 
@@ -2725,17 +2725,17 @@ void
 ICCallStubCompiler::pushArrayArguments(MacroAssembler& masm, Address arrayVal,
                                        AllocatableGeneralRegisterSet regs)
 {
     // Load start and end address of values to copy.
     // guardFunApply has already gauranteed that the array is packed and contains
     // no holes.
     Register startReg = regs.takeAny();
     Register endReg = regs.takeAny();
-    masm.extractObject(arrayVal, startReg);
+    masm.unboxObject(arrayVal, startReg);
     masm.loadPtr(Address(startReg, NativeObject::offsetOfElements()), startReg);
     masm.load32(Address(startReg, ObjectElements::offsetOfInitializedLength()), endReg);
     masm.alignJitStackBasedOnNArgs(endReg);
     masm.lshiftPtr(Imm32(ValueShift), endReg);
     masm.addPtr(startReg, endReg);
 
     // Copying pre-decrements endReg by 8 until startReg is reached
     Label copyDone;
@@ -3541,17 +3541,17 @@ ICCall_ScriptedApplyArray::Compiler::gen
     masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE + sizeof(Value)));
 
     // All pushes after this use Push instead of push to make sure ARM can align
     // stack properly for call.
     Register scratch = regs.takeAny();
     EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
 
     // Reload argc from length of array.
-    masm.extractObject(arrayVal, argcReg);
+    masm.unboxObject(arrayVal, argcReg);
     masm.loadPtr(Address(argcReg, NativeObject::offsetOfElements()), argcReg);
     masm.load32(Address(argcReg, ObjectElements::offsetOfInitializedLength()), argcReg);
 
     masm.Push(argcReg);
     masm.Push(target);
     masm.Push(scratch);
 
     // Load nargs into scratch for underflow check, and then load jitcode pointer into target.
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -74,16 +74,26 @@ BaselineScript::BaselineScript(uint32_t 
 # ifdef DEBUG
     traceLoggerScriptsEnabled_(false),
     traceLoggerEngineEnabled_(false),
 # endif
     traceLoggerScriptEvent_(),
 #endif
     postDebugPrologueOffset_(postDebugPrologueOffset),
     flags_(0),
+    icEntriesOffset_(0),
+    icEntries_(0),
+    pcMappingIndexOffset_(0),
+    pcMappingIndexEntries_(0),
+    pcMappingOffset_(0),
+    pcMappingSize_(0),
+    bytecodeTypeMapOffset_(0),
+    yieldEntriesOffset_(0),
+    traceLoggerToggleOffsetsOffset_(0),
+    numTraceLoggerToggleOffsets_(0),
     inlinedBytecodeLength_(0),
     maxInliningDepth_(UINT8_MAX),
     pendingBuilder_(nullptr),
     controlFlowGraph_(nullptr)
 { }
 
 static bool
 CheckFrame(InterpreterFrame* fp)
--- a/js/src/jit/BytecodeAnalysis.cpp
+++ b/js/src/jit/BytecodeAnalysis.cpp
@@ -13,17 +13,18 @@
 #include "vm/JSScript-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 BytecodeAnalysis::BytecodeAnalysis(TempAllocator& alloc, JSScript* script)
   : script_(script),
     infos_(alloc),
-    usesEnvironmentChain_(false)
+    usesEnvironmentChain_(false),
+    hasTryFinally_(false)
 {
 }
 
 // Bytecode range containing only catch or finally code.
 struct CatchFinallyRange
 {
     uint32_t start; // Inclusive.
     uint32_t end;   // Exclusive.
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1123,17 +1123,17 @@ GetPropIRGenerator::tryAttachCrossCompar
     // such as de-lazifying type info.
     {
         AutoRealm ar(cx_, unwrapped);
 
         // The first CCW for iframes is almost always wrapping another WindowProxy
         // so we optimize for that case as well.
         isWindowProxy = IsWindowProxy(unwrapped);
         if (isWindowProxy) {
-            MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == unwrapped->realm()->maybeGlobal());
+            MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == &unwrapped->nonCCWGlobal());
             unwrapped = cx_->global();
             MOZ_ASSERT(unwrapped);
         }
 
         NativeGetPropCacheability canCache =
             CanAttachNativeGetProp(cx_, unwrapped, id, &holder, &shape, pc_,
                                 resultFlags_, isTemporarilyUnoptimizable_);
         if (canCache != CanAttachReadSlot)
@@ -1636,18 +1636,18 @@ GetPropIRGenerator::tryAttachTypedObject
     writer.loadTypedObjectResult(objId, fieldOffset, layout, typeDescr);
 
     // Only monitor the result if the type produced by this stub might vary.
     bool monitorLoad = false;
     if (SimpleTypeDescrKeyIsScalar(typeDescr)) {
         Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr);
         monitorLoad = type == Scalar::Uint32;
     } else {
-        ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
-        monitorLoad = type != ReferenceTypeDescr::TYPE_STRING;
+        ReferenceType type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
+        monitorLoad = type != ReferenceType::TYPE_STRING;
     }
 
     if (monitorLoad)
         writer.typeMonitorResult();
     else
         writer.returnFromIC();
 
     trackAttached("TypedObject");
@@ -3332,24 +3332,24 @@ SetPropIRGenerator::tryAttachTypedObject
         writer.returnFromIC();
 
         trackAttached("TypedObject");
         return true;
     }
 
     // For reference types, guard on the RHS type first, so that
     // StoreTypedObjectReferenceProperty is infallible.
-    ReferenceTypeDescr::Type type = fieldDescr->as<ReferenceTypeDescr>().type();
+    ReferenceType type = fieldDescr->as<ReferenceTypeDescr>().type();
     switch (type) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
         break;
-      case ReferenceTypeDescr::TYPE_OBJECT:
+      case ReferenceType::TYPE_OBJECT:
         writer.guardIsObjectOrNull(rhsId);
         break;
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
         writer.guardType(rhsId, JSVAL_TYPE_STRING);
         break;
     }
 
     writer.storeTypedObjectReferenceProperty(objId, fieldOffset, layout, type, rhsId);
     writer.returnFromIC();
 
     trackAttached("TypedObject");
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -868,17 +868,17 @@ class MOZ_RAII CacheIRWriter : public JS
         writeOperandId(rhs);
         buffer_.writeByte(changeGroup);
         addStubField(uintptr_t(newGroup), StubField::Type::ObjectGroup);
         addStubField(uintptr_t(newShape), StubField::Type::Shape);
         addStubField(numNewSlots, StubField::Type::RawWord);
     }
 
     void storeTypedObjectReferenceProperty(ObjOperandId obj, uint32_t offset,
-                                           TypedThingLayout layout, ReferenceTypeDescr::Type type,
+                                           TypedThingLayout layout, ReferenceType type,
                                            ValOperandId rhs)
     {
         writeOpWithOperandId(CacheOp::StoreTypedObjectReferenceProperty, obj);
         addStubField(offset, StubField::Type::RawWord);
         buffer_.writeByte(uint32_t(layout));
         buffer_.writeByte(uint32_t(type));
         writeOperandId(rhs);
     }
@@ -1220,18 +1220,18 @@ class MOZ_RAII CacheIRReader
     Scalar::Type scalarType() { return Scalar::Type(buffer_.readByte()); }
     uint32_t typeDescrKey() { return buffer_.readByte(); }
     JSWhyMagic whyMagic() { return JSWhyMagic(buffer_.readByte()); }
     JSOp jsop() { return JSOp(buffer_.readByte()); }
     int32_t int32Immediate() { return buffer_.readSigned(); }
     uint32_t uint32Immediate() { return buffer_.readUnsigned(); }
     void* pointer() { return buffer_.readRawPointer(); }
 
-    ReferenceTypeDescr::Type referenceTypeDescrType() {
-        return ReferenceTypeDescr::Type(buffer_.readByte());
+    ReferenceType referenceTypeDescrType() {
+        return ReferenceType(buffer_.readByte());
     }
 
     uint8_t readByte() {
         return buffer_.readByte();
     }
     bool readBool() {
         uint8_t b = buffer_.readByte();
         MOZ_ASSERT(b <= 1);
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -1722,17 +1722,17 @@ CacheIRCompiler::emitLoadProto()
     return true;
 }
 
 bool
 CacheIRCompiler::emitLoadEnclosingEnvironment()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Register reg = allocator.defineRegister(masm, reader.objOperandId());
-    masm.extractObject(Address(obj, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
+    masm.unboxObject(Address(obj, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
     return true;
 }
 
 bool
 CacheIRCompiler::emitLoadWrapperTarget()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Register reg = allocator.defineRegister(masm, reader.objOperandId());
@@ -2427,35 +2427,35 @@ CacheIRCompiler::emitLoadTypedObjectResu
 {
     MOZ_ASSERT(output.hasValue());
 
     if (SimpleTypeDescrKeyIsScalar(typeDescr)) {
         Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr);
         masm.loadFromTypedArray(type, fieldAddr, output.valueReg(),
                                 /* allowDouble = */ true, scratch, nullptr);
     } else {
-        ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
+        ReferenceType type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
         switch (type) {
-          case ReferenceTypeDescr::TYPE_ANY:
+          case ReferenceType::TYPE_ANY:
             masm.loadValue(fieldAddr, output.valueReg());
             break;
 
-          case ReferenceTypeDescr::TYPE_OBJECT: {
+          case ReferenceType::TYPE_OBJECT: {
             Label notNull, done;
             masm.loadPtr(fieldAddr, scratch);
             masm.branchTestPtr(Assembler::NonZero, scratch, scratch, &notNull);
             masm.moveValue(NullValue(), output.valueReg());
             masm.jump(&done);
             masm.bind(&notNull);
             masm.tagValue(JSVAL_TYPE_OBJECT, scratch, output.valueReg());
             masm.bind(&done);
             break;
           }
 
-          case ReferenceTypeDescr::TYPE_STRING:
+          case ReferenceType::TYPE_STRING:
             masm.loadPtr(fieldAddr, scratch);
             masm.tagValue(JSVAL_TYPE_STRING, scratch, output.valueReg());
             break;
 
           default:
             MOZ_CRASH("Invalid ReferenceTypeDescr");
         }
     }
@@ -2661,41 +2661,41 @@ CacheIRCompiler::emitCallPrintString()
 bool
 CacheIRCompiler::emitBreakpoint()
 {
     masm.breakpoint();
     return true;
 }
 
 void
-CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTypeDescr::Type type,
+CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceType type,
                                                    const Address& dest, Register scratch)
 {
     // Callers will post-barrier this store.
 
     switch (type) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
         EmitPreBarrier(masm, dest, MIRType::Value);
         masm.storeValue(val, dest);
         break;
 
-      case ReferenceTypeDescr::TYPE_OBJECT: {
+      case ReferenceType::TYPE_OBJECT: {
         EmitPreBarrier(masm, dest, MIRType::Object);
         Label isNull, done;
         masm.branchTestObject(Assembler::NotEqual, val, &isNull);
         masm.unboxObject(val, scratch);
         masm.storePtr(scratch, dest);
         masm.jump(&done);
         masm.bind(&isNull);
         masm.storePtr(ImmWord(0), dest);
         masm.bind(&done);
         break;
       }
 
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
         EmitPreBarrier(masm, dest, MIRType::String);
         masm.unboxString(val, scratch);
         masm.storePtr(scratch, dest);
         break;
     }
 }
 
 void
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -651,17 +651,17 @@ class MOZ_RAII CacheIRCompiler
         // zeroing its register is pointless).
         return JitOptions.spectreObjectMitigationsMisc && !allocator.isDeadAfterInstruction(objId);
     }
 
     void emitLoadTypedObjectResultShared(const Address& fieldAddr, Register scratch,
                                          uint32_t typeDescr,
                                          const AutoOutputRegister& output);
 
-    void emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTypeDescr::Type type,
+    void emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceType type,
                                            const Address& dest, Register scratch);
 
     void emitRegisterEnumerator(Register enumeratorsList, Register iter, Register scratch);
 
   private:
     void emitPostBarrierShared(Register obj, const ConstantOrRegister& val, Register scratch,
                                Register maybeIndex);
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -661,19 +661,17 @@ class OutOfLineTestObject : public OutOf
     Label* ifDoesntEmulateUndefined_;
 
 #ifdef DEBUG
     bool initialized() { return ifEmulatesUndefined_ != nullptr; }
 #endif
 
   public:
     OutOfLineTestObject()
-#ifdef DEBUG
       : ifEmulatesUndefined_(nullptr), ifDoesntEmulateUndefined_(nullptr)
-#endif
     { }
 
     void accept(CodeGenerator* codegen) final {
         MOZ_ASSERT(initialized());
         codegen->emitOOLTestObject(objreg_, ifEmulatesUndefined_, ifDoesntEmulateUndefined_,
                                    scratch_);
     }
 
@@ -3420,22 +3418,22 @@ CodeGenerator::visitStoreSlotT(LStoreSlo
     if (lir->mir()->needsBarrier())
         emitPreBarrier(dest);
 
     MIRType valueType = lir->mir()->value()->type();
 
     if (valueType == MIRType::ObjectOrNull) {
         masm.storeObjectOrNull(ToRegister(lir->value()), dest);
     } else {
-        ConstantOrRegister value;
+        mozilla::Maybe<ConstantOrRegister> value;
         if (lir->value()->isConstant())
-            value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
+            value.emplace(ConstantOrRegister(lir->value()->toConstant()->toJSValue()));
         else
-            value = TypedOrValueRegister(valueType, ToAnyRegister(lir->value()));
-        masm.storeUnboxedValue(value, valueType, dest, lir->mir()->slotType());
+            value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(lir->value())));
+        masm.storeUnboxedValue(value.ref(), valueType, dest, lir->mir()->slotType());
     }
 }
 
 void
 CodeGenerator::visitStoreSlotV(LStoreSlotV* lir)
 {
     Register base = ToRegister(lir->slots());
     int32_t offset = lir->mir()->slot() * sizeof(Value);
@@ -3623,23 +3621,23 @@ CodeGenerator::visitSetPropertyPolymorph
 
 void
 CodeGenerator::visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins)
 {
     Register obj = ToRegister(ins->obj());
     Register temp1 = ToRegister(ins->temp1());
     Register temp2 = ToRegister(ins->temp2());
 
-    ConstantOrRegister value;
+    mozilla::Maybe<ConstantOrRegister> value;
     if (ins->mir()->value()->isConstant())
-        value = ConstantOrRegister(ins->mir()->value()->toConstant()->toJSValue());
+        value.emplace(ConstantOrRegister(ins->mir()->value()->toConstant()->toJSValue()));
     else
-        value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(ins->value()));
-
-    emitSetPropertyPolymorphic(ins, obj, temp1, temp2, value);
+        value.emplace(TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(ins->value())));
+
+    emitSetPropertyPolymorphic(ins, obj, temp1, temp2, value.ref());
 }
 
 void
 CodeGenerator::visitElements(LElements* lir)
 {
     Address elements(ToRegister(lir->object()), NativeObject::offsetOfElements());
     masm.loadPtr(elements, ToRegister(lir->output()));
 }
@@ -9383,56 +9381,56 @@ static const VMFunction SetDenseElementI
 
 void
 CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
 {
     Register object, elements;
     LInstruction* ins = ool->ins();
     const LAllocation* index;
     MIRType valueType;
-    ConstantOrRegister value;
+    mozilla::Maybe<ConstantOrRegister> value;
     Register spectreTemp;
 
     if (ins->isStoreElementHoleV()) {
         LStoreElementHoleV* store = ins->toStoreElementHoleV();
         object = ToRegister(store->object());
         elements = ToRegister(store->elements());
         index = store->index();
         valueType = store->mir()->value()->type();
-        value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
+        value.emplace(TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value)));
         spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
     } else if (ins->isFallibleStoreElementV()) {
         LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
         object = ToRegister(store->object());
         elements = ToRegister(store->elements());
         index = store->index();
         valueType = store->mir()->value()->type();
-        value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
+        value.emplace(TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value)));
         spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
     } else if (ins->isStoreElementHoleT()) {
         LStoreElementHoleT* store = ins->toStoreElementHoleT();
         object = ToRegister(store->object());
         elements = ToRegister(store->elements());
         index = store->index();
         valueType = store->mir()->value()->type();
         if (store->value()->isConstant())
-            value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
+            value.emplace(ConstantOrRegister(store->value()->toConstant()->toJSValue()));
         else
-            value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
+            value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(store->value())));
         spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
     } else { // ins->isFallibleStoreElementT()
         LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
         object = ToRegister(store->object());
         elements = ToRegister(store->elements());
         index = store->index();
         valueType = store->mir()->value()->type();
         if (store->value()->isConstant())
-            value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
+            value.emplace(ConstantOrRegister(store->value()->toConstant()->toJSValue()));
         else
-            value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
+            value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(store->value())));
         spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
     }
 
     Register indexReg = ToRegister(index);
 
     // If index == initializedLength, try to bump the initialized length inline.
     // If index > initializedLength, call a stub. Note that this relies on the
     // condition flags sticking from the incoming branch.
@@ -9483,17 +9481,17 @@ CodeGenerator::visitOutOfLineStoreElemen
         // Jump to the inline path where we will store the value.
         masm.jump(ool->rejoinStore());
     }
 
     masm.bind(ool->callStub());
     saveLive(ins);
 
     pushArg(Imm32(ool->strict()));
-    pushArg(value);
+    pushArg(value.ref());
     if (index->isConstant())
         pushArg(Imm32(ToInt32(index)));
     else
         pushArg(ToRegister(index));
     pushArg(object);
     callVM(SetDenseElementInfo, ins);
 
     restoreLive(ins);
@@ -9732,23 +9730,23 @@ CodeGenerator::visitArrayPushV(LArrayPus
 }
 
 void
 CodeGenerator::visitArrayPushT(LArrayPushT* lir)
 {
     Register obj = ToRegister(lir->object());
     Register elementsTemp = ToRegister(lir->temp());
     Register length = ToRegister(lir->output());
-    ConstantOrRegister value;
+    mozilla::Maybe<ConstantOrRegister> value;
     if (lir->value()->isConstant())
-        value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
+        value.emplace(ConstantOrRegister(lir->value()->toConstant()->toJSValue()));
     else
-        value = TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value()));
+        value.emplace(TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value())));
     Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
-    emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
+    emitArrayPush(lir, obj, value.ref(), elementsTemp, length, spectreTemp);
 }
 
 typedef JSObject* (*ArraySliceDenseFn)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
 static const VMFunction ArraySliceDenseInfo =
     FunctionInfo<ArraySliceDenseFn>(array_slice_dense, "array_slice_dense");
 
 void
 CodeGenerator::visitArraySlice(LArraySlice* lir)
@@ -11714,92 +11712,91 @@ CodeGenerator::visitLoadElementFromState
         // Add table entries if the table is inlined.
         for (size_t i = 0, e = array->numElements(); i < e; i++)
             jumpTable->addTableEntry(masm);
     }
 
     // Add inlined code for loading arguments from where they are allocated.
     for (size_t i = 0, e = array->numElements(); i < e; i++) {
         MDefinition* elem = array->getElement(i);
-        ConstantOrRegister input;
+        mozilla::Maybe<ConstantOrRegister> input;
 
         jumpTable->addCodeEntry(masm);
         Register typeReg = Register::Invalid();
         const LAllocation* a = lir->getOperand(1 + BOX_PIECES * i);
         if (a->isBogus()) {
             if (elem->type() == MIRType::Null) {
-                input = NullValue();
+                input.emplace(NullValue());
             } else if (elem->type() == MIRType::Undefined) {
-                input = UndefinedValue();
+                input.emplace(UndefinedValue());
             } else if (elem->isConstant() && elem->isEmittedAtUses()) {
-                input = elem->toConstant()->toJSValue();
+                input.emplace(elem->toConstant()->toJSValue());
             } else {
                 MOZ_CRASH("Unsupported element constant allocation.");
             }
         } else if (a->isMemory()) {
             if (elem->type() == MIRType::Double) {
                 masm.loadDouble(ToAddress(a), tempD);
-                input = TypedOrValueRegister(elem->type(), AnyRegister(tempD));
+                input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(tempD)));
             } else if (elem->type() == MIRType::Value) {
                 typeReg = temp0;
                 masm.loadPtr(ToAddress(a), temp0);
 #ifdef JS_PUNBOX64
-                input = TypedOrValueRegister(ValueOperand(temp0));
+                input.emplace(TypedOrValueRegister(ValueOperand(temp0)));
 #endif
             } else {
                 typeReg = temp0;
                 size_t width = StackSlotAllocator::width(LDefinition::TypeFrom(elem->type()));
                 if (width == 4)
                     masm.load32(ToAddress(a), temp0);
                 else if (width == 8)
                     masm.loadPtr(ToAddress(a), temp0);
                 else
                     MOZ_CRASH("Unsupported load size");
-                input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
+                input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
             }
         } else if (a->isGeneralReg()) {
             typeReg = ToRegister(a);
-            input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
 #ifdef JS_PUNBOX64
             if (elem->type() != MIRType::Value)
-                input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
+                input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
             else
-                input = TypedOrValueRegister(ValueOperand(typeReg));
+                input.emplace(TypedOrValueRegister(ValueOperand(typeReg)));
 #else
             if (elem->type() != MIRType::Value)
-                input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
+                input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
 #endif
         } else if (a->isFloatReg()) {
-            input = TypedOrValueRegister(elem->type(), AnyRegister(ToFloatRegister(a)));
+            input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(ToFloatRegister(a))));
         } else if (a->isConstantValue()) {
-            input = a->toConstant()->toJSValue();
+            input.emplace(a->toConstant()->toJSValue());
         } else {
             MOZ_CRASH("Unsupported element allocation.");
         }
 
 #ifdef JS_NUNBOX32
         if (elem->type() == MIRType::Value) {
             static_assert(TYPE_INDEX == 0, "Unexpected type allocation index");
             static_assert(PAYLOAD_INDEX == 1, "Unexpected payload allocation index");
             const LAllocation* a1 = lir->getOperand(1 + BOX_PIECES * i + 1);
             MOZ_ASSERT(!a1->isBogus());
             MOZ_ASSERT(typeReg != Register::Invalid());
             if (a1->isMemory()) {
                 masm.loadPtr(ToAddress(a1), temp1);
-                input = TypedOrValueRegister(ValueOperand(typeReg, temp1));
+                input.emplace(TypedOrValueRegister(ValueOperand(typeReg, temp1)));
             } else if (a1->isGeneralReg()) {
-                input = TypedOrValueRegister(ValueOperand(typeReg, ToRegister(a1)));
+                input.emplace(TypedOrValueRegister(ValueOperand(typeReg, ToRegister(a1))));
             } else {
                 MOZ_CRASH("Unsupported Value allocation.");
             }
         } else {
             MOZ_ASSERT(lir->getOperand(1 + BOX_PIECES * i + 1)->isBogus());
         }
 #endif
-        masm.moveValue(input, out);
+        masm.moveValue(input.ref(), out);
 
         // For the last entry, fall-through.
         if (i + 1 < e)
             masm.jump(&join);
     }
 
     addOutOfLineCode(jumpTable, lir->mir());
     masm.bind(&join);
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -247,17 +247,17 @@ class CompileInfo
         // If the script uses an environment in body, the environment chain
         // will need to be observable.
         needsBodyEnvironmentObject_ = script->needsBodyEnvironment();
         funNeedsSomeEnvironmentObject_ = fun ? fun->needsSomeEnvironmentObject() : false;
     }
 
     explicit CompileInfo(unsigned nlocals)
       : script_(nullptr), fun_(nullptr), osrPc_(nullptr),
-        analysisMode_(Analysis_None), scriptNeedsArgsObj_(false),
+        analysisMode_(Analysis_None), scriptNeedsArgsObj_(false), hadOverflowBailout_(false),
         mayReadFrameArgsDirectly_(false), inlineScriptTree_(nullptr),
         needsBodyEnvironmentObject_(false), funNeedsSomeEnvironmentObject_(false)
     {
         nimplicit_ = 0;
         nargs_ = 0;
         nlocals_ = nlocals;
         nstack_ = 1;  /* For FunctionCompiler::pushPhiInput/popPhiOutput */
         nslots_ = nlocals_ + nstack_;
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -386,17 +386,18 @@ JSContext::allocateOsrTempData(size_t si
 void
 JSContext::freeOsrTempData()
 {
     js_free(osrTempData_);
     osrTempData_ = nullptr;
 }
 
 JitRealm::JitRealm()
-  : stubCodes_(nullptr)
+  : stubCodes_(nullptr),
+    stringsCanBeInNursery(false)
 {
 }
 
 JitRealm::~JitRealm()
 {
     js_delete(stubCodes_);
 }
 
@@ -839,28 +840,34 @@ IonScript::IonScript(IonCompilationId co
     runtimeSize_(0),
     icIndex_(0),
     icEntries_(0),
     safepointIndexOffset_(0),
     safepointIndexEntries_(0),
     safepointsStart_(0),
     safepointsSize_(0),
     frameSlots_(0),
+    argumentSlots_(0),
     frameSize_(0),
     bailoutTable_(0),
     bailoutEntries_(0),
     osiIndexOffset_(0),
     osiIndexEntries_(0),
     snapshots_(0),
     snapshotsListSize_(0),
     snapshotsRVATableSize_(0),
+    recovers_(0),
+    recoversSize_(0),
     constantTable_(0),
     constantEntries_(0),
+    sharedStubList_(0),
+    sharedStubEntries_(0),
     invalidationCount_(0),
     compilationId_(compilationId),
+    optimizationLevel_(OptimizationLevel::Normal),
     osrPcMismatchCounter_(0),
     fallbackStubSpace_()
 {
 }
 
 IonScript*
 IonScript::New(JSContext* cx, IonCompilationId compilationId,
                uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -131,16 +131,17 @@ IonBuilder::IonBuilder(JSContext* analys
     analysisContext(analysisContext),
     baselineFrame_(baselineFrame),
     constraints_(constraints),
     thisTypes(nullptr),
     argTypes(nullptr),
     typeArray(nullptr),
     typeArrayHint(0),
     bytecodeTypeMap(nullptr),
+    current(nullptr),
     loopDepth_(loopDepth),
     blockWorklist(*temp),
     cfgCurrent(nullptr),
     cfg(nullptr),
     trackedOptimizationSites_(*temp),
     lexicalCheck_(nullptr),
     callerResumePoint_(nullptr),
     callerBuilder_(nullptr),
@@ -7953,17 +7954,17 @@ AbortReasonOr<Ok>
 IonBuilder::getElemTryReferenceElemOfTypedObject(bool* emitted,
                                                  MDefinition* obj,
                                                  MDefinition* index,
                                                  TypedObjectPrediction objPrediction,
                                                  TypedObjectPrediction elemPrediction)
 {
     MOZ_ASSERT(objPrediction.ofArrayKind());
 
-    ReferenceTypeDescr::Type elemType = elemPrediction.referenceType();
+    ReferenceType elemType = elemPrediction.referenceType();
     uint32_t elemSize = ReferenceTypeDescr::size(elemType);
 
     LinearSum indexAsByteOffset(alloc());
     if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
         return Ok();
 
     trackOptimizationSuccess();
     *emitted = true;
@@ -8011,57 +8012,57 @@ IonBuilder::pushScalarLoadFromTypedObjec
     load->setResultType(knownType);
 
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::pushReferenceLoadFromTypedObject(MDefinition* typedObj,
                                              const LinearSum& byteOffset,
-                                             ReferenceTypeDescr::Type type,
+                                             ReferenceType type,
                                              PropertyName* name)
 {
     // Find location within the owner object.
     MDefinition* elements;
     MDefinition* scaledOffset;
     int32_t adjustment;
     uint32_t alignment = ReferenceTypeDescr::alignment(type);
     MOZ_TRY(loadTypedObjectElements(typedObj, byteOffset, alignment, &elements, &scaledOffset, &adjustment));
 
     TemporaryTypeSet* observedTypes = bytecodeTypes(pc);
 
     MInstruction* load = nullptr;  // initialize to silence GCC warning
     BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, alloc(), constraints(),
                                                        typedObj, name, observedTypes);
 
     switch (type) {
-      case ReferenceTypeDescr::TYPE_ANY: {
+      case ReferenceType::TYPE_ANY: {
         // Make sure the barrier reflects the possibility of reading undefined.
         bool bailOnUndefined = barrier == BarrierKind::NoBarrier &&
                                !observedTypes->hasType(TypeSet::UndefinedType());
         if (bailOnUndefined)
             barrier = BarrierKind::TypeTagOnly;
         load = MLoadElement::New(alloc(), elements, scaledOffset, false, false, adjustment);
         break;
       }
-      case ReferenceTypeDescr::TYPE_OBJECT: {
+      case ReferenceType::TYPE_OBJECT: {
         // Make sure the barrier reflects the possibility of reading null. When
         // there is no other barrier needed we include the null bailout with
         // MLoadUnboxedObjectOrNull, which avoids the need to box the result
         // for a type barrier instruction.
         MLoadUnboxedObjectOrNull::NullBehavior nullBehavior;
         if (barrier == BarrierKind::NoBarrier && !observedTypes->hasType(TypeSet::NullType()))
             nullBehavior = MLoadUnboxedObjectOrNull::BailOnNull;
         else
             nullBehavior = MLoadUnboxedObjectOrNull::HandleNull;
         load = MLoadUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, nullBehavior,
                                              adjustment);
         break;
       }
-      case ReferenceTypeDescr::TYPE_STRING: {
+      case ReferenceType::TYPE_STRING: {
         load = MLoadUnboxedString::New(alloc(), elements, scaledOffset, adjustment);
         observedTypes->addType(TypeSet::StringType(), alloc().lifoAlloc());
         break;
       }
     }
 
     current->add(load);
     current->push(load);
@@ -8950,17 +8951,17 @@ IonBuilder::setElemTryTypedObject(bool* 
 AbortReasonOr<Ok>
 IonBuilder::setElemTryReferenceElemOfTypedObject(bool* emitted,
                                                  MDefinition* obj,
                                                  MDefinition* index,
                                                  TypedObjectPrediction objPrediction,
                                                  MDefinition* value,
                                                  TypedObjectPrediction elemPrediction)
 {
-    ReferenceTypeDescr::Type elemType = elemPrediction.referenceType();
+    ReferenceType elemType = elemPrediction.referenceType();
     uint32_t elemSize = ReferenceTypeDescr::size(elemType);
 
     LinearSum indexAsByteOffset(alloc());
     if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction, &indexAsByteOffset))
         return Ok();
 
     return setPropTryReferenceTypedObjectValue(emitted, obj, indexAsByteOffset,
                                                elemType, value, nullptr);
@@ -10598,17 +10599,17 @@ IonBuilder::getPropTryScalarPropOfTypedO
 }
 
 AbortReasonOr<Ok>
 IonBuilder::getPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* typedObj,
                                                  int32_t fieldOffset,
                                                  TypedObjectPrediction fieldPrediction,
                                                  PropertyName* name)
 {
-    ReferenceTypeDescr::Type fieldType = fieldPrediction.referenceType();
+    ReferenceType fieldType = fieldPrediction.referenceType();
 
     TypeSet::ObjectKey* globalKey = TypeSet::ObjectKey::get(&script()->global());
     if (globalKey->hasFlags(constraints(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER))
         return Ok();
 
     trackOptimizationSuccess();
     *emitted = true;
 
@@ -11713,17 +11714,17 @@ IonBuilder::setPropTryTypedObject(bool* 
 AbortReasonOr<Ok>
 IonBuilder::setPropTryReferencePropOfTypedObject(bool* emitted,
                                                  MDefinition* obj,
                                                  int32_t fieldOffset,
                                                  MDefinition* value,
                                                  TypedObjectPrediction fieldPrediction,
                                                  PropertyName* name)
 {
-    ReferenceTypeDescr::Type fieldType = fieldPrediction.referenceType();
+    ReferenceType fieldType = fieldPrediction.referenceType();
 
     TypeSet::ObjectKey* globalKey = TypeSet::ObjectKey::get(&script()->global());
     if (globalKey->hasFlags(constraints(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER))
         return Ok();
 
     LinearSum byteOffset(alloc());
     if (!byteOffset.add(fieldOffset))
         return abort(AbortReason::Disable, "Overflow of field offset.");
@@ -13558,29 +13559,29 @@ IonBuilder::setPropTryScalarTypedObjectV
     *emitted = true;
     return resumeAfter(store);
 }
 
 AbortReasonOr<Ok>
 IonBuilder::setPropTryReferenceTypedObjectValue(bool* emitted,
                                                 MDefinition* typedObj,
                                                 const LinearSum& byteOffset,
-                                                ReferenceTypeDescr::Type type,
+                                                ReferenceType type,
                                                 MDefinition* value,
                                                 PropertyName* name)
 {
     MOZ_ASSERT(!*emitted);
 
     // Make sure we aren't adding new type information for writes of object and value
     // references.
-    if (type != ReferenceTypeDescr::TYPE_STRING) {
-        MOZ_ASSERT(type == ReferenceTypeDescr::TYPE_ANY ||
-                   type == ReferenceTypeDescr::TYPE_OBJECT);
+    if (type != ReferenceType::TYPE_STRING) {
+        MOZ_ASSERT(type == ReferenceType::TYPE_ANY ||
+                   type == ReferenceType::TYPE_OBJECT);
         MIRType implicitType =
-            (type == ReferenceTypeDescr::TYPE_ANY) ? MIRType::Undefined : MIRType::Null;
+            (type == ReferenceType::TYPE_ANY) ? MIRType::Undefined : MIRType::Null;
 
         if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &typedObj, name, &value,
                                           /* canModify = */ true, implicitType))
         {
             trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
             return Ok();
         }
     }
@@ -13590,30 +13591,30 @@ IonBuilder::setPropTryReferenceTypedObje
     MDefinition* scaledOffset;
     int32_t adjustment;
     uint32_t alignment = ReferenceTypeDescr::alignment(type);
     MOZ_TRY(loadTypedObjectElements(typedObj, byteOffset, alignment,
                                     &elements, &scaledOffset, &adjustment));
 
     MInstruction* store = nullptr;  // initialize to silence GCC warning
     switch (type) {
-      case ReferenceTypeDescr::TYPE_ANY:
+      case ReferenceType::TYPE_ANY:
         if (needsPostBarrier(value))
             current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
         store = MStoreElement::New(alloc(), elements, scaledOffset, value, false, adjustment);
         store->toStoreElement()->setNeedsBarrier();
         break;
-      case ReferenceTypeDescr::TYPE_OBJECT:
+      case ReferenceType::TYPE_OBJECT:
         // Note: We cannot necessarily tell at this point whether a post
         // barrier is needed, because the type policy may insert ToObjectOrNull
         // instructions later, and those may require a post barrier. Therefore,
         // defer the insertion of post barriers to the type policy.
         store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, typedObj, adjustment);
         break;
-      case ReferenceTypeDescr::TYPE_STRING:
+      case ReferenceType::TYPE_STRING:
         // See previous comment. The StoreUnboxedString type policy may insert
         // ToString instructions that require a post barrier.
         store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value, typedObj, adjustment);
         break;
     }
 
     current->add(store);
     current->push(value);
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -283,17 +283,17 @@ class IonBuilder
                                             PropertyName* name, MDefinition* value);
     AbortReasonOr<Ok> setPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* obj,
                                                            int32_t fieldOffset, MDefinition* value,
                                                            TypedObjectPrediction fieldPrediction,
                                                            PropertyName* name);
     AbortReasonOr<Ok> setPropTryReferenceTypedObjectValue(bool* emitted,
                                                           MDefinition* typedObj,
                                                           const LinearSum& byteOffset,
-                                                          ReferenceTypeDescr::Type type,
+                                                          ReferenceType type,
                                                           MDefinition* value,
                                                           PropertyName* name);
     AbortReasonOr<Ok> setPropTryScalarPropOfTypedObject(bool* emitted,
                                                         MDefinition* obj,
                                                         int32_t fieldOffset,
                                                         MDefinition* value,
                                                         TypedObjectPrediction fieldTypeReprs);
     AbortReasonOr<Ok> setPropTryScalarTypedObjectValue(bool* emitted,
@@ -380,17 +380,17 @@ class IonBuilder
                                              const LinearSum& byteOffset,
                                              TypedObjectPrediction derivedTypeDescrs,
                                              MDefinition* derivedTypeObj);
     AbortReasonOr<Ok> pushScalarLoadFromTypedObject(MDefinition* obj,
                                                     const LinearSum& byteoffset,
                                                     ScalarTypeDescr::Type type);
     AbortReasonOr<Ok> pushReferenceLoadFromTypedObject(MDefinition* typedObj,
                                                        const LinearSum& byteOffset,
-                                                       ReferenceTypeDescr::Type type,
+                                                       ReferenceType type,
                                                        PropertyName* name);
 
     // jsop_setelem() helpers.
     AbortReasonOr<Ok> setElemTryTypedArray(bool* emitted, MDefinition* object,
                                            MDefinition* index, MDefinition* value);
     AbortReasonOr<Ok> setElemTryTypedObject(bool* emitted, MDefinition* obj,
                                             MDefinition* index, MDefinition* value);
     AbortReasonOr<Ok> initOrSetElemTryDense(bool* emitted, MDefinition* object,
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -1690,40 +1690,40 @@ IonCacheIRCompiler::emitStoreUnboxedProp
 }
 
 bool
 IonCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     int32_t offset = int32StubField(reader.stubOffset());
     TypedThingLayout layout = reader.typedThingLayout();
-    ReferenceTypeDescr::Type type = reader.referenceTypeDescrType();
+    ReferenceType type = reader.referenceTypeDescrType();
 
     ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
 
     AutoScratchRegister scratch1(allocator, masm);
     AutoScratchRegister scratch2(allocator, masm);
 
     // We don't need to check property types if the property is always a
     // string.
-    if (type != ReferenceTypeDescr::TYPE_STRING) {
+    if (type != ReferenceType::TYPE_STRING) {
         FailurePath* failure;
         if (!addFailurePath(&failure))
             return false;
         EmitCheckPropertyTypes(masm, typeCheckInfo_, obj, TypedOrValueRegister(val),
                                *liveRegs_, failure->label());
     }
 
     // Compute the address being written to.
     LoadTypedThingData(masm, layout, obj, scratch1);
     Address dest(scratch1, offset);
 
     emitStoreTypedObjectReferenceProp(val, type, dest, scratch2);
 
-    if (needsPostBarrier() && type != ReferenceTypeDescr::TYPE_STRING)
+    if (needsPostBarrier() && type != ReferenceType::TYPE_STRING)
         emitPostBarrierSlot(obj, val, scratch1);
     return true;
 }
 
 bool
 IonCacheIRCompiler::emitStoreTypedObjectScalarProperty()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -63,20 +63,17 @@ class JitCode : public gc::TenuredCell
     uint32_t dataRelocTableBytes_;    // Size of the data relocation table.
     uint8_t headerSize_ : 5;          // Number of bytes allocated before codeStart.
     uint8_t kind_ : 3;                // jit::CodeKind, for the memory reporters.
     bool invalidated_ : 1;            // Whether the code object has been invalidated.
                                       // This is necessary to prevent GC tracing.
     bool hasBytecodeMap_ : 1;         // Whether the code object has been registered with
                                       // native=>bytecode mapping tables.
 
-    JitCode()
-      : code_(nullptr),
-        pool_(nullptr)
-    { }
+    JitCode() = delete;
     JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize, ExecutablePool* pool,
             CodeKind kind)
       : code_(code),
         pool_(pool),
         bufferSize_(bufferSize),
         insnSize_(0),
         dataSize_(0),
         jumpRelocTableBytes_(0),
--- a/js/src/jit/IonControlFlow.cpp
+++ b/js/src/jit/IonControlFlow.cpp
@@ -10,16 +10,17 @@
 
 using namespace js;
 using namespace js::jit;
 using mozilla::DebugOnly;
 
 ControlFlowGenerator::ControlFlowGenerator(TempAllocator& temp, JSScript* script)
   : script(script),
     current(nullptr),
+    pc(nullptr),
     alloc_(temp),
     blocks_(temp),
     cfgStack_(temp),
     loops_(temp),
     switches_(temp),
     labels_(temp),
     aborted_(false),
     checkedTryFinally_(false)
--- a/js/src/jit/IonOptimizationLevels.h
+++ b/js/src/jit/IonOptimizationLevels.h
@@ -144,17 +144,46 @@ class OptimizationInfo
     // are inlined, as a fraction of compilerWarmUpThreshold.
     double inliningWarmUpThresholdFactor_;
 
     // How many invocations or loop iterations are needed before a function
     // is hot enough to recompile the outerScript to inline that function,
     // as a multiplication of inliningWarmUpThreshold.
     uint32_t inliningRecompileThresholdFactor_;
 
-    OptimizationInfo()
+    constexpr OptimizationInfo()
+      : level_(OptimizationLevel::Normal),
+        eaa_(false),
+        ama_(false),
+        edgeCaseAnalysis_(false),
+        eliminateRedundantChecks_(false),
+        inlineInterpreted_(false),
+        inlineNative_(false),
+        eagerSimdUnbox_(false),
+        gvn_(false),
+        licm_(false),
+        rangeAnalysis_(false),
+        loopUnrolling_(false),
+        reordering_(false),
+        autoTruncate_(false),
+        sincos_(false),
+        sink_(false),
+        registerAllocator_(RegisterAllocator_Backtracking),
+        inlineMaxBytecodePerCallSiteHelperThread_(0),
+        inlineMaxBytecodePerCallSiteMainThread_(0),
+        inlineMaxCalleeInlinedBytecodeLength_(0),
+        inlineMaxTotalBytecodeLength_(0),
+        inliningMaxCallerBytecodeLength_(0),
+        maxInlineDepth_(0),
+        scalarReplacement_(false),
+        smallFunctionMaxInlineDepth_(0),
+        compilerWarmUpThreshold_(0),
+        compilerSmallFunctionWarmUpThreshold_(0),
+        inliningWarmUpThresholdFactor_(0.0),
+        inliningRecompileThresholdFactor_(0)
     { }
 
     void initNormalOptimizationInfo();
     void initWasmOptimizationInfo();
 
     OptimizationLevel level() const {
         return level_;
     }
--- a/js/src/jit/JitAllocPolicy.h
+++ b/js/src/jit/JitAllocPolicy.h
@@ -7,16 +7,18 @@
 #ifndef jit_JitAllocPolicy_h
 #define jit_JitAllocPolicy_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/OperatorNewExtensions.h"
 #include "mozilla/TypeTraits.h"
 
+#include <utility>
+
 #include "ds/LifoAlloc.h"
 #include "jit/InlineList.h"
 #include "jit/Ion.h"
 #include "vm/JSContext.h"
 
 namespace js {
 namespace jit {
 
@@ -184,21 +186,23 @@ class TempObjectPool
   public:
     TempObjectPool()
       : alloc_(nullptr)
     {}
     void setAllocator(TempAllocator& alloc) {
         MOZ_ASSERT(freed_.empty());
         alloc_ = &alloc;
     }
-    T* allocate() {
+    template <typename... Args>
+    T* allocate(Args&&... args) {
         MOZ_ASSERT(alloc_);
         if (freed_.empty())
-            return new(alloc_->fallible()) T();
-        return freed_.popFront();
+            return new (alloc_->fallible()) T(std::forward<Args>(args)...);
+        T* res = freed_.popFront();
+        return new (res) T(std::forward<Args>(args)...);
     }
     void free(T* obj) {
         freed_.pushFront(obj);
     }
     void clear() {
         freed_.clear();
     }
 };
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -1536,16 +1536,17 @@ SnapshotIterator::SnapshotIterator(const
     instructionResults_(nullptr)
 {
 }
 
 SnapshotIterator::SnapshotIterator()
   : snapshot_(nullptr, 0, 0, 0),
     recover_(snapshot_, nullptr, 0),
     fp_(nullptr),
+    machine_(nullptr),
     ionScript_(nullptr),
     instructionResults_(nullptr)
 {
 }
 
 int32_t
 SnapshotIterator::readOuterNumActualArgs() const
 {
@@ -2049,28 +2050,32 @@ SnapshotIterator::maybeReadAllocByIndex(
         skip();
 
     return s;
 }
 
 InlineFrameIterator::InlineFrameIterator(JSContext* cx, const JSJitFrameIter* iter)
   : calleeTemplate_(cx),
     calleeRVA_(),
-    script_(cx)
+    script_(cx),
+    pc_(nullptr),
+    numActualArgs_(0)
 {
     resetOn(iter);
 }
 
 InlineFrameIterator::InlineFrameIterator(JSContext* cx, const InlineFrameIterator* iter)
   : frame_(iter ? iter->frame_ : nullptr),
     framesRead_(0),
     frameCount_(iter ? iter->frameCount_ : UINT32_MAX),
     calleeTemplate_(cx),
     calleeRVA_(),
-    script_(cx)
+    script_(cx),
+    pc_(nullptr),
+    numActualArgs_(0)
 {
     if (frame_) {
         machine_ = iter->machine_;
         start_ = SnapshotIterator(*frame_, &machine_);
 
         // findNextFrame will iterate to the next frame and init. everything.
         // Therefore to settle on the same frame, we report one frame less readed.
         framesRead_ = iter->framesRead_ - 1;
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -225,18 +225,17 @@ static const uint32_t NO_FRAME_SIZE_CLAS
 class FrameSizeClass
 {
     uint32_t class_;
 
     explicit FrameSizeClass(uint32_t class_) : class_(class_)
     { }
 
   public:
-    FrameSizeClass()
-    { }
+    FrameSizeClass() = delete;
 
     static FrameSizeClass None() {
         return FrameSizeClass(NO_FRAME_SIZE_CLASS_ID);
     }
     static FrameSizeClass FromClass(uint32_t class_) {
         return FrameSizeClass(class_);
     }
 
--- a/js/src/jit/JitRealm.h
+++ b/js/src/jit/JitRealm.h
@@ -27,18 +27,26 @@
 namespace js {
 namespace jit {
 
 class FrameSizeClass;
 
 struct EnterJitData
 {
     explicit EnterJitData(JSContext* cx)
-      : envChain(cx),
-        result(cx)
+      : jitcode(nullptr),
+        osrFrame(nullptr),
+        calleeToken(nullptr),
+        maxArgv(nullptr),
+        maxArgc(0),
+        numActualArgs(0),
+        osrNumStackValues(0),
+        envChain(cx),
+        result(cx),
+        constructing(false)
     {}
 
     uint8_t* jitcode;
     InterpreterFrame* osrFrame;
 
     void* calleeToken;
 
     Value* maxArgv;
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -1459,31 +1459,31 @@ class LSnapshot : public TempObject
 
 struct SafepointSlotEntry {
     // Flag indicating whether this is a slot in the stack or argument space.
     uint32_t stack:1;
 
     // Byte offset of the slot, as in LStackSlot or LArgument.
     uint32_t slot:31;
 
-    SafepointSlotEntry() { }
+    SafepointSlotEntry() : stack(0), slot(0) { }
     SafepointSlotEntry(bool stack, uint32_t slot)
       : stack(stack), slot(slot)
     { }
     explicit SafepointSlotEntry(const LAllocation* a)
       : stack(a->isStackSlot()), slot(a->memorySlot())
     { }
 };
 
 struct SafepointNunboxEntry {
     uint32_t typeVreg;
     LAllocation type;
     LAllocation payload;
 
-    SafepointNunboxEntry() { }
+    SafepointNunboxEntry() : typeVreg(0) { }
     SafepointNunboxEntry(uint32_t typeVreg, LAllocation type, LAllocation payload)
       : typeVreg(typeVreg), type(type), payload(payload)
     { }
 };
 
 class LSafepoint : public TempObject
 {
     typedef SafepointSlotEntry SlotEntry;
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -484,16 +484,18 @@ MBasicBlock::New(MIRGraph& graph, const 
 
 MBasicBlock::MBasicBlock(MIRGraph& graph, const CompileInfo& info, BytecodeSite* site, Kind kind)
   : unreachable_(false),
     specialized_(false),
     graph_(graph),
     info_(info),
     predecessors_(graph.alloc()),
     stackPosition_(info_.firstStackSlot()),
+    id_(0),
+    domIndex_(0),
     numDominated_(0),
     pc_(site->pc()),
     lir_(nullptr),
     callerResumePoint_(nullptr),
     entryResumePoint_(nullptr),
     outerResumePoint_(nullptr),
     successorWithPhis_(nullptr),
     positionInPhiSuccessor_(0),
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -2803,16 +2803,17 @@ MacroAssembler::alignJitStackBasedOnNArg
 
 // ===============================================================
 
 MacroAssembler::MacroAssembler(JSContext* cx)
   : framePushed_(0),
 #ifdef DEBUG
     inCall_(false),
 #endif
+    dynamicAlignment_(false),
     emitProfilingInstrumentation_(false)
 {
     jitContext_.emplace(cx, (js::jit::TempAllocator*)nullptr);
     alloc_.emplace(cx);
     moveResolver_.setAllocator(*jitContext_->temp);
 #if defined(JS_CODEGEN_ARM)
     initWithAllocator();
     m_buffer.id = GetJitContext()->getNextAssemblerId();
@@ -2822,16 +2823,17 @@ MacroAssembler::MacroAssembler(JSContext
 #endif
 }
 
 MacroAssembler::MacroAssembler()
   : framePushed_(0),
 #ifdef DEBUG
     inCall_(false),
 #endif
+    dynamicAlignment_(false),
     emitProfilingInstrumentation_(false)
 {
     JitContext* jcx = GetJitContext();
 
     if (!jcx->temp) {
         JSContext* cx = jcx->cx;
         MOZ_ASSERT(cx);
         alloc_.emplace(cx);
@@ -2848,16 +2850,17 @@ MacroAssembler::MacroAssembler()
 #endif
 }
 
 MacroAssembler::MacroAssembler(WasmToken, TempAllocator& alloc)
   : framePushed_(0),
 #ifdef DEBUG
     inCall_(false),
 #endif
+    dynamicAlignment_(false),
     emitProfilingInstrumentation_(false)
 {
     moveResolver_.setAllocator(alloc);
 
 #if defined(JS_CODEGEN_ARM)
     initWithAllocator();
     m_buffer.id = 0;
 #elif defined(JS_CODEGEN_ARM64)
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -2188,25 +2188,25 @@ class MacroAssembler : public MacroAssem
                               const ConstantOrRegister& value, Label* failure);
 
     void debugAssertIsObject(const ValueOperand& val);
     void debugAssertObjHasFixedSlots(Register obj, Register scratch);
 
     void branchIfNativeIteratorNotReusable(Register ni, Label* notReusable);
 
     using MacroAssemblerSpecific::extractTag;
-    Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
         if (reg.hasValue())
             return extractTag(reg.valueReg(), scratch);
         mov(ImmWord(MIRTypeToTag(reg.type())), scratch);
         return scratch;
     }
 
     using MacroAssemblerSpecific::extractObject;
-    Register extractObject(const TypedOrValueRegister& reg, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const TypedOrValueRegister& reg, Register scratch) {
         if (reg.hasValue())
             return extractObject(reg.valueReg(), scratch);
         MOZ_ASSERT(reg.type() == MIRType::Object);
         return reg.typedReg().gpr();
     }
 
     // Inline version of js_TypedArray_uint8_clamp_double.
     // This function clobbers the input register.
--- a/js/src/jit/MoveResolver.cpp
+++ b/js/src/jit/MoveResolver.cpp
@@ -11,16 +11,17 @@
 
 #include "jit/MacroAssembler.h"
 #include "jit/RegisterSets.h"
 
 using namespace js;
 using namespace js::jit;
 
 MoveOperand::MoveOperand(MacroAssembler& masm, const ABIArg& arg)
+  : disp_(0)
 {
     switch (arg.kind()) {
       case ABIArg::GPR:
         kind_ = REG;
         code_ = arg.gpr().code();
         break;
 #ifdef JS_CODEGEN_REGISTER_PAIR
       case ABIArg::GPR_PAIR:
@@ -59,20 +60,19 @@ MoveResolver::resetState()
     curCycles_ = 0;
 }
 
 bool
 MoveResolver::addMove(const MoveOperand& from, const MoveOperand& to, MoveOp::Type type)
 {
     // Assert that we're not doing no-op moves.
     MOZ_ASSERT(!(from == to));
-    PendingMove* pm = movePool_.allocate();
+    PendingMove* pm = movePool_.allocate(from, to, type);
     if (!pm)
         return false;
-    new (pm) PendingMove(from, to, type);
     pending_.pushBack(pm);
     return true;
 }
 
 // Given move (A -> B), this function attempts to find any move (B -> *) in the
 // pending move list, and returns the first one.
 MoveResolver::PendingMove*
 MoveResolver::findBlockingMove(const PendingMove* last)
@@ -200,24 +200,24 @@ MoveResolver::resolve()
     // This logic is only applicable because ARM only uses registers d0-d15,
     // all of which alias s0-s31. Double registers d16-d31 are unused.
     // Therefore there is never a double move that cannot be split.
     // If this changes in the future, the algorithm will have to be fixed.
     for (auto iter = pending_.begin(); iter != pending_.end(); ++iter) {
         PendingMove* pm = *iter;
 
         if (isDoubleAliasedAsSingle(pm->from()) || isDoubleAliasedAsSingle(pm->to())) {
-            PendingMove* lower = movePool_.allocate();
+            MoveOperand fromLower = SplitIntoLowerHalf(pm->from());
+            MoveOperand toLower = SplitIntoLowerHalf(pm->to());
+
+            PendingMove* lower = movePool_.allocate(fromLower, toLower, MoveOp::FLOAT32);
             if (!lower)
                 return false;
 
             // Insert the new node before the current position to not affect iteration.
-            MoveOperand fromLower = SplitIntoLowerHalf(pm->from());
-            MoveOperand toLower = SplitIntoLowerHalf(pm->to());
-            new (lower) PendingMove(fromLower, toLower, MoveOp::FLOAT32);
             pending_.insertBefore(pm, lower);
 
             // Overwrite pm in place for the upper move. Iteration proceeds as normal.
             MoveOperand fromUpper = SplitIntoUpperHalf(pm->from());
             MoveOperand toUpper = SplitIntoUpperHalf(pm->to());
             pm->overwrite(fromUpper, toUpper, MoveOp::FLOAT32);
         }
     }
--- a/js/src/jit/MoveResolver.h
+++ b/js/src/jit/MoveResolver.h
@@ -40,21 +40,20 @@ class MoveOperand
     };
 
   private:
     Kind kind_;
     uint32_t code_;
     int32_t disp_;
 
   public:
-    MoveOperand()
+    MoveOperand() = delete;
+    explicit MoveOperand(Register reg) : kind_(REG), code_(reg.code()), disp_(0)
     { }
-    explicit MoveOperand(Register reg) : kind_(REG), code_(reg.code())
-    { }
-    explicit MoveOperand(FloatRegister reg) : kind_(FLOAT_REG), code_(reg.code())
+    explicit MoveOperand(FloatRegister reg) : kind_(FLOAT_REG), code_(reg.code()), disp_(0)
     { }
     MoveOperand(Register reg, int32_t disp, Kind kind = MEMORY)
         : kind_(kind),
         code_(reg.code()),
         disp_(disp)
     {
         MOZ_ASSERT(isMemoryOrEffectiveAddress());
 
@@ -202,18 +201,17 @@ class MoveOp
     // of the cycle. For example, given these moves:
     //       INT32 move a -> b
     //     GENERAL move b -> a
     // the move resolver starts by copying b into a temporary location, so that
     // the last move can read it. This copy needs to use use type GENERAL.
     Type endCycleType_;
 
   public:
-    MoveOp()
-    { }
+    MoveOp() = delete;
     MoveOp(const MoveOperand& from, const MoveOperand& to, Type type)
       : from_(from),
         to_(to),
         cycleBegin_(false),
         cycleEnd_(false),
         cycleBeginSlot_(-1),
         cycleEndSlot_(-1),
         type_(type),
@@ -265,18 +263,18 @@ class MoveOp
 class MoveResolver
 {
   private:
     struct PendingMove
       : public MoveOp,
         public TempObject,
         public InlineListNode<PendingMove>
     {
-        PendingMove()
-        { }
+        PendingMove() = delete;
+
         PendingMove(const MoveOperand& from, const MoveOperand& to, Type type)
           : MoveOp(from, to, type)
         { }
 
         void setCycleBegin(Type endCycleType, int cycleSlot) {
             MOZ_ASSERT(!cycleBegin_);
             cycleBegin_ = true;
             cycleBeginSlot_ = cycleSlot;
--- a/js/src/jit/OptimizationTracking.h
+++ b/js/src/jit/OptimizationTracking.h
@@ -449,17 +449,19 @@ struct IonTrackedTypeWithAddendum
             JSScript* script;
             uint32_t offset;
         };
         JSFunction* constructor;
     };
 
     explicit IonTrackedTypeWithAddendum(TypeSet::Type type)
       : type(type),
-        hasAddendum(HasNothing)
+        hasAddendum(HasNothing),
+        script(nullptr),
+        offset(0)
     { }
 
     IonTrackedTypeWithAddendum(TypeSet::Type type, JSScript* script, uint32_t offset)
       : type(type),
         hasAddendum(HasAllocationSite),
         script(script),
         offset(offset)
     { }
--- a/js/src/jit/RangeAnalysis.h
+++ b/js/src/jit/RangeAnalysis.h
@@ -190,25 +190,25 @@ class Range : public TempObject {
     // 2) hasInt32UpperBound_ == false implies upper_ == JSVAL_INT_MAX
     //
     // As a second and less precise range analysis, we represent the maximal
     // exponent taken by a value. The exponent is calculated by taking the
     // absolute value and looking at the position of the highest bit.  All
     // exponent computation have to be over-estimations of the actual result. On
     // the Int32 this over approximation is rectified.
 
-    int32_t lower_;
-    int32_t upper_;
+    MOZ_INIT_OUTSIDE_CTOR int32_t lower_;
+    MOZ_INIT_OUTSIDE_CTOR int32_t upper_;
 
-    bool hasInt32LowerBound_;
-    bool hasInt32UpperBound_;
+    MOZ_INIT_OUTSIDE_CTOR bool hasInt32LowerBound_;
+    MOZ_INIT_OUTSIDE_CTOR bool hasInt32UpperBound_;
 
-    FractionalPartFlag canHaveFractionalPart_ : 1;
-    NegativeZeroFlag canBeNegativeZero_ : 1;
-    uint16_t max_exponent_;
+    MOZ_INIT_OUTSIDE_CTOR FractionalPartFlag canHaveFractionalPart_ : 1;
+    MOZ_INIT_OUTSIDE_CTOR NegativeZeroFlag canBeNegativeZero_ : 1;
+    MOZ_INIT_OUTSIDE_CTOR uint16_t max_exponent_;
 
     // Any symbolic lower or upper bound computed for this term.
     const SymbolicBound* symbolicLower_;
     const SymbolicBound* symbolicUpper_;
 
     // This function simply makes several MOZ_ASSERTs to verify the internal
     // consistency of this range.
     void assertInvariants() const {
--- a/js/src/jit/RegisterSets.h
+++ b/js/src/jit/RegisterSets.h
@@ -241,18 +241,17 @@ class ConstantOrRegister
         // placement-new'd into existence.
         MOZ_PUSH_DISABLE_NONTRIVIAL_UNION_WARNINGS
         U() {}
         MOZ_POP_DISABLE_NONTRIVIAL_UNION_WARNINGS
     } data;
 
   public:
 
-    ConstantOrRegister()
-    {}
+    ConstantOrRegister() = delete;
 
     MOZ_IMPLICIT ConstantOrRegister(const Value& value)
       : constant_(true)
     {
         MOZ_ASSERT(constant());
         new (&data.constant) Value(value);
     }
 
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -31,23 +31,26 @@ struct CopyValueToRematerializedFrame
         *slots++ = v;
     }
 };
 
 RematerializedFrame::RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
                                          InlineFrameIterator& iter, MaybeReadFallback& fallback)
   : prevUpToDate_(false),
     isDebuggee_(iter.script()->isDebuggee()),
+    hasInitialEnv_(false),
     isConstructing_(iter.isConstructing()),
     hasCachedSavedFrame_(false),
     top_(top),
     pc_(iter.pc()),
     frameNo_(iter.frameNo()),
     numActualArgs_(numActualArgs),
-    script_(iter.script())
+    script_(iter.script()),
+    envChain_(nullptr),
+    argsObj_(nullptr)
 {
     if (iter.isFunctionFrame())
         callee_ = iter.callee(fallback);
     else
         callee_ = nullptr;
 
     CopyValueToRematerializedFrame op(slots_);
     iter.readFrameArgsAndLocals(cx, op, op, &envChain_, &hasInitialEnv_, &returnValue_,
--- a/js/src/jit/Safepoints.cpp
+++ b/js/src/jit/Safepoints.cpp
@@ -390,17 +390,19 @@ SafepointWriter::endEntry()
 {
     JitSpew(JitSpew_Safepoints, "    -- entry ended at %d", uint32_t(stream_.length()));
 }
 
 SafepointReader::SafepointReader(IonScript* script, const SafepointIndex* si)
   : stream_(script->safepoints() + si->safepointOffset(),
             script->safepoints() + script->safepointsSize()),
     frameSlots_((script->frameSlots() / sizeof(intptr_t)) + 1), // Stack slot counts are inclusive.
-    argumentSlots_(script->argumentSlots() / sizeof(intptr_t))
+    argumentSlots_(script->argumentSlots() / sizeof(intptr_t)),
+    nunboxSlotsRemaining_(0),
+    slotsOrElementsSlotsRemaining_(0)
 {
     osiCallPointOffset_ = stream_.readUnsigned();
 
     // gcSpills is a subset of allGprSpills.
     allGprSpills_ = GeneralRegisterSet(ReadRegisterMask(stream_));
     if (allGprSpills_.empty()) {
         gcSpills_ = allGprSpills_;
         valueSpills_ = allGprSpills_;
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -369,16 +369,17 @@ class ObjectMemoryView : public MDefinit
     void loadOffset(MInstruction* ins, size_t offset);
     void visitObjectGuard(MInstruction* ins, MDefinition* operand);
 };
 
 const char* ObjectMemoryView::phaseName = "Scalar Replacement of Object";
 
 ObjectMemoryView::ObjectMemoryView(TempAllocator& alloc, MInstruction* obj)
   : alloc_(alloc),
+    undefinedVal_(nullptr),
     obj_(obj),
     startBlock_(obj->block()),
     state_(nullptr),
     lastResumePoint_(nullptr),
     oom_(false)
 {
     // Annotate snapshots RValue such that we recover the store first.
     obj_->setIncompleteObject();
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -2303,21 +2303,21 @@ SimpleTypeDescrKeyIsScalar(uint32_t key)
 
 inline ScalarTypeDescr::Type
 ScalarTypeFromSimpleTypeDescrKey(uint32_t key)
 {
     MOZ_ASSERT(SimpleTypeDescrKeyIsScalar(key));
     return ScalarTypeDescr::Type(key >> 1);
 }
 
-inline ReferenceTypeDescr::Type
+inline ReferenceType
 ReferenceTypeFromSimpleTypeDescrKey(uint32_t key)
 {
     MOZ_ASSERT(!SimpleTypeDescrKeyIsScalar(key));
-    return ReferenceTypeDescr::Type(key >> 1);
+    return ReferenceType(key >> 1);
 }
 
 // JSOP_NEWARRAY
 // JSOP_NEWINIT
 
 class ICNewArray_Fallback : public ICFallbackStub
 {
     friend class ICStubSpace;
--- a/js/src/jit/StupidAllocator.h
+++ b/js/src/jit/StupidAllocator.h
@@ -48,17 +48,18 @@ class StupidAllocator : public RegisterA
     // Type indicating an index into registers.
     typedef uint32_t RegisterIndex;
 
     // Information about each virtual register.
     Vector<LDefinition*, 0, SystemAllocPolicy> virtualRegisters;
 
   public:
     StupidAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph)
-      : RegisterAllocator(mir, lir, graph)
+      : RegisterAllocator(mir, lir, graph),
+        registerCount(0)
     {
     }
 
     MOZ_MUST_USE bool go();
 
   private:
     MOZ_MUST_USE bool init();
 
--- a/js/src/jit/TypedObjectPrediction.cpp
+++ b/js/src/jit/TypedObjectPrediction.cpp
@@ -196,17 +196,17 @@ TypedObjectPrediction::extractType() con
 }
 
 ScalarTypeDescr::Type
 TypedObjectPrediction::scalarType() const
 {
     return extractType<ScalarTypeDescr>();
 }
 
-ReferenceTypeDescr::Type
+ReferenceType
 TypedObjectPrediction::referenceType() const
 {
     return extractType<ReferenceTypeDescr>();
 }
 
 SimdType
 TypedObjectPrediction::simdType() const
 {
--- a/js/src/jit/TypedObjectPrediction.h
+++ b/js/src/jit/TypedObjectPrediction.h
@@ -113,17 +113,18 @@ class TypedObjectPrediction {
                              size_t* index) const;
 
   public:
 
     ///////////////////////////////////////////////////////////////////////////
     // Constructing a prediction. Generally, you start with an empty
     // prediction and invoke addDescr() repeatedly.
 
-    TypedObjectPrediction() {
+    TypedObjectPrediction()
+      : data_() {
         kind_ = Empty;
     }
 
     explicit TypedObjectPrediction(const TypeDescr& descr) {
         setDescr(descr);
     }
 
     TypedObjectPrediction(const StructTypeDescr& descr, size_t fields) {
@@ -161,18 +162,18 @@ class TypedObjectPrediction {
     // of its type is known.
     bool hasKnownSize(uint32_t* out) const;
 
     //////////////////////////////////////////////////////////////////////
     // Simple operations
     //
     // Only valid when |kind()| is Scalar, Reference, or Simd (as appropriate).
 
-    ScalarTypeDescr::Type scalarType() const;
-    ReferenceTypeDescr::Type referenceType() const;
+    Scalar::Type scalarType() const;
+    ReferenceType referenceType() const;
     SimdType simdType() const;
 
     ///////////////////////////////////////////////////////////////////////////
     // Queries valid only for arrays.
 
     // Returns true if the length of the array is statically known,
     // and sets |*length| appropriately. Otherwise returns false.
     bool hasKnownArrayLength(int32_t* length) const;
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -2779,111 +2779,111 @@ MacroAssemblerARMCompat::testPrimitive(A
     return cond == Equal ? Below : AboveOrEqual;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testGCThing(Assembler::Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
+    Register tag = extractTag(address, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
     return cond == Equal ? AboveOrEqual : Below;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testMagic(Assembler::Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_MAGIC));
+    Register tag = extractTag(address, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_MAGIC));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_INT32));
+    Register tag = extractTag(address, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_INT32));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testDouble(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testDouble(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testDouble(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testBoolean(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testBoolean(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testBoolean(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testNull(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testNull(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testNull(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testUndefined(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testUndefined(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testUndefined(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testString(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testString(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testString(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testSymbol(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testSymbol(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testSymbol(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testObject(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testObject(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testObject(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testNumber(Condition cond, const Address& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    return testNumber(cond, scratch);
+    Register tag = extractTag(address, scratch);
+    return testNumber(cond, tag);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testDouble(Condition cond, Register tag)
 {
     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     Condition actual = (cond == Equal) ? Below : AboveOrEqual;
     ma_cmp(tag, ImmTag(JSVAL_TAG_CLEAR));
@@ -2898,109 +2898,109 @@ MacroAssemblerARMCompat::testNumber(Cond
     return cond == Equal ? BelowOrEqual : Above;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testUndefined(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_UNDEFINED));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_UNDEFINED));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testNull(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_NULL));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_NULL));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testBoolean(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_BOOLEAN));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_BOOLEAN));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testString(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_STRING));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_STRING));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testSymbol(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_SYMBOL));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_SYMBOL));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testInt32(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_INT32));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_INT32));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testObject(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_OBJECT));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_OBJECT));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testDouble(Condition cond, const BaseIndex& src)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     Assembler::Condition actual = (cond == Equal) ? Below : AboveOrEqual;
     ScratchRegisterScope scratch(asMasm());
-    extractTag(src, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_CLEAR));
+    Register tag = extractTag(src, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_CLEAR));
     return actual;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testMagic(Condition cond, const BaseIndex& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_TAG_MAGIC));
+    Register tag = extractTag(address, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_TAG_MAGIC));
     return cond;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testGCThing(Condition cond, const BaseIndex& address)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     ScratchRegisterScope scratch(asMasm());
-    extractTag(address, scratch);
-    ma_cmp(scratch, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
+    Register tag = extractTag(address, scratch);
+    ma_cmp(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
     return cond == Equal ? AboveOrEqual : Below;
 }
 
 // Unboxing code.
 void
 MacroAssemblerARMCompat::unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType type)
 {
     auto movPayloadToDest = [&]() {
@@ -4926,17 +4926,17 @@ MacroAssembler::branchPtrInNurseryChunk(
 void
 MacroAssembler::branchValueIsNurseryCell(Condition cond, const Address& address,
                                          Register temp, Label* label)
 {
     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     Label done, checkAddress;
 
     Register tag = temp;
-    extractTag(address, tag);
+    tag = extractTag(address, tag);
     branchTestObject(Assembler::Equal, tag, &checkAddress);
     branchTestString(Assembler::NotEqual, tag, cond == Assembler::Equal ? &done : label);
 
     bind(&checkAddress);
     loadPtr(ToPayload(address), temp);
     SecondScratchRegisterScope scratch2(*this);
     branchPtrInNurseryChunk(cond, temp, scratch2, label);
 
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -820,34 +820,34 @@ class MacroAssemblerARMCompat : public M
 
     // Boxing code.
     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister);
     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
 
     // Extended unboxing API. If the payload is already in a register, returns
     // that register. Otherwise, provides a move to the given scratch register,
     // and returns that.
-    Register extractObject(const Address& address, Register scratch);
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT);
         return value.payloadReg();
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL);
         return value.payloadReg();
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractTag(const Address& address, Register scratch);
-    Register extractTag(const BaseIndex& address, Register scratch);
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         return value.typeReg();
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& src, FloatRegister dest);
     void loadInt32OrDouble(Register base, Register index,
                            FloatRegister dest, int32_t shift = defaultShift);
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -794,17 +794,16 @@ JitRuntime::generateVMWrapper(JSContext*
 
     masm.setupUnalignedABICall(regs.getAny());
     masm.passABIArg(cxreg);
 
     size_t argDisp = 0;
 
     // Copy any arguments.
     for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
-        MoveOperand from;
         switch (f.argProperties(explicitArg)) {
           case VMFunction::WordByValue:
             masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
             argDisp += sizeof(void*);
             break;
           case VMFunction::DoubleByValue:
             // Values should be passed by reference, not by value, so we assert
             // that the argument is a double-precision float.
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -989,17 +989,17 @@ MacroAssembler::branchValueIsNurseryObje
                                            Label* label)
 {
     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     MOZ_ASSERT(temp != ScratchReg && temp != ScratchReg2); // Both may be used internally.
 
     Label done;
     branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
 
-    extractObject(value, temp);
+    unboxObject(value, temp);
     orPtr(Imm32(gc::ChunkMask), temp);
     branch32(cond, Address(temp, gc::ChunkLocationOffsetFromLastByte),
              Imm32(int32_t(gc::ChunkLocation::Nursery)), label);
 
     bind(&done);
 }
 
 void
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -395,43 +395,43 @@ class MacroAssemblerCompat : public vixl
     }
 
     void boxValue(JSValueType type, Register src, Register dest) {
         Orr(ARMRegister(dest, 64), ARMRegister(src, 64), Operand(ImmShiftedTag(type).value));
     }
     void splitTag(Register src, Register dest) {
         ubfx(ARMRegister(dest, 64), ARMRegister(src, 64), JSVAL_TAG_SHIFT, (64 - JSVAL_TAG_SHIFT));
     }
-    Register extractTag(const Address& address, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch) {
         loadPtr(address, scratch);
         splitTag(scratch, scratch);
         return scratch;
     }
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         splitTag(value.valueReg(), scratch);
         return scratch;
     }
-    Register extractObject(const Address& address, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register scratch) {
         loadPtr(address, scratch);
         unboxObject(scratch, scratch);
         return scratch;
     }
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         unboxObject(value, scratch);
         return scratch;
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         unboxSymbol(value, scratch);
         return scratch;
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         unboxInt32(value, scratch);
         return scratch;
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         unboxBoolean(value, scratch);
         return scratch;
     }
 
     inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
 
     void emitSet(Condition cond, Register dest) {
         Cset(ARMRegister(dest, 64), cond);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -610,17 +610,16 @@ JitRuntime::generateVMWrapper(JSContext*
 
     masm.setupUnalignedABICall(regs.getAny());
     masm.passABIArg(reg_cx);
 
     size_t argDisp = 0;
 
     // Copy arguments.
     for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
-        MoveOperand from;
         switch (f.argProperties(explicitArg)) {
           case VMFunction::WordByValue:
             masm.passABIArg(MoveOperand(argsBase, argDisp),
                             (f.argPassedInFloatReg(explicitArg) ? MoveOp::DOUBLE : MoveOp::GENERAL));
             argDisp += sizeof(void*);
             break;
 
           case VMFunction::WordByRef:
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -391,35 +391,35 @@ class MacroAssemblerMIPSCompat : public 
 
     // boxing code
     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister);
     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
 
     // Extended unboxing API. If the payload is already in a register, returns
     // that register. Otherwise, provides a move to the given scratch register,
     // and returns that.
-    Register extractObject(const Address& address, Register scratch);
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractString(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractString(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractTag(const Address& address, Register scratch);
-    Register extractTag(const BaseIndex& address, Register scratch);
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         return value.typeReg();
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& address, FloatRegister dest);
     void loadInt32OrDouble(Register base, Register index,
                            FloatRegister dest, int32_t shift = defaultShift);
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2153,17 +2153,17 @@ void
 MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value,
                                            Register temp, Label* label)
 {
     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
 
     Label done;
     branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
 
-    extractObject(value, SecondScratchReg);
+    unboxObject(value, SecondScratchReg);
     orPtr(Imm32(gc::ChunkMask), SecondScratchReg);
     branch32(cond, Address(SecondScratchReg, gc::ChunkLocationOffsetFromLastByte),
              Imm32(int32_t(gc::ChunkLocation::Nursery)), label);
 
     bind(&done);
 }
 
 void
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -447,40 +447,40 @@ class MacroAssemblerMIPS64Compat : publi
 
     // boxing code
     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister);
     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
 
     // Extended unboxing API. If the payload is already in a register, returns
     // that register. Otherwise, provides a move to the given scratch register,
     // and returns that.
-    Register extractObject(const Address& address, Register scratch);
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         unboxObject(value, scratch);
         return scratch;
     }
-    Register extractString(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractString(const ValueOperand& value, Register scratch) {
         unboxString(value, scratch);
         return scratch;
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         unboxSymbol(value, scratch);
         return scratch;
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         unboxInt32(value, scratch);
         return scratch;
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         unboxBoolean(value, scratch);
         return scratch;
     }
-    Register extractTag(const Address& address, Register scratch);
-    Register extractTag(const BaseIndex& address, Register scratch);
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchRegister);
         splitTag(value, scratch);
         return scratch;
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void loadInt32OrDouble(const Address& src, FloatRegister dest);
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -327,22 +327,22 @@ class MacroAssemblerNone : public Assemb
     template <typename T> void unboxObject(T, Register) { MOZ_CRASH(); }
     template <typename T> void unboxDouble(T, FloatRegister) { MOZ_CRASH(); }
     template <typename T> void unboxPrivate(T, Register) { MOZ_CRASH(); }
     void unboxValue(const ValueOperand&, AnyRegister, JSValueType) { MOZ_CRASH(); }
     void unboxNonDouble(const ValueOperand&, Register, JSValueType) { MOZ_CRASH();}
     void unboxNonDouble(const Address&, Register, JSValueType) { MOZ_CRASH();}
     void unboxGCThingForPreBarrierTrampoline(const Address&, Register) { MOZ_CRASH(); }
     void notBoolean(ValueOperand) { MOZ_CRASH(); }
-    Register extractObject(Address, Register) { MOZ_CRASH(); }
-    Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
-    Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
-    Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
-    Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }
-    template <typename T> Register extractTag(T, Register) { MOZ_CRASH(); }
+    MOZ_MUST_USE Register extractObject(Address, Register) { MOZ_CRASH(); }
+    MOZ_MUST_USE Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
+    MOZ_MUST_USE Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
+    MOZ_MUST_USE Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
+    MOZ_MUST_USE Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }
+    template <typename T> MOZ_MUST_USE Register extractTag(T, Register) { MOZ_CRASH(); }
 
     void convertFloat32ToInt32(FloatRegister, Register, Label*, bool v = true) { MOZ_CRASH(); }
     void convertDoubleToInt32(FloatRegister, Register, Label*, bool v = true) { MOZ_CRASH(); }
     void convertBoolToInt32(Register, Register) { MOZ_CRASH(); }
 
     void convertDoubleToFloat32(FloatRegister, FloatRegister) { MOZ_CRASH(); }
     void convertInt32ToFloat32(Register, FloatRegister) { MOZ_CRASH(); }
 
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -70,17 +70,18 @@ CodeGeneratorShared::CodeGeneratorShared
     trackedOptimizationsTypesTableOffset_(0),
     trackedOptimizationsAttemptsTableOffset_(0),
     osrEntryOffset_(0),
     skipArgCheckEntryOffset_(0),
 #ifdef CHECK_OSIPOINT_REGISTERS
     checkOsiPointRegisters(JitOptions.checkOsiPointRegisters),
 #endif
     frameDepth_(graph->paddedLocalSlotsSize() + graph->argumentsSize()),
-    frameInitialAdjustment_(0)
+    frameInitialAdjustment_(0),
+    frameClass_(FrameSizeClass::None())
 {
     if (gen->isProfilerInstrumentationEnabled())
         masm.enableProfilingInstrumentation();
 
     if (gen->compilingWasm()) {
         // Since wasm uses the system ABI which does not necessarily use a
         // regular array where all slots are sizeof(Value), it maintains the max
         // argument stack depth separately.
@@ -102,17 +103,17 @@ CodeGeneratorShared::CodeGeneratorShared
             // instead relies on the a priori stack adjustment. This must be the
             // last adjustment of frameDepth_.
             frameDepth_ += ComputeByteAlignment(sizeof(wasm::Frame) + frameDepth_,
                                                 WasmStackAlignment);
         }
 
         // FrameSizeClass is only used for bailing, which cannot happen in
         // wasm code.
-        frameClass_ = FrameSizeClass::None();
+        MOZ_ASSERT(frameClass_ == FrameSizeClass::None());
     } else {
         frameClass_ = FrameSizeClass::FromDepth(frameDepth_);
     }
 }
 
 bool
 CodeGeneratorShared::generatePrologue()
 {
--- a/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h
+++ b/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h
@@ -238,16 +238,17 @@ class BranchDeadlineSet
             earliest_ = deadline;
             earliestRange_ = rangeIdx;
         }
         return true;
     }
 
   public:
     explicit BranchDeadlineSet(LifoAlloc& alloc)
+      : earliestRange_(0)
     {
         // Manually construct vectors in the uninitialized aligned storage.
         // This is because C++ arrays can otherwise only be constructed with
         // the default constructor.
         for (unsigned r = 0; r < NumRanges; r++)
             new (&vectorForRange(r)) RangeVector(alloc);
     }
 
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -32,16 +32,17 @@ class LIRGeneratorShared
     MResumePoint* lastResumePoint_;
     LRecoverInfo* cachedRecoverInfo_;
     LOsiPoint* osiPoint_;
 
     LIRGeneratorShared(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : gen(gen),
         graph(graph),
         lirGraph_(lirGraph),
+        current(nullptr),
         lastResumePoint_(nullptr),
         cachedRecoverInfo_(nullptr),
         osiPoint_(nullptr)
     { }
 
     MIRGenerator* mir() {
         return gen;
     }
--- a/js/src/jit/x64/Assembler-x64.cpp
+++ b/js/src/jit/x64/Assembler-x64.cpp
@@ -257,17 +257,19 @@ class RelocationIterator
 {
     CompactBufferReader reader_;
     uint32_t tableStart_;
     uint32_t offset_;
     uint32_t extOffset_;
 
   public:
     explicit RelocationIterator(CompactBufferReader& reader)
-      : reader_(reader)
+      : reader_(reader),
+        offset_(0),
+        extOffset_(0)
     {
         tableStart_ = reader_.readFixedUint32_t();
     }
 
     bool read() {
         if (!reader_.more())
             return false;
         offset_ = reader_.readUnsigned();
--- a/js/src/jit/x64/Bailouts-x64.cpp
+++ b/js/src/jit/x64/Bailouts-x64.cpp
@@ -42,32 +42,34 @@ class BailoutStack
 } // namespace js
 
 #if defined(_WIN32)
 # pragma pack(pop)
 #endif
 
 BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
                                    BailoutStack* bailout)
-  : machine_(bailout->machineState())
+  : machine_(bailout->machineState()),
+    activation_(nullptr)
 {
     uint8_t* sp = bailout->parentStackPointer();
     framePointer_ = sp + bailout->frameSize();
     topFrameSize_ = framePointer_ - sp;
 
     JSScript* script = ScriptFromCalleeToken(((JitFrameLayout*) framePointer_)->calleeToken());
     topIonScript_ = script->ionScript();
 
     attachOnJitActivation(activations);
     snapshotOffset_ = bailout->snapshotOffset();
 }
 
 BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
                                    InvalidationBailoutStack* bailout)
-  : machine_(bailout->machine())
+  : machine_(bailout->machine()),
+    activation_(nullptr)
 {
     framePointer_ = (uint8_t*) bailout->fp();
     topFrameSize_ = framePointer_ - bailout->sp();
     topIonScript_ = bailout->ionScript();
     attachOnJitActivation(activations);
 
     uint8_t* returnAddressToFp_ = bailout->osiPointReturnAddress();
     const OsiIndex* osiIndex = topIonScript_->getOsiIndex(returnAddressToFp_);
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -479,17 +479,17 @@ MacroAssembler::branchValueIsNurseryObje
                                            Label* label)
 {
     MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     MOZ_ASSERT(temp != InvalidReg);
 
     Label done;
     branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
 
-    extractObject(value, temp);
+    unboxObject(value, temp);
     orPtr(Imm32(gc::ChunkMask), temp);
     branch32(cond, Address(temp, gc::ChunkLocationOffsetFromLastByte),
              Imm32(int32_t(gc::ChunkLocation::Nursery)), label);
 
     bind(&done);
 }
 
 template <typename T>
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -870,48 +870,48 @@ class MacroAssemblerX64 : public MacroAs
     void unboxGCThingForPreBarrierTrampoline(const Address& src, Register dest) {
         movq(ImmWord(JSVAL_PAYLOAD_MASK_GCTHING), dest);
         andq(Operand(src), dest);
     }
 
     // Extended unboxing API. If the payload is already in a register, returns
     // that register. Otherwise, provides a move to the given scratch register,
     // and returns that.
-    Register extractObject(const Address& address, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         unboxObject(address, scratch);
         return scratch;
     }
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         unboxObject(value, scratch);
         return scratch;
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         unboxSymbol(value, scratch);
         return scratch;
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         unboxInt32(value, scratch);
         return scratch;
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         unboxBoolean(value, scratch);
         return scratch;
     }
-    Register extractTag(const Address& address, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         loadPtr(address, scratch);
         splitTag(scratch, scratch);
         return scratch;
     }
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         MOZ_ASSERT(scratch != ScratchReg);
         splitTag(value, scratch);
         return scratch;
     }
 
     inline void unboxValue(const ValueOperand& src, AnyRegister dest, JSValueType type);
 
     // These two functions use the low 32-bits of the full value register.
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -681,17 +681,16 @@ JitRuntime::generateVMWrapper(JSContext*
 
     masm.setupUnalignedABICall(regs.getAny());
     masm.passABIArg(cxreg);
 
     size_t argDisp = 0;
 
     // Copy arguments.
     for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
-        MoveOperand from;
         switch (f.argProperties(explicitArg)) {
           case VMFunction::WordByValue:
             if (f.argPassedInFloatReg(explicitArg))
                 masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::DOUBLE);
             else
                 masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
             argDisp += sizeof(void*);
             break;
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -824,39 +824,39 @@ class MacroAssemblerX86 : public MacroAs
 
     void notBoolean(const ValueOperand& val) {
         xorl(Imm32(1), val.payloadReg());
     }
 
     // Extended unboxing API. If the payload is already in a register, returns
     // that register. Otherwise, provides a move to the given scratch register,
     // and returns that.
-    Register extractObject(const Address& address, Register dest) {
+    MOZ_MUST_USE Register extractObject(const Address& address, Register dest) {
         unboxObject(address, dest);
         return dest;
     }
-    Register extractObject(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
         unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT, scratch);
         return value.payloadReg();
     }
-    Register extractSymbol(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
         unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL, scratch);
         return value.payloadReg();
     }
-    Register extractInt32(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractBoolean(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
         return value.payloadReg();
     }
-    Register extractTag(const Address& address, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const Address& address, Register scratch) {
         movl(tagOf(address), scratch);
         return scratch;
     }
-    Register extractTag(const ValueOperand& value, Register scratch) {
+    MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
         return value.typeReg();
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToDouble(operand.payloadReg(), dest);
     }
     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
         convertInt32ToFloat32(operand.payloadReg(), dest);
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -695,17 +695,16 @@ JitRuntime::generateVMWrapper(JSContext*
 
     masm.setupUnalignedABICall(regs.getAny());
     masm.passABIArg(cxreg);
 
     size_t argDisp = 0;
 
     // Copy arguments.
     for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
-        MoveOperand from;
         switch (f.argProperties(explicitArg)) {
           case VMFunction::WordByValue:
             masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
             argDisp += sizeof(void*);
             break;
           case VMFunction::DoubleByValue:
             // We don't pass doubles in float registers on x86, so no need
             // to check for argPassedInFloatReg.
--- a/js/src/jsapi-tests/testPreserveJitCode.cpp
+++ b/js/src/jsapi-tests/testPreserveJitCode.cpp
@@ -2,16 +2,18 @@
  * 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/. */
 
 // For js::jit::IsIonEnabled().
 #include "jit/Ion.h"
 
 #include "jsapi-tests/tests.h"
 
+#include "vm/JSObject-inl.h"
+
 using namespace JS;
 
 static void
 ScriptCallback(JSRuntime* rt, void* data, JSScript* script, const JS::AutoRequireNoGC& nogc)
 {
     unsigned& count = *static_cast<unsigned*>(data);
     if (script->hasIonScript())
         ++count;
@@ -23,17 +25,17 @@ BEGIN_TEST(test_PreserveJitCode)
     CHECK(testPreserveJitCode(true, 1));
     return true;
 }
 
 unsigned
 countIonScripts(JSObject* global)
 {
     unsigned count = 0;
-    js::IterateScripts(cx, global->realm(), &count, ScriptCallback);
+    js::IterateScripts(cx, global->nonCCWRealm(), &count, ScriptCallback);
     return count;
 }
 
 bool
 testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts)
 {
     cx->options().setBaseline(true);
     cx->options().setIon(true);
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -7,16 +7,18 @@
 #include "js/UbiNodeDominatorTree.h"
 #include "js/UbiNodePostOrder.h"
 #include "js/UbiNodeShortestPaths.h"
 #include "jsapi-tests/tests.h"
 #include "util/Text.h"
 #include "vm/Realm.h"
 #include "vm/SavedFrame.h"
 
+#include "vm/JSObject-inl.h"
+
 using JS::RootedObject;
 using JS::RootedScript;
 using JS::RootedString;
 using namespace js;
 
 // A helper JS::ubi::Node concrete implementation that can be used to make mock
 // graphs for testing traversals with.
 struct FakeNode
@@ -123,18 +125,18 @@ BEGIN_TEST(test_ubiNodeCompartment)
 
     JS::RealmOptions globalOptions;
     RootedObject global2(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
                                                 JS::FireOnNewGlobalHook, globalOptions));
     CHECK(global2);
     CHECK(global1->compartment() != global2->compartment());
     CHECK(JS::ubi::Node(global2).compartment() == global2->compartment());
     CHECK(JS::ubi::Node(global2).compartment() != global1->compartment());
-    CHECK(JS::ubi::Node(global2).realm() == global2->realm());
-    CHECK(JS::ubi::Node(global2).realm() != global1->realm());
+    CHECK(JS::ubi::Node(global2).realm() == global2->nonCCWRealm());
+    CHECK(JS::ubi::Node(global2).realm() != global1->nonCCWRealm());
 
     JS::CompileOptions options(cx);
 
     // Create a script in the original realm...
     RootedScript script1(cx);
     CHECK(JS::Compile(cx, options, "", 0, &script1));
 
     {
@@ -142,18 +144,18 @@ BEGIN_TEST(test_ubiNodeCompartment)
         // there, too.
         JSAutoRealm ar(cx, global2);
 
         RootedScript script2(cx);
         CHECK(JS::Compile(cx, options, "", 0, &script2));
 
         CHECK(JS::ubi::Node(script1).compartment() == global1->compartment());
         CHECK(JS::ubi::Node(script2).compartment() == global2->compartment());
-        CHECK(JS::ubi::Node(script1).realm() == global1->realm());
-        CHECK(JS::ubi::Node(script2).realm() == global2->realm());
+        CHECK(JS::ubi::Node(script1).realm() == global1->nonCCWRealm());
+        CHECK(JS::ubi::Node(script2).realm() == global2->nonCCWRealm());
 
         // Now create a wrapper for global1 in global2's compartment.
         RootedObject wrappedGlobal1(cx, global1);
         CHECK(cx->compartment()->wrap(cx, &wrappedGlobal1));
 
         // Cross-compartment wrappers have a compartment() but not a realm().
         CHECK(JS::ubi::Node(wrappedGlobal1).zone() == cx->zone());
         CHECK(JS::ubi::Node(wrappedGlobal1).compartment() == cx->compartment());
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -880,17 +880,17 @@ JS_TransplantObject(JSContext* cx, Handl
 
     JS::Compartment* destination = target->compartment();
 
     if (origobj->compartment() == destination) {
         // If the original object is in the same compartment as the
         // destination, then we know that we won't find a wrapper in the
         // destination's cross compartment map and that the same
         // object will continue to work.
-        AutoRealmUnchecked ar(cx, origobj->realm());
+        AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
         if (!JSObject::swap(cx, origobj, target))
             MOZ_CRASH();
         newIdentity = origobj;
     } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
         // There might already be a wrapper for the original object in
         // the new compartment. If there is, we use its identity and swap
         // in the contents of |target|.
         newIdentity = &p->value().get().toObject();
@@ -914,17 +914,17 @@ JS_TransplantObject(JSContext* cx, Handl
     // `newIdentity == origobj`, because this process also clears out any
     // cached wrapper state.
     if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
         MOZ_CRASH();
 
     // Lastly, update the original object to point to the new one.
     if (origobj->compartment() != destination) {
         RootedObject newIdentityWrapper(cx, newIdentity);
-        AutoRealmUnchecked ar(cx, origobj->realm());
+        AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
         if (!JS_WrapObject(cx, &newIdentityWrapper))
             MOZ_CRASH();
         MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
         if (!JSObject::swap(cx, origobj, newIdentityWrapper))
             MOZ_CRASH();
         if (!origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv))
             MOZ_CRASH();
     }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -707,17 +707,16 @@ class JS_PUBLIC_API(ContextOptions) {
         dumpStackOnDebuggeeWouldRun_(false),
         werror_(false),
         strictMode_(false),
         extraWarnings_(false),
         streams_(false)
 #ifdef FUZZING
         , fuzzing_(false)
 #endif
-        , arrayProtoValues_(true)
     {
     }
 
     bool baseline() const { return baseline_; }
     ContextOptions& setBaseline(bool flag) {
         baseline_ = flag;
         return *this;
     }
@@ -871,22 +870,16 @@ class JS_PUBLIC_API(ContextOptions) {
 #ifdef FUZZING
     bool fuzzing() const { return fuzzing_; }
     ContextOptions& setFuzzing(bool flag) {
         fuzzing_ = flag;
         return *this;
     }
 #endif
 
-    bool arrayProtoValues() const { return arrayProtoValues_; }
-    ContextOptions& setArrayProtoValues(bool flag) {
-        arrayProtoValues_ = flag;
-        return *this;
-    }
-
     void disableOptionsForSafeMode() {
         setBaseline(false);
         setIon(false);
         setAsmJS(false);
         setWasm(false);
         setWasmBaseline(false);
         setWasmIon(false);
 #ifdef ENABLE_WASM_GC
@@ -913,17 +906,16 @@ class JS_PUBLIC_API(ContextOptions) {
     bool dumpStackOnDebuggeeWouldRun_ : 1;
     bool werror_ : 1;
     bool strictMode_ : 1;
     bool extraWarnings_ : 1;
     bool streams_: 1;
 #ifdef FUZZING
     bool fuzzing_ : 1;
 #endif
-    bool arrayProtoValues_ : 1;
 
 };
 
 JS_PUBLIC_API(ContextOptions&)
 ContextOptionsRef(JSContext* cx);
 
 /**
  * Initialize the runtime's self-hosted code. Embeddings should call this
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -609,17 +609,17 @@ js::RemapWrapper(JSContext* cx, JSObject
     RootedObject newTarget(cx, newTargetArg);
     MOZ_ASSERT(wobj->is<CrossCompartmentWrapperObject>());
     MOZ_ASSERT(!newTarget->is<CrossCompartmentWrapperObject>());
     JSObject* origTarget = Wrapper::wrappedObject(wobj);
     MOZ_ASSERT(origTarget);
     MOZ_ASSERT(!JS_IsDeadWrapper(origTarget),
                "We don't want a dead proxy in the wrapper map");
     Value origv = ObjectValue(*origTarget);
-    Realm* wrealm = wobj->realm();
+    Realm* wrealm = wobj->deprecatedRealm();
     JS::Compartment* wcompartment = wobj->compartment();
 
     AutoDisableProxyCheck adpc;
 
     // If we're mapping to a different target (as opposed to just recomputing
     // for the same target), we must not have an existing wrapper for the new
     // target, otherwise this will break.
     MOZ_ASSERT_IF(origTarget != newTarget,
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -495,17 +495,16 @@ static bool enableSharedMemory = SHARED_
 static bool enableWasmBaseline = false;
 static bool enableWasmIon = false;
 #ifdef ENABLE_WASM_GC
 static bool enableWasmGc = false;
 #endif
 static bool enableTestWasmAwaitTier2 = false;
 static bool enableAsyncStacks = false;
 static bool enableStreams = false;
-static bool enableArrayProtoValues = true;
 #ifdef JS_GC_ZEAL
 static uint32_t gZealBits = 0;
 static uint32_t gZealFrequency = 0;
 #endif
 static bool printTiming = false;
 static const char* jsCacheDir = nullptr;
 static const char* jsCacheAsmJSPath = nullptr;
 static RCFile* gErrFile = nullptr;
@@ -8522,32 +8521,30 @@ SetContextOptions(JSContext* cx, const O
     enableWasmBaseline = !op.getBoolOption("no-wasm-baseline");
     enableWasmIon = !op.getBoolOption("no-wasm-ion");
 #ifdef ENABLE_WASM_GC
     enableWasmGc = op.getBoolOption("wasm-gc");
 #endif
     enableTestWasmAwaitTier2 = op.getBoolOption("test-wasm-await-tier2");
     enableAsyncStacks = !op.getBoolOption("no-async-stacks");
     enableStreams = op.getBoolOption("enable-streams");
-    enableArrayProtoValues = !op.getBoolOption("no-array-proto-values");
 
     JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
                              .setIon(enableIon)
                              .setAsmJS(enableAsmJS)
                              .setWasm(enableWasm)
                              .setWasmBaseline(enableWasmBaseline)
                              .setWasmIon(enableWasmIon)
 #ifdef ENABLE_WASM_GC
                              .setWasmGc(enableWasmGc)
 #endif
                              .setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
                              .setNativeRegExp(enableNativeRegExp)
                              .setAsyncStack(enableAsyncStacks)
-                             .setStreams(enableStreams)
-                             .setArrayProtoValues(enableArrayProtoValues);
+                             .setStreams(enableStreams);
 
     if (op.getBoolOption("no-unboxed-objects"))
         jit::JitOptions.disableUnboxedObjects = true;
 
     if (const char* str = op.getStringOption("cache-ir-stubs")) {
         if (strcmp(str, "on") == 0)
             jit::JitOptions.disableCacheIR = false;
         else if (strcmp(str, "off") == 0)
@@ -8832,18 +8829,18 @@ SetWorkerContextOptions(JSContext* cx)
                              .setWasm(enableWasm)
                              .setWasmBaseline(enableWasmBaseline)
                              .setWasmIon(enableWasmIon)
 #ifdef ENABLE_WASM_GC
                              .setWasmGc(enableWasmGc)
 #endif
                              .setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
                              .setNativeRegExp(enableNativeRegExp)
-                             .setStreams(enableStreams)
-                             .setArrayProtoValues(enableArrayProtoValues);
+                             .setStreams(enableStreams);
+
     cx->runtime()->setOffthreadIonCompilationEnabled(offthreadCompilation);
     cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
 #ifdef JS_GC_ZEAL
     if (gZealBits && gZealFrequency) {
         for (size_t i = 0; i < size_t(gc::ZealMode::Count); i++) {
             if (gZealBits & (1 << i))
                 cx->runtime()->gc.setZeal(i, gZealFrequency);
@@ -9089,17 +9086,16 @@ main(int argc, char** argv, char** envp)
 #ifdef ENABLE_WASM_GC
         || !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features")
 #else
         || !op.addBoolOption('\0', "wasm-gc", "No-op")
 #endif
         || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
         || !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
         || !op.addBoolOption('\0', "enable-streams", "Enable WHATWG Streams")
-        || !op.addBoolOption('\0', "no-array-proto-values", "Remove Array.prototype.values")
 #ifdef ENABLE_SHARED_ARRAY_BUFFER
         || !op.addStringOption('\0', "shared-memory", "on/off",
                                "SharedArrayBuffer and Atomics "
 #  if SHARED_MEMORY_DEFAULT
                                "(default: on, off to disable)"
 #  else
                                "(default: off, on to enable)"
 #  endif
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -10664,17 +10664,17 @@ DebuggerObject::unwrap(JSContext* cx, Ha
     if (!unwrapped) {
         result.set(nullptr);
         return true;
     }
 
     // Don't allow unwrapping to create a D.O whose referent is in an
     // invisible-to-Debugger global. (If our referent is a *wrapper* to such,
     // and the wrapper is in a visible realm, that's fine.)
-    if (unwrapped->realm()->creationOptions().invisibleToDebugger()) {
+    if (unwrapped->deprecatedRealm()->creationOptions().invisibleToDebugger()) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
         return false;
     }
 
     return dbg->wrapDebuggeeObject(cx, unwrapped, result);
 }
 
 /* static */ bool
@@ -11540,17 +11540,37 @@ Debugger::isDebuggerCrossCompartmentEdge
     } else if (obj->is<DebuggerObject>()) {
         referent = static_cast<gc::Cell*>(obj->as<DebuggerObject>().getPrivate());
     } else if (obj->is<DebuggerEnvironment>()) {
         referent = static_cast<gc::Cell*>(obj->as<DebuggerEnvironment>().getPrivate());
     }
 
     return referent == target;
 }
-#endif
+
+static void
+CheckDebuggeeThingRealm(Realm* realm, bool invisibleOk)
+{
+    MOZ_ASSERT(!realm->creationOptions().mergeable());
+    MOZ_ASSERT_IF(!invisibleOk, !realm->creationOptions().invisibleToDebugger());
+}
+
+void
+js::CheckDebuggeeThing(JSScript* script, bool invisibleOk)
+{
+    CheckDebuggeeThingRealm(script->realm(), invisibleOk);
+}
+
+void
+js::CheckDebuggeeThing(JSObject* obj, bool invisibleOk)
+{
+    if (Realm* realm = JS::GetObjectRealmOrNull(obj))
+        CheckDebuggeeThingRealm(realm, invisibleOk);
+}
+#endif // DEBUG
 
 
 /*** JS::dbg::GarbageCollectionEvent **************************************************************/
 
 namespace JS {
 namespace dbg {
 
 /* static */ GarbageCollectionEvent::Ptr
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -84,16 +84,24 @@ class DebuggerMemory;
 class ScriptedOnStepHandler;
 class ScriptedOnPopHandler;
 class WasmInstanceObject;
 
 typedef HashSet<ReadBarrieredGlobalObject,
                 MovableCellHasher<ReadBarrieredGlobalObject>,
                 ZoneAllocPolicy> WeakGlobalObjectSet;
 
+#ifdef DEBUG
+extern void
+CheckDebuggeeThing(JSScript* script, bool invisibleOk);
+
+extern void
+CheckDebuggeeThing(JSObject* obj, bool invisibleOk);
+#endif
+
 /*
  * A weakmap from GC thing keys to JSObject values that supports the keys being
  * in different compartments to the values. All values must be in the same
  * compartment.
  *
  * The purpose of this is to allow the garbage collector to easily find edges
  * from debuggee object compartments to debugger compartments when calculating
  * the compartment groups.  Note that these edges are the inverse of the edges
@@ -156,19 +164,19 @@ class DebuggerWeakMap : private WeakMap<
 
     MOZ_MUST_USE bool init(uint32_t len = 16) {
         return Base::init(len) && zoneCounts.init();
     }
 
     template<typename KeyInput, typename ValueInput>
     bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
         MOZ_ASSERT(v->compartment() == this->compartment);
-        MOZ_ASSERT(!k->realm()->creationOptions().mergeable());
-        MOZ_ASSERT_IF(!InvisibleKeysOk,
-                      !k->realm()->creationOptions().invisibleToDebugger());
+#ifdef DEBUG
+        CheckDebuggeeThing(k, InvisibleKeysOk);
+#endif
         MOZ_ASSERT(!Base::has(k));
         if (!incZoneCount(k->zone()))
             return false;
         bool ok = Base::relookupOrAdd(p, k, v);
         if (!ok)
             decZoneCount(k->zone());
         return ok;
     }
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -2547,17 +2547,17 @@ DebugEnvironments::hasDebugEnvironment(J
     return nullptr;
 }
 
 /* static */ bool
 DebugEnvironments::addDebugEnvironment(JSContext* cx, Handle<EnvironmentObject*> env,
                                        Handle<DebugEnvironmentProxy*> debugEnv)
 {
     MOZ_ASSERT(cx->realm() == env->realm());
-    MOZ_ASSERT(cx->realm() == debugEnv->realm());
+    MOZ_ASSERT(cx->realm() == debugEnv->nonCCWRealm());
 
     if (!CanUseDebugEnvironmentMaps(cx))
         return true;
 
     DebugEnvironments* envs = ensureRealmData(cx);
     if (!envs)
         return false;
 
@@ -2580,17 +2580,17 @@ DebugEnvironments::hasDebugEnvironment(J
     return nullptr;
 }
 
 /* static */ bool
 DebugEnvironments::addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
                                        Handle<DebugEnvironmentProxy*> debugEnv)
 {
     MOZ_ASSERT(!ei.hasSyntacticEnvironment());
-    MOZ_ASSERT(cx->realm() == debugEnv->realm());
+    MOZ_ASSERT(cx->realm() == debugEnv->nonCCWRealm());
     // Generators should always have environments.
     MOZ_ASSERT_IF(ei.scope().is<FunctionScope>(),
                   !ei.scope().as<FunctionScope>().canonicalFunction()->isGenerator() &&
                   !ei.scope().as<FunctionScope>().canonicalFunction()->isAsync());
 
     if (!CanUseDebugEnvironmentMaps(cx))
         return true;
 
@@ -2862,17 +2862,17 @@ DebugEnvironments::updateLiveEnvironment
      * fp, simply popping fp effectively clears the flag for us, at exactly
      * the time when execution resumes fp->prev().
      */
     for (AllFramesIter i(cx); !i.done(); ++i) {
         if (!i.hasUsableAbstractFramePtr())
             continue;
 
         AbstractFramePtr frame = i.abstractFramePtr();
-        if (frame.environmentChain()->realm() != cx->realm())
+        if (frame.realm() != cx->realm())
             continue;
 
         if (frame.isFunctionFrame()) {
             if (frame.callee()->isGenerator() || frame.callee()->isAsync())
                 continue;
         }
 
         if (!frame.isDebuggee())
@@ -2891,17 +2891,17 @@ DebugEnvironments::updateLiveEnvironment
                     return false;
                 if (!envs->liveEnvs.put(&ei.environment(), LiveEnvironmentVal(ei)))
                     return false;
             }
         }
 
         if (frame.prevUpToDate())
             return true;
-        MOZ_ASSERT(frame.environmentChain()->realm()->isDebuggee());
+        MOZ_ASSERT(frame.realm()->isDebuggee());
         frame.setPrevUpToDate();
     }
 
     return true;
 }
 
 LiveEnvironmentVal*
 DebugEnvironments::hasLiveEnvironment(EnvironmentObject& env)
@@ -2930,17 +2930,17 @@ DebugEnvironments::unsetPrevUpToDateUnti
     for (AllFramesIter i(cx); !i.done(); ++i) {
         if (!i.hasUsableAbstractFramePtr())
             continue;
 
         AbstractFramePtr frame = i.abstractFramePtr();
         if (frame == until)
             return;
 
-        if (frame.environmentChain()->realm() != cx->realm())
+        if (frame.realm() != cx->realm())
             continue;
 
         frame.unsetPrevUpToDate();
     }
 }
 
 /* static */ void
 DebugEnvironments::forwardLiveFrame(JSContext* cx, AbstractFramePtr from, AbstractFramePtr to)
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -186,16 +186,20 @@ js::CancelOffThreadWasmTier2Generator()
 }
 
 bool
 js::StartOffThreadIonCompile(jit::IonBuilder* builder, const AutoLockHelperThreadState& lock)
 {
     if (!HelperThreadState().ionWorklist(lock).append(builder))
         return false;
 
+    // The build is moving off-thread. Freeze the LifoAlloc to prevent any
+    // unwanted mutations.
+    builder->alloc().lifoAlloc()->setReadOnly();
+
     HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER, lock);
     return true;
 }
 
 bool
 js::StartOffThreadIonFree(jit::IonBuilder* builder, const AutoLockHelperThreadState& lock)
 {
     MOZ_ASSERT(CanUseExtraThreads());
@@ -1992,16 +1996,20 @@ HelperThread::handleIonWorkload(AutoLock
 {
     MOZ_ASSERT(HelperThreadState().canStartIonCompile(locked));
     MOZ_ASSERT(idle());
 
     // Find the IonBuilder in the worklist with the highest priority, and
     // remove it from the worklist.
     jit::IonBuilder* builder = HelperThreadState().highestPriorityPendingIonCompile(locked);
 
+    // The build is taken by this thread. Unfreeze the LifoAlloc to allow
+    // mutations.
+    builder->alloc().lifoAlloc()->setReadWrite();
+
     currentTask.emplace(builder);
 
     JSRuntime* rt = builder->script()->compartment()->runtimeFromAnyThread();
 
     {
         AutoUnlockHelperThreadState unlock(locked);
 
         TraceLoggerThread* logger = TraceLoggerForCurrentThread();
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -283,19 +283,19 @@ HasOwnProperty(JSContext* cx, HandleValu
         return false;
 
     // Step 3.
     return HasOwnProperty(cx, obj, key, result);
 }
 
 
 inline bool
-GetIntrinsicOperation(JSContext* cx, jsbytecode* pc, MutableHandleValue vp)
+GetIntrinsicOperation(JSContext* cx, HandleScript script, jsbytecode* pc, MutableHandleValue vp)
 {
-    RootedPropertyName name(cx, cx->currentScript()->getName(pc));
+    RootedPropertyName name(cx, script->getName(pc));
     return GlobalObject::getIntrinsicValue(cx, cx->global(), name, vp);
 }
 
 inline bool
 SetIntrinsicOperation(JSContext* cx, JSScript* script, jsbytecode* pc, HandleValue val)
 {
     RootedPropertyName name(cx, script->getName(pc));
     return GlobalObject::setIntrinsicValue(cx, cx->global(), name, val);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3265,17 +3265,17 @@ CASE(JSOP_GETIMPORT)
 
     TypeScript::Monitor(cx, script, REGS.pc, rval);
 }
 END_CASE(JSOP_GETIMPORT)
 
 CASE(JSOP_GETINTRINSIC)
 {
     ReservedRooted<Value> rval(&rootValue0);
-    if (!GetIntrinsicOperation(cx, REGS.pc, &rval))
+    if (!GetIntrinsicOperation(cx, script, REGS.pc, &rval))
         goto error;
 
     PUSH_COPY(rval);
     TypeScript::Monitor(cx, script, REGS.pc, rval);
 }
 END_CASE(JSOP_GETINTRINSIC)
 
 CASE(JSOP_UINT16)
--- a/js/src/vm/JSContext-inl.h
+++ b/js/src/vm/JSContext-inl.h
@@ -473,19 +473,32 @@ JSContext::enterAtomsZone(const js::Auto
     // Only one thread can be in the atoms zone at a time.
     MOZ_ASSERT(runtime_->currentThreadHasExclusiveAccess());
 
     realm_ = nullptr;
     zone_ = runtime_->atomsZone(lock);
     arenas_ = &zone_->arenas;
 }
 
-template <typename T>
+inline void
+JSContext::enterRealmOf(JSObject* target)
+{
+    MOZ_ASSERT(JS::CellIsNotGray(target));
+    enterRealm(target->deprecatedRealm());
+}
+
 inline void
-JSContext::enterRealmOf(const T& target)
+JSContext::enterRealmOf(JSScript* target)
+{
+    MOZ_ASSERT(JS::CellIsNotGray(target));
+    enterRealm(target->realm());
+}
+
+inline void
+JSContext::enterRealmOf(js::ObjectGroup* target)
 {
     MOZ_ASSERT(JS::CellIsNotGray(target));
     enterRealm(target->realm());
 }
 
 inline void
 JSContext::enterNullRealm()
 {
@@ -524,53 +537,51 @@ JSContext::setRealm(JS::Realm* realm)
     MOZ_ASSERT_IF(realm, CurrentThreadCanAccessZone(realm->zone()));
 
     realm_ = realm;
     zone_ = realm ? realm->zone() : nullptr;
     arenas_ = zone_ ? &zone_->arenas : nullptr;
 }
 
 inline JSScript*
-JSContext::currentScript(jsbytecode** ppc,
-                         MaybeAllowCrossCompartment allowCrossCompartment) const
+JSContext::currentScript(jsbytecode** ppc, AllowCrossRealm allowCrossRealm) const
 {
     if (ppc)
         *ppc = nullptr;
 
     js::Activation* act = activation();
     if (!act)
         return nullptr;
 
     MOZ_ASSERT(act->cx() == this);
 
-    if (!allowCrossCompartment && act->compartment() != compartment())
+    // Cross-compartment implies cross-realm.
+    if (allowCrossRealm == AllowCrossRealm::DontAllow && act->compartment() != compartment())
         return nullptr;
 
+    JSScript* script = nullptr;
+    jsbytecode* pc = nullptr;
     if (act->isJit()) {
         if (act->hasWasmExitFP())
             return nullptr;
-        JSScript* script = nullptr;
-        js::jit::GetPcScript(const_cast<JSContext*>(this), &script, ppc);
-        MOZ_ASSERT(allowCrossCompartment || script->compartment() == compartment());
-        return script;
+        js::jit::GetPcScript(const_cast<JSContext*>(this), &script, &pc);
+    } else {
+        js::InterpreterFrame* fp = act->asInterpreter()->current();
+        MOZ_ASSERT(!fp->runningInJit());
+        script = fp->script();
+        pc = act->asInterpreter()->regs().pc;
     }
 
-    MOZ_ASSERT(act->isInterpreter());
-
-    js::InterpreterFrame* fp = act->asInterpreter()->current();
-    MOZ_ASSERT(!fp->runningInJit());
+    MOZ_ASSERT(script->containsPC(pc));
 
-    JSScript* script = fp->script();
-    MOZ_ASSERT(allowCrossCompartment || script->compartment() == compartment());
+    if (allowCrossRealm == AllowCrossRealm::DontAllow && script->realm() != realm())
+        return nullptr;
 
-    if (ppc) {
-        *ppc = act->asInterpreter()->regs().pc;
-        MOZ_ASSERT(script->containsPC(*ppc));
-    }
-
+    if (ppc)
+        *ppc = pc;
     return script;
 }
 
 inline js::RuntimeCaches&
 JSContext::caches()
 {
     return runtime()->caches();
 }
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -207,18 +207,19 @@ struct JSContext : public JS::RootingCon
     inline void setRealm(JS::Realm* realm);
     inline void enterRealm(JS::Realm* realm);
     inline void enterAtomsZone(const js::AutoLockForExclusiveAccess& lock);
 
     friend class js::AutoAtomsZone;
     friend class js::AutoRealm;
 
   public:
-    template <typename T>
-    inline void enterRealmOf(const T& target);
+    inline void enterRealmOf(JSObject* target);
+    inline void enterRealmOf(JSScript* target);
+    inline void enterRealmOf(js::ObjectGroup* target);
     inline void enterNullRealm();
 
     inline void leaveRealm(JS::Realm* oldRealm);
     inline void leaveAtomsZone(JS::Realm* oldRealm,
                                const js::AutoLockForExclusiveAccess& lock);
 
     void setHelperThread(js::HelperThread* helperThread);
     js::HelperThread* helperThread() const { return helperThread_; }
@@ -704,26 +705,27 @@ struct JSContext : public JS::RootingCon
         return activation()->asInterpreter()->current();
     }
     js::InterpreterRegs& interpreterRegs() const {
         return activation()->asInterpreter()->regs();
     }
 
     /*
      * Get the topmost script and optional pc on the stack. By default, this
-     * function only returns a JSScript in the current compartment, returning
-     * nullptr if the current script is in a different compartment. This
-     * behavior can be overridden by passing ALLOW_CROSS_COMPARTMENT.
+     * function only returns a JSScript in the current realm, returning nullptr
+     * if the current script is in a different realm. This behavior can be
+     * overridden by passing AllowCrossRealm::Allow.
      */
-    enum MaybeAllowCrossCompartment {
-        DONT_ALLOW_CROSS_COMPARTMENT = false,
-        ALLOW_CROSS_COMPARTMENT = true
+    enum class AllowCrossRealm {
+        DontAllow = false,
+        Allow = true
     };
-    inline JSScript* currentScript(jsbytecode** pc = nullptr,
-                                   MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const;
+    inline JSScript*
+    currentScript(jsbytecode** pc = nullptr,
+                  AllowCrossRealm allowCrossRealm = AllowCrossRealm::DontAllow) const;
 
     inline js::Nursery& nursery();
     inline void minorGC(JS::gcreason::Reason reason);
 
   public:
     bool isExceptionPending() const {
         return throwing;
     }
--- a/js/src/vm/JSObject-inl.h
+++ b/js/src/vm/JSObject-inl.h
@@ -388,31 +388,29 @@ SetNewObjectMetadata(JSContext* cx, T* o
     return obj;
 }
 
 } // namespace js
 
 inline js::GlobalObject&
 JSObject::deprecatedGlobal() const
 {
-    return *realm()->unsafeUnbarrieredMaybeGlobal();
+    return *deprecatedRealm()->unsafeUnbarrieredMaybeGlobal();
 }
 
 inline js::GlobalObject&
 JSObject::nonCCWGlobal() const
 {
-    MOZ_ASSERT(!js::IsCrossCompartmentWrapper(this));
-
     /*
      * The global is read-barriered so that it is kept live by access through
      * the Realm. When accessed through a JSObject, however, the global will be
      * already kept live by the black JSObject's group pointer, so does not
      * need to be read-barriered.
      */
-    return *realm()->unsafeUnbarrieredMaybeGlobal();
+    return *nonCCWRealm()->unsafeUnbarrieredMaybeGlobal();
 }
 
 inline bool
 JSObject::hasAllFlags(js::BaseShape::Flag flags) const
 {
     MOZ_ASSERT(flags);
     if (js::Shape* shape = maybeShape())
         return shape->hasAllObjectFlags(flags);
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -2987,21 +2987,16 @@ PropertySpecNameToId(JSContext* cx, cons
 static bool
 DefineFunctionFromSpec(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs, unsigned flags,
                        DefineAsIntrinsic intrinsic)
 {
     RootedId id(cx);
     if (!PropertySpecNameToId(cx, fs->name, &id))
         return false;
 
-    if (StandardProtoKeyOrNull(obj) == JSProto_Array && id == NameToId(cx->names().values)) {
-        if (!cx->options().arrayProtoValues())
-            return true;
-    }
-
     JSFunction* fun = NewFunctionFromSpec(cx, fs, id);
     if (!fun)
         return false;
 
     if (intrinsic == AsIntrinsic)
         fun->setIsIntrinsic();
 
     RootedValue funVal(cx, ObjectValue(*fun));
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -157,17 +157,16 @@ class JSObject : public js::gc::Cell
      * might have a lazy group, use getGroup() below, otherwise group().
      */
     bool hasLazyGroup() const {
         return group_->lazy();
     }
 
     JS::Compartment* compartment() const { return group_->compartment(); }
     JS::Compartment* maybeCompartment() const { return compartment(); }
-    JS::Realm* realm() const { return group_->realm(); }
 
     inline js::Shape* maybeShape() const;
     inline js::Shape* ensureShape(JSContext* cx);
 
     enum GenerateShape {
         GENERATE_NONE,
         GENERATE_SHAPE
     };
@@ -428,19 +427,37 @@ class JSObject : public js::gc::Cell
      * non-EnvironmentObjects can be on the environment chain).
      */
     inline JSObject* enclosingEnvironment() const;
 
     // Deprecated: call nonCCWGlobal or NativeObject::global() instead!
     inline js::GlobalObject& deprecatedGlobal() const;
 
     // Cross-compartment wrappers are not associated with a single realm/global,
-    // so this method asserts the object is not a CCW.
+    // so these methods assert the object is not a CCW.
     inline js::GlobalObject& nonCCWGlobal() const;
 
+    JS::Realm* nonCCWRealm() const {
+        MOZ_ASSERT(!js::IsCrossCompartmentWrapper(this));
+        return group_->realm();
+    }
+
+    // Returns the object's realm even if the object is a CCW (be careful, in
+    // this case the realm is not very meaningful because wrappers are shared by
+    // all realms in the compartment).
+    JS::Realm* maybeCCWRealm() const {
+        return group_->realm();
+    }
+
+    // Deprecated: call nonCCWRealm(), maybeCCWRealm(), or NativeObject::realm()
+    // instead!
+    JS::Realm* deprecatedRealm() const {
+        return group_->realm();
+    }
+
     /*
      * ES5 meta-object properties and operations.
      */
 
   public:
     // Indicates whether a non-proxy is extensible.  Don't call on proxies!
     // This method really shouldn't exist -- but there are a few internal
     // places that want it (JITs and the like), and it'd be a pain to mark them
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3314,42 +3314,46 @@ js::GetScriptLineExtent(JSScript* script
         if (maxLineNo < lineno)
             maxLineNo = lineno;
     }
 
     return 1 + maxLineNo - script->lineno();
 }
 
 void
-js::DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
-                                         const char** file, unsigned* linenop,
-                                         uint32_t* pcOffset, bool* mutedErrors,
-                                         LineOption opt)
+js::DescribeScriptedCallerForDirectEval(JSContext* cx, HandleScript script, jsbytecode* pc,
+                                        const char** file, unsigned* linenop, uint32_t* pcOffset,
+                                        bool* mutedErrors)
 {
-    if (opt == CALLED_FROM_JSOP_EVAL) {
-        jsbytecode* pc = nullptr;
-        maybeScript.set(cx->currentScript(&pc));
-        static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
-                    "next op after a spread must be at consistent offset");
-        static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH,
-                    "next op after a direct eval must be at consistent offset");
-        MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_STRICTEVAL ||
-                   JSOp(*pc) == JSOP_SPREADEVAL || JSOp(*pc) == JSOP_STRICTSPREADEVAL);
-
-        bool isSpread = JSOp(*pc) == JSOP_SPREADEVAL || JSOp(*pc) == JSOP_STRICTSPREADEVAL;
-        jsbytecode* nextpc = pc + (isSpread ? JSOP_SPREADEVAL_LENGTH : JSOP_EVAL_LENGTH);
-        MOZ_ASSERT(*nextpc == JSOP_LINENO);
-
-        *file = maybeScript->filename();
-        *linenop = GET_UINT32(nextpc);
-        *pcOffset = pc - maybeScript->code();
-        *mutedErrors = maybeScript->mutedErrors();
-        return;
-    }
-
+    MOZ_ASSERT(script->containsPC(pc));
+
+    static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
+                  "next op after a spread must be at consistent offset");
+    static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH,
+                  "next op after a direct eval must be at consistent offset");
+
+    MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_STRICTEVAL ||
+               JSOp(*pc) == JSOP_SPREADEVAL || JSOp(*pc) == JSOP_STRICTSPREADEVAL);
+
+    bool isSpread = (JSOp(*pc) == JSOP_SPREADEVAL ||
+                     JSOp(*pc) == JSOP_STRICTSPREADEVAL);
+    jsbytecode* nextpc = pc + (isSpread ? JSOP_SPREADEVAL_LENGTH : JSOP_EVAL_LENGTH);
+    MOZ_ASSERT(*nextpc == JSOP_LINENO);
+
+    *file = script->filename();
+    *linenop = GET_UINT32(nextpc);
+    *pcOffset = script->pcToOffset(pc);
+    *mutedErrors = script->mutedErrors();
+}
+
+void
+js::DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
+                                         const char** file, unsigned* linenop, uint32_t* pcOffset,
+                                         bool* mutedErrors)
+{
     NonBuiltinFrameIter iter(cx, cx->realm()->principals());
 
     if (iter.done()) {
         maybeScript.set(nullptr);
         *file = nullptr;
         *linenop = 0;
         *pcOffset = 0;
         *mutedErrors = false;
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2521,31 +2521,31 @@ PCToLineNumber(JSScript* script, jsbytec
 extern unsigned
 PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbytecode* pc,
                unsigned* columnp = nullptr);
 
 /*
  * This function returns the file and line number of the script currently
  * executing on cx. If there is no current script executing on cx (e.g., a
  * native called directly through JSAPI (e.g., by setTimeout)), nullptr and 0
- * are returned as the file and line. Additionally, this function avoids the
- * full linear scan to compute line number when the caller guarantees that the
- * script compilation occurs at a JSOP_EVAL/JSOP_SPREADEVAL.
+ * are returned as the file and line.
  */
-
-enum LineOption {
-    CALLED_FROM_JSOP_EVAL,
-    NOT_CALLED_FROM_JSOP_EVAL
-};
-
 extern void
 DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
-                                     const char** file, unsigned* linenop,
-                                     uint32_t* pcOffset, bool* mutedErrors,
-                                     LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
+                                     const char** file, unsigned* linenop, uint32_t* pcOffset,
+                                     bool* mutedErrors);
+
+/*
+ * Like DescribeScriptedCallerForCompilation, but this function avoids looking
+ * up the script/pc and the full linear scan to compute line number.
+ */
+extern void
+DescribeScriptedCallerForDirectEval(JSContext* cx, HandleScript script, jsbytecode* pc,
+                                    const char** file, unsigned* linenop, uint32_t* pcOffset,
+                                    bool* mutedErrors);
 
 JSScript*
 CloneScriptIntoFunction(JSContext* cx, HandleScope enclosingScope, HandleFunction fun,
                         HandleScript src);
 
 JSScript*
 CloneGlobalScript(JSContext* cx, ScopeKind scopeKind, HandleScript src);
 
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -456,17 +456,17 @@ StatsCellCallback(JSRuntime* rt, void* d
                   size_t thingSize)
 {
     StatsClosure* closure = static_cast<StatsClosure*>(data);
     RuntimeStats* rtStats = closure->rtStats;
     ZoneStats* zStats = rtStats->currZoneStats;
     switch (traceKind) {
       case JS::TraceKind::Object: {
         JSObject* obj = static_cast<JSObject*>(thing);
-        RealmStats& realmStats = obj->realm()->realmStats();
+        RealmStats& realmStats = obj->maybeCCWRealm()->realmStats();
         JS::ClassInfo info;        // This zeroes all the sizes.
         info.objectsGCHeap += thingSize;
 
         obj->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);
 
         // These classes require special handling due to shared resources which
         // we must be careful not to report twice.
         if (obj->is<WasmModuleObject>()) {
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -2431,17 +2431,17 @@ js::GetNameBoundInEnvironment(JSContext*
 /*** [[Set]] *************************************************************************************/
 
 static bool
 MaybeReportUndeclaredVarAssignment(JSContext* cx, HandleString propname)
 {
     unsigned flags;
     {
         jsbytecode* pc;
-        JSScript* script = cx->currentScript(&pc, JSContext::ALLOW_CROSS_COMPARTMENT);
+        JSScript* script = cx->currentScript(&pc, JSContext::AllowCrossRealm::Allow);
         if (!script)
             return true;
 
         // If the code is not strict and extra warnings aren't enabled, then no
         // check is needed.
         if (IsStrictSetPC(pc))
             flags = JSREPORT_ERROR;
         else if (cx->realm()->behaviors().extraWarnings(cx))
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -1469,18 +1469,20 @@ class NativeObject : public ShapedObject
     inline js::gc::AllocKind allocKindForTenure() const;
 
     void updateShapeAfterMovingGC();
     void sweepDictionaryListPointer();
     void updateDictionaryListPointerAfterMinorGC(NativeObject* old);
 
     // Native objects are never wrappers, so a native object always has a realm
     // and global.
+    JS::Realm* realm() const {
+        return nonCCWRealm();
+    }
     inline js::GlobalObject& global() const;
-    JS::Realm* realm() const { return JSObject::realm(); }
 
     /* JIT Accessors */
     static size_t offsetOfElements() { return offsetof(NativeObject, elements_); }
     static size_t offsetOfFixedElements() {
         return sizeof(NativeObject) + sizeof(ObjectElements);
     }
 
     static size_t getFixedSlotOffset(size_t slot) {
--- a/js/src/vm/Realm-inl.h
+++ b/js/src/vm/Realm-inl.h
@@ -41,17 +41,20 @@ JS::Realm::globalIsAboutToBeFinalized()
 {
     MOZ_ASSERT(zone_->isGCSweeping());
     return global_ && js::gc::IsAboutToBeFinalizedUnbarriered(global_.unsafeGet());
 }
 
 /* static */ inline js::ObjectRealm&
 js::ObjectRealm::get(const JSObject* obj)
 {
-    return obj->realm()->objects_;
+    // Note: obj might be a CCW if we're accessing ObjectRealm::enumerators.
+    // CCWs here are fine because we always return the same ObjectRealm for a
+    // particular (CCW) object.
+    return obj->maybeCCWRealm()->objects_;
 }
 
 template <typename T>
 js::AutoRealm::AutoRealm(JSContext* cx, const T& target)
   : cx_(cx),
     origin_(cx->realm())
 {
     cx_->enterRealmOf(target);
--- a/js/src/vm/Realm.cpp
+++ b/js/src/vm/Realm.cpp
@@ -637,22 +637,22 @@ Realm::forgetAllocationMetadataBuilder()
     CancelOffThreadIonCompile(this);
 
     allocationMetadataBuilder_ = nullptr;
 }
 
 void
 Realm::setNewObjectMetadata(JSContext* cx, HandleObject obj)
 {
-    MOZ_ASSERT(obj->realm() == this);
+    MOZ_ASSERT(obj->maybeCCWRealm() == this);
     assertSameCompartment(cx, compartment(), obj);
 
     AutoEnterOOMUnsafeRegion oomUnsafe;
     if (JSObject* metadata = allocationMetadataBuilder_->build(cx, obj, oomUnsafe)) {
-        MOZ_ASSERT(metadata->realm() == obj->realm());
+        MOZ_ASSERT(metadata->maybeCCWRealm() == obj->maybeCCWRealm());
         assertSameCompartment(cx, metadata);
 
         if (!objects_.objectMetadataTable) {
             auto table = cx->make_unique<ObjectWeakMap>(cx);
             if (!table || !table->init())
                 oomUnsafe.crash("setNewObjectMetadata");
 
             objects_.objectMetadataTable = std::move(table);
@@ -1011,17 +1011,17 @@ JS_PUBLIC_API(JS::Realm*)
 JS::GetCurrentRealmOrNull(JSContext* cx)
 {
     return cx->realm();
 }
 
 JS_PUBLIC_API(JS::Realm*)
 JS::GetObjectRealmOrNull(JSObject* obj)
 {
-    return IsCrossCompartmentWrapper(obj) ? nullptr : obj->realm();
+    return IsCrossCompartmentWrapper(obj) ? nullptr : obj->nonCCWRealm();
 }
 
 JS_PUBLIC_API(void*)
 JS::GetRealmPrivate(JS::Realm* realm)
 {
     return realm->realmPrivate();
 }
 
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -779,25 +779,25 @@ public:
     AutoMaybeEnterFrameRealm(JSContext* cx,
                              HandleObject obj
                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
         MOZ_RELEASE_ASSERT(cx->realm());
         if (obj)
-            MOZ_RELEASE_ASSERT(obj->realm());
+            MOZ_RELEASE_ASSERT(obj->deprecatedRealm());
 
         // Note that obj might be null here, since we're doing this before
         // UnwrapSavedFrame.
-        if (obj && cx->realm() != obj->realm())
+        if (obj && cx->realm() != obj->deprecatedRealm())
         {
             JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes;
             if (subsumes && subsumes(cx->realm()->principals(),
-                                     obj->realm()->principals()))
+                                     obj->deprecatedRealm()->principals()))
             {
                 ar_.emplace(cx, obj);
             }
         }
     }
 
  private:
     Maybe<JSAutoRealm> ar_;
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -492,17 +492,17 @@ inline bool
 AbstractFramePtr::pushVarEnvironment(JSContext* cx, HandleScope scope)
 {
     return js::PushVarEnvironmentObject(cx, scope, *this);
 }
 
 inline JS::Realm*
 AbstractFramePtr::realm() const
 {
-    return environmentChain()->realm();
+    return environmentChain()->nonCCWRealm();
 }
 
 inline unsigned
 AbstractFramePtr::numActualArgs() const
 {
     if (isInterpreterFrame())
         return asInterpreterFrame()->numActualArgs();
     if (isBaselineFrame())
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -805,18 +805,16 @@ ReloadPrefsCallback(const char* pref, vo
         JS_SetGCZeal(cx, (uint8_t)zeal, zeal_frequency);
     }
 #endif // JS_GC_ZEAL
 
 #ifdef FUZZING
     bool fuzzingEnabled = Preferences::GetBool("fuzzing.enabled");
 #endif
 
-    bool arrayProtoValues = Preferences::GetBool(JS_OPTIONS_DOT_STR "array_prototype_values");
-
     JS::ContextOptionsRef(cx).setBaseline(useBaseline)
                              .setIon(useIon)
                              .setAsmJS(useAsmJS)
                              .setWasm(useWasm)
                              .setWasmIon(useWasmIon)
                              .setWasmBaseline(useWasmBaseline)
 #ifdef ENABLE_WASM_GC
                              .setWasmGc(useWasmGc)
@@ -826,18 +824,17 @@ ReloadPrefsCallback(const char* pref, vo
                              .setAsyncStack(useAsyncStack)
                              .setThrowOnDebuggeeWouldRun(throwOnDebuggeeWouldRun)
                              .setDumpStackOnDebuggeeWouldRun(dumpStackOnDebuggeeWouldRun)
                              .setWerror(werror)
 #ifdef FUZZING
                              .setFuzzing(fuzzingEnabled)
 #endif
                              .setStreams(streams)
-                             .setExtraWarnings(extraWarnings)
-                             .setArrayProtoValues(arrayProtoValues);
+                             .setExtraWarnings(extraWarnings);
 
     nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
     if (xr) {
         bool safeMode = false;
         xr->GetInSafeMode(&safeMode);
         if (safeMode) {
             JS::ContextOptionsRef(cx).disableOptionsForSafeMode();
         }
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -98,16 +98,17 @@
 #include "nsApplicationCacheService.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "TouchManager.h"
 #include "DecoderDoctorLogger.h"
 #include "MediaDecoder.h"
+#include "mozilla/ClearSiteData.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StaticPresData.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
 #include "mozilla/dom/U2FTokenManager.h"
 #include "mozilla/dom/PointerEventHandler.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "nsThreadManager.h"
@@ -280,16 +281,18 @@ nsLayoutStatics::Initialize()
   if (XRE_IsParentProcess()) {
     // On content process we initialize DOMPrefs when PContentChild is fully
     // initialized.
     mozilla::dom::DOMPrefs::Initialize();
   }
 
   nsThreadManager::InitializeShutdownObserver();
 
+  ClearSiteData::Initialize();
+
   return NS_OK;
 }
 
 void
 nsLayoutStatics::Shutdown()
 {
   // Don't need to shutdown nsWindowMemoryReporter, that will be done by the
   // memory reporter manager.
@@ -388,9 +391,11 @@ nsLayoutStatics::Shutdown()
 
   DisplayItemClip::Shutdown();
 
   CacheObserver::Shutdown();
 
   PromiseDebugging::Shutdown();
 
   BlobURLProtocolHandler::RemoveDataEntries();
+
+  ClearSiteData::Shutdown();
 }
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -239,16 +239,17 @@ DisplayItemData::DisplayItemData(LayerMa
   }
 
 }
 
 void
 DisplayItemData::AddFrame(nsIFrame* aFrame)
 {
   MOZ_RELEASE_ASSERT(mLayer);
+  MOZ_RELEASE_ASSERT(!mFrameList.Contains(aFrame));
   mFrameList.AppendElement(aFrame);
 
   SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
   array.AppendElement(this);
 }
 
 void
 DisplayItemData::RemoveFrame(nsIFrame* aFrame)
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2776,17 +2776,17 @@ public:
 
   bool In3DContextAndBackfaceIsHidden()
   {
     return mBackfaceHidden;
   }
 
   bool HasSameTypeAndClip(const nsDisplayItem* aOther) const
   {
-    return GetType() == aOther->GetType() &&
+    return GetPerFrameKey() == aOther->GetPerFrameKey() &&
            GetClipChain() == aOther->GetClipChain();
   }
 
   bool HasSameContent(const nsDisplayItem* aOther) const
   {
     return mFrame->GetContent() == aOther->Frame()->GetContent();
   }
 
@@ -5695,22 +5695,16 @@ public:
   NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
     return mozilla::LAYER_ACTIVE;
   }
 
-  virtual bool CanMerge(const nsDisplayItem* aItem) const override
-  {
-    // Items with the same fixed position frame can be merged.
-    return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
-  }
-
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   const ActiveScrolledRoot* GetContainerASR() const
   {
@@ -5762,22 +5756,16 @@ public:
   NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
     return mozilla::LAYER_ACTIVE_FORCE;
   }
 
-  virtual bool CanMerge(const nsDisplayItem* aItem) const override
-  {
-    // Items with the same fixed position frame can be merged.
-    return HasSameTypeAndClip(aItem) && mFrame == aItem->Frame();
-  }
-
   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const override
   {
     return mIsFixedBackground;
   }
 
   virtual uint32_t GetPerFrameKey() const override {
     return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
   }
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1469076.html
@@ -0,0 +1,12 @@
+<style>
+* { display: contents }
+</style>
+<script>
+function go() {
+  a.parentElement.animate({"ping": [0, 1]}, 0.281207776578);
+}
+</script>
+<body onload=go()>
+></br>
+<shadow>
+<details id="a">
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -284,8 +284,9 @@ pref(dom.webcomponents.shadowdom.enabled
 pref(dom.webcomponents.shadowdom.enabled,true) load 1449243.html
 load 1450691.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1453206.html
 load 1454140.html
 load 1455108.html
 load 1457288.html
 load 1457985.html
 pref(dom.webcomponents.shadowdom.enabled,true) load 1468640.html
+load 1469076.html
--- a/layout/tools/reftest/reftest.jsm
+++ b/layout/tools/reftest/reftest.jsm
@@ -374,16 +374,17 @@ function ReadTests() {
             });
         } else if (manifests) {
             // Parse reftest manifests
             logger.debug("Reading " + manifests.length + " manifests");
             manifests = JSON.parse(manifests);
             g.urlsFilterRegex = manifests[null];
 
             var globalFilter = manifests.hasOwnProperty("") ? new RegExp(manifests[""]) : null;
+            delete manifests[""];
             var manifestURLs = Object.keys(manifests);
 
             // Ensure we read manifests from higher up the directory tree first so that we
             // process includes before reading the included manifest again
             manifestURLs.sort(function(a,b) {return a.length - b.length})
             manifestURLs.forEach(function(manifestURL) {
                 logger.info("Reading manifest " + manifestURL);
                 var filter = manifests[manifestURL] ? new RegExp(manifests[manifestURL]) : null;
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -112,16 +112,32 @@ VARCACHE_PREF(
 )
 
 // If true. then the service worker interception and the ServiceWorkerManager
 // will live in the parent process.  This only takes effect on browser start.
 // Note, this is not currently safe to use for normal browsing yet.
 PREF("dom.serviceWorkers.parent_intercept", bool, false)
 
 //---------------------------------------------------------------------------
+// Clear-Site-Data prefs
+//---------------------------------------------------------------------------
+
+#ifdef NIGHTLY
+# define PREF_VALUE true
+#else
+# define PREF_VALUE false
+#endif
+VARCACHE_PREF(
+  "dom.clearSiteData.enabled",
+   dom_clearSiteData_enabled,
+  bool, PREF_VALUE
+)
+#undef PREF_VALUE
+
+//---------------------------------------------------------------------------
 // Full-screen prefs
 //---------------------------------------------------------------------------
 
 #ifdef RELEASE_OR_BETA
 # define PREF_VALUE false
 #else
 # define PREF_VALUE true
 #endif
@@ -1023,12 +1039,22 @@ PREF("preferences.allow.omt-write", bool
 
 VARCACHE_PREF(
   "view_source.editor.external",
    view_source_editor_external,
   bool, false
 )
 
 //---------------------------------------------------------------------------
+// Anti-Tracking prefs
+//---------------------------------------------------------------------------
+
+VARCACHE_PREF(
+  "privacy.trackingprotection.storagerestriction.enabled",
+   privacy_trackingprotection_storagerestriction_enabled,
+  RelaxedAtomicBool, false
+)
+
+//---------------------------------------------------------------------------
 // End of prefs
 //---------------------------------------------------------------------------
 
 // clang-format on
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1327,18 +1327,16 @@ pref("dom.event.coalesce_mouse_move",   
 pref("dom.webcomponents.shadowdom.enabled", true);
 pref("dom.webcomponents.customelements.enabled", true);
 #else
 pref("dom.webcomponents.shadowdom.enabled", false);
 pref("dom.webcomponents.customelements.enabled", false);
 #endif
 
 pref("javascript.enabled",                  true);
-// Enable Array.prototype.values
-pref("javascript.options.array_prototype_values", true);
 pref("javascript.options.strict",           false);
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     false);
 #endif
 pref("javascript.options.baselinejit",      true);
 pref("javascript.options.ion",              true);
 pref("javascript.options.asmjs",            true);
 pref("javascript.options.wasm",             true);
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -167,32 +167,37 @@ CookieServiceChild::ActorDestroy(ActorDe
 void
 CookieServiceChild::TrackCookieLoad(nsIChannel *aChannel)
 {
   if (!mIPCOpen) {
     return;
   }
 
   bool isForeign = false;
+  bool isTrackingResource = false;
   nsCOMPtr<nsIURI> uri;
   aChannel->GetURI(getter_AddRefs(uri));
   if (RequireThirdPartyCheck()) {
     mThirdPartyUtil->IsThirdPartyChannel(aChannel, uri, &isForeign);
   }
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   mozilla::OriginAttributes attrs;
   if (loadInfo) {
     attrs = loadInfo->GetOriginAttributes();
   }
   URIParams uriParams;
   SerializeURI(uri, uriParams);
   bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
   bool isSameSiteForeign = NS_IsSameSiteForeign(aChannel, uri);
-  SendPrepareCookieList(uriParams, isForeign, isSafeTopLevelNav,
-                        isSameSiteForeign, attrs);
+  SendPrepareCookieList(uriParams, isForeign, isTrackingResource,
+                        isSafeTopLevelNav, isSameSiteForeign, attrs);
 }
 
 mozilla::ipc::IPCResult
 CookieServiceChild::RecvRemoveAll(){
   mCookiesMap.Clear();
   return IPC_OK();
 }
 
@@ -323,16 +328,17 @@ CookieServiceChild::PrefChanged(nsIPrefB
       mCookieTimer->SetDelay(gMoveCookiesIntervalSeconds * 1000);
     }
   }
 }
 
 void
 CookieServiceChild::GetCookieStringFromCookieHashTable(nsIURI                 *aHostURI,
                                                        bool                   aIsForeign,
+                                                       bool                   aIsTrackingResource,
                                                        bool                   aIsSafeTopLevelNav,
                                                        bool                   aIsSameSiteForeign,
                                                        const OriginAttributes &aOriginAttrs,
                                                        nsCString              &aCookieString)
 {
   nsCOMPtr<nsIEffectiveTLDService> TLDService =
     do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
   NS_ASSERTION(TLDService, "Can't get TLDService");
@@ -356,17 +362,17 @@ CookieServiceChild::GetCookieStringFromC
   int64_t currentTimeInUsec = PR_Now();
   int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
 
   nsCOMPtr<nsICookiePermission> permissionService = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
   CookieStatus cookieStatus =
     nsCookieService::CheckPrefs(permissionService, mCookieBehavior,
                                 mThirdPartySession,
                                 mThirdPartyNonsecureSession, aHostURI,
-                                aIsForeign, nullptr,
+                                aIsForeign, aIsTrackingResource, nullptr,
                                 CountCookiesFromHashTable(baseDomain, aOriginAttrs),
                                 aOriginAttrs);
 
   if (cookieStatus != STATUS_ACCEPTED && cookieStatus != STATUS_ACCEPT_SESSION) {
     return;
   }
 
   cookiesList->Sort(CompareCookiesForSending());
@@ -417,25 +423,26 @@ CookieServiceChild::GetCookieStringFromC
       }
     }
   }
 }
 
 void
 CookieServiceChild::GetCookieStringSyncIPC(nsIURI                 *aHostURI,
                                            bool                   aIsForeign,
+                                           bool                   aIsTrackingResource,
                                            bool                   aIsSafeTopLevelNav,
                                            bool                   aIsSameSiteForeign,
                                            const OriginAttributes &aAttrs,
                                            nsAutoCString          &aCookieString)
 {
   URIParams uriParams;
   SerializeURI(aHostURI, uriParams);
 
-  SendGetCookieString(uriParams, aIsForeign, aIsSafeTopLevelNav, aIsSameSiteForeign, aAttrs, &aCookieString);
+  SendGetCookieString(uriParams, aIsForeign, aIsTrackingResource, aIsSafeTopLevelNav, aIsSameSiteForeign, aAttrs, &aCookieString);
 }
 
 uint32_t
 CookieServiceChild::CountCookiesFromHashTable(const nsCString &aBaseDomain,
                                               const OriginAttributes &aOriginAttrs)
 {
   CookiesList *cookiesList = nullptr;
 
@@ -549,29 +556,36 @@ CookieServiceChild::GetCookieStringInter
     }
   }
 
   // Asynchronously call the parent.
   bool isForeign = true;
   if (RequireThirdPartyCheck())
     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
+  bool isTrackingResource = false;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
+
   bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
   bool isSameSiteForeign = NS_IsSameSiteForeign(aChannel, aHostURI);
 
   nsAutoCString result;
   if (!mIPCSync) {
-    GetCookieStringFromCookieHashTable(aHostURI, !!isForeign, isSafeTopLevelNav,
-                                       isSameSiteForeign, attrs, result);
+    GetCookieStringFromCookieHashTable(aHostURI, isForeign, isTrackingResource,
+                                       isSafeTopLevelNav, isSameSiteForeign,
+                                       attrs, result);
   } else {
     if (!mIPCOpen) {
       return NS_ERROR_NOT_AVAILABLE;
     }
-    GetCookieStringSyncIPC(aHostURI, !!isForeign, isSafeTopLevelNav,
-                           isSameSiteForeign, attrs, result);
+    GetCookieStringSyncIPC(aHostURI, isForeign, isTrackingResource,
+                           isSafeTopLevelNav, isSameSiteForeign, attrs, result);
   }
 
   if (!result.IsEmpty())
     *aCookieString = ToNewCString(result);
 
   return NS_OK;
 }
 
@@ -592,16 +606,22 @@ CookieServiceChild::SetCookieStringInter
   if (scheme.EqualsLiteral("moz-nullprincipal"))
     return NS_OK;
 
   // Determine whether the request is foreign. Failure is acceptable.
   bool isForeign = true;
   if (RequireThirdPartyCheck())
     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
+  bool isTrackingResource = false;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
+
   nsDependentCString cookieString(aCookieString);
   nsDependentCString stringServerTime;
   if (aServerTime)
     stringServerTime.Rebind(aServerTime);
 
   URIParams hostURIParams;
   SerializeURI(aHostURI, hostURIParams);
 
@@ -616,17 +636,17 @@ CookieServiceChild::SetCookieStringInter
     if (loadInfo) {
       attrs = loadInfo->GetOriginAttributes();
     }
   }
 
   // Asynchronously call the parent.
   if (mIPCOpen) {
     SendSetCookieString(hostURIParams, channelURIParams,
-                        !!isForeign, cookieString,
+                        isForeign, isTrackingResource, cookieString,
                         stringServerTime, attrs, aFromHttp);
   }
 
   if (mIPCSync) {
     return NS_OK;
   }
 
   bool requireHostMatch;
@@ -635,17 +655,17 @@ CookieServiceChild::SetCookieStringInter
     GetBaseDomain(mTLDService, aHostURI, baseDomain, requireHostMatch);
 
   nsCOMPtr<nsICookiePermission> permissionService = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
 
   CookieStatus cookieStatus =
     nsCookieService::CheckPrefs(permissionService, mCookieBehavior,
                                 mThirdPartySession,
                                 mThirdPartyNonsecureSession, aHostURI,
-                                isForeign, aCookieString,
+                                isForeign, isTrackingResource, aCookieString,
                                 CountCookiesFromHashTable(baseDomain, attrs),
                                 attrs);
 
   if (cookieStatus != STATUS_ACCEPTED && cookieStatus != STATUS_ACCEPT_SESSION) {
     return NS_OK;
   }
 
   nsCString serverTimeString(aServerTime);
--- a/netwerk/cookie/CookieServiceChild.h
+++ b/netwerk/cookie/CookieServiceChild.h
@@ -60,24 +60,26 @@ protected:
                      nsCString &aOriginatingCharset);
 
   nsresult GetCookieStringInternal(nsIURI *aHostURI,
                                    nsIChannel *aChannel,
                                    char **aCookieString);
 
   void GetCookieStringFromCookieHashTable(nsIURI *aHostURI,
                                           bool aIsForeign,
+                                          bool aIsTrackingResource,
                                           bool aIsSafeTopLevelNav,
                                           bool aIsSameSiteForeign,
                                           const OriginAttributes &aAttrs,
                                           nsCString &aCookieString);
 
   void
   GetCookieStringSyncIPC(nsIURI                 *aHostURI,
                          bool                    aIsForeign,
+                         bool                    aIsTrackingResource,
                          bool                    aIsSafeTopLevelNav,
                          bool                    aIsSameSiteForeign,
                          const OriginAttributes &aAttrs,
                          nsAutoCString          &aCookieString);
 
   nsresult SetCookieStringInternal(nsIURI *aHostURI,
                                    nsIChannel *aChannel,
                                    const char *aCookieString,
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -150,18 +150,26 @@ CookieServiceParent::TrackCookieLoad(nsI
   bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
   bool aIsSameSiteForeign = NS_IsSameSiteForeign(aChannel, uri);
 
   // Send matching cookies to Child.
   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil;
   thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
   bool isForeign = true;
   thirdPartyUtil->IsThirdPartyChannel(aChannel, uri, &isForeign);
+
+  bool isTrackingResource = false;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
+
   nsTArray<nsCookie*> foundCookieList;
-  mCookieService->GetCookiesForURI(uri, isForeign, isSafeTopLevelNav, aIsSameSiteForeign,
+  mCookieService->GetCookiesForURI(uri, isForeign, isTrackingResource,
+                                   isSafeTopLevelNav, aIsSameSiteForeign,
                                    false, attrs, foundCookieList);
   nsTArray<CookieStruct> matchingCookiesList;
   SerialializeCookieList(foundCookieList, matchingCookiesList, uri);
   Unused << SendTrackCookiesLoad(matchingCookiesList, attrs);
 }
 
 void
 CookieServiceParent::SerialializeCookieList(const nsTArray<nsCookie*> &aFoundCookieList,
@@ -182,25 +190,27 @@ CookieServiceParent::SerialializeCookieL
     cookieStruct->isSecure() = cookie->IsSecure();
     cookieStruct->sameSite() = cookie->SameSite();
   }
 }
 
 mozilla::ipc::IPCResult
 CookieServiceParent::RecvPrepareCookieList(const URIParams        &aHost,
                                            const bool             &aIsForeign,
+                                           const bool             &aIsTrackingResource,
                                            const bool             &aIsSafeTopLevelNav,
                                            const bool             &aIsSameSiteForeign,
                                            const OriginAttributes &aAttrs)
 {
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
 
   // Send matching cookies to Child.
   nsTArray<nsCookie*> foundCookieList;
-  mCookieService->GetCookiesForURI(hostURI, aIsForeign, aIsSafeTopLevelNav, aIsSameSiteForeign,
+  mCookieService->GetCookiesForURI(hostURI, aIsForeign, aIsTrackingResource,
+                                   aIsSafeTopLevelNav, aIsSameSiteForeign,
                                    false, aAttrs, foundCookieList);
   nsTArray<CookieStruct> matchingCookiesList;
   SerialializeCookieList(foundCookieList, matchingCookiesList, hostURI);
   Unused << SendTrackCookiesLoad(matchingCookiesList, aAttrs);
   return IPC_OK();
 }
 
 void
@@ -208,38 +218,41 @@ CookieServiceParent::ActorDestroy(ActorD
 {
   // Nothing needed here. Called right before destructor since this is a
   // non-refcounted class.
 }
 
 mozilla::ipc::IPCResult
 CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
                                          const bool& aIsForeign,
+                                         const bool& aIsTrackingResource,
                                          const bool& aIsSafeTopLevelNav,
                                          const bool& aIsSameSiteForeign,
                                          const OriginAttributes& aAttrs,
                                          nsCString* aResult)
 {
   if (!mCookieService)
     return IPC_OK();
 
   // Deserialize URI. Having a host URI is mandatory and should always be
   // provided by the child; thus we consider failure fatal.
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
   if (!hostURI)
     return IPC_FAIL_NO_REASON(this);
-  mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aIsSafeTopLevelNav, aIsSameSiteForeign,
+  mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aIsTrackingResource,
+                                          aIsSafeTopLevelNav, aIsSameSiteForeign,
                                           false, aAttrs, *aResult);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
                                          const URIParams& aChannelURI,
                                          const bool& aIsForeign,
+                                         const bool& aIsTrackingResource,
                                          const nsCString& aCookieString,
                                          const nsCString& aServerTime,
                                          const OriginAttributes& aAttrs,
                                          const bool& aFromHttp)
 {
   if (!mCookieService)
     return IPC_OK();
 
@@ -266,17 +279,18 @@ CookieServiceParent::RecvSetCookieString
                      getter_AddRefs(dummyChannel));
 
   // NB: dummyChannel could be null if something failed in CreateDummyChannel.
   nsDependentCString cookieString(aCookieString, 0);
 
   // We set this to true while processing this cookie update, to make sure
   // we don't send it back to the same content process.
   mProcessingCookie = true;
-  mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
+  mCookieService->SetCookieStringInternal(hostURI, aIsForeign,
+                                          aIsTrackingResource, cookieString,
                                           aServerTime, aFromHttp, aAttrs,
                                           dummyChannel);
   mProcessingCookie = false;
   return IPC_OK();
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/cookie/CookieServiceParent.h
+++ b/netwerk/cookie/CookieServiceParent.h
@@ -37,31 +37,34 @@ public:
   // sure that we are only forwarding those cookie updates to other content
   // processes, not the one they originated from.
   bool ProcessingCookie() { return mProcessingCookie; }
 protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual mozilla::ipc::IPCResult RecvGetCookieString(const URIParams& aHost,
                                                       const bool& aIsForeign,
+                                                      const bool& aIsTrackingResource,
                                                       const bool& aIsSafeTopLevelNav,
                                                       const bool& aIsSameSiteForeign,
                                                       const OriginAttributes& aAttrs,
                                                       nsCString* aResult) override;
 
   virtual mozilla::ipc::IPCResult RecvSetCookieString(const URIParams& aHost,
                                                       const URIParams& aChannelURI,
                                                       const bool& aIsForeign,
+                                                      const bool& aIsTrackingResource,
                                                       const nsCString& aCookieString,
                                                       const nsCString& aServerTime,
                                                       const OriginAttributes& aAttrs,
                                                       const bool& aFromHttp) override;
   virtual
   mozilla::ipc::IPCResult RecvPrepareCookieList(const URIParams &aHost,
                                                 const bool &aIsForeign,
+                                                const bool &aIsTackingResource,
                                                 const bool &aIsSafeTopLevelNav,
                                                 const bool &aIsSameSiteForeign,
                                                 const OriginAttributes &aAttrs) override;
 
   void
   SerialializeCookieList(const nsTArray<nsCookie*> &aFoundCookieList,
                          nsTArray<CookieStruct> &aCookiesList,
                          nsIURI *aHostURI);
--- a/netwerk/cookie/PCookieService.ipdl
+++ b/netwerk/cookie/PCookieService.ipdl
@@ -41,16 +41,18 @@ parent:
    * @param host
    *        Same as the 'aURI' argument to nsICookieService.getCookieString.
    * @param isForeign
    *        True if the the request is third party, for purposes of allowing
    *        access to cookies. This should be obtained from
    *        mozIThirdPartyUtil.isThirdPartyChannel. Third party requests may be
    *        rejected depending on user preferences; if those checks are
    *        disabled, this parameter is ignored.
+   * @param isTrackingResource
+   *        True if the the request has been marked as tracking.
    * @param isSafeTopLevelNav
    *        True for safe methods like e.g. GET.
    * @param isSameSiteForeign
    *        True if the same-site cookie originates from a cross-site context.
    * @param fromHttp
    *        Whether the result is for an HTTP request header. This should be
    *        true for nsICookieService.getCookieStringFromHttp calls, false
    *        otherwise.
@@ -61,16 +63,17 @@ parent:
    * @see nsICookieService.getCookieString
    * @see nsICookieService.getCookieStringFromHttp
    * @see mozIThirdPartyUtil.isThirdPartyChannel
    *
    * @return the resulting cookie string.
    */
   nested(inside_cpow) sync GetCookieString(URIParams host,
                                            bool isForeign,
+                                           bool isTrackingResource,
                                            bool isSafeTopLevelNav,
                                            bool isSameSiteForeign,
                                            OriginAttributes attrs)
        returns (nsCString result);
 
   /*
    * Set a cookie string.
    *
@@ -79,16 +82,18 @@ parent:
    * @param channelURI
    *        The URI of the request.
    * @param isForeign
    *        True if the the request is third party, for purposes of allowing
    *        access to cookies. This should be obtained from
    *        mozIThirdPartyUtil.isThirdPartyChannel. Third party requests may be
    *        rejected depending on user preferences; if those checks are
    *        disabled, this parameter is ignored.
+   * @param isTrackingResource
+   *        True if the the request has been marked as tracking.
    * @param cookieString
    *        Same as the 'aCookie' argument to nsICookieService.setCookieString.
    * @param serverTime
    *        Same as the 'aServerTime' argument to
    *        nsICookieService.setCookieStringFromHttp. If the string is empty or
    *        null (e.g. for non-HTTP requests), the current local time is used.
    * @param fromHttp
    *        Whether the result is for an HTTP request header. This should be
@@ -100,23 +105,25 @@ parent:
    *
    * @see nsICookieService.setCookieString
    * @see nsICookieService.setCookieStringFromHttp
    * @see mozIThirdPartyUtil.isThirdPartyChannel
    */
   nested(inside_cpow) async SetCookieString(URIParams host,
                                             URIParams channelURI,
                                             bool isForeign,
+                                            bool isTrackingResource,
                                             nsCString cookieString,
                                             nsCString serverTime,
                                             OriginAttributes attrs,
                                             bool aFromHttp);
 
   async PrepareCookieList(URIParams host,
                           bool isForeign,
+                          bool isTrackingResource,
                           bool isSafeTopLevelNav,
                           bool isSameSiteForeign,
                           OriginAttributes attrs);
 
   async __delete__();
 
 child:
   async TrackCookiesLoad(CookieStruct[] cookiesList,
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -51,16 +51,17 @@
 #include "nsISimpleEnumerator.h"
 #include "nsIInputStream.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsNetCID.h"
 #include "mozilla/storage.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/ScopeExit.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/Telemetry.h"
 #include "nsIConsoleService.h"
 #include "nsVariant.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
 // Create key from baseDomain that will access the default cookie namespace.
@@ -2030,26 +2031,33 @@ nsCookieService::GetCookieStringCommon(n
 {
   NS_ENSURE_ARG(aHostURI);
   NS_ENSURE_ARG(aCookie);
 
   // Determine whether the request is foreign. Failure is acceptable.
   bool isForeign = true;
   mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
+  bool isTrackingResource = false;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
+
   // Get originAttributes.
   OriginAttributes attrs;
   if (aChannel) {
     NS_GetOriginAttributes(aChannel, attrs);
   }
 
   bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
   bool isSameSiteForeign = NS_IsSameSiteForeign(aChannel, aHostURI);
   nsAutoCString result;
-  GetCookieStringInternal(aHostURI, isForeign, isSafeTopLevelNav, isSameSiteForeign,
+  GetCookieStringInternal(aHostURI, isForeign, isTrackingResource,
+                          isSafeTopLevelNav, isSameSiteForeign,
                           aHttpBound, attrs, result);
   *aCookie = result.IsEmpty() ? nullptr : ToNewCString(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieString(nsIURI     *aHostURI,
                                  nsIPrompt  *aPrompt,
@@ -2124,32 +2132,39 @@ nsCookieService::SetCookieStringCommon(n
 {
   NS_ENSURE_ARG(aHostURI);
   NS_ENSURE_ARG(aCookieHeader);
 
   // Determine whether the request is foreign. Failure is acceptable.
   bool isForeign = true;
   mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
+  bool isTrackingResource = false;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
+  if (httpChannel) {
+    isTrackingResource = httpChannel->GetIsTrackingResource();
+  }
+
   // Get originAttributes.
   OriginAttributes attrs;
   if (aChannel) {
     NS_GetOriginAttributes(aChannel, attrs);
   }
 
   nsDependentCString cookieString(aCookieHeader);
   nsDependentCString serverTime(aServerTime ? aServerTime : "");
-  SetCookieStringInternal(aHostURI, isForeign, cookieString,
+  SetCookieStringInternal(aHostURI, isForeign, isTrackingResource, cookieString,
                           serverTime, aFromHttp, attrs, aChannel);
   return NS_OK;
 }
 
 void
 nsCookieService::SetCookieStringInternal(nsIURI                 *aHostURI,
                                          bool                    aIsForeign,
+                                         bool                    aIsTrackingResource,
                                          nsDependentCString     &aCookieHeader,
                                          const nsCString        &aServerTime,
                                          bool                    aFromHttp,
                                          const OriginAttributes &aOriginAttrs,
                                          nsIChannel             *aChannel)
 {
   NS_ASSERTION(aHostURI, "null host!");
 
@@ -2182,18 +2197,19 @@ nsCookieService::SetCookieStringInternal
   // check default prefs
   uint32_t priorCookieCount = 0;
   nsAutoCString hostFromURI;
   aHostURI->GetHost(hostFromURI);
   CountCookiesFromHost(hostFromURI, &priorCookieCount);
   CookieStatus cookieStatus = CheckPrefs(mPermissionService, mCookieBehavior,
                                          mThirdPartySession,
                                          mThirdPartyNonsecureSession, aHostURI,
-                                         aIsForeign, aCookieHeader.get(),
-                                         priorCookieCount, aOriginAttrs);
+                                         aIsForeign, aIsTrackingResource,
+                                         aCookieHeader.get(), priorCookieCount,
+                                         aOriginAttrs);
 
   // fire a notification if third party or if cookie was rejected
   // (but not if there was an error)
   switch (cookieStatus) {
   case STATUS_REJECTED:
     NotifyRejected(aHostURI);
     if (aIsForeign) {
       NotifyThirdParty(aHostURI, false, aChannel);
@@ -3114,16 +3130,17 @@ nsCookieService::PathMatches(nsCookie* a
   // either the paths match exactly, or the cookie path is a prefix of
   // the given path.
   return true;
 }
 
 void
 nsCookieService::GetCookiesForURI(nsIURI *aHostURI,
                                   bool aIsForeign,
+                                  bool aIsTrackingResource,
                                   bool aIsSafeTopLevelNav,
                                   bool aIsSameSiteForeign,
                                   bool aHttpBound,
                                   const OriginAttributes& aOriginAttrs,
                                   nsTArray<nsCookie*>& aCookieList)
 {
   NS_ASSERTION(aHostURI, "null host!");
 
@@ -3155,18 +3172,19 @@ nsCookieService::GetCookiesForURI(nsIURI
   }
 
   // check default prefs
   uint32_t priorCookieCount = 0;
   CountCookiesFromHost(hostFromURI, &priorCookieCount);
   CookieStatus cookieStatus = CheckPrefs(mPermissionService, mCookieBehavior,
                                          mThirdPartySession,
                                          mThirdPartyNonsecureSession, aHostURI,
-                                         aIsForeign, nullptr,
-                                         priorCookieCount, aOriginAttrs);
+                                         aIsForeign, aIsTrackingResource,
+                                         nullptr, priorCookieCount,
+                                         aOriginAttrs);
 
   // for GetCookie(), we don't fire rejection notifications.
   switch (cookieStatus) {
   case STATUS_REJECTED:
   case STATUS_REJECTED_WITH_ERROR:
     return;
   default:
     break;
@@ -3287,25 +3305,27 @@ nsCookieService::GetCookiesForURI(nsIURI
   // this is required per RFC2109.  if cookies match in length,
   // then sort by creation time (see bug 236772).
   aCookieList.Sort(CompareCookiesForSending());
 }
 
 void
 nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
                                          bool aIsForeign,
+                                         bool aIsTrackingResource,
                                          bool aIsSafeTopLevelNav,
                                          bool aIsSameSiteForeign,
                                          bool aHttpBound,
                                          const OriginAttributes& aOriginAttrs,
                                          nsCString &aCookieString)
 {
   AutoTArray<nsCookie*, 8> foundCookieList;
-  GetCookiesForURI(aHostURI, aIsForeign, aIsSafeTopLevelNav, aIsSameSiteForeign,
-                   aHttpBound, aOriginAttrs, foundCookieList);
+  GetCookiesForURI(aHostURI, aIsForeign, aIsTrackingResource,
+                   aIsSafeTopLevelNav, aIsSameSiteForeign, aHttpBound,
+                   aOriginAttrs, foundCookieList);
 
   nsCookie* cookie;
   for (uint32_t i = 0; i < foundCookieList.Length(); ++i) {
     cookie = foundCookieList.ElementAt(i);
 
     // check if we have anything to write
     if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
       // if we've already added a cookie to the return list, append a "; " so
@@ -4132,16 +4152,17 @@ static inline bool IsSubdomainOf(const n
 
 CookieStatus
 nsCookieService::CheckPrefs(nsICookiePermission    *aPermissionService,
                             uint8_t                 aCookieBehavior,
                             bool                    aThirdPartySession,
                             bool                    aThirdPartyNonsecureSession,
                             nsIURI                 *aHostURI,
                             bool                    aIsForeign,
+                            bool                    aIsTrackingResource,
                             const char             *aCookieHeader,
                             const int               aNumOfCookies,
                             const OriginAttributes &aOriginAttrs)
 {
   nsresult rv;
 
   // don't let ftp sites get/set cookies (could be a security issue)
   bool ftp;
@@ -4153,16 +4174,23 @@ nsCookieService::CheckPrefs(nsICookiePer
   nsCOMPtr<nsIPrincipal> principal =
       BasePrincipal::CreateCodebasePrincipal(aHostURI, aOriginAttrs);
 
   if (!principal) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "non-codebase principals cannot get/set cookies");
     return STATUS_REJECTED_WITH_ERROR;
   }
 
+  // No cookies allowed if this request comes from a tracker, in a 3rd party
+  // context, when anti-tracking protection is enabled.
+  if (aIsForeign && aIsTrackingResource &&
+      StaticPrefs::privacy_trackingprotection_storagerestriction_enabled()) {
+      return STATUS_REJECTED;
+  }
+
   // check the permission list first; if we find an entry, it overrides
   // default prefs. see bug 184059.
   if (aPermissionService) {
     nsCookieAccess access;
     // Not passing an nsIChannel here is probably OK; our implementation
     // doesn't do anything with it anyway.
     rv = aPermissionService->CanAccess(principal, &access);
 
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -265,19 +265,19 @@ class nsCookieService final : public nsI
   static void AppClearDataObserverInit();
   static nsCString GetPathFromURI(nsIURI *aHostURI);
   static nsresult GetBaseDomain(nsIEffectiveTLDService *aTLDService, nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
   static nsresult GetBaseDomainFromHost(nsIEffectiveTLDService *aTLDService, const nsACString &aHost, nsCString &aBaseDomain);
   static bool DomainMatches(nsCookie* aCookie, const nsACString& aHost);
   static bool IsSameSiteEnabled();
   static bool PathMatches(nsCookie* aCookie, const nsACString& aPath);
   static bool CanSetCookie(nsIURI *aHostURI, const nsCookieKey& aKey, nsCookieAttributes &aCookieAttributes, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel, bool aLeaveSercureAlone, bool &aSetCookie, mozIThirdPartyUtil* aThirdPartyUtil);
-  static CookieStatus CheckPrefs(nsICookiePermission *aPermissionServices, uint8_t aCookieBehavior, bool aThirdPartySession, bool aThirdPartyNonsecureSession, nsIURI *aHostURI, bool aIsForeign, const char *aCookieHeader, const int aNumOfCookies, const OriginAttributes& aOriginAttrs);
+  static CookieStatus CheckPrefs(nsICookiePermission *aPermissionServices, uint8_t aCookieBehavior, bool aThirdPartySession, bool aThirdPartyNonsecureSession, nsIURI *aHostURI, bool aIsForeign, bool aIsTrackingResource, const char *aCookieHeader, const int aNumOfCookies, const OriginAttributes& aOriginAttrs);
   static int64_t ParseServerTime(const nsCString &aServerTime);
-  void GetCookiesForURI(nsIURI *aHostURI, bool aIsForeign, bool aIsSafeTopLevelNav, bool aIsTopLevelForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsTArray<nsCookie*>& aCookieList);
+  void GetCookiesForURI(nsIURI *aHostURI, bool aIsForeign, bool aIsTrackingResource, bool aIsSafeTopLevelNav, bool aIsTopLevelForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsTArray<nsCookie*>& aCookieList);
 
   protected:
     virtual ~nsCookieService();
 
     void                          PrefChanged(nsIPrefBranch *aPrefBranch);
     void                          InitDBStates();
     OpenDBResult                  TryInitDB(bool aDeleteExistingDB);
     void                          InitDBConn();
@@ -293,19 +293,19 @@ class nsCookieService final : public nsI
     void                          HandleDBClosed(DBState* aDBState);
     void                          HandleCorruptDB(DBState* aDBState);
     void                          RebuildCorruptDB(DBState* aDBState);
     OpenDBResult                  Read();
     mozilla::UniquePtr<ConstCookie> GetCookieFromRow(mozIStorageStatement *aRow, const OriginAttributes &aOriginAttributes);
     void                          EnsureReadComplete(bool aInitDBConn);
     nsresult                      NormalizeHost(nsCString &aHost);
     nsresult                      GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
-    void                          GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aIsSafeTopLevelNav, bool aIsTopLevelForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsCString &aCookie);
+    void                          GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aIsTrackingResource, bool aIsSafeTopLevelNav, bool aIsTopLevelForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsCString &aCookie);
     nsresult                      SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
-    void                          SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, nsIChannel* aChannel);
+    void                          SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aIsTrackingResource, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, nsIChannel* aChannel);
     bool                          SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
     void                          AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
     void                          RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr);
     void                          AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
     void                          UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
     static bool                   GetTokenValue(nsACString::const_char_iterator &aIter, nsACString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
     static bool                   ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
     bool                          RequireThirdPartyCheck();
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -37,16 +37,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIObserverService.h"
 #include "nsProxyRelease.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsINetworkInterceptController.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/PerformanceStorage.h"
+#include "mozilla/Services.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsStreamUtils.h"
 #include "nsThreadUtils.h"
 #include "nsContentSecurityManager.h"
 #include "nsIChannelEventSink.h"
 #include "nsILoadGroupChild.h"
 #include "mozilla/ConsoleReportCollector.h"
 #include "LoadInfo.h"
@@ -2374,17 +2375,17 @@ HttpBaseChannel::SetTopWindowURIIfUnknow
 NS_IMETHODIMP
 HttpBaseChannel::GetTopWindowURI(nsIURI **aTopWindowURI)
 {
   nsresult rv = NS_OK;
   nsCOMPtr<mozIThirdPartyUtil> util;
   // Only compute the top window URI once. In e10s, this must be computed in the
   // child. The parent gets the top window URI through HttpChannelOpenArgs.
   if (!mTopWindowURI) {
-    util = do_GetService(THIRDPARTYUTIL_CONTRACTID);
+    util = services::GetThirdPartyUtil();
     if (!util) {
       return NS_ERROR_NOT_AVAILABLE;
     }
     nsCOMPtr<mozIDOMWindowProxy> win;
     rv = util->GetTopWindowForChannel(this, getter_AddRefs(win));
     if (NS_SUCCEEDED(rv)) {
       rv = util->GetURIFromWindow(win, getter_AddRefs(mTopWindowURI));
 #if DEBUG
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -40,28 +40,30 @@
 #include "nsIStreamTransportService.h"
 #include "prnetdb.h"
 #include "nsEscape.h"
 #include "nsStreamUtils.h"
 #include "nsIOService.h"
 #include "nsDNSPrefetch.h"
 #include "nsChannelClassifier.h"
 #include "nsIRedirectResultListener.h"
+#include "mozIThirdPartyUtil.h"
 #include "mozilla/dom/ContentVerifier.h"
 #include "mozilla/TimeStamp.h"
 #include "nsError.h"
 #include "nsPrintfCString.h"
 #include "nsAlgorithm.h"
 #include "nsQueryObject.h"
 #include "nsThreadUtils.h"
 #include "GeckoProfiler.h"
 #include "nsIConsoleService.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
 #include "nsISSLSocketControl.h"
 #include "sslt.h"
 #include "nsContentUtils.h"
 #include "nsContentSecurityManager.h"
 #include "nsIClassOfService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptError.h"
@@ -97,16 +99,17 @@
 #include "nsIDeprecationWarner.h"
 #include "nsIDocument.h"
 #include "nsICompressConvStats.h"
 #include "nsCORSListenerProxy.h"
 #include "nsISocketProvider.h"
 #include "mozilla/extensions/StreamFilterParent.h"
 #include "mozilla/net/Predictor.h"
 #include "mozilla/MathAlgorithms.h"
+#include "mozilla/StaticPrefs.h"
 #include "CacheControlParser.h"
 #include "nsMixedContentBlocker.h"
 #include "CacheStorageService.h"
 #include "HttpChannelParent.h"
 #include "InterceptedHttpChannel.h"
 #include "nsIBufferedStreams.h"
 #include "nsIFileStreams.h"
 #include "nsIMIMEInputStream.h"
@@ -3732,16 +3735,40 @@ nsHttpChannel::OpenCacheEntryInternal(bo
 
     if (mPostID) {
         extension.Append(nsPrintfCString("%d", mPostID));
     }
     if (mTRR) {
         extension.Append("TRR");
     }
 
+    if (StaticPrefs::privacy_trackingprotection_storagerestriction_enabled() &&
+        mIsTrackingResource) {
+        nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
+            services::GetThirdPartyUtil();
+        if (thirdPartyUtil) {
+            bool thirdParty = false;
+            Unused << thirdPartyUtil->IsThirdPartyChannel(this,
+                                                          nullptr,
+                                                          &thirdParty);
+            if (thirdParty) {
+                nsCOMPtr<nsIURI> topWindowURI;
+                rv = GetTopWindowURI(getter_AddRefs(topWindowURI));
+                NS_ENSURE_SUCCESS(rv, rv);
+
+                nsAutoString topWindowOrigin;
+                rv = nsContentUtils::GetUTFOrigin(topWindowURI, topWindowOrigin);
+                NS_ENSURE_SUCCESS(rv, rv);
+
+                extension.Append("-trackerFor:");
+                extension.Append(NS_ConvertUTF16toUTF8(topWindowOrigin));
+            }
+        }
+    }
+
     mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
     mCacheQueueSizeWhenOpen = CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
 
     if (sRCWNEnabled && maybeRCWN && !mApplicationCacheForWrite) {
         bool hasAltData = false;
         uint32_t sizeInKb = 0;
         rv = cacheStorage->GetCacheIndexEntryAttrs(openURI, extension,
                                                    &hasAltData, &sizeInKb);
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,35 +8,35 @@
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz",
       "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw=="
     },
     "acorn-jsx": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
       "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
       "requires": {
-        "acorn": "3.3.0"
+        "acorn": "^3.0.4"
       },
       "dependencies": {
         "acorn": {
           "version": "3.3.0",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
           "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
         }
       }
     },
     "ajv": {
       "version": "5.5.2",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
       "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
       "requires": {
-        "co": "4.6.0",
-        "fast-deep-equal": "1.1.0",
-        "fast-json-stable-stringify": "2.0.0",
-        "json-schema-traverse": "0.3.1"
+        "co": "^4.6.0",
+        "fast-deep-equal": "^1.0.0",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.3.0"
       }
     },
     "ajv-keywords": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
       "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I="
     },
     "ansi-escapes": {
@@ -54,25 +54,25 @@
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
       "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
     },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
       "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
       "requires": {
-        "sprintf-js": "1.0.3"
+        "sprintf-js": "~1.0.2"
       }
     },
     "array-union": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
       "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
       "requires": {
-        "array-uniq": "1.0.3"
+        "array-uniq": "^1.0.1"
       }
     },
     "array-uniq": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
       "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
     },
     "arrify": {
@@ -80,99 +80,99 @@
       "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
       "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
     },
     "babel-code-frame": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
       "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
       "requires": {
-        "chalk": "1.1.3",
-        "esutils": "2.0.2",
-        "js-tokens": "3.0.2"
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
       },
       "dependencies": {
         "chalk": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
           }
         },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
           "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
           "requires": {
-            "ansi-regex": "2.1.1"
+            "ansi-regex": "^2.0.0"
           }
         }
       }
     },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
       "requires": {
-        "balanced-match": "1.0.0",
+        "balanced-match": "^1.0.0",
         "concat-map": "0.0.1"
       }
     },
     "buffer-from": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
       "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ=="
     },
     "caller-path": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
       "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
       "requires": {
-        "callsites": "0.2.0"
+        "callsites": "^0.2.0"
       }
     },
     "callsites": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="
     },
     "chalk": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
       "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
       "requires": {
-        "ansi-styles": "3.2.1",
-        "escape-string-regexp": "1.0.5",
-        "supports-color": "5.4.0"
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
       },
       "dependencies": {
         "ansi-styles": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
           "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
           "requires": {
-            "color-convert": "1.9.2"
+            "color-convert": "^1.9.0"
           }
         },
         "supports-color": {
           "version": "5.4.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
           "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
           "requires": {
-            "has-flag": "3.0.0"
+            "has-flag": "^3.0.0"
           }
         }
       }
     },
     "chardet": {
       "version": "0.4.2",
       "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
       "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
@@ -182,17 +182,17 @@
       "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
       "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="
     },
     "cli-cursor": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
       "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
       "requires": {
-        "restore-cursor": "2.0.0"
+        "restore-cursor": "^2.0.0"
       }
     },
     "cli-width": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
     },
     "co": {
@@ -218,35 +218,35 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
     "concat-stream": {
       "version": "1.6.2",
       "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
       "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
       "requires": {
-        "buffer-from": "1.1.0",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6",
-        "typedarray": "0.0.6"
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
       }
     },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "cross-spawn": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
       "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
       "requires": {
-        "lru-cache": "4.1.3",
-        "shebang-command": "1.2.0",
-        "which": "1.3.1"
+        "lru-cache": "^4.0.1",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
       }
     },
     "debug": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
       "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
       "requires": {
         "ms": "2.0.0"
@@ -257,40 +257,40 @@
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
     },
     "del": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
       "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
       "requires": {
-        "globby": "5.0.0",
-        "is-path-cwd": "1.0.0",
-        "is-path-in-cwd": "1.0.1",
-        "object-assign": "4.1.1",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1",
-        "rimraf": "2.6.2"
+        "globby": "^5.0.0",
+        "is-path-cwd": "^1.0.0",
+        "is-path-in-cwd": "^1.0.0",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "rimraf": "^2.2.8"
       }
     },
     "doctrine": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
       "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
       "requires": {
-        "esutils": "2.0.2"
+        "esutils": "^2.0.2"
       }
     },
     "dom-serializer": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
       "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
       "requires": {
-        "domelementtype": "1.1.3",
-        "entities": "1.1.1"
+        "domelementtype": "~1.1.1",
+        "entities": "~1.1.1"
       },
       "dependencies": {
         "domelementtype": {
           "version": "1.1.3",
           "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
         }
       }
@@ -300,26 +300,26 @@
       "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
       "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
     },
     "domhandler": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
       "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
       "requires": {
-        "domelementtype": "1.3.0"
+        "domelementtype": "1"
       }
     },
     "domutils": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
       "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
       "requires": {
-        "dom-serializer": "0.1.0",
-        "domelementtype": "1.3.0"
+        "dom-serializer": "0",
+        "domelementtype": "1"
       }
     },
     "entities": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
       "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
     },
     "escape-string-regexp": {
@@ -327,62 +327,62 @@
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
     "eslint": {
       "version": "4.19.1",
       "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
       "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
       "requires": {
-        "ajv": "5.5.2",
-        "babel-code-frame": "6.26.0",
-        "chalk": "2.4.1",
-        "concat-stream": "1.6.2",
-        "cross-spawn": "5.1.0",
-        "debug": "3.1.0",
-        "doctrine": "2.1.0",
-        "eslint-scope": "3.7.1",
-        "eslint-visitor-keys": "1.0.0",
-        "espree": "3.5.4",
-        "esquery": "1.0.1",
-        "esutils": "2.0.2",
-        "file-entry-cache": "2.0.0",
-        "functional-red-black-tree": "1.0.1",
-        "glob": "7.1.2",
-        "globals": "11.5.0",
-        "ignore": "3.3.8",
-        "imurmurhash": "0.1.4",
-        "inquirer": "3.3.0",
-        "is-resolvable": "1.1.0",
-        "js-yaml": "3.12.0",
-        "json-stable-stringify-without-jsonify": "1.0.1",
-        "levn": "0.3.0",
-        "lodash": "4.17.10",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.1",
-        "natural-compare": "1.4.0",
-        "optionator": "0.8.2",
-        "path-is-inside": "1.0.2",
-        "pluralize": "7.0.0",
-        "progress": "2.0.0",
-        "regexpp": "1.1.0",
-        "require-uncached": "1.0.3",
-        "semver": "5.5.0",
-        "strip-ansi": "4.0.0",
-        "strip-json-comments": "2.0.1",
+        "ajv": "^5.3.0",
+        "babel-code-frame": "^6.22.0",
+        "chalk": "^2.1.0",
+        "concat-stream": "^1.6.0",
+        "cross-spawn": "^5.1.0",
+        "debug": "^3.1.0",
+        "doctrine": "^2.1.0",
+        "eslint-scope": "^3.7.1",
+        "eslint-visitor-keys": "^1.0.0",
+        "espree": "^3.5.4",
+        "esquery": "^1.0.0",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^2.0.0",
+        "functional-red-black-tree": "^1.0.1",
+        "glob": "^7.1.2",
+        "globals": "^11.0.1",
+        "ignore": "^3.3.3",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^3.0.6",
+        "is-resolvable": "^1.0.0",
+        "js-yaml": "^3.9.1",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.4",
+        "minimatch": "^3.0.2",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.2",
+        "path-is-inside": "^1.0.2",
+        "pluralize": "^7.0.0",
+        "progress": "^2.0.0",
+        "regexpp": "^1.0.1",
+        "require-uncached": "^1.0.3",
+        "semver": "^5.3.0",
+        "strip-ansi": "^4.0.0",
+        "strip-json-comments": "~2.0.1",
         "table": "4.0.2",
-        "text-table": "0.2.0"
+        "text-table": "~0.2.0"
       }
     },
     "eslint-plugin-html": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.3.tgz",
       "integrity": "sha512-ArFnlfQxwYSz/CP0zvk8Cy3MUhcDpT3o6jgO8eKD/b8ezcLVBrgkYzmMv+7S/ya+Yl9pN+Cz2tsgYp/zElkQzA==",
       "requires": {
-        "htmlparser2": "3.9.2"
+        "htmlparser2": "^3.8.2"
       }
     },
     "eslint-plugin-mozilla": {
       "version": "file:tools/lint/eslint/eslint-plugin-mozilla",
       "requires": {
         "htmlparser2": "3.9.2",
         "ini-parser": "0.0.2",
         "sax": "1.2.4"
@@ -393,66 +393,66 @@
       "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.0.2.tgz",
       "integrity": "sha512-JnwpoH8Sv4QOjrTDutENBHzSnyYtspdjtglYtqUtAHe6f6LLKqykJle+UwFPg23GGwt5hI3amS9CRDezW8GAww=="
     },
     "eslint-plugin-react": {
       "version": "7.1.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.1.0.tgz",
       "integrity": "sha1-J3cKzzn1/UnNCvQIPOWBBOs5DUw=",
       "requires": {
-        "doctrine": "2.1.0",
-        "has": "1.0.3",
-        "jsx-ast-utils": "1.4.1"
+        "doctrine": "^2.0.0",
+        "has": "^1.0.1",
+        "jsx-ast-utils": "^1.4.1"
       }
     },
     "eslint-plugin-spidermonkey-js": {
       "version": "file:tools/lint/eslint/eslint-plugin-spidermonkey-js"
     },
     "eslint-scope": {
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
       "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
       "requires": {
-        "esrecurse": "4.2.1",
-        "estraverse": "4.2.0"
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
       }
     },
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
       "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
     },
     "espree": {
       "version": "3.5.4",
       "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
       "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
       "requires": {
-        "acorn": "5.6.2",
-        "acorn-jsx": "3.0.1"
+        "acorn": "^5.5.0",
+        "acorn-jsx": "^3.0.0"
       }
     },
     "esprima": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
       "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
     },
     "esquery": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
       "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
       "requires": {
-        "estraverse": "4.2.0"
+        "estraverse": "^4.0.0"
       }
     },
     "esrecurse": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
       "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
       "requires": {
-        "estraverse": "4.2.0"
+        "estraverse": "^4.1.0"
       }
     },
     "estraverse": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
       "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
     },
     "esutils": {
@@ -460,19 +460,19 @@
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
       "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
     },
     "external-editor": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
       "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
       "requires": {
-        "chardet": "0.4.2",
-        "iconv-lite": "0.4.23",
-        "tmp": "0.0.33"
+        "chardet": "^0.4.0",
+        "iconv-lite": "^0.4.17",
+        "tmp": "^0.0.33"
       }
     },
     "fast-deep-equal": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
       "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
     },
     "fast-json-stable-stringify": {
@@ -485,37 +485,37 @@
       "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
     },
     "figures": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
       "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
       "requires": {
-        "escape-string-regexp": "1.0.5"
+        "escape-string-regexp": "^1.0.5"
       }
     },
     "file-entry-cache": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
       "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
       "requires": {
-        "flat-cache": "1.3.0",
-        "object-assign": "4.1.1"
+        "flat-cache": "^1.2.1",
+        "object-assign": "^4.0.1"
       }
     },
     "flat-cache": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
       "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
       "requires": {
-        "circular-json": "0.3.3",
-        "del": "2.2.2",
-        "graceful-fs": "4.1.11",
-        "write": "0.2.1"
+        "circular-json": "^0.3.1",
+        "del": "^2.0.2",
+        "graceful-fs": "^4.1.2",
+        "write": "^0.2.1"
       }
     },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "function-bind": {
@@ -528,87 +528,87 @@
       "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
       "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
     },
     "glob": {
       "version": "7.1.2",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
       "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
       "requires": {
-        "fs.realpath": "1.0.0",
-        "inflight": "1.0.6",
-        "inherits": "2.0.3",
-        "minimatch": "3.0.4",
-        "once": "1.4.0",
-        "path-is-absolute": "1.0.1"
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
       }
     },
     "globals": {
       "version": "11.5.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz",
       "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ=="
     },
     "globby": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
       "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
       "requires": {
-        "array-union": "1.0.2",
-        "arrify": "1.0.1",
-        "glob": "7.1.2",
-        "object-assign": "4.1.1",
-        "pify": "2.3.0",
-        "pinkie-promise": "2.0.1"
+        "array-union": "^1.0.1",
+        "arrify": "^1.0.0",
+        "glob": "^7.0.3",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
       }
     },
     "graceful-fs": {
       "version": "4.1.11",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
       "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
     },
     "has": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
       "requires": {
-        "function-bind": "1.1.1"
+        "function-bind": "^1.1.1"
       }
     },
     "has-ansi": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
       "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
       "requires": {
-        "ansi-regex": "2.1.1"
+        "ansi-regex": "^2.0.0"
       }
     },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
       "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
     },
     "htmlparser2": {
       "version": "3.9.2",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
       "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
       "requires": {
-        "domelementtype": "1.3.0",
-        "domhandler": "2.4.2",
-        "domutils": "1.7.0",
-        "entities": "1.1.1",
-        "inherits": "2.0.3",
-        "readable-stream": "2.3.6"
+        "domelementtype": "^1.3.0",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.2"
       }
     },
     "iconv-lite": {
       "version": "0.4.23",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
       "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
       "requires": {
-        "safer-buffer": "2.1.2"
+        "safer-buffer": ">= 2.1.2 < 3"
       }
     },
     "ignore": {
       "version": "3.3.8",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
       "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg=="
     },
     "imurmurhash": {
@@ -616,18 +616,18 @@
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
     },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
       "requires": {
-        "once": "1.4.0",
-        "wrappy": "1.0.2"
+        "once": "^1.3.0",
+        "wrappy": "1"
       }
     },
     "inherits": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
     },
     "ini-parser": {
@@ -635,30 +635,30 @@
       "resolved": "https://registry.npmjs.org/ini-parser/-/ini-parser-0.0.2.tgz",
       "integrity": "sha1-+kF4flZ3Y7P/Zdel2alO23QHh+8="
     },
     "inquirer": {
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
       "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
       "requires": {
-        "ansi-escapes": "3.1.0",
-        "chalk": "2.4.1",
-        "cli-cursor": "2.1.0",
-        "cli-width": "2.2.0",
-        "external-editor": "2.2.0",
-        "figures": "2.0.0",
-        "lodash": "4.17.10",
+        "ansi-escapes": "^3.0.0",
+        "chalk": "^2.0.0",
+        "cli-cursor": "^2.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^2.0.4",
+        "figures": "^2.0.0",
+        "lodash": "^4.3.0",
         "mute-stream": "0.0.7",
-        "run-async": "2.3.0",
-        "rx-lite": "4.0.8",
-        "rx-lite-aggregates": "4.0.8",
-        "string-width": "2.1.1",
-        "strip-ansi": "4.0.0",
-        "through": "2.3.8"
+        "run-async": "^2.2.0",
+        "rx-lite": "^4.0.8",
+        "rx-lite-aggregates": "^4.0.8",
+        "string-width": "^2.1.0",
+        "strip-ansi": "^4.0.0",
+        "through": "^2.3.6"
       }
     },
     "is-fullwidth-code-point": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
       "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
     },
     "is-path-cwd": {
@@ -666,25 +666,25 @@
       "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
       "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0="
     },
     "is-path-in-cwd": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
       "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
       "requires": {
-        "is-path-inside": "1.0.1"
+        "is-path-inside": "^1.0.0"
       }
     },
     "is-path-inside": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
       "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
       "requires": {
-        "path-is-inside": "1.0.2"
+        "path-is-inside": "^1.0.1"
       }
     },
     "is-promise": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
       "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
     },
     "is-resolvable": {
@@ -707,18 +707,18 @@
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
       "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
     },
     "js-yaml": {
       "version": "3.12.0",
       "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
       "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
       "requires": {
-        "argparse": "1.0.10",
-        "esprima": "4.0.0"
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
       }
     },
     "json-schema-traverse": {
       "version": "0.3.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
       "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
     },
     "json-stable-stringify-without-jsonify": {
@@ -731,45 +731,45 @@
       "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
       "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE="
     },
     "levn": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
       "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
       "requires": {
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2"
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
       }
     },
     "lodash": {
       "version": "4.17.10",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
       "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
     },
     "lru-cache": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
       "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
       "requires": {
-        "pseudomap": "1.0.2",
-        "yallist": "2.1.2"
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
       }
     },
     "mimic-fn": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
       "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
     },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
       "requires": {
-        "brace-expansion": "1.1.11"
+        "brace-expansion": "^1.1.7"
       }
     },
     "minimist": {
       "version": "0.0.8",
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
     },
     "mkdirp": {
@@ -800,38 +800,38 @@
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
       "requires": {
-        "wrappy": "1.0.2"
+        "wrappy": "1"
       }
     },
     "onetime": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
       "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
       "requires": {
-        "mimic-fn": "1.2.0"
+        "mimic-fn": "^1.0.0"
       }
     },
     "optionator": {
       "version": "0.8.2",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
       "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
       "requires": {
-        "deep-is": "0.1.3",
-        "fast-levenshtein": "2.0.6",
-        "levn": "0.3.0",
-        "prelude-ls": "1.1.2",
-        "type-check": "0.3.2",
-        "wordwrap": "1.0.0"
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
       }
     },
     "os-tmpdir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
     },
     "path-is-absolute": {
@@ -854,17 +854,17 @@
       "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
       "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
     },
     "pinkie-promise": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
       "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
       "requires": {
-        "pinkie": "2.0.4"
+        "pinkie": "^2.0.0"
       }
     },
     "pluralize": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
       "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow=="
     },
     "prelude-ls": {
@@ -887,80 +887,80 @@
       "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
       "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
     },
     "readable-stream": {
       "version": "2.3.6",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
       "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
       "requires": {
-        "core-util-is": "1.0.2",
-        "inherits": "2.0.3",
-        "isarray": "1.0.0",
-        "process-nextick-args": "2.0.0",
-        "safe-buffer": "5.1.2",
-        "string_decoder": "1.1.1",
-        "util-deprecate": "1.0.2"
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
       }
     },
     "regexpp": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
       "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw=="
     },
     "require-uncached": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "requires": {
-        "caller-path": "0.1.0",
-        "resolve-from": "1.0.1"
+        "caller-path": "^0.1.0",
+        "resolve-from": "^1.0.0"
       }
     },
     "resolve-from": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
       "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="
     },
     "restore-cursor": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
       "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
       "requires": {
-        "onetime": "2.0.1",
-        "signal-exit": "3.0.2"
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
       }
     },
     "rimraf": {
       "version": "2.6.2",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
       "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
       "requires": {
-        "glob": "7.1.2"
+        "glob": "^7.0.5"
       }
     },
     "run-async": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
       "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
       "requires": {
-        "is-promise": "2.1.0"
+        "is-promise": "^2.1.0"
       }
     },
     "rx-lite": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
       "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ="
     },
     "rx-lite-aggregates": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
       "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
       "requires": {
-        "rx-lite": "4.0.8"
+        "rx-lite": "*"
       }
     },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safer-buffer": {
@@ -978,17 +978,17 @@
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
       "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
     },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
       "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
       "requires": {
-        "shebang-regex": "1.0.0"
+        "shebang-regex": "^1.0.0"
       }
     },
     "shebang-regex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
       "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
     },
     "signal-exit": {
@@ -996,47 +996,47 @@
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
       "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
     },
     "slice-ansi": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
       "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
       "requires": {
-        "is-fullwidth-code-point": "2.0.0"
+        "is-fullwidth-code-point": "^2.0.0"
       }
     },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
       "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
       "requires": {
-        "is-fullwidth-code-point": "2.0.0",
-        "strip-ansi": "4.0.0"
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^4.0.0"
       }
     },
     "string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
       "requires": {
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "~5.1.0"
       }
     },
     "strip-ansi": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
       "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
       "requires": {
-        "ansi-regex": "3.0.0"
+        "ansi-regex": "^3.0.0"
       },
       "dependencies": {
         "ansi-regex": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
           "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
         }
       }
@@ -1051,22 +1051,22 @@
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
       "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
     },
     "table": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
       "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
       "requires": {
-        "ajv": "5.5.2",
-        "ajv-keywords": "2.1.1",
-        "chalk": "2.4.1",
-        "lodash": "4.17.10",
+        "ajv": "^5.2.3",
+        "ajv-keywords": "^2.1.0",
+        "chalk": "^2.1.0",
+        "lodash": "^4.17.4",
         "slice-ansi": "1.0.0",
-        "string-width": "2.1.1"
+        "string-width": "^2.1.1"
       }
     },
     "text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
       "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
     },
     "through": {
@@ -1074,25 +1074,25 @@
       "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
     },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
       "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
       "requires": {
-        "os-tmpdir": "1.0.2"
+        "os-tmpdir": "~1.0.2"
       }
     },
     "type-check": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
       "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
       "requires": {
-        "prelude-ls": "1.1.2"
+        "prelude-ls": "~1.1.2"
       }
     },
     "typedarray": {
       "version": "0.0.6",
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
     },
     "util-deprecate": {
@@ -1100,17 +1100,17 @@
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
       "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
       "requires": {
-        "isexe": "2.0.0"
+        "isexe": "^2.0.0"
       }
     },
     "wordwrap": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
       "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
     },
     "wrappy": {
@@ -1118,17 +1118,17 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "write": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
       "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
       "requires": {
-        "mkdirp": "0.5.1"
+        "mkdirp": "^0.5.1"
       }
     },
     "yallist": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
       "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
     }
   }
--- a/python/mozbuild/mozbuild/backend/cargo_build_defs.py
+++ b/python/mozbuild/mozbuild/backend/cargo_build_defs.py
@@ -24,21 +24,67 @@ cargo_extra_outputs = {
         'libglobal_static.a',
         'src/os/unix/global_static.o',
     ],
     'selectors': [
         'ascii_case_insensitive_html_attributes.rs',
     ],
     'style': [
         'gecko/atom_macro.rs',
+        'gecko/bindings.rs',
         'gecko/pseudo_element_definition.rs',
+        'gecko/structs.rs',
         'gecko_properties.rs',
+        'longhands/background.rs',
+        'longhands/border.rs',
+        'longhands/box.rs',
+        'longhands/color.rs',
+        'longhands/column.rs',
+        'longhands/counters.rs',
+        'longhands/effects.rs',
+        'longhands/font.rs',
+        'longhands/inherited_box.rs',
+        'longhands/inherited_svg.rs',
+        'longhands/inherited_table.rs',
+        'longhands/inherited_text.rs',
+        'longhands/inherited_ui.rs',
+        'longhands/list.rs',
+        'longhands/margin.rs',
+        'longhands/outline.rs',
+        'longhands/padding.rs',
+        'longhands/position.rs',
+        'longhands/svg.rs',
+        'longhands/table.rs',
+        'longhands/text.rs',
+        'longhands/ui.rs',
+        'longhands/xul.rs',
         'properties.rs',
-        'gecko/bindings.rs',
-        'gecko/structs.rs',
+        'shorthands/background.rs',
+        'shorthands/border.rs',
+        'shorthands/box.rs',
+        'shorthands/color.rs',
+        'shorthands/column.rs',
+        'shorthands/counters.rs',
+        'shorthands/effects.rs',
+        'shorthands/font.rs',
+        'shorthands/inherited_box.rs',
+        'shorthands/inherited_svg.rs',
+        'shorthands/inherited_table.rs',
+        'shorthands/inherited_text.rs',
+        'shorthands/inherited_ui.rs',
+        'shorthands/list.rs',
+        'shorthands/margin.rs',
+        'shorthands/outline.rs',
+        'shorthands/padding.rs',
+        'shorthands/position.rs',
+        'shorthands/svg.rs',
+        'shorthands/table.rs',
+        'shorthands/text.rs',
+        'shorthands/ui.rs',
+        'shorthands/xul.rs',
     ],
     'webrender': [
         'shaders.rs',
     ],
 }
 
 cargo_extra_flags = {
     'style': [
--- a/servo/components/style/properties/build.py
+++ b/servo/components/style/properties/build.py
@@ -14,36 +14,91 @@ sys.path.insert(0, BASE)  # For importin
 from mako import exceptions
 from mako.lookup import TemplateLookup
 from mako.template import Template
 
 import data
 
 RE_PYTHON_ADDR = re.compile(r'<.+? object at 0x[0-9a-fA-F]+>')
 
+OUT_DIR = os.environ.get("OUT_DIR", "")
+
+STYLE_STRUCT_LIST = [
+    "background",
+    "border",
+    "box",
+    "color",
+    "column",
+    "counters",
+    "effects",
+    "font",
+    "inherited_box",
+    "inherited_table",
+    "inherited_text",
+    "inherited_ui",
+    "inherited_svg",
+    "list",
+    "margin",
+    "outline",
+    "padding",
+    "position",
+    "table",
+    "text",
+    "ui",
+    "svg",
+    "xul",
+]
+
 
 def main():
     usage = "Usage: %s [ servo | gecko ] [ style-crate | geckolib <template> | html ]" % sys.argv[0]
     if len(sys.argv) < 3:
         abort(usage)
     product = sys.argv[1]
     output = sys.argv[2]
 
     if product not in ["servo", "gecko"] or output not in ["style-crate", "geckolib", "html"]:
         abort(usage)
 
     properties = data.PropertiesData(product=product)
-    template = os.path.join(BASE, "properties.mako.rs")
-    rust = render(template, product=product, data=properties, __file__=template)
+    files = {}
+    for kind in ["longhands", "shorthands"]:
+        files[kind] = {}
+        for struct in STYLE_STRUCT_LIST:
+            file_name = os.path.join(BASE, kind, "{}.mako.rs".format(struct))
+            if kind == "shorthands" and not os.path.exists(file_name):
+                files[kind][struct] = ""
+                continue
+            files[kind][struct] = render(
+                file_name,
+                product = product,
+                data = properties,
+            )
+    properties_template = os.path.join(BASE, "properties.mako.rs")
+    files["properties"] = render(
+        properties_template,
+        product = product,
+        data = properties,
+        __file__ = properties_template,
+        OUT_DIR = OUT_DIR,
+    )
     if output == "style-crate":
-        write(os.environ["OUT_DIR"], "properties.rs", rust)
+        write(OUT_DIR, "properties.rs", files["properties"])
+        for kind in ["longhands", "shorthands"]:
+            for struct in files[kind]:
+                write(
+                    os.path.join(OUT_DIR, kind),
+                    "{}.rs".format(struct),
+                    files[kind][struct],
+                )
+
         if product == "gecko":
             template = os.path.join(BASE, "gecko.mako.rs")
             rust = render(template, data=properties)
-            write(os.environ["OUT_DIR"], "gecko_properties.rs", rust)
+            write(OUT_DIR, "gecko_properties.rs", rust)
     elif output == "geckolib":
         if len(sys.argv) < 4:
             abort(usage)
         template = sys.argv[3]
         header = render(template, data=properties)
         sys.stdout.write(header)
     elif output == "html":
         write_html(properties)
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -33,16 +33,20 @@ def maybe_moz_logical_alias(product, sid
 
 def to_rust_ident(name):
     name = name.replace("-", "_")
     if name in ["static", "super", "box", "move"]:  # Rust keywords
         name += "_"
     return name
 
 
+def to_snake_case(ident):
+    return re.sub("([A-Z]+)", lambda m: "_" + m.group(1).lower(), ident).strip("_")
+
+
 def to_camel_case(ident):
     return re.sub("(^|_|-)([a-z0-9])", lambda m: m.group(2).upper(), ident.strip("_").strip("-"))
 
 
 def to_camel_case_lower(ident):
     camel = to_camel_case(ident)
     return camel[0].lower() + camel[1:]
 
@@ -446,17 +450,17 @@ class Method(object):
     def stub(self):
         return self.signature() + "{ unimplemented!() }"
 
 
 class StyleStruct(object):
     def __init__(self, name, inherited, gecko_name=None, additional_methods=None):
         self.gecko_struct_name = "Gecko" + name
         self.name = name
-        self.name_lower = name.lower()
+        self.name_lower = to_snake_case(name)
         self.ident = to_rust_ident(self.name_lower)
         self.longhands = []
         self.inherited = inherited
         self.gecko_name = gecko_name or name
         self.gecko_ffi_name = "nsStyle" + self.gecko_name
         self.additional_methods = additional_methods or []
 
 
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -19,17 +19,17 @@ use smallvec::SmallVec;
 use std::fmt::{self, Write};
 use std::iter::{DoubleEndedIterator, Zip};
 use std::slice::Iter;
 use str::{CssString, CssStringBorrow, CssStringWriter};
 use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
 use stylesheets::{CssRuleType, Origin, UrlExtraData};
 use super::*;
 use values::computed::Context;
-#[cfg(feature = "gecko")] use properties::animated_properties::AnimationValueMap;
+use properties::animated_properties::AnimationValueMap;
 
 /// The animation rules.
 ///
 /// The first one is for Animation cascade level, and the second one is for
 /// Transition cascade level.
 pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
                           pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
 
@@ -682,17 +682,16 @@ impl PropertyDeclarationBlock {
                     QuirksMode::NoQuirks,
                 ).to_css(dest)
             },
             (ref d, _) => d.to_css(dest),
         }
     }
 
     /// Convert AnimationValueMap to PropertyDeclarationBlock.
-    #[cfg(feature = "gecko")]
     pub fn from_animation_value_map(animation_value_map: &AnimationValueMap) -> Self {
         let len = animation_value_map.len();
         let mut declarations = Vec::with_capacity(len);
         let mut longhands = LonghandIdSet::new();
 
         for (property, animation_value) in animation_value_map.iter() {
           longhands.insert(*property);
           declarations.push(animation_value.uncompute());
@@ -702,17 +701,16 @@ impl PropertyDeclarationBlock {
             declarations,
             longhands,
             declarations_importance: SmallBitVec::from_elem(len, false),
         }
     }
 
     /// Returns true if the declaration block has a CSSWideKeyword for the given
     /// property.
-    #[cfg(feature = "gecko")]
     pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
         if let Some(id) = property.longhand_id() {
             if !self.longhands.contains(id) {
                 return false
             }
         }
         self.declarations.iter().any(|decl|
             decl.id().is_or_is_longhand_of(property) &&
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -20,17 +20,17 @@ use properties::longhands;
 use properties::longhands::font_weight::computed_value::T as FontWeight;
 use properties::longhands::visibility::computed_value::T as Visibility;
 use properties::PropertyId;
 use properties::{LonghandId, ShorthandId};
 use servo_arc::Arc;
 use smallvec::SmallVec;
 use std::{cmp, ptr};
 use std::mem::{self, ManuallyDrop};
-#[cfg(feature = "gecko")] use hash::FnvHashMap;
+use hash::FnvHashMap;
 use super::ComputedValues;
 use values::CSSFloat;
 use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
 use values::animated::color::RGBA as AnimatedRGBA;
 use values::animated::effects::Filter as AnimatedFilter;
 #[cfg(feature = "gecko")] use values::computed::TransitionProperty;
 use values::computed::{Angle, CalcLengthOrPercentage};
 use values::computed::{ClipRect, Context};
@@ -224,18 +224,18 @@ impl AnimatedProperty {
             _ => return None,
         })
     }
 }
 
 /// A collection of AnimationValue that were composed on an element.
 /// This HashMap stores the values that are the last AnimationValue to be
 /// composed for each TransitionProperty.
-#[cfg(feature = "gecko")]
 pub type AnimationValueMap = FnvHashMap<LonghandId, AnimationValue>;
+
 #[cfg(feature = "gecko")]
 unsafe impl HasFFI for AnimationValueMap {
     type FFIType = RawServoAnimationValueMap;
 }
 #[cfg(feature = "gecko")]
 unsafe impl HasSimpleFFI for AnimationValueMap {}
 
 /// An enum to represent a single computed value belonging to an animated
rename from servo/components/style/properties/longhand/background.mako.rs
rename to servo/components/style/properties/longhands/background.mako.rs
rename from servo/components/style/properties/longhand/border.mako.rs
rename to servo/components/style/properties/longhands/border.mako.rs
rename from servo/components/style/properties/longhand/box.mako.rs
rename to servo/components/style/properties/longhands/box.mako.rs
rename from servo/components/style/properties/longhand/color.mako.rs
rename to servo/components/style/properties/longhands/color.mako.rs
rename from servo/components/style/properties/longhand/column.mako.rs
rename to servo/components/style/properties/longhands/column.mako.rs
rename from servo/components/style/properties/longhand/counters.mako.rs
rename to servo/components/style/properties/longhands/counters.mako.rs
rename from servo/components/style/properties/longhand/effects.mako.rs
rename to servo/components/style/properties/longhands/effects.mako.rs
rename from servo/components/style/properties/longhand/font.mako.rs
rename to servo/components/style/properties/longhands/font.mako.rs
rename from servo/components/style/properties/longhand/inherited_box.mako.rs
rename to servo/components/style/properties/longhands/inherited_box.mako.rs
rename from servo/components/style/properties/longhand/inherited_svg.mako.rs
rename to servo/components/style/properties/longhands/inherited_svg.mako.rs
rename from servo/components/style/properties/longhand/inherited_table.mako.rs
rename to servo/components/style/properties/longhands/inherited_table.mako.rs
rename from servo/components/style/properties/longhand/inherited_text.mako.rs
rename to servo/components/style/properties/longhands/inherited_text.mako.rs
rename from servo/components/style/properties/longhand/inherited_ui.mako.rs
rename to servo/components/style/properties/longhands/inherited_ui.mako.rs
rename from servo/components/style/properties/longhand/list.mako.rs
rename to servo/components/style/properties/longhands/list.mako.rs
rename from servo/components/style/properties/longhand/margin.mako.rs
rename to servo/components/style/properties/longhands/margin.mako.rs
rename from servo/components/style/properties/longhand/outline.mako.rs
rename to servo/components/style/properties/longhands/outline.mako.rs
rename from servo/components/style/properties/longhand/padding.mako.rs
rename to servo/components/style/properties/longhands/padding.mako.rs
rename from servo/components/style/properties/longhand/position.mako.rs
rename to servo/components/style/properties/longhands/position.mako.rs
rename from servo/components/style/properties/longhand/svg.mako.rs
rename to servo/components/style/properties/longhands/svg.mako.rs
rename from servo/components/style/properties/longhand/table.mako.rs
rename to servo/components/style/properties/longhands/table.mako.rs
rename from servo/components/style/properties/longhand/text.mako.rs
rename to servo/components/style/properties/longhands/text.mako.rs
rename from servo/components/style/properties/longhand/ui.mako.rs
rename to servo/components/style/properties/longhands/ui.mako.rs
rename from servo/components/style/properties/longhand/xul.mako.rs
rename to servo/components/style/properties/longhands/xul.mako.rs
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -92,39 +92,19 @@ macro_rules! expanded {
             )+
         }
     }
 }
 
 /// A module with all the code for longhand properties.
 #[allow(missing_docs)]
 pub mod longhands {
-    <%include file="/longhand/background.mako.rs" />
-    <%include file="/longhand/border.mako.rs" />
-    <%include file="/longhand/box.mako.rs" />
-    <%include file="/longhand/color.mako.rs" />
-    <%include file="/longhand/column.mako.rs" />
-    <%include file="/longhand/counters.mako.rs" />
-    <%include file="/longhand/effects.mako.rs" />
-    <%include file="/longhand/font.mako.rs" />
-    <%include file="/longhand/inherited_box.mako.rs" />
-    <%include file="/longhand/inherited_table.mako.rs" />
-    <%include file="/longhand/inherited_text.mako.rs" />
-    <%include file="/longhand/inherited_ui.mako.rs" />
-    <%include file="/longhand/list.mako.rs" />
-    <%include file="/longhand/margin.mako.rs" />
-    <%include file="/longhand/outline.mako.rs" />
-    <%include file="/longhand/padding.mako.rs" />
-    <%include file="/longhand/position.mako.rs" />
-    <%include file="/longhand/table.mako.rs" />
-    <%include file="/longhand/text.mako.rs" />
-    <%include file="/longhand/ui.mako.rs" />
-    <%include file="/longhand/inherited_svg.mako.rs" />
-    <%include file="/longhand/svg.mako.rs" />
-    <%include file="/longhand/xul.mako.rs" />
+    % for style_struct in data.style_structs:
+    include!("${repr(os.path.join(OUT_DIR, 'longhands/{}.rs'.format(style_struct.name_lower)))[1:-1]}");
+    % endfor
 }
 
 macro_rules! unwrap_or_initial {
     ($prop: ident) => (unwrap_or_initial!($prop, $prop));
     ($prop: ident, $expr: expr) =>
         ($expr.unwrap_or_else(|| $prop::get_initial_specified_value()));
 }
 
@@ -132,33 +112,47 @@ macro_rules! unwrap_or_initial {
 /// serialization helpers.
 #[allow(missing_docs)]
 pub mod shorthands {
     use cssparser::Parser;
     use parser::{Parse, ParserContext};
     use style_traits::{ParseError, StyleParseErrorKind};
     use values::specified;
 
-    <%include file="/shorthand/serialize.mako.rs" />
-    <%include file="/shorthand/background.mako.rs" />
-    <%include file="/shorthand/border.mako.rs" />
-    <%include file="/shorthand/box.mako.rs" />
-    <%include file="/shorthand/column.mako.rs" />
-    <%include file="/shorthand/font.mako.rs" />
-    <%include file="/shorthand/inherited_text.mako.rs" />
-    <%include file="/shorthand/list.mako.rs" />
-    <%include file="/shorthand/margin.mako.rs" />
-    <%include file="/shorthand/mask.mako.rs" />
-    <%include file="/shorthand/outline.mako.rs" />
-    <%include file="/shorthand/padding.mako.rs" />
-    <%include file="/shorthand/position.mako.rs" />
-    <%include file="/shorthand/inherited_svg.mako.rs" />
-    <%include file="/shorthand/text.mako.rs" />
-
-    // We don't defined the 'all' shorthand using the regular helpers:shorthand
+    use style_traits::{CssWriter, ToCss};
+    use values::specified::{BorderStyle, Color};
+    use std::fmt::{self, Write};
+
+    fn serialize_directional_border<W, I,>(
+        dest: &mut CssWriter<W>,
+        width: &I,
+        style: &BorderStyle,
+        color: &Color,
+    ) -> fmt::Result
+    where
+        W: Write,
+        I: ToCss,
+    {
+        width.to_css(dest)?;
+        // FIXME(emilio): Should we really serialize the border style if it's
+        // `solid`?
+        dest.write_str(" ")?;
+        style.to_css(dest)?;
+        if *color != Color::CurrentColor {
+            dest.write_str(" ")?;
+            color.to_css(dest)?;
+        }
+        Ok(())
+    }
+
+    % for style_struct in data.style_structs:
+    include!("${repr(os.path.join(OUT_DIR, 'shorthands/{}.rs'.format(style_struct.name_lower)))[1:-1]}");
+    % endfor
+
+    // We didn't define the 'all' shorthand using the regular helpers:shorthand
     // mechanism, since it causes some very large types to be generated.
     //
     // Also, make sure logical properties appear before its physical
     // counter-parts, in order to prevent bugs like:
     //
     //   https://bugzilla.mozilla.org/show_bug.cgi?id=1410028
     //
     // FIXME(emilio): Adopt the resolution from:
@@ -3847,17 +3841,17 @@ where
                 }
             % endif
 
             let discriminant = longhand_id as usize;
             (CASCADE_PROPERTY[discriminant])(&*declaration, &mut context);
         }
         % if category_to_cascade_now == "early":
             let writing_mode =
-                WritingMode::new(context.builder.get_inheritedbox());
+                WritingMode::new(context.builder.get_inherited_box());
             context.builder.writing_mode = writing_mode;
 
             let mut _skip_font_family = false;
 
             % if product == "gecko":
 
                 // <svg:text> is not affected by text zoom, and it uses a preshint to
                 // disable it. We fix up the struct when this happens by unzooming
deleted file mode 100644
--- a/servo/components/style/properties/shorthand/serialize.mako.rs
+++ /dev/null
@@ -1,27 +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 style_traits::{CssWriter, ToCss};
-use values::specified::{BorderStyle, Color};
-use std::fmt::{self, Write};
-
-fn serialize_directional_border<W, I,>(
-    dest: &mut CssWriter<W>,
-    width: &I,
-    style: &BorderStyle,
-    color: &Color,
-) -> fmt::Result
-where
-    W: Write,
-    I: ToCss,
-{
-    width.to_css(dest)?;
-    dest.write_str(" ")?;
-    style.to_css(dest)?;
-    if *color != Color::CurrentColor {
-        dest.write_str(" ")?;
-        color.to_css(dest)?;
-    }
-    Ok(())
-}
rename from servo/components/style/properties/shorthand/background.mako.rs
rename to servo/components/style/properties/shorthands/background.mako.rs
rename from servo/components/style/properties/shorthand/border.mako.rs
rename to servo/components/style/properties/shorthands/border.mako.rs
rename from servo/components/style/properties/shorthand/box.mako.rs
rename to servo/components/style/properties/shorthands/box.mako.rs
rename from servo/components/style/properties/shorthand/column.mako.rs
rename to servo/components/style/properties/shorthands/column.mako.rs
rename from servo/components/style/properties/shorthand/font.mako.rs
rename to servo/components/style/properties/shorthands/font.mako.rs
rename from servo/components/style/properties/shorthand/inherited_svg.mako.rs
rename to servo/components/style/properties/shorthands/inherited_svg.mako.rs
rename from servo/components/style/properties/shorthand/inherited_text.mako.rs
rename to servo/components/style/properties/shorthands/inherited_text.mako.rs
rename from servo/components/style/properties/shorthand/list.mako.rs
rename to servo/components/style/properties/shorthands/list.mako.rs
rename from servo/components/style/properties/shorthand/margin.mako.rs
rename to servo/components/style/properties/shorthands/margin.mako.rs
rename from servo/components/style/properties/shorthand/outline.mako.rs
rename to servo/components/style/properties/shorthands/outline.mako.rs
rename from servo/components/style/properties/shorthand/padding.mako.rs
rename to servo/components/style/properties/shorthands/padding.mako.rs
rename from servo/components/style/properties/shorthand/position.mako.rs
rename to servo/components/style/properties/shorthands/position.mako.rs
rename from servo/components/style/properties/shorthand/mask.mako.rs
rename to servo/components/style/properties/shorthands/svg.mako.rs
rename from servo/components/style/properties/shorthand/text.mako.rs
rename to servo/components/style/properties/shorthands/text.mako.rs
--- a/servo/components/style/sharing/mod.rs
+++ b/servo/components/style/sharing/mod.rs
@@ -810,17 +810,21 @@ impl<E: TElement> StyleSharingCache<E> {
 
         debug!(
             "Sharing allowed between {:?} and {:?}",
             target.element, candidate.element
         );
         Some(candidate.element.borrow_data().unwrap().share_styles())
     }
 
-    /// Attempts to find an element in the cache with the given primary rule node and parent.
+    /// Attempts to find an element in the cache with the given primary rule
+    /// node and parent.
+    ///
+    /// FIXME(emilio): re-measure this optimization, and remove if it's not very
+    /// useful... It's probably not worth the complexity / obscure bugs.
     pub fn lookup_by_rules(
         &mut self,
         shared_context: &SharedStyleContext,
         inherited: &ComputedValues,
         rules: &StrongRuleNode,
         visited_rules: Option<&StrongRuleNode>,
         target: E,
     ) -> Option<PrimaryStyle> {
@@ -836,28 +840,37 @@ impl<E: TElement> StyleSharingCache<E> {
             let data = candidate.element.borrow_data().unwrap();
             let style = data.styles.primary();
             if style.rules.as_ref() != Some(&rules) {
                 return None;
             }
             if style.visited_rules() != visited_rules {
                 return None;
             }
-
+            // NOTE(emilio): We only need to check name / namespace because we
+            // do name-dependent style adjustments, like the display: contents
+            // to display: none adjustment.
+            if target.namespace() != candidate.element.namespace() {
+                return None;
+            }