Merge autoland to mozilla-central. a=merge
authorCiure Andrei <aciure@mozilla.com>
Fri, 24 May 2019 00:51:34 +0300
changeset 475222 d551d37b9ad0dd1c8ad2e87c74344f623fc4b694
parent 475166 9a89e2b0fa9d7e6393deb47452e3954d4c5adf66 (current diff)
parent 475221 ae1b2b5ee05c54ecdb80876134eda2f4973640b6 (diff)
child 475291 c87317c4190283cc4352331417babef3d3f9546d
child 475401 83e89748aaac69c8ca94ef64847d9fd1640cbd63
push id36057
push useraciure@mozilla.com
push dateThu, 23 May 2019 21:52:03 +0000
treeherdermozilla-central@d551d37b9ad0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone69.0a1
first release with
nightly linux32
d551d37b9ad0 / 69.0a1 / 20190523215203 / files
nightly linux64
d551d37b9ad0 / 69.0a1 / 20190523215203 / files
nightly mac
d551d37b9ad0 / 69.0a1 / 20190523215203 / files
nightly win32
d551d37b9ad0 / 69.0a1 / 20190523215203 / files
nightly win64
d551d37b9ad0 / 69.0a1 / 20190523215203 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central. a=merge
devtools/client/themes/images/alerticon-unused.svg
testing/web-platform/meta/css/css-scroll-snap/nested-scrollIntoView-snaps.html.ini
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -532,17 +532,32 @@ Accessible* Accessible::ChildAtPoint(int
   nsRect screenRect = startFrame->GetScreenRectInAppUnits();
   nsPoint offset(presContext->DevPixelsToAppUnits(aX) - screenRect.X(),
                  presContext->DevPixelsToAppUnits(aY) - screenRect.Y());
 
   // We need to take into account a non-1 resolution set on the presshell.
   // This happens in mobile platforms with async pinch zooming.
   offset = offset.RemoveResolution(presContext->PresShell()->GetResolution());
 
-  nsIFrame* foundFrame = nsLayoutUtils::GetFrameForPoint(startFrame, offset);
+  // We need to translate with the offset of the edge of the visual
+  // viewport from top edge of the layout viewport.
+  offset += presContext->PresShell()->GetVisualViewportOffset() -
+            presContext->PresShell()->GetLayoutViewportOffset();
+
+  EnumSet<nsLayoutUtils::FrameForPointOption> options = {
+#ifdef MOZ_WIDGET_ANDROID
+      // This is needed in Android to ignore the clipping of the scroll frame
+      // when zoomed in. May regress something on other platforms, so
+      // keeping it Android-exclusive for now.
+      nsLayoutUtils::FrameForPointOption::IgnoreRootScrollFrame
+#endif
+  };
+
+  nsIFrame* foundFrame =
+      nsLayoutUtils::GetFrameForPoint(startFrame, offset, options);
 
   nsIContent* content = nullptr;
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   DocAccessible* contentDocAcc =
@@ -640,21 +655,28 @@ nsRect Accessible::RelativeBounds(nsIFra
 
 nsRect Accessible::BoundsInAppUnits() const {
   nsIFrame* boundingFrame = nullptr;
   nsRect unionRectTwips = RelativeBounds(&boundingFrame);
   if (!boundingFrame) {
     return nsRect();
   }
 
+  PresShell* presShell = mDoc->PresContext()->PresShell();
+
+  // We need to inverse translate with the offset of the edge of the visual
+  // viewport from top edge of the layout viewport.
+  nsPoint viewportOffset = presShell->GetVisualViewportOffset() -
+                           presShell->GetLayoutViewportOffset();
+  unionRectTwips.MoveBy(-viewportOffset);
+
   // We need to take into account a non-1 resolution set on the presshell.
   // This happens in mobile platforms with async pinch zooming. Here we
   // scale the bounds before adding the screen-relative offset.
-  unionRectTwips.ScaleRoundOut(
-      mDoc->PresContext()->PresShell()->GetResolution());
+  unionRectTwips.ScaleRoundOut(presShell->GetResolution());
   // We have the union of the rectangle, now we need to put it in absolute
   // screen coords.
   nsRect orgRectPixels = boundingFrame->GetScreenRectInAppUnits();
   unionRectTwips.MoveBy(orgRectPixels.X(), orgRectPixels.Y());
 
   return unionRectTwips;
 }
 
--- a/accessible/html/HTMLSelectAccessible.cpp
+++ b/accessible/html/HTMLSelectAccessible.cpp
@@ -299,17 +299,17 @@ bool HTMLComboboxAccessible::RemoveChild
   if (AccessibleWrap::RemoveChild(aChild)) {
     mListAccessible = nullptr;
     return true;
   }
   return false;
 }
 
 void HTMLComboboxAccessible::Shutdown() {
-  MOZ_ASSERT(mDoc->IsDefunct() || !mListAccessible);
+  MOZ_ASSERT(!mDoc || mDoc->IsDefunct() || !mListAccessible);
   if (mListAccessible) {
     mListAccessible->Shutdown();
     mListAccessible = nullptr;
   }
 
   AccessibleWrap::Shutdown();
 }
 
--- a/accessible/interfaces/msaa/ISimpleDOMNode.idl
+++ b/accessible/interfaces/msaa/ISimpleDOMNode.idl
@@ -8,17 +8,17 @@ cpp_quote("//")
 cpp_quote("// ISimpleDOMNode")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
 cpp_quote("// An interface that extends MSAA's IAccessible to provide readonly DOM node information via cross-process COM.")
 cpp_quote("//")
 cpp_quote("// get_nodeInfo(")
 cpp_quote("//  /* [out] */ BSTR  *nodeName,   // For elements, this is the tag name")
 cpp_quote("//  /* [out] */ short  *nameSpaceID,")
 cpp_quote("//  /* [out] */ BSTR  *nodeValue, ")
-cpp_quote("//  /* [out] */ unsigned int    *numChildren); ") 
+cpp_quote("//  /* [out] */ unsigned int    *numChildren); ")
 cpp_quote("//  /* [out] */ unsigned int    *uniqueID;  // In Win32 accessible events we generate, the target's childID matches to this")
 cpp_quote("//  /* [out] */ unsigned short  *nodeType,")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
 cpp_quote("// Get the basic information about a node.")
 cpp_quote("// The namespace ID can be mapped to an URI using nsISimpleDOMDocument::get_nameSpaceURIForID()")
 cpp_quote("//")
 cpp_quote("// get_attributes(")
 cpp_quote("//  /* [in]  */ unsigned short maxAttribs,")
@@ -119,54 +119,54 @@ interface ISimpleDOMNode : IUnknown
     [out] BSTR *nodeName,   // for performance returns NULL for text nodes (true nodeName would be "#text")
     [out] short *nameSpaceID,
     [out] BSTR *nodeValue,
     [out] unsigned int *numChildren,
     [out] unsigned int *uniqueID, // In Win32 accessible events we generate, the target's childID matches to this
     [out, retval] unsigned short *nodeType
   );
 
-  [propget] HRESULT attributes(  
+  [propget] HRESULT attributes(
     [in] unsigned short maxAttribs,
-    [out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribNames, 
-    [out, size_is(maxAttribs), length_is(*numAttribs)] short *nameSpaceID,  
+    [out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribNames,
+    [out, size_is(maxAttribs), length_is(*numAttribs)] short *nameSpaceID,
     [out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribValues,
     [out, retval] unsigned short *numAttribs
   );
 
-  [propget] HRESULT attributesForNames(  
+  [propget] HRESULT attributesForNames(
     [in] unsigned short numAttribs,
-    [in, size_is(numAttribs), length_is(numAttribs)] BSTR *attribNames, 
-    [in, size_is(numAttribs), length_is(numAttribs)] short *nameSpaceID,  
+    [in, size_is(numAttribs), length_is(numAttribs)] BSTR *attribNames,
+    [in, size_is(numAttribs), length_is(numAttribs)] short *nameSpaceID,
     [out, retval, size_is(numAttribs), length_is(numAttribs)] BSTR *attribValues
   );
 
-  [propget] HRESULT computedStyle(  
+  [propget] HRESULT computedStyle(
     [in] unsigned short maxStyleProperties,
     [in] boolean useAlternateView,  // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes
-    [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties, 
+    [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties,
     [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues,
     [out, retval] unsigned short *numStyleProperties
   );
 
-  [propget] HRESULT computedStyleForProperties(  
-    [in] unsigned short numStyleProperties, 
+  [propget] HRESULT computedStyleForProperties(
+    [in] unsigned short numStyleProperties,
     [in] boolean useAlternateView,  // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes
-    [in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties, 
+    [in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties,
     [out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues
   );
 
   HRESULT scrollTo([in] boolean placeTopLeft);
 
   [propget] HRESULT parentNode([out, retval] ISimpleDOMNode **node);
   [propget] HRESULT firstChild([out, retval] ISimpleDOMNode **node);
   [propget] HRESULT lastChild([out, retval] ISimpleDOMNode **node);
   [propget] HRESULT previousSibling([out, retval] ISimpleDOMNode **node);
   [propget] HRESULT nextSibling([out, retval] ISimpleDOMNode **node);
-  [propget] HRESULT childAt([in] unsigned childIndex, 
+  [propget] HRESULT childAt([in] unsigned childIndex,
                             [out, retval] ISimpleDOMNode **node);
 
   [propget] HRESULT innerHTML([out, retval] BSTR *innerHTML);
 
   [propget, local] HRESULT localInterface([out][retval] void **localInterface);
 
   [propget, call_as(get_localInterface)]
   HRESULT remoteLocalInterface([out][retval] IUnknown **localInterface);
--- a/accessible/interfaces/msaa/ISimpleDOMText.idl
+++ b/accessible/interfaces/msaa/ISimpleDOMText.idl
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 import "objidl.idl";
 import "oaidl.idl";
-        
+
 cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
 cpp_quote("//")
 cpp_quote("// ISimpleDOMText")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
 cpp_quote("// An interface that extends MSAA's IAccessible to provide important additional capabilities on text nodes")
 cpp_quote("//")
 cpp_quote("// [propget] domText(/* out,retval */ BSTR *domText")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
@@ -52,28 +52,28 @@ cpp_quote("")
 cpp_quote("")
 
 [object, uuid(4e747be5-2052-4265-8af0-8ecad7aad1c0)]
 interface ISimpleDOMText: IUnknown
 {
   // Includes whitespace in DOM
   [propget] HRESULT domText([out, retval] BSTR *domText);
 
-  HRESULT get_clippedSubstringBounds([in] unsigned int startIndex, 
-                                     [in] unsigned int endIndex, 
+  HRESULT get_clippedSubstringBounds([in] unsigned int startIndex,
+                                     [in] unsigned int endIndex,
                                      [out] int *x,
                                      [out] int *y,
                                      [out] int *width,
                                      [out] int *height);
 
-  HRESULT get_unclippedSubstringBounds([in] unsigned int startIndex, 
-                                       [in] unsigned int endIndex, 
+  HRESULT get_unclippedSubstringBounds([in] unsigned int startIndex,
+                                       [in] unsigned int endIndex,
                                        [out] int *x,
                                        [out] int *y,
                                        [out] int *width,
                                        [out] int *height);
 
-  HRESULT scrollToSubstring([in] unsigned int startIndex, 
+  HRESULT scrollToSubstring([in] unsigned int startIndex,
                             [in] unsigned int endIndex);
 
   [propget] HRESULT fontFamily([out, retval] BSTR *fontFamily);
 };
 
--- a/accessible/interfaces/nsIAccessibleEvent.idl
+++ b/accessible/interfaces/nsIAccessibleEvent.idl
@@ -14,21 +14,21 @@ webidl Node;
 #define NS_ACCESSIBLE_EVENT_TOPIC "accessible-event"
 %}
 
 /**
  * An interface for accessibility events listened to
  * by in-process accessibility clients, which can be used
  * to find out how to get accessibility and DOM interfaces for
  * the event and its target. To listen to in-process accessibility invents,
- * make your object an nsIObserver, and listen for accessible-event by 
+ * make your object an nsIObserver, and listen for accessible-event by
  * using code something like this:
- *   nsCOMPtr<nsIObserverService> observerService = 
+ *   nsCOMPtr<nsIObserverService> observerService =
  *     do_GetService("@mozilla.org/observer-service;1", &rv);
- *   if (NS_SUCCEEDED(rv)) 
+ *   if (NS_SUCCEEDED(rv))
  *     rv = observerService->AddObserver(this, "accessible-event", PR_TRUE);
  */
 [scriptable, builtinclass, uuid(20c69a40-6c2c-42a3-a578-6f4473aab9dd)]
 interface nsIAccessibleEvent : nsISupports
 {
   /**
    * An object has been created.
    */
@@ -185,17 +185,17 @@ interface nsIAccessibleEvent : nsISuppor
    * An application is about to enter drag-and-drop mode
    */
   const unsigned long EVENT_DRAGDROP_START = 0x001F;
 
   /**
    * An application is about to exit drag-and-drop mode
    */
   const unsigned long EVENT_DRAGDROP_END = 0x0020;
-  
+
   /**
    * A dialog box has been displayed
    */
   const unsigned long EVENT_DIALOG_START = 0x0021;
 
   /**
    * A dialog box has been closed
    */
@@ -433,23 +433,23 @@ interface nsIAccessibleEvent : nsISuppor
    */
   const unsigned long EVENT_LAST_ENTRY = 0x005A;
 
   /**
    * The type of event, based on the enumerated event values
    * defined in this interface.
    */
   readonly attribute unsigned long eventType;
-  
+
   /**
    * The nsIAccessible associated with the event.
    * May return null if no accessible is available
    */
   readonly attribute nsIAccessible accessible;
-  
+
   /**
    * The nsIAccessibleDocument that the event target nsIAccessible
    * resides in. This can be used to get the DOM window,
    * the DOM document and the window handler, among other things.
    */
   readonly attribute nsIAccessibleDocument accessibleDocument;
 
   /**
--- a/accessible/interfaces/nsIAccessibleRole.idl
+++ b/accessible/interfaces/nsIAccessibleRole.idl
@@ -118,17 +118,17 @@ interface nsIAccessibleRole : nsISupport
   const unsigned long ROLE_PANE = 16;
 
   /**
    * Represents a graphical image used to represent data.
    */
   const unsigned long ROLE_CHART = 17;
 
   /**
-   * Represents a dialog box or message box. It is used for xul:dialog, 
+   * Represents a dialog box or message box. It is used for xul:dialog,
    * role="dialog".
    */
   const unsigned long ROLE_DIALOG = 18;
 
   /**
    * Represents a window border.
    */
   const unsigned long ROLE_BORDER = 19;
@@ -704,37 +704,37 @@ interface nsIAccessibleRole : nsISupport
    * A item of list that is shown by combobox;
    */
   const unsigned long ROLE_COMBOBOX_OPTION = 115;
 
   /**
    * An image map -- has child links representing the areas
    */
   const unsigned long ROLE_IMAGE_MAP = 116;
-  
+
   /**
    * An option in a listbox
    */
   const unsigned long ROLE_OPTION = 117;
-  
+
   /**
    * A rich option in a listbox, it can have other widgets as children
    */
   const unsigned long ROLE_RICH_OPTION = 118;
-  
+
   /**
    * A list of options
    */
   const unsigned long ROLE_LISTBOX = 119;
 
   /**
    * Represents a mathematical equation in the accessible name
    */
   const unsigned long ROLE_FLAT_EQUATION = 120;
-  
+
   /**
    * Represents a cell within a grid. It is used for role="gridcell". Unlike
    * ROLE_CELL, it allows the calculation of the accessible name from subtree.
    * Also, see ROLE_TABLE.
    */
   const unsigned long ROLE_GRID_CELL = 121;
 
   /**
--- a/accessible/interfaces/nsIAccessibleStates.idl
+++ b/accessible/interfaces/nsIAccessibleStates.idl
@@ -54,24 +54,24 @@ interface nsIAccessibleStates : nsISuppo
 /**
  * Extended state flags (for now non-MSAA, for Java and Gnome/ATK support)
  * "Extended state flags" has separate value space from "MSAA State flags".
  */
   const unsigned long  EXT_STATE_SUPPORTS_AUTOCOMPLETION = 0x00000001;  // For editable areas that have any kind of autocompletion
   const unsigned long  EXT_STATE_DEFUNCT                 = 0x00000002;  // Object no longer exists
   const unsigned long  EXT_STATE_SELECTABLE_TEXT         = 0x00000004;  // For text which is selectable, object must implement nsIAccessibleText
   const unsigned long  EXT_STATE_EDITABLE                = 0x00000008;  // Implements nsIAccessibleEditableText
-  const unsigned long  EXT_STATE_ACTIVE                  = 0x00000010;  // This window is currently the active window    
-  const unsigned long  EXT_STATE_MODAL                   = 0x00000020;  // Must do something with control before leaving it    
-  const unsigned long  EXT_STATE_MULTI_LINE              = 0x00000040;  // Edit control that can take multiple lines    
+  const unsigned long  EXT_STATE_ACTIVE                  = 0x00000010;  // This window is currently the active window
+  const unsigned long  EXT_STATE_MODAL                   = 0x00000020;  // Must do something with control before leaving it
+  const unsigned long  EXT_STATE_MULTI_LINE              = 0x00000040;  // Edit control that can take multiple lines
   const unsigned long  EXT_STATE_HORIZONTAL              = 0x00000080;  // Uses horizontal layout
   const unsigned long  EXT_STATE_OPAQUE                  = 0x00000100;  // Indicates this object paints every pixel within its rectangular region.
-  const unsigned long  EXT_STATE_SINGLE_LINE             = 0x00000200;  // This text object can only contain 1 line of text    
-  const unsigned long  EXT_STATE_TRANSIENT               = 0x00000400;  // 
-  const unsigned long  EXT_STATE_VERTICAL                = 0x00000800;  // Especially used for sliders and scrollbars  
+  const unsigned long  EXT_STATE_SINGLE_LINE             = 0x00000200;  // This text object can only contain 1 line of text
+  const unsigned long  EXT_STATE_TRANSIENT               = 0x00000400;  //
+  const unsigned long  EXT_STATE_VERTICAL                = 0x00000800;  // Especially used for sliders and scrollbars
   const unsigned long  EXT_STATE_STALE                   = 0x00001000;  // Object not dead, but not up-to-date either
   const unsigned long  EXT_STATE_ENABLED                 = 0x00002000;  // A widget that is not unavailable
   const unsigned long  EXT_STATE_SENSITIVE               = 0x00004000;  // Same as ENABLED for now
   const unsigned long  EXT_STATE_EXPANDABLE              = 0x00008000;  // If COLLAPSED or EXPANDED
   const unsigned long  EXT_STATE_PINNED                  = 0x00010000;  // Indicates object is pinned.
   const unsigned long  EXT_STATE_CURRENT                 = 0x00020000;  // Indicates object is the current item in its container
 };
 
--- a/accessible/ipc/win/handler/HandlerData.idl
+++ b/accessible/ipc/win/handler/HandlerData.idl
@@ -138,17 +138,17 @@ interface HandlerData
 interface IHandlerControl : IUnknown
 {
   HRESULT Invalidate();
   HRESULT OnTextChange([in] long aHwnd, [in] long aIA2UniqueId,
                        [in] VARIANT_BOOL aIsInsert,
                        [in] IA2TextSegment* aText);
 }
 
-typedef struct _IARelationData 
+typedef struct _IARelationData
 {
   BSTR mType;
   long mNTargets;
 } IARelationData;
 
 typedef struct _AccChildData
 {
   NEWEST_IA2_INTERFACE* mAccessible;
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<blocklist lastupdate="1558349549359" xmlns="http://www.mozilla.org/2006/addons-blocklist">
+<blocklist lastupdate="1558536765550" xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i1211" id="flvto@hotger.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
@@ -2992,16 +2992,48 @@
     <emItem blockID="4bda902e-fb36-417b-940f-992ab7a18fde" id="/^((\{78d3cced-d2a7-46e9-9fea-5be7ed61eea8\})|(\{3233777f-a1a7-4ea4-8c2c-fba1a0a68383\})|(\{0eb43948-2a3d-4490-b32d-7ca37dd83f07\})|(\{64fd625d-2977-46a6-96ca-77f81ebfd54d\})|(\{6e138cae-1be3-449e-a964-b3c3060d89b9\})|(\{f875c255-8b92-4229-95e1-6d9adaf20dd7\})|(\{3c62ef7f-ae8f-4baa-9d2d-27a377480b79\})|(\{35a91fe5-c255-498b-9f9f-bec506fdb257\})|(\{7d3c52e6-2b7f-4ce8-b28b-032306fe32df\})|(\{0ecf6f68-d506-4239-bc69-f77de8f03758\})|(\{7290f2b1-3d70-4990-a828-40c775c05f82\})|(\{50150580-86bc-460f-ae3a-12e51b9d842e\})|(\{a1b46cda-8a83-48e0-b355-7eca4250694f\})|(\{614d8f88-b5b4-4897-adc0-0207613f4d4f\})|(\{ddc259e9-3738-4b18-a00c-9259dad206ae\})|(\{5b2bf836-5322-4161-82dd-fcc8ac6e4247\})|(\{97a90c0a-5e3d-47bf-aacc-230e4cb1f2d1\}))$/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="413065ac-176f-440d-b4a7-0f928f3e330d" id="jid1-HfFCNbAsKx6Aow@jetpack">
       <prefs/>
       <versionRange minVersion="0" maxVersion="2.9.1.0" severity="3"/>
     </emItem>
+    <emItem blockID="0225ae55-626d-42b2-8f48-46ec95ec89f8" id="/^((\{2b3eed60-8f6e-4afc-99f1-38d12f4253da\})|(\{3a6f9dac-3a93-4f6f-8b74-9ebc0f501306\})|(\{46bba8e9-7a75-4dd6-932e-bdd74141cb87\})|(\{4b480ab6-b63a-43f8-b4f4-d312972ab086\})|(\{6106687e-ca0c-4d7e-93bc-115929e4d299\})|(\{717ce133-3c0a-448e-b6ed-fc7d22b76534\})|(\{7224f1ae-c342-4bb5-8441-d324a8951624\})|(\{768e9638-2eba-42e4-a13a-4f3f1df391a2\})|(\{7b655f43-c871-46d2-8f6d-31989e8ee939\})|(\{7e46c692-9488-4671-8c39-7830f92628b0\})|(\{83bc6b56-545f-4ba1-a80b-f82d55cc0f68\})|(\{970a774e-b7a7-498f-b3f2-d88b14b4dab1\})|(\{9d2e8731-3287-46eb-9c19-ece63fe693c7\})|(\{a37ccd20-e04f-4949-b055-98ca58639606\})|(\{af85f82c-3e8f-4ee5-ab53-b8d3aaac34ec\})|(\{b35c6d47-8b07-4d49-89a9-dfe8c10f58f6\})|(\{c2485579-368c-4593-a1cd-985b2fa0b990\})|(\{c85c16ba-78b4-41b3-9201-f80fa662c52f\})|(\{c97e5535-6f2e-4d34-a5a3-0e6e07f7fd13\})|(\{ce7db166-9564-482f-91d9-3a450ec3216d\})|(\{d64a2c73-ff21-4e3e-998f-ec2dc42ad725\})|(\{db6d93c3-67a0-410c-b7bd-f72f267f0cec\})|(\{e513775f-359f-47aa-a3d9-eddc946aabe0\})|(\{f70258e4-643b-4ec2-9c84-de89009eec61\})|(\{f8794e87-82b2-4df4-bce6-db207f62c165\}))$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="2212748f-ad60-497f-af7b-50d20b326e40" id="{da993d54-9605-42f7-a32f-9f565245070c}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="41137e55-8a11-4259-a009-42c29daadf17" id="{ac4be7d1-4db6-4b4c-bf48-e345350bcb59}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="a5fa8f77-7761-4996-a11d-d8cf723103da" id="{dc6176c4-a192-4a92-849f-ad13abe889ad}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="efecef61-549b-4c13-8a52-394c636dd24b" id="/^((\{ec19994c-c5a5-46d9-bd4d-0fc417c6f4b8\})|(\{a0be7e8d-b0a3-460b-8a52-429c79e49ee2\})|(\{1814dd58-4147-4cca-a0a3-c5aa35966d9c\}))$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="9c5f5681-8547-4e65-9c05-5796e483b8e1" id="/^((\{3e20d1e2-a7ee-4ce2-ab9c-51c8300a8ff6\})|(\{30906bbc-0942-445b-89c8-f74dac0edb8f\}))$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="7e86024e-5621-4ded-bc16-184f94fa2e29" id="{a37a7625-b64e-45f3-8b79-f71634f14438}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
+    <emItem blockID="43966df2-e95c-415b-bffc-13814e1d2b11" id="{3fc1db2b-e7db-4512-b24e-1faf4d3a1b4d}">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
   </emItems>
   <pluginItems>
     <pluginItem blockID="p332">
       <match exp="libflashplayer\.so" name="filename"/>
       <match exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" name="description"/>
       <infoURL>https://get.adobe.com/flashplayer/</infoURL>
       <versionRange severity="0" vulnerabilitystatus="1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
--- a/browser/base/content/test/menubar/browser.ini
+++ b/browser/base/content/test/menubar/browser.ini
@@ -1,3 +1,5 @@
 [DEFAULT]
 
 [browser_file_menu_import_wizard.js]
+[browser_window_menu_list.js]
+skip-if = os != "mac" # Mac only feature
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/menubar/browser_window_menu_list.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_window_menu_list() {
+  // This title is different depending on the build. For example, it's "Nightly"
+  // for a local build, "Mozilla Firefox" for an official release build.
+  const windowTitle = window.document.title;
+  await checkWindowMenu([windowTitle, "Browser chrome tests"]);
+  let newWindow = await BrowserTestUtils.openNewBrowserWindow();
+  await checkWindowMenu([windowTitle, "Browser chrome tests", windowTitle]);
+  await BrowserTestUtils.closeWindow(newWindow);
+});
+
+async function checkWindowMenu(labels) {
+  let menu = document.querySelector("#windowMenu");
+  // We can't toggle menubar items on OSX, so mocking instead.
+  await new Promise(resolve => {
+    menu.addEventListener("popupshown", resolve, { once: true });
+    menu.dispatchEvent(new MouseEvent("popupshowing"));
+    menu.dispatchEvent(new MouseEvent("popupshown"));
+  });
+
+  let menuitems = [...menu.querySelectorAll("menuseparator ~ menuitem")];
+  is(menuitems.length, labels.length, "Correct number of windows in the menu");
+  is(menuitems.map(item => item.label).join(","), labels.join(","), "Correct labels on menuitems");
+  for (let menuitem of menuitems) {
+    ok(menuitem instanceof customElements.get("menuitem"), "sibling is menuitem");
+  }
+
+  // We can't toggle menubar items on OSX, so mocking instead.
+  await new Promise(resolve => {
+    menu.addEventListener("popuphidden", resolve, { once: true });
+    menu.dispatchEvent(new MouseEvent("popuphiding"));
+    menu.dispatchEvent(new MouseEvent("popuphidden"));
+  });
+}
--- a/browser/base/content/test/performance/browser_startup_mainthreadio.js
+++ b/browser/base/content/test/performance/browser_startup_mainthreadio.js
@@ -284,26 +284,16 @@ const startupPhases = {
       close: 11,
     },
     { // bug 1545167
       path: "/etc/mime.types",
       condition: LINUX,
       read: 3,
       close: 3,
     },
-    {
-      path: "UChrm:userChrome.css",
-      condition: WIN,
-      stat: 1,
-    },
-    { // bug 1541233
-      path: "UChrm:userContent.css",
-      condition: WIN,
-      stat: 1,
-    },
     { // bug 1541246
       path: "XREUSysExt:",
       condition: WIN,
       stat: 1,
     },
     { // bug 1541246
       path: "XRESysExtDev:",
       condition: WIN,
--- a/browser/components/migration/nsIBrowserProfileMigrator.idl
+++ b/browser/components/migration/nsIBrowserProfileMigrator.idl
@@ -22,24 +22,24 @@ interface nsIBrowserProfileMigrator : ns
   const unsigned short PASSWORDS   = 0x0010;
   const unsigned short BOOKMARKS   = 0x0020;
   const unsigned short OTHERDATA   = 0x0040;
   const unsigned short SESSION     = 0x0080;
 
   /**
    * Copy user profile information to the current active profile.
    * @param aItems   list of data items to migrate. see above for values.
-   * @param aStartup helper interface which is non-null if called during startup. 
+   * @param aStartup helper interface which is non-null if called during startup.
    * @param aProfile profile to migrate from, if there is more than one.
    */
   void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in jsval aProfile);
 
   /**
    * A bit field containing profile items that this migrator
-   * offers for import. 
+   * offers for import.
    * @param   aProfile the profile that we are looking for available data
    *          to import
    * @param   aDoingStartup "true" if the profile is not currently being used.
    * @return  Promise containing a bit field containing profile items (see above)
    * @note    a return value of 0 represents no items rather than ALL.
    */
   jsval getMigrateData(in jsval aProfile, in boolean aDoingStartup);
 
--- a/browser/components/shell/nsIShellService.idl
+++ b/browser/components/shell/nsIShellService.idl
@@ -21,42 +21,42 @@ interface nsIShellService : nsISupports
    *                      false if the check should be made for HTTP only.
    *                      This parameter may be ignored on some platforms.
    */
   boolean isDefaultBrowser([optional] in boolean aForAllTypes);
 
   /**
    * Registers Firefox as the "Default Browser."
    *
-   * @param aClaimAllTypes Register Firefox as the handler for 
+   * @param aClaimAllTypes Register Firefox as the handler for
    *                       additional protocols (ftp, chrome etc)
    *                       and web documents (.html, .xhtml etc).
    * @param aForAllUsers   Whether or not Firefox should attempt
    *                       to become the default browser for all
-   *                       users on a multi-user system. 
+   *                       users on a multi-user system.
    */
   void setDefaultBrowser(in boolean aClaimAllTypes, in boolean aForAllUsers);
 
-  /** 
+  /**
    * Flags for positioning/sizing of the Desktop Background image.
    */
   const long BACKGROUND_TILE      = 1;
   const long BACKGROUND_STRETCH   = 2;
   const long BACKGROUND_CENTER    = 3;
   const long BACKGROUND_FILL      = 4;
   const long BACKGROUND_FIT       = 5;
   const long BACKGROUND_SPAN      = 6;
 
     /**
-     * Sets the desktop background image using either the HTML <IMG> 
+     * Sets the desktop background image using either the HTML <IMG>
      * element supplied or the background image of the element supplied.
      *
      * @param aImageElement Either a HTML <IMG> element or an element with
      *                      a background image from which to source the
-     *                      background image. 
+     *                      background image.
      * @param aPosition     How to place the image on the desktop
      * @param aImageName    The image name. Equivalent to the leaf name of the
      *                      location.href.
      */
   void setDesktopBackground(in Element aElement,
                             in long aPosition,
                             in ACString aImageName);
 
@@ -65,23 +65,23 @@ interface nsIShellService : nsISupports
    * openApplication.
    */
   const long APPLICATION_MAIL        = 0;
   const long APPLICATION_NEWS        = 1;
 
   /**
    * Opens the application specified. If more than one application of the
    * given type is available on the system, the default or "preferred"
-   * application is used. 
+   * application is used.
    */
   void openApplication(in long aApplication);
 
-  /** 
-   * The desktop background color, visible when no background image is 
-   * used, or if the background image is centered and does not fill the 
+  /**
+   * The desktop background color, visible when no background image is
+   * used, or if the background image is centered and does not fill the
    * entire screen. A rgb value, where (r << 16 | g << 8 | b)
    */
   attribute unsigned long desktopBackgroundColor;
 
   /**
    * Opens an application with a specific URI to load.
    * @param   application
    *          The application file (or bundle directory, on OS X)
--- a/browser/config/mozconfigs/win64-aarch64/common-opt
+++ b/browser/config/mozconfigs/win64-aarch64/common-opt
@@ -17,8 +17,14 @@ export MOZILLA_OFFICIAL=1
 . $topsrcdir/build/win64-aarch64/mozconfig.vs-latest
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 if test -n "$MOZ_ARTIFACT_TASK_WIN32_OPT"; then
   ac_add_options --enable-eme=widevine
 fi
+
+# Temporary signal to toolchain.configure that our compiler is patched to
+# support CFG, until such support can be assumed.
+if test -z "$USE_ARTIFACT"; then
+  ac_add_options --enable-hardening
+fi
--- a/browser/config/mozconfigs/win64-aarch64/common-win64
+++ b/browser/config/mozconfigs/win64-aarch64/common-win64
@@ -1,9 +1,3 @@
 # This file is used by all AArch64 Win64 builds
 
 ac_add_options --target=aarch64-windows-mingw32
-
-# Temporary signal to toolchain.configure that our compiler is patched to
-# support CFG, until such support can be assumed.
-if test -z "$USE_ARTIFACT"; then
-  ac_add_options --enable-hardening
-fi
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -283,16 +283,17 @@
 
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
 @RESPATH@/browser/@PREF_DIR@/firefox.js
 @RESPATH@/browser/@PREF_DIR@/firefox-branding.js
 @RESPATH@/greprefs.js
 @RESPATH@/defaults/autoconfig/prefcalls.js
 @RESPATH@/browser/defaults/permissions
+; Remote Settings JSON dumps
 @RESPATH@/browser/defaults/settings/blocklists
 @RESPATH@/browser/defaults/settings/pinning
 @RESPATH@/browser/defaults/settings/main
 @RESPATH@/browser/defaults/settings/security-state
 
 ; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
 ; Technically this is an app pref file, but we are keeping it in the original
 ; gre location for now.
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -6,17 +6,20 @@ from __future__ import print_function, u
 
 import errno
 import json
 import os
 import platform
 import subprocess
 import sys
 import uuid
-import __builtin__
+if sys.version_info[0] < 3:
+    import __builtin__ as builtins
+else:
+    import builtins
 
 from types import ModuleType
 
 
 STATE_DIR_FIRST_RUN = '''
 mach and the build system store shared state in a common directory on the
 filesystem. The following directory will be created:
 
@@ -429,9 +432,9 @@ class ImportHook(object):
                 os.remove(module.__file__)
             del sys.modules[module.__name__]
             module = self(name, globals, locals, fromlist, level)
 
         return module
 
 
 # Install our hook
-__builtin__.__import__ = ImportHook(__builtin__.__import__)
+builtins.__import__ = ImportHook(builtins.__import__)
--- a/chrome/nsIChromeRegistry.idl
+++ b/chrome/nsIChromeRegistry.idl
@@ -44,17 +44,17 @@ interface nsIChromeRegistry : nsISupport
 interface nsIXULChromeRegistry : nsIChromeRegistry
 {
   // If the optional asBCP47 parameter is true, the locale code will be
   // converted to a BCP47 language tag; in particular, this means that
   // "ja-JP-mac" will be returned as "ja-JP-x-lvariant-mac", which can be
   // passed to ECMA402 Intl API methods without throwing a RangeError.
   ACString getSelectedLocale(in ACString packageName,
                              [optional] in boolean asBCP47);
-  
+
   // Get whether the default writing direction of the locale is RTL
   // (or may be overridden by intl.uidirection pref)
   boolean isLocaleRTL(in ACString package);
 
   /**
    * Installable skin XBL is not always granted the same privileges as other
    * chrome. This asks the chrome registry whether scripts are allowed to be
    * run for a particular chrome URI. Do not pass non-chrome URIs to this
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -709,21 +709,18 @@ endif
 define src_objdep
 $(basename $3$(notdir $1)).$2: $1 $$(call mkdir_deps,$$(MDDEPDIR))
 endef
 $(foreach f,$(CSRCS) $(SSRCS) $(CPPSRCS) $(CMSRCS) $(CMMSRCS) $(ASFILES),$(eval $(call src_objdep,$(f),$(OBJ_SUFFIX))))
 $(foreach f,$(HOST_CSRCS) $(HOST_CPPSRCS) $(HOST_CMSRCS) $(HOST_CMMSRCS),$(eval $(call src_objdep,$(f),$(_OBJ_SUFFIX),host_)))
 
 # The Rust compiler only outputs library objects, and so we need different
 # mangling to generate dependency rules for it.
-mk_libname = $(basename lib$(notdir $1)).rlib
-src_libdep = $(call mk_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
 mk_global_crate_libname = $(basename lib$(notdir $1)).$(LIB_SUFFIX)
 crate_src_libdep = $(call mk_global_crate_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
-$(foreach f,$(RSSRCS),$(eval $(call src_libdep,$(f))))
 $(foreach f,$(RS_STATICLIB_CRATE_SRC),$(eval $(call crate_src_libdep,$(f))))
 
 $(OBJS) $(HOST_OBJS) $(PROGOBJS) $(HOST_PROGOBJS): $(GLOBAL_DEPS)
 
 # Rules for building native targets must come first because of the host_ prefix
 $(HOST_COBJS):
 	$(REPORT_BUILD_VERBOSE)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CPPFLAGS) $(HOST_CFLAGS) $(NSPR_CFLAGS) $(_VPATH_SRCS)
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -96,17 +96,16 @@ devtools.jar:
     skin/images/copy.svg (themes/images/copy.svg)
     skin/images/animation-fast-track.svg (themes/images/animation-fast-track.svg)
     skin/images/performance-details-waterfall.svg (themes/images/performance-details-waterfall.svg)
     skin/images/performance-details-call-tree.svg (themes/images/performance-details-call-tree.svg)
     skin/images/performance-details-flamegraph.svg (themes/images/performance-details-flamegraph.svg)
     skin/breadcrumbs.css (themes/breadcrumbs.css)
     skin/chart.css (themes/chart.css)
     skin/widgets.css (themes/widgets.css)
-    skin/images/alerticon-unused.svg (themes/images/alerticon-unused.svg)
     skin/rules.css (themes/rules.css)
     skin/images/command-paintflashing.svg (themes/images/command-paintflashing.svg)
     skin/images/command-screenshot.svg (themes/images/command-screenshot.svg)
     skin/images/command-responsivemode.svg (themes/images/command-responsivemode.svg)
     skin/images/command-replay.svg (themes/images/command-replay.svg)
     skin/images/command-pick.svg (themes/images/command-pick.svg)
     skin/images/command-pick-accessibility.svg (themes/images/command-pick-accessibility.svg)
     skin/images/command-frames.svg (themes/images/command-frames.svg)
--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -547,16 +547,20 @@ netmonitor.toolbar.status3=Status
 # LOCALIZATION NOTE (netmonitor.toolbar.method): This is the label displayed
 # in the network table toolbar, above the "method" column.
 netmonitor.toolbar.method=Method
 
 # LOCALIZATION NOTE (netmonitor.toolbar.file): This is the label displayed
 # in the network table toolbar, above the "file" column.
 netmonitor.toolbar.file=File
 
+# LOCALIZATION NOTE (netmonitor.toolbar.url): This is the label displayed
+# in the network table toolbar, above the "url" column.
+netmonitor.toolbar.url=URL
+
 # LOCALIZATION NOTE (netmonitor.toolbar.protocol): This is the label displayed
 # in the network table toolbar, above the "protocol" column.
 netmonitor.toolbar.protocol=Protocol
 
 # LOCALIZATION NOTE (netmonitor.toolbar.domain): This is the label displayed
 # in the network table toolbar, above the "domain" column.
 netmonitor.toolbar.domain=Domain
 
--- a/devtools/client/netmonitor/src/components/RequestListColumnDomain.js
+++ b/devtools/client/netmonitor/src/components/RequestListColumnDomain.js
@@ -1,22 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { Component } = require("devtools/client/shared/vendor/react");
-const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const { Component, createFactory } = require("devtools/client/shared/vendor/react");
+const { td } = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const { getFormattedIPAndPort } = require("../utils/format-utils");
-const { L10N } = require("../utils/l10n");
 const { propertiesEqual } = require("../utils/request-utils");
-
-const { div } = dom;
+const SecurityState = createFactory(require("./SecurityState"));
 
 const UPDATED_DOMAIN_PROPS = [
   "remoteAddress",
   "securityState",
   "urlDetails",
 ];
 
 class RequestListColumnDomain extends Component {
@@ -27,47 +25,35 @@ class RequestListColumnDomain extends Co
     };
   }
 
   shouldComponentUpdate(nextProps) {
     return !propertiesEqual(UPDATED_DOMAIN_PROPS, this.props.item, nextProps.item);
   }
 
   render() {
-    const { item, onSecurityIconMouseDown } = this.props;
-    const { remoteAddress, remotePort, securityState,
-      urlDetails: { host, isLocal } } = item;
-    const iconClassList = ["requests-security-state-icon"];
-    let iconTitle;
+    const {
+      item,
+      onSecurityIconMouseDown,
+    } = this.props;
+
+    const {
+      remoteAddress,
+      remotePort,
+      urlDetails: {
+        host,
+        isLocal,
+      },
+    } = item;
+
     const title = host + (remoteAddress ?
       ` (${getFormattedIPAndPort(remoteAddress, remotePort)})` : "");
 
-    let realSecurityState = securityState;
-
-    // Locally delivered files such as http://localhost and file:// paths
-    // are considered to have been delivered securely.
-    if (isLocal) {
-      realSecurityState = "secure";
-    }
-
-    if (realSecurityState) {
-      iconClassList.push(`security-state-${realSecurityState}`);
-      iconTitle = L10N.getStr(`netmonitor.security.state.${realSecurityState}`);
-    }
-
     return (
-      dom.td({ className: "requests-list-column requests-list-domain", title },
-        div({
-          className: iconClassList.join(" "),
-          onMouseDown: onSecurityIconMouseDown,
-          title: iconTitle,
-        }),
-        item.isThirdPartyTrackingResource && div({
-          className: "tracking-resource",
-          title: L10N.getStr("netmonitor.trackingResource.tooltip"),
-        }),
+      td({ className: "requests-list-column requests-list-domain", title },
+        SecurityState({item, onSecurityIconMouseDown, isLocal}),
         host,
       )
     );
   }
 }
 
 module.exports = RequestListColumnDomain;
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/src/components/RequestListColumnUrl.js
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { Component, createFactory } = require("devtools/client/shared/vendor/react");
+const { td } = require("devtools/client/shared/vendor/react-dom-factories");
+const { L10N } = require("../utils/l10n");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { getFormattedIPAndPort } = require("../utils/format-utils");
+const { propertiesEqual } = require("../utils/request-utils");
+const SecurityState = createFactory(require("./SecurityState"));
+const UPDATED_FILE_PROPS = [
+  "remoteAddress",
+  "securityState",
+  "urlDetails",
+];
+
+class RequestListColumnUrl extends Component {
+  static get propTypes() {
+    return {
+      item: PropTypes.object.isRequired,
+      onSecurityIconMouseDown: PropTypes.func.isRequired,
+    };
+  }
+
+  shouldComponentUpdate(nextProps) {
+    return !propertiesEqual(UPDATED_FILE_PROPS, this.props.item, nextProps.item);
+  }
+
+  render() {
+    const {
+      item: { urlDetails },
+    } = this.props;
+
+    const {
+      item,
+      onSecurityIconMouseDown,
+    } = this.props;
+
+    const {
+      remoteAddress,
+      remotePort,
+      urlDetails: {
+        isLocal,
+      },
+    } = item;
+
+    const title = (remoteAddress ?
+      ` (${getFormattedIPAndPort(remoteAddress, remotePort)})` : "");
+
+    // deals with returning whole url
+    const originalURL = urlDetails.url;
+    const decodedFileURL = urlDetails.unicodeUrl;
+    const ORIGINAL_FILE_URL = L10N.getFormatStr("netRequest.originalFileURL.tooltip",
+      originalURL);
+    const DECODED_FILE_URL = L10N.getFormatStr("netRequest.decodedFileURL.tooltip",
+      decodedFileURL);
+    const urlToolTip = originalURL === decodedFileURL ?
+      originalURL : ORIGINAL_FILE_URL + "\n\n" + DECODED_FILE_URL;
+
+    return (
+      td({
+          className: "requests-list-column requests-list-url",
+          title: urlToolTip + title,
+      },
+        SecurityState({item, onSecurityIconMouseDown, isLocal}),
+        originalURL
+      )
+    );
+  }
+}
+
+module.exports = RequestListColumnUrl;
--- a/devtools/client/netmonitor/src/components/RequestListItem.js
+++ b/devtools/client/netmonitor/src/components/RequestListItem.js
@@ -25,16 +25,17 @@ const { RESPONSE_HEADERS } = require("..
   RequestListColumnRemoteIP,
   RequestListColumnResponseHeader,
   RequestListColumnScheme,
   RequestListColumnSetCookies,
   RequestListColumnStatus,
   RequestListColumnTime,
   RequestListColumnTransferredSize,
   RequestListColumnType,
+  RequestListColumnUrl,
   RequestListColumnWaterfall
 */
 
 loader.lazyGetter(this, "RequestListColumnCause", function() {
   return createFactory(require("./RequestListColumnCause"));
 });
 loader.lazyGetter(this, "RequestListColumnContentSize", function() {
   return createFactory(require("./RequestListColumnContentSize"));
@@ -43,16 +44,19 @@ loader.lazyGetter(this, "RequestListColu
   return createFactory(require("./RequestListColumnCookies"));
 });
 loader.lazyGetter(this, "RequestListColumnDomain", function() {
   return createFactory(require("./RequestListColumnDomain"));
 });
 loader.lazyGetter(this, "RequestListColumnFile", function() {
   return createFactory(require("./RequestListColumnFile"));
 });
+loader.lazyGetter(this, "RequestListColumnUrl", function() {
+  return createFactory(require("./RequestListColumnUrl"));
+});
 loader.lazyGetter(this, "RequestListColumnMethod", function() {
   return createFactory(require("./RequestListColumnMethod"));
 });
 loader.lazyGetter(this, "RequestListColumnProtocol", function() {
   return createFactory(require("./RequestListColumnProtocol"));
 });
 loader.lazyGetter(this, "RequestListColumnRemoteIP", function() {
   return createFactory(require("./RequestListColumnRemoteIP"));
@@ -218,20 +222,24 @@ class RequestListItem extends Component 
         tabIndex: 0,
         onContextMenu,
         onMouseDown,
         onDoubleClick,
       },
         columns.status && RequestListColumnStatus({ item }),
         columns.method && RequestListColumnMethod({ item }),
         columns.domain && RequestListColumnDomain({
-            item,
-            onSecurityIconMouseDown,
+          item,
+          onSecurityIconMouseDown,
         }),
         columns.file && RequestListColumnFile({ item }),
+        columns.url && RequestListColumnUrl({
+          item,
+          onSecurityIconMouseDown,
+        }),
         columns.protocol && RequestListColumnProtocol({ item }),
         columns.scheme && RequestListColumnScheme({ item }),
         columns.remoteip && RequestListColumnRemoteIP({ item }),
         columns.cause && RequestListColumnCause({
           item,
           onCauseBadgeMouseDown,
         }),
         columns.type && RequestListColumnType({ item }),
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/src/components/SecurityState.js
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { Component } = require("devtools/client/shared/vendor/react");
+const { div } = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { L10N } = require("../utils/l10n");
+const { propertiesEqual } = require("../utils/request-utils");
+
+const UPDATED_DOMAIN_PROPS = [
+  "remoteAddress",
+  "securityState",
+  "urlDetails",
+];
+
+class SecurityState extends Component {
+  static get propTypes() {
+    return {
+      item: PropTypes.object.isRequired,
+      onSecurityIconMouseDown: PropTypes.func.isRequired,
+    };
+  }
+
+  shouldComponentUpdate(nextProps) {
+    return !propertiesEqual(UPDATED_DOMAIN_PROPS, this.props.item, nextProps.item);
+  }
+
+  render() {
+    const {
+      item,
+      onSecurityIconMouseDown,
+    } = this.props;
+
+    const {
+      securityState,
+      urlDetails: {
+        isLocal,
+      },
+    } = item;
+    const iconClassList = ["requests-security-state-icon"];
+
+    let iconTitle;
+    let realSecurityState = securityState;
+
+    // Locally delivered files such as http://localhost and file:// paths
+    // are considered to have been delivered securely.
+    if (isLocal) {
+      realSecurityState = "secure";
+    }
+
+    if (realSecurityState) {
+      iconClassList.push(`security-state-${realSecurityState}`);
+      iconTitle = L10N.getStr(`netmonitor.security.state.${realSecurityState}`);
+    }
+
+    return (
+      div({},
+        div({
+          className: iconClassList.join(" "),
+          onMouseDown: onSecurityIconMouseDown,
+          title: iconTitle,
+        }),
+        item.isThirdPartyTrackingResource && div({
+          className: "tracking-resource",
+          title: L10N.getStr("netmonitor.trackingResource.tooltip"),
+        }),
+      )
+    );
+  }
+}
+
+module.exports = SecurityState;
--- a/devtools/client/netmonitor/src/components/moz.build
+++ b/devtools/client/netmonitor/src/components/moz.build
@@ -25,23 +25,25 @@ DevToolsModules(
     'RequestListColumnRemoteIP.js',
     'RequestListColumnResponseHeader.js',
     'RequestListColumnScheme.js',
     'RequestListColumnSetCookies.js',
     'RequestListColumnStatus.js',
     'RequestListColumnTime.js',
     'RequestListColumnTransferredSize.js',
     'RequestListColumnType.js',
+    'RequestListColumnUrl.js',
     'RequestListColumnWaterfall.js',
     'RequestListContent.js',
     'RequestListEmptyNotice.js',
     'RequestListHeader.js',
     'RequestListItem.js',
     'ResponsePanel.js',
     'SecurityPanel.js',
+    'SecurityState.js',
     'SourceEditor.js',
     'StackTracePanel.js',
     'StatisticsPanel.js',
     'StatusBar.js',
     'StatusCode.js',
     'TabboxPanel.js',
     'TimingsPanel.js',
     'Toolbar.js',
--- a/devtools/client/netmonitor/src/constants.js
+++ b/devtools/client/netmonitor/src/constants.js
@@ -186,24 +186,28 @@ const HEADERS = [
     canFilter: true,
     filterKey: "status-code",
   },
   {
     name: "method",
     canFilter: true,
   },
   {
-      name: "domain",
-      canFilter: true,
+    name: "domain",
+    canFilter: true,
   },
   {
     name: "file",
     canFilter: false,
   },
   {
+    name: "url",
+    canFilter: true,
+  },
+  {
     name: "protocol",
     canFilter: true,
   },
   {
     name: "scheme",
     canFilter: true,
   },
   {
--- a/devtools/client/netmonitor/src/reducers/ui.js
+++ b/devtools/client/netmonitor/src/reducers/ui.js
@@ -25,16 +25,17 @@ const {
   SET_COLUMNS_WIDTH,
 } = require("../constants");
 
 const cols = {
   status: true,
   method: true,
   domain: true,
   file: true,
+  url: false,
   protocol: false,
   scheme: false,
   remoteip: false,
   cause: true,
   type: true,
   cookies: false,
   setCookies: false,
   transferred: true,
--- a/devtools/client/netmonitor/test/browser_net_security-redirect.js
+++ b/devtools/client/netmonitor/test/browser_net_security-redirect.js
@@ -20,20 +20,28 @@ add_task(async function() {
     content.wrappedJSObject.performRequests(1, url);
   });
   await wait;
 
   is(store.getState().requests.requests.size, 2,
      "There were two requests due to redirect.");
 
   const [
-    initialSecurityIcon,
-    redirectSecurityIcon,
+    initialDomainSecurityIcon,
+    initialUrlSecurityIcon,
+    redirectDomainSecurityIcon,
+    redirectUrlSecurityIcon,
   ] = document.querySelectorAll(".requests-security-state-icon");
 
-  ok(initialSecurityIcon.classList.contains("security-state-insecure"),
-     "Initial request was marked insecure.");
+  ok(initialDomainSecurityIcon.classList.contains("security-state-insecure"),
+     "Initial request was marked insecure for domain column.");
+
+  ok(redirectDomainSecurityIcon.classList.contains("security-state-secure"),
+     "Redirected request was marked secure for domain column.");
 
-  ok(redirectSecurityIcon.classList.contains("security-state-secure"),
-     "Redirected request was marked secure.");
+  ok(initialUrlSecurityIcon.classList.contains("security-state-insecure"),
+    "Initial request was marked insecure for URL column.");
+
+  ok(redirectUrlSecurityIcon.classList.contains("security-state-secure"),
+    "Redirected request was marked secure for URL column.");
 
   await teardown(monitor);
 });
--- a/devtools/client/netmonitor/test/browser_net_tracking-resources.js
+++ b/devtools/client/netmonitor/test/browser_net_tracking-resources.js
@@ -25,13 +25,17 @@ add_task(async function() {
   const { document, store, windowRequire } = monitor.panelWin;
   const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
 
   store.dispatch(Actions.batchEnable(false));
 
   // Execute request with third party tracking protection flag.
   await performRequests(monitor, tab, 1);
 
-  const requests = document.querySelectorAll(".request-list-item .tracking-resource");
-  is(requests.length, 1, "There should be one tracking request");
+  const domainRequests =
+    document.querySelectorAll(".requests-list-domain .tracking-resource");
+  const UrlRequests = document.querySelectorAll(".requests-list-url .tracking-resource");
+
+  is(domainRequests.length, 1, "There should be one domain column tracking request");
+  is(UrlRequests.length, 1, "There should be one URL column tracking request");
 
   await teardown(monitor);
 });
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -113,26 +113,27 @@ Services.prefs.setBoolPref("devtools.deb
 
 // Always reset some prefs to their original values after the test finishes.
 const gDefaultFilters = Services.prefs.getCharPref("devtools.netmonitor.filters");
 
 // Reveal many columns for test
 Services.prefs.setCharPref(
   "devtools.netmonitor.visibleColumns",
   "[\"cause\",\"contentSize\",\"cookies\",\"domain\",\"duration\"," +
-  "\"endTime\",\"file\",\"latency\",\"method\",\"protocol\"," +
+  "\"endTime\",\"file\",\"url\",\"latency\",\"method\",\"protocol\"," +
   "\"remoteip\",\"responseTime\",\"scheme\",\"setCookies\"," +
   "\"startTime\",\"status\",\"transferred\",\"type\",\"waterfall\"]"
 );
 
 Services.prefs.setCharPref("devtools.netmonitor.columnsData",
 '[{"name":"status","minWidth":30,"width":5},' +
   '{"name":"method","minWidth":30,"width":5},' +
   '{"name":"domain","minWidth":30,"width":10},' +
   '{"name":"file","minWidth":30,"width":25},' +
+  '{"name":"url","minWidth":30,"width":25},' +
   '{"name":"cause","minWidth":30,"width":10},' +
   '{"name":"type","minWidth":30,"width":5},' +
   '{"name":"transferred","minWidth":30,"width":10},' +
   '{"name":"contentSize","minWidth":30,"width":5},' +
   '{"name":"waterfall","minWidth":150,"width":25}]');
 
 // Increase UI limit for responses rendered using CodeMirror in tests.
 Services.prefs.setIntPref("devtools.netmonitor.response.ui.limit", 1024 * 105);
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -163,17 +163,17 @@ pref("devtools.application.enabled", fal
 // The default Network Monitor UI settings
 pref("devtools.netmonitor.panes-network-details-width", 550);
 pref("devtools.netmonitor.panes-network-details-height", 450);
 pref("devtools.netmonitor.filters", "[\"all\"]");
 pref("devtools.netmonitor.visibleColumns",
   "[\"status\",\"method\",\"domain\",\"file\",\"cause\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]"
 );
 pref("devtools.netmonitor.columnsData",
-  '[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
+  '[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"url","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
 
 // Support for columns resizing pref is now enabled (after merge date 03/18/19).
 pref("devtools.netmonitor.features.resizeColumns", true);
 
 pref("devtools.netmonitor.response.ui.limit", 10240);
 
 // Save request/response bodies yes/no.
 pref("devtools.netmonitor.saveRequestAndResponseBodies", true);
--- a/devtools/client/shared/components/SearchBox.js
+++ b/devtools/client/shared/components/SearchBox.js
@@ -27,17 +27,17 @@ class SearchBox extends PureComponent {
       keyShortcut: PropTypes.string,
       learnMoreTitle: PropTypes.string,
       learnMoreUrl: PropTypes.string,
       onBlur: PropTypes.func,
       onChange: PropTypes.func.isRequired,
       onFocus: PropTypes.func,
       onKeyDown: PropTypes.func,
       placeholder: PropTypes.string.isRequired,
-      type: PropTypes.string.isRequired,
+      type: PropTypes.string,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.state = {
       value: "",
--- a/devtools/client/themes/images/alert.svg
+++ b/devtools/client/themes/images/alert.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13.5 12.7" width="12" height="12">
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
   <path fill="context-fill" d="M6 0a1 1 0 0 1 .89.54l5 9.6A1 1 0 0 1 11 11.6H1a1 1 0 0 1-.89-1.46l5-9.6A1 1 0 0 1 6 0zm-.25 8a.75.75 0 0 0-.75.75v.5c0 .41.34.75.75.75h.5c.41 0 .75-.34.75-.75v-.5A.75.75 0 0 0 6.25 8h-.5zM7 3.7a1 1 0 1 0-2 0v2.6a1 1 0 1 0 2 0V3.7z" />
 </svg>
deleted file mode 100644
--- a/devtools/client/themes/images/alerticon-unused.svg
+++ /dev/null
@@ -1,8 +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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 14 14">
-  <path stroke="context-stroke" fill="none" d="M13 7C13 10.31 10.31 13 7 13C3.69 13 1 10.31 1 7C1 3.69 3.69 1 7 1C10.31 1 13 3.69 13 7Z"/>
-  <path fill="context-fill" d="M7.54 5.88C8.02 5.88 8.41 6.26 8.41 6.74C8.41 7.6 8.41 9.29 8.41 10.15C8.41 10.63 8.02 11.02 7.54 11.02C7.2 11.02 7.05 11.02 6.71 11.02C6.23 11.02 5.84 10.63 5.84 10.15C5.84 9.29 5.84 7.6 5.84 6.74C5.84 6.26 6.23 5.88 6.71 5.88C7.05 5.88 7.2 5.88 7.54 5.88Z"/>
-  <path fill="context-fill" d="M8.41 4.11C8.41 4.82 7.83 5.4 7.12 5.4C6.42 5.4 5.84 4.82 5.84 4.11C5.84 3.4 6.42 2.83 7.12 2.83C7.83 2.83 8.41 3.4 8.41 4.11Z"/>
-</svg>
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -360,32 +360,30 @@
   background-clip: content-box;
 }
 
 .ruleview-warning,
 .ruleview-unused-warning {
   display: inline-block;
   width: 12px;
   height: 12px;
-  background-size: cover;
+  background-size: 12px;
+  background-repeat: no-repeat;
+  -moz-context-properties: fill;
 }
 
 .ruleview-warning {
   background-image: url(chrome://devtools/skin/images/alert.svg);
-  background-position: 0.73px 0.4px;
-  -moz-context-properties: fill;
   fill: var(--yellow-60);
 }
 
 .ruleview-unused-warning {
-  background-image: url(chrome://devtools/skin/images/alerticon-unused.svg);
+  background-image: url(chrome://devtools/skin/images/webconsole/info.svg);
   background-color: var(--theme-sidebar-background);
-  -moz-context-properties: fill, stroke;
-  fill: var(--theme-icon-dimmed-color);
-  stroke: var(--theme-icon-dimmed-color);
+  fill: var(--theme-icon-dimmed-color);  
 }
 
 .ruleview-unused-warning:hover {
   fill: var(--theme-icon-color);
   stroke: var(--theme-icon-color);
 }
 
 .ruleview-rule:not(:hover) .ruleview-enableproperty {
--- a/devtools/client/webconsole/components/FilterBar.js
+++ b/devtools/client/webconsole/components/FilterBar.js
@@ -23,17 +23,16 @@ const SearchBox = createFactory(require(
 
 loader.lazyRequireGetter(this, "PropTypes", "devtools/client/shared/vendor/react-prop-types");
 
 class FilterBar extends Component {
   static get propTypes() {
     return {
       dispatch: PropTypes.func.isRequired,
       filter: PropTypes.object.isRequired,
-      attachRefToWebConsoleUI: PropTypes.func.isRequired,
       persistLogs: PropTypes.bool.isRequired,
       hidePersistLogsCheckbox: PropTypes.bool.isRequired,
       showContentMessages: PropTypes.bool.isRequired,
       hideShowContentMessagesCheckbox: PropTypes.bool.isRequired,
       filteredMessagesCount: PropTypes.object.isRequired,
       closeButtonVisible: PropTypes.bool,
       closeSplitConsole: PropTypes.func,
     };
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -1659,24 +1659,25 @@ const ThreadActor = ActorClassWithSpec(t
     // and so we also need to be sure that there is still a source actor for the source.
     let sourceActor;
     if (this._debuggerSourcesSeen.has(source) && this.sources.hasSourceActor(source)) {
       sourceActor = this.sources.getSourceActor(source);
     } else {
       sourceActor = this.sources.createSourceActor(source);
     }
 
-    if (this._onLoadBreakpointURLs.has(source.url)) {
-      this.setBreakpoint({ sourceUrl: source.url, line: 1 }, {});
+    const sourceUrl = sourceActor.url;
+    if (this._onLoadBreakpointURLs.has(sourceUrl)) {
+      this.setBreakpoint({ sourceUrl, line: 1 }, {});
     }
 
     const bpActors = this.breakpointActorMap.findActors()
-    .filter((actor) => {
-      return actor.location.sourceUrl && actor.location.sourceUrl == source.url;
-    });
+    .filter((actor) =>
+      actor.location.sourceUrl && actor.location.sourceUrl == sourceUrl
+    );
 
     for (const actor of bpActors) {
       sourceActor.applyBreakpoint(actor);
     }
 
     this._debuggerSourcesSeen.add(source);
     return true;
   },
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_breakpoint-23.js
@@ -0,0 +1,29 @@
+/* eslint-disable max-nested-callbacks */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Bug 1552453 - Verify that breakpoints are hit for evaluated
+ * scripts that contain a source url pragma.
+ */
+add_task(threadClientTest(async ({ threadClient, targetFront }) => {
+  await threadClient.setBreakpoint(
+    { sourceUrl: "http://example.com/code.js", line: 2, column: 1 },
+    {}
+  );
+
+  info("Create a new script with the displayUrl code.js");
+  const consoleFront = await targetFront.getFront("console");
+  consoleFront.evaluateJSAsync("function f() {\n return 5; \n}\n//# sourceURL=http://example.com/code.js");
+
+  const sourcePacket = await waitForEvent(threadClient, "newSource");
+  equal(sourcePacket.source.url, "http://example.com/code.js");
+
+  info("Evaluate f() and pause at line 2");
+  consoleFront.evaluateJSAsync("f()");
+  const pausedPacket = await waitForPause(threadClient);
+  equal(pausedPacket.why.type, "breakpoint");
+  equal(pausedPacket.frame.where.line, 2);
+}));
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -127,16 +127,17 @@ skip-if = true # tests for breakpoint ac
 [test_breakpoint-18.js]
 [test_breakpoint-19.js]
 skip-if = true
 reason = bug 1104838
 [test_breakpoint-20.js]
 [test_breakpoint-21.js]
 [test_breakpoint-22.js]
 skip-if = true # breakpoint sliding is not supported bug 1525685
+[test_breakpoint-23.js]
 [test_conditional_breakpoint-01.js]
 [test_conditional_breakpoint-02.js]
 [test_conditional_breakpoint-03.js]
 [test_logpoint-01.js]
 [test_logpoint-02.js]
 [test_listsources-01.js]
 [test_listsources-02.js]
 [test_listsources-03.js]
--- a/devtools/shared/client/thread-client.js
+++ b/devtools/shared/client/thread-client.js
@@ -1,21 +1,33 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
+const {
+  arg,
+  DebuggerClient,
+} = require("devtools/shared/client/debugger-client");
 const eventSource = require("devtools/shared/client/event-source");
-const {ThreadStateTypes} = require("devtools/shared/client/constants");
+const { ThreadStateTypes } = require("devtools/shared/client/constants");
 
-loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/object-client");
-loader.lazyRequireGetter(this, "SourceFront", "devtools/shared/fronts/source", true);
+loader.lazyRequireGetter(
+  this,
+  "ObjectClient",
+  "devtools/shared/client/object-client"
+);
+loader.lazyRequireGetter(
+  this,
+  "SourceFront",
+  "devtools/shared/fronts/source",
+  true
+);
 
 /**
  * Creates a thread client for the remote debugging protocol server. This client
  * is a front to the thread actor created in the server side, hiding the
  * protocol details in a traditional JavaScript API.
  *
  * @param client DebuggerClient
  * @param actor string
@@ -45,63 +57,68 @@ ThreadClient.prototype = {
   },
 
   get _transport() {
     return this.client._transport;
   },
 
   _assertPaused: function(command) {
     if (!this.paused) {
-      throw Error(command + " command sent while not paused. Currently " + this._state);
+      throw Error(
+        command + " command sent while not paused. Currently " + this._state
+      );
     }
   },
 
   /**
    * Resume a paused thread. If the optional limit parameter is present, then
    * the thread will also pause when that limit is reached.
    *
    * @param [optional] object limit
    *        An object with a type property set to the appropriate limit (next,
    *        step, or finish) per the remote debugging protocol specification.
    *        Use null to specify no limit.
    * @param bool aRewind
    *        Whether execution should rewind until the limit is reached, rather
    *        than proceeding forwards. This parameter has no effect if the
    *        server does not support rewinding.
    */
-  _doResume: DebuggerClient.requester({
-    type: "resume",
-    resumeLimit: arg(0),
-    rewind: arg(1),
-  }, {
-    before: function(packet) {
-      this._assertPaused("resume");
-
-      // Put the client in a tentative "resuming" state so we can prevent
-      // further requests that should only be sent in the paused state.
-      this._previousState = this._state;
-      this._state = "resuming";
-
-      return packet;
+  _doResume: DebuggerClient.requester(
+    {
+      type: "resume",
+      resumeLimit: arg(0),
+      rewind: arg(1),
     },
-    after: function(response) {
-      if (response.error && this._state == "resuming") {
-        // There was an error resuming, update the state to the new one
-        // reported by the server, if given (only on wrongState), otherwise
-        // reset back to the previous state.
-        if (response.state) {
-          this._state = ThreadStateTypes[response.state];
-        } else {
-          this._state = this._previousState;
+    {
+      before: function(packet) {
+        this._assertPaused("resume");
+
+        // Put the client in a tentative "resuming" state so we can prevent
+        // further requests that should only be sent in the paused state.
+        this._previousState = this._state;
+        this._state = "resuming";
+
+        return packet;
+      },
+      after: function(response) {
+        if (response.error && this._state == "resuming") {
+          // There was an error resuming, update the state to the new one
+          // reported by the server, if given (only on wrongState), otherwise
+          // reset back to the previous state.
+          if (response.state) {
+            this._state = ThreadStateTypes[response.state];
+          } else {
+            this._state = this._previousState;
+          }
         }
-      }
-      delete this._previousState;
-      return response;
-    },
-  }),
+        delete this._previousState;
+        return response;
+      },
+    }
+  ),
 
   /**
    * Reconfigure the thread actor.
    *
    * @param object options
    *        A dictionary object of the new options to use in the thread actor.
    */
   reconfigure: DebuggerClient.requester({
@@ -209,24 +226,27 @@ ThreadClient.prototype = {
     type: "pauseOnExceptions",
     pauseOnExceptions: arg(0),
     ignoreCaughtExceptions: arg(1),
   }),
 
   /**
    * Detach from the thread actor.
    */
-  detach: DebuggerClient.requester({
-    type: "detach",
-  }, {
-    after: function(response) {
-      this.client.unregisterClient(this);
-      return response;
+  detach: DebuggerClient.requester(
+    {
+      type: "detach",
     },
-  }),
+    {
+      after: function(response) {
+        this.client.unregisterClient(this);
+        return response;
+      },
+    }
+  ),
 
   /**
    * Promote multiple pause-lifetime object actors to thread-lifetime ones.
    *
    * @param array actors
    *        An array with actor IDs to promote.
    */
   threadGrips: DebuggerClient.requester({
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -95,17 +95,17 @@ interface nsIContentViewer : nsISupports
    * In this case, the corresponding docshell will not allow navigation.
    */
   readonly attribute boolean beforeUnloadFiring;
 
   void pageHide(in boolean isUnload);
 
   /**
    * All users of a content viewer are responsible for calling both
-   * close() and destroy(), in that order. 
+   * close() and destroy(), in that order.
    *
    * close() should be called when the load of a new page for the next
    * content viewer begins, and destroy() should be called when the next
    * content viewer replaces this one.
    *
    * |historyEntry| sets the session history entry for the content viewer.  If
    * this is null, then Destroy() will be called on the document by close().
    * If it is non-null, the document will not be destroyed, and the following
--- a/docshell/base/nsIDocShellTreeItem.idl
+++ b/docshell/base/nsIDocShellTreeItem.idl
@@ -10,17 +10,17 @@ interface mozIDOMWindowProxy;
 interface nsIDocShellTreeOwner;
 interface nsPIDOMWindowOuter;
 
 webidl Document;
 
 /**
  * The nsIDocShellTreeItem supplies the methods that are required of any item
  * that wishes to be able to live within the docshell tree either as a middle
- * node or a leaf. 
+ * node or a leaf.
  */
 
 [scriptable, builtinclass, uuid(9b7c586f-9214-480c-a2c4-49b526fff1a6)]
 interface nsIDocShellTreeItem : nsISupports
 {
 	/*
 	name of the DocShellTreeItem
 	*/
@@ -41,17 +41,17 @@ interface nsIDocShellTreeItem : nsISuppo
 	const long typeChrome=0;            // typeChrome must equal 0
 	const long typeContent=1;           // typeContent must equal 1
 	const long typeContentWrapper=2;    // typeContentWrapper must equal 2
 	const long typeChromeWrapper=3;     // typeChromeWrapper must equal 3
 
 	const long typeAll=0x7FFFFFFF;
 
 	/*
-	The type this item is.  
+	The type this item is.
 	*/
 	readonly attribute long itemType;
 	[noscript,notxpcom,nostdcall] long ItemType();
 
 	/*
 	Parent DocShell.
 	*/
 	readonly attribute nsIDocShellTreeItem parent;
@@ -60,30 +60,30 @@ interface nsIDocShellTreeItem : nsISuppo
 	This getter returns the same thing parent does however if the parent
 	is of a different itemType, or if the parent is an <iframe mozbrowser>.
 	It will instead return nullptr.  This call is a convience function for
 	Ithose wishing to not cross the boundaries at which item types change.
 	*/
 	readonly attribute nsIDocShellTreeItem sameTypeParent;
 
 	/*
-	Returns the root DocShellTreeItem.  This is a convience equivalent to 
+	Returns the root DocShellTreeItem.  This is a convience equivalent to
 	getting the parent and its parent until there isn't a parent.
 	*/
 	readonly attribute nsIDocShellTreeItem rootTreeItem;
 
 	/*
-	Returns the root DocShellTreeItem of the same type.  This is a convience 
-	equivalent to getting the parent of the same type and its parent until 
+	Returns the root DocShellTreeItem of the same type.  This is a convience
+	equivalent to getting the parent of the same type and its parent until
 	there isn't a parent.
 	*/
 	readonly attribute nsIDocShellTreeItem sameTypeRootTreeItem;
 
 	/*
-	Returns the docShellTreeItem with the specified name.  Search order is as 
+	Returns the docShellTreeItem with the specified name.  Search order is as
 	follows...
 	1.)  Check name of self, if it matches return it.
 	2.)  For each immediate child.
 		a.) Check name of child and if it matches return it.
 		b.)  Ask the child to perform the check
 			i.) Do not ask a child if it is the aRequestor
 			ii.) Do not ask a child if it is of a different item type.
 	3.)  If there is a parent of the same item type ask parent to perform the check
@@ -109,35 +109,35 @@ interface nsIDocShellTreeItem : nsISuppo
 	                                     in nsIDocShellTreeItem aRequestor,
 	                                     in nsIDocShellTreeItem aOriginalRequestor,
 	                                     in bool aSkipTabGroup);
 
 	/*
 	The owner of the DocShell Tree.  This interface will be called upon when
 	the docshell has things it needs to tell to the owner of the docshell.
 	Note that docShell tree ownership does not cross tree types.  Meaning
-	setting ownership on a chrome tree does not set ownership on the content 
+	setting ownership on a chrome tree does not set ownership on the content
 	sub-trees.  A given tree's boundaries are identified by the type changes.
 	Trees of different types may be connected, but should not be traversed
 	for things such as ownership.
-	
-	Note implementers of this interface should NOT effect the lifetime of the 
+
+	Note implementers of this interface should NOT effect the lifetime of the
 	parent DocShell by holding this reference as it creates a cycle.  Owners
 	when releasing this interface should set the treeOwner to nullptr.
 	Implementers of this interface are guaranteed that when treeOwner is
 	set that the poitner is valid without having to addref.
-	
-	Further note however when others try to get the interface it should be 
-	addref'd before handing it to them. 
+
+	Further note however when others try to get the interface it should be
+	addref'd before handing it to them.
 	*/
 	readonly attribute nsIDocShellTreeOwner treeOwner;
 	[noscript] void setTreeOwner(in nsIDocShellTreeOwner treeOwner);
 
 	/*
-	The current number of DocShells which are immediate children of the 
+	The current number of DocShells which are immediate children of the
 	this object.
 	*/
 	readonly attribute long childCount;
 
 	/*
 	Add a new child DocShellTreeItem.  Adds to the end of the list.
 	Note that this does NOT take a reference to the child.  The child stays
 	alive only as long as it's referenced from outside the docshell tree.
--- a/docshell/base/nsIDocumentLoaderFactory.idl
+++ b/docshell/base/nsIDocumentLoaderFactory.idl
@@ -23,17 +23,17 @@ webidl Document;
  * The component is a service, so use GetService, not CreateInstance to get it.
  */
 
 [scriptable, uuid(e795239e-9d3c-47c4-b063-9e600fb3b287)]
 interface nsIDocumentLoaderFactory : nsISupports {
     nsIContentViewer createInstance(in string aCommand,
                               in nsIChannel aChannel,
                               in nsILoadGroup aLoadGroup,
-                              in ACString aContentType, 
+                              in ACString aContentType,
                               in nsIDocShell aContainer,
                               in nsISupports aExtraInfo,
                               out nsIStreamListener aDocListenerResult);
 
     nsIContentViewer createInstanceForDocument(in nsISupports aContainer,
                                          in Document aDocument,
                                          in string aCommand);
 };
--- a/docshell/base/nsIRefreshURI.idl
+++ b/docshell/base/nsIRefreshURI.idl
@@ -10,24 +10,24 @@ interface nsIChannel;
 interface nsIPrincipal;
 interface nsIURI;
 
 [scriptable, uuid(a5e61a3c-51bd-45be-ac0c-e87b71860656)]
 interface nsIRefreshURI : nsISupports {
     /**
       * Load a uri after waiting for aMillis milliseconds. If the docshell
       * is busy loading a page currently, the refresh request will be
-      * queued and executed when the current load finishes. 
+      * queued and executed when the current load finishes.
       *
       * @param aUri The uri to refresh.
       * @param aPrincipal The triggeringPrincipal for the refresh load
       *   May be null, in which case the principal of current document will be
       *   applied.
       * @param aMillis The number of milliseconds to wait.
-      * @param aRepeat Flag to indicate if the uri is to be 
+      * @param aRepeat Flag to indicate if the uri is to be
       *                repeatedly refreshed every aMillis milliseconds.
       * @param aMetaRefresh Flag to indicate if this is a Meta refresh.
       */
     void refreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal,
                     in long aMillis, in boolean aRepeat,
                     in boolean aMetaRefresh);
 
     /**
@@ -40,34 +40,34 @@ interface nsIRefreshURI : nsISupports {
       * @param aMillis The number of milliseconds by which this refresh would
       *                be delayed if it were not being forced.
       * @param aMetaRefresh Flag to indicate if this is a meta refresh.
       */
     void forceRefreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal,
                          in long aMillis, in boolean aMetaRefresh);
 
     /**
-      * Checks the passed in channel to see if there is a refresh header, 
+      * Checks the passed in channel to see if there is a refresh header,
       * if there is, will setup a timer to refresh the uri found
       * in the header. If docshell is busy loading a page currently, the
-      * request will be queued and executed when the current page 
-      * finishes loading. 
+      * request will be queued and executed when the current page
+      * finishes loading.
       *
       * Returns the NS_REFRESHURI_HEADER_FOUND success code if a refresh
       * header was found and successfully setup.
       *
-      * @param aChannel The channel to be parsed. 
+      * @param aChannel The channel to be parsed.
       */
-    void setupRefreshURI(in nsIChannel aChannel); 
+    void setupRefreshURI(in nsIChannel aChannel);
 
     /**
       * Parses the passed in header string and sets up a refreshURI if
-      * a "refresh" header is found. If docshell is busy loading a page 
-      * currently, the request will be queued and executed when 
-      * the current page finishes loading. 
+      * a "refresh" header is found. If docshell is busy loading a page
+      * currently, the request will be queued and executed when
+      * the current page finishes loading.
       *
       * @param aBaseURI base URI to resolve refresh uri with.
       * @param aPrincipal The triggeringPrincipal for the refresh load
       *   May be null, in which case the principal of current document will be
       *   applied.
       * @param aHeader  The meta refresh header string.
       */
     void setupRefreshURIFromHeader(in nsIURI aBaseURI,
--- a/docshell/base/nsIScrollable.idl
+++ b/docshell/base/nsIScrollable.idl
@@ -4,17 +4,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 "nsISupports.idl"
 
 /**
  * The nsIScrollable is an interface that can be implemented by a control that
- * supports scrolling.  This is a generic interface without concern for the 
+ * supports scrolling.  This is a generic interface without concern for the
  * type of content that may be inside.
  */
 [scriptable, uuid(3507fc93-313e-4a4c-8ca8-4d0ea0f97315)]
 interface nsIScrollable : nsISupports
 {
   /**
    * Constants declaring the two scroll orientations a scrollbar can be in.
    * ScrollOrientation_X - Horizontal scrolling.  When passing this
--- a/docshell/base/nsITooltipListener.idl
+++ b/docshell/base/nsITooltipListener.idl
@@ -1,13 +1,13 @@
 /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
+
 #include "nsISupports.idl"
 
 /**
  * An optional interface for embedding clients wishing to receive
  * notifications for when a tooltip should be displayed or removed.
  * The embedder implements this interface on the web browser chrome
  * object associated with the window that notifications are required
  * for.
@@ -30,15 +30,15 @@ interface nsITooltipListener : nsISuppor
      * @note
      * Coordinates are specified in pixels, relative to the top-left
      * corner of the browser area.
      *
      * @return <code>NS_OK</code> if the tooltip was displayed.
      */
     void onShowTooltip(in long aXCoords, in long aYCoords, in AString aTipText,
                        in AString aTipDir);
-  
+
     /**
      * Called when the tooltip should be hidden, either because the pointer
      * has moved or the tooltip has timed out.
      */
     void onHideTooltip();
 };
--- a/docshell/base/nsITooltipTextProvider.idl
+++ b/docshell/base/nsITooltipTextProvider.idl
@@ -1,24 +1,24 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
+
 #include "nsISupports.idl"
 
 webidl Node;
 
 /**
  * An interface implemented by a tooltip text provider service. This
  * service is called to discover what tooltip text is associated
  * with the node that the pointer is positioned over.
  *
  * Embedders may implement and register their own tooltip text provider
- * service if they wish to provide different tooltip text. 
+ * service if they wish to provide different tooltip text.
  *
  * The default service returns the text stored in the TITLE
  * attribute of the node or a containing parent.
  *
  * @note
  * The tooltip text provider service is registered with the contract
  * defined in NS_TOOLTIPTEXTPROVIDER_CONTRACTID.
  *
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -140,17 +140,17 @@ interface nsIWebNavigation : nsISupports
   const unsigned long LOAD_FLAGS_BYPASS_PROXY    = 0x0200;
 
   /**
    * This flag specifies that a reload was triggered as a result of detecting
    * an incorrect character encoding while parsing a previously loaded
    * document.
    */
   const unsigned long LOAD_FLAGS_CHARSET_CHANGE  = 0x0400;
- 
+
   /**
    * If this flag is set, Stop() will be called before the load starts
    * and will stop both content and network activity (the default is to
    * only stop network activity).  Effectively, this passes the
    * STOP_CONTENT flag to Stop(), in addition to the STOP_NETWORK flag.
    */
   const unsigned long LOAD_FLAGS_STOP_CONTENT    = 0x0800;
 
@@ -163,17 +163,17 @@ interface nsIWebNavigation : nsISupports
     This flag is set when a user explicitly disables the Mixed Content
     Blocker, and allows Mixed Content to load on an https page.
   */
   const unsigned long LOAD_FLAGS_ALLOW_MIXED_CONTENT = 0x2000;
 
   /**
    * This flag specifies that this is the first load in this object.
    * Set with care, since setting incorrectly can cause us to assume that
-   * nothing was actually loaded in this object if the load ends up being 
+   * nothing was actually loaded in this object if the load ends up being
    * handled by an external application.  This flag must not be passed to
    * Reload.
    */
   const unsigned long LOAD_FLAGS_FIRST_LOAD = 0x4000;
 
   /**
    * This flag specifies that the load should not be subject to popup
    * blocking checks.  This flag must not be passed to Reload.
--- a/docshell/base/nsIWebNavigationInfo.idl
+++ b/docshell/base/nsIWebNavigationInfo.idl
@@ -34,17 +34,17 @@ interface nsIWebNavigationInfo : nsISupp
    * "XPCOM plug-ins".
    */
   const unsigned long PLUGIN = 2;
 
   /**
    * @note Other return types may be added here in the future as they become
    * relevant.
    */
-  
+
   /**
    * Returned by isTypeSupported to indicate that a type is supported via some
    * other means.
    */
   const unsigned long OTHER = 1 << 15;
 
   /**
    * Query whether aType is supported.
--- a/docshell/base/nsIWebPageDescriptor.idl
+++ b/docshell/base/nsIWebPageDescriptor.idl
@@ -13,17 +13,17 @@
 interface nsIWebPageDescriptor : nsISupports
 {
   const unsigned long DISPLAY_AS_SOURCE = 0x0001;
   const unsigned long DISPLAY_NORMAL    = 0x0002;
 
  /**
   * Tells the object to load the page specified by the page descriptor
   *
-  * @throws NS_ERROR_FAILURE - 
+  * @throws NS_ERROR_FAILURE -
   */
   void loadPage(in nsISupports aPageDescriptor, in unsigned long aDisplayType);
 
 
  /**
   * Retrieves the page descriptor for the curent document.
   */
   readonly attribute nsISupports currentDescriptor;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3286,21 +3286,17 @@ CORSMode Element::AttrValueToCORSMode(co
   if (!aValue) {
     return CORS_NONE;
   }
 
   return CORSMode(aValue->GetEnumValue());
 }
 
 static const char* GetFullscreenError(CallerType aCallerType) {
-  if (!nsContentUtils::IsRequestFullscreenAllowed(aCallerType)) {
-    return "FullscreenDeniedNotInputDriven";
-  }
-
-  return nullptr;
+  return nsContentUtils::CheckRequestFullscreenAllowed(aCallerType);
 }
 
 already_AddRefed<Promise> Element::RequestFullscreen(CallerType aCallerType,
                                                      ErrorResult& aRv) {
   auto request = FullscreenRequest::Create(this, aCallerType, aRv);
   RefPtr<Promise> promise = request->GetPromise();
 
   if (!FeaturePolicyUtils::IsFeatureAllowed(OwnerDoc(),
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6576,34 +6576,46 @@ bool nsContentUtils::ChannelShouldInheri
          // One more check here.  CheckMayLoad will always return true for the
          // system principal, but we do NOT want to inherit in that case.
          !aLoadingPrincipal->IsSystemPrincipal());
   }
   return inherit;
 }
 
 /* static */
-bool nsContentUtils::IsRequestFullscreenAllowed(CallerType aCallerType) {
-  // If more time has elapsed since the user input than is specified by the
-  // dom.event.handling-user-input-time-limit pref (default 1 second), this
-  // function also returns false.
-
+const char* nsContentUtils::CheckRequestFullscreenAllowed(
+    CallerType aCallerType) {
   if (!StaticPrefs::full_screen_api_allow_trusted_requests_only() ||
       aCallerType == CallerType::System) {
-    return true;
-  }
-
-  if (EventStateManager::IsHandlingUserInput()) {
-    TimeDuration timeout = HandlingUserInputTimeout();
-    return timeout <= TimeDuration(nullptr) ||
-           (TimeStamp::Now() - EventStateManager::GetHandlingInputStart()) <=
-               timeout;
-  }
-
-  return false;
+    return nullptr;
+  }
+
+  if (!EventStateManager::IsHandlingUserInput()) {
+    return "FullscreenDeniedNotInputDriven";
+  }
+
+  // If more time has elapsed since the user input than is specified by the
+  // dom.event.handling-user-input-time-limit pref (default 1 second),
+  // disallow fullscreen
+  TimeDuration timeout = HandlingUserInputTimeout();
+  if (timeout > TimeDuration(nullptr) &&
+      (TimeStamp::Now() - EventStateManager::GetHandlingInputStart()) >
+          timeout) {
+    return "FullscreenDeniedNotInputDriven";
+  }
+
+  // Entering full-screen on mouse mouse event is only allowed with left mouse
+  // button
+  if (StaticPrefs::full_screen_api_mouse_event_allow_left_button_only() &&
+      (EventStateManager::sCurrentMouseBtn == MouseButton::eMiddle ||
+       EventStateManager::sCurrentMouseBtn == MouseButton::eRight)) {
+    return "FullscreenDeniedMouseEventOnlyLeftBtn";
+  }
+
+  return nullptr;
 }
 
 /* static */
 bool nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal) {
   if (StaticPrefs::dom_allow_cut_copy() &&
       EventStateManager::IsHandlingUserInput()) {
     return true;
   }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2327,22 +2327,24 @@ class nsContentUtils {
    * Determine whether a content node is focused or not,
    *
    * @param aContent the content node to check
    * @return true if the content node is focused, false otherwise.
    */
   static bool IsFocusedContent(const nsIContent* aContent);
 
   /**
-   * Returns true if requests for fullscreen are allowed in the current
+   * Returns nullptr if requests for fullscreen are allowed in the current
    * context. Requests are only allowed if the user initiated them (like with
    * a mouse-click or key press), unless this check has been disabled by
    * setting the pref "full-screen-api.allow-trusted-requests-only" to false.
+   * If fullscreen is not allowed, a key for the error message is returned.
    */
-  static bool IsRequestFullscreenAllowed(mozilla::dom::CallerType aCallerType);
+  static const char* CheckRequestFullscreenAllowed(
+      mozilla::dom::CallerType aCallerType);
 
   /**
    * Returns true if calling execCommand with 'cut' or 'copy' arguments is
    * allowed for the given subject principal. These are only allowed if the user
    * initiated them (like with a mouse-click or key press).
    */
   static bool IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal);
 
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -174,16 +174,35 @@ class EncodingScope {
   RefPtr<Selection> mSelection;
   RefPtr<nsRange> mRange;
   nsCOMPtr<nsINode> mNode;
   bool mNodeIsContainer = false;
 };
 
 bool EncodingScope::IsLimited() const { return mSelection || mRange || mNode; }
 
+struct RangeBoundaryPathsAndOffsets {
+  using ContainerPath = AutoTArray<nsIContent*, 8>;
+  using ContainerOffsets = AutoTArray<int32_t, 8>;
+
+  // The first node is the range's boundary node, the following ones the
+  // ancestors.
+  ContainerPath mStartContainerPath;
+  // The first offset represents where at the boundary node the range starts.
+  // Each other offset is the index of the child relative to its parent.
+  ContainerOffsets mStartContainerOffsets;
+
+  // The first node is the range's boundary node, the following one the
+  // ancestors.
+  ContainerPath mEndContainerPath;
+  // The first offset represents where at the boundary node the range ends.
+  // Each other offset is the index of the child relative to its parent.
+  ContainerOffsets mEndContainerOffsets;
+};
+
 class nsDocumentEncoder : public nsIDocumentEncoder {
  public:
   nsDocumentEncoder();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsDocumentEncoder)
   NS_DECL_NSIDOCUMENTENCODER
 
@@ -258,26 +277,27 @@ class nsDocumentEncoder : public nsIDocu
         }
       }
     }
     return false;
   }
 
   virtual bool IncludeInContext(nsINode* aNode);
 
-  void Clear();
+  void ReleaseDocumentReferenceAndInitialize(bool aClearCachedSerializer);
 
   class MOZ_STACK_CLASS AutoReleaseDocumentIfNeeded final {
    public:
     explicit AutoReleaseDocumentIfNeeded(nsDocumentEncoder* aEncoder)
         : mEncoder(aEncoder) {}
 
     ~AutoReleaseDocumentIfNeeded() {
       if (mEncoder->mFlags & RequiresReinitAfterOutput) {
-        mEncoder->Clear();
+        const bool clearCachedSerializer = false;
+        mEncoder->ReleaseDocumentReferenceAndInitialize(clearCachedSerializer);
       }
     }
 
    private:
     nsDocumentEncoder* mEncoder;
   };
 
   nsCOMPtr<Document> mDocument;
@@ -291,35 +311,33 @@ class nsDocumentEncoder : public nsIDocu
   const Encoding* mEncoding;
   uint32_t mFlags;
   uint32_t mWrapColumn;
   uint32_t mStartDepth;
   uint32_t mEndDepth;
   int32_t mStartRootIndex;
   int32_t mEndRootIndex;
   AutoTArray<nsINode*, 8> mCommonAncestors;
-  AutoTArray<nsIContent*, 8> mStartNodes;
-  AutoTArray<int32_t, 8> mStartOffsets;
-  AutoTArray<nsIContent*, 8> mEndNodes;
-  AutoTArray<int32_t, 8> mEndOffsets;
+  RangeBoundaryPathsAndOffsets mRangeBoundaryPathsAndOffsets;
   AutoTArray<AutoTArray<nsINode*, 8>, 8> mRangeContexts;
   // Whether the serializer cares about being notified to scan elements to
   // keep track of whether they are preformatted.  This stores the out
   // argument of nsIContentSerializer::Init().
   bool mNeedsPreformatScanning;
   bool mHaltRangeHint;
   // Used when context has already been serialized for
   // table cell selections (where parent is <tr>)
   bool mDisableContextSerialize;
   bool mIsCopying;  // Set to true only while copying
   nsStringBuffer* mCachedBuffer;
 };
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocumentEncoder)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsDocumentEncoder, Clear())
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(
+    nsDocumentEncoder, ReleaseDocumentReferenceAndInitialize(true))
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocumentEncoder)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION(nsDocumentEncoder, mDocument,
                          mEncodingScope.mSelection, mEncodingScope.mRange,
@@ -337,16 +355,19 @@ void nsDocumentEncoder::Initialize(bool 
   mStartDepth = 0;
   mEndDepth = 0;
   mStartRootIndex = 0;
   mEndRootIndex = 0;
   mNeedsPreformatScanning = false;
   mHaltRangeHint = false;
   mDisableContextSerialize = false;
   mEncodingScope = {};
+  mCommonParent = nullptr;
+  mNodeFixup = nullptr;
+  mRangeBoundaryPathsAndOffsets = {};
   if (aClearCachedSerializer) {
     mSerializer = nullptr;
   }
 }
 
 static bool ParentIsTR(nsIContent* aContent) {
   mozilla::dom::Element* parent = aContent->GetParentElement();
   if (!parent) {
@@ -766,23 +787,28 @@ nsresult nsDocumentEncoder::SerializeRan
     return NS_OK;
   }
 
   nsresult rv = NS_OK;
 
   // get start and end nodes for this recursion level
   nsCOMPtr<nsIContent> startNode, endNode;
   {
+    auto& startContainerPath =
+        mRangeBoundaryPathsAndOffsets.mStartContainerPath;
+    auto& endContainerPath = mRangeBoundaryPathsAndOffsets.mEndContainerPath;
     int32_t start = mStartRootIndex - aDepth;
-    if (start >= 0 && (uint32_t)start <= mStartNodes.Length())
-      startNode = mStartNodes[start];
+    if (start >= 0 && (uint32_t)start <= startContainerPath.Length()) {
+      startNode = startContainerPath[start];
+    }
 
     int32_t end = mEndRootIndex - aDepth;
-    if (end >= 0 && (uint32_t)end <= mEndNodes.Length())
-      endNode = mEndNodes[end];
+    if (end >= 0 && (uint32_t)end <= endContainerPath.Length()) {
+      endNode = endContainerPath[end];
+    }
   }
 
   if (startNode != content && endNode != content) {
     // node is completely contained in range.  Serialize the whole subtree
     // rooted by this node.
     rv = SerializeToStringRecursive(aNode, aString, false);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
@@ -811,23 +837,29 @@ nsresult nsDocumentEncoder::SerializeRan
         if ((startNode == content) && !mHaltRangeHint) mStartDepth++;
         if ((endNode == content) && !mHaltRangeHint) mEndDepth++;
 
         // serialize the start of this node
         rv = SerializeNodeStart(*aNode, 0, -1, aString);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
+      const auto& startContainerOffsets =
+          mRangeBoundaryPathsAndOffsets.mStartContainerOffsets;
+      const auto& endContainerOffsets =
+          mRangeBoundaryPathsAndOffsets.mEndContainerOffsets;
       // do some calculations that will tell us which children of this
       // node are in the range.
       int32_t startOffset = 0, endOffset = -1;
-      if (startNode == content && mStartRootIndex >= aDepth)
-        startOffset = mStartOffsets[mStartRootIndex - aDepth];
-      if (endNode == content && mEndRootIndex >= aDepth)
-        endOffset = mEndOffsets[mEndRootIndex - aDepth];
+      if (startNode == content && mStartRootIndex >= aDepth) {
+        startOffset = startContainerOffsets[mStartRootIndex - aDepth];
+      }
+      if (endNode == content && mEndRootIndex >= aDepth) {
+        endOffset = endContainerOffsets[mEndRootIndex - aDepth];
+      }
       // generated content will cause offset values of -1 to be returned.
       uint32_t childCount = content->GetChildCount();
 
       if (startOffset == -1) startOffset = 0;
       if (endOffset == -1)
         endOffset = childCount;
       else {
         // if we are at the "tip" of the selection, endOffset is fine.
@@ -939,30 +971,34 @@ nsresult nsDocumentEncoder::SerializeRan
   int32_t startOffset = aRange->StartOffset();
 
   nsINode* endContainer = aRange->GetEndContainer();
   NS_ENSURE_TRUE(endContainer, NS_ERROR_FAILURE);
   int32_t endOffset = aRange->EndOffset();
 
   mStartDepth = mEndDepth = 0;
   mCommonAncestors.Clear();
-  mStartNodes.Clear();
-  mStartOffsets.Clear();
-  mEndNodes.Clear();
-  mEndOffsets.Clear();
+
+  mRangeBoundaryPathsAndOffsets = {};
+  auto& startContainerPath = mRangeBoundaryPathsAndOffsets.mStartContainerPath;
+  auto& startContainerOffsets =
+      mRangeBoundaryPathsAndOffsets.mStartContainerOffsets;
+  auto& endContainerPath = mRangeBoundaryPathsAndOffsets.mEndContainerPath;
+  auto& endContainerOffsets =
+      mRangeBoundaryPathsAndOffsets.mEndContainerOffsets;
 
   nsContentUtils::GetAncestors(mCommonParent, mCommonAncestors);
-  nsContentUtils::GetAncestorsAndOffsets(startContainer, startOffset,
-                                         &mStartNodes, &mStartOffsets);
-  nsContentUtils::GetAncestorsAndOffsets(endContainer, endOffset, &mEndNodes,
-                                         &mEndOffsets);
+  nsContentUtils::GetAncestorsAndOffsets(
+      startContainer, startOffset, &startContainerPath, &startContainerOffsets);
+  nsContentUtils::GetAncestorsAndOffsets(
+      endContainer, endOffset, &endContainerPath, &endContainerOffsets);
 
   nsCOMPtr<nsIContent> commonContent = do_QueryInterface(mCommonParent);
-  mStartRootIndex = mStartNodes.IndexOf(commonContent);
-  mEndRootIndex = mEndNodes.IndexOf(commonContent);
+  mStartRootIndex = startContainerPath.IndexOf(commonContent);
+  mEndRootIndex = endContainerPath.IndexOf(commonContent);
 
   nsresult rv = NS_OK;
 
   rv = SerializeRangeContextStart(mCommonAncestors, aOutputString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (startContainer == endContainer && IsTextNode(startContainer)) {
     if (mFlags & SkipInvisibleContent) {
@@ -986,22 +1022,21 @@ nsresult nsDocumentEncoder::SerializeRan
     NS_ENSURE_SUCCESS(rv, rv);
   }
   rv = SerializeRangeContextEnd(aOutputString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return rv;
 }
 
-void nsDocumentEncoder::Clear() {
+void nsDocumentEncoder::ReleaseDocumentReferenceAndInitialize(
+    bool aClearCachedSerializer) {
   mDocument = nullptr;
-  mCommonParent = nullptr;
-  mNodeFixup = nullptr;
 
-  Initialize(false);
+  Initialize(aClearCachedSerializer);
 }
 
 NS_IMETHODIMP
 nsDocumentEncoder::EncodeToString(nsAString& aOutputString) {
   return EncodeToStringWithMaxLength(0, aOutputString);
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsIDocumentEncoder.idl
+++ b/dom/base/nsIDocumentEncoder.idl
@@ -226,16 +226,17 @@ interface nsIDocumentEncoder : nsISuppor
    * Release reference of Document after using encodeTo* method to recycle
    * this encoder without holding Document. To use this encoder again,
    * we have to call init again.
    */
   const unsigned long RequiresReinitAfterOutput = (1 << 28);
 
   /**
    * Initialize with a pointer to the document and the mime type.
+   * Resets wrap column to 72 and resets node fixup.
    * @param aDocument Document to encode.
    * @param aMimeType MimeType to use. May also be set by SetMimeType.
    * @param aFlags Flags to use while encoding. May also be set by SetFlags.
    */
   void init(in Document aDocument,
             in AString aMimeType,
             in unsigned long aFlags);
   [noscript] void nativeInit(in Document aDocument,
--- a/dom/base/nsISelectionDisplay.idl
+++ b/dom/base/nsISelectionDisplay.idl
@@ -12,26 +12,26 @@ interface nsISelectionDisplay : nsISuppo
    const short DISPLAY_TEXT = 1;   //display text selected.
    const short DISPLAY_IMAGES = 2; //show images selected
    const short DISPLAY_FRAMES = 4; //display hrules ect.
    const short DISPLAY_ALL = 7; //display all. used for isEditor as well
 
    /*
    SetSelectionFlags used to set whether you want to see HRULES/IMAGES with border.
     also used to tell if the presshell is an editor right now. this should change
-    
+
     @param aToggle -either DISPLAY_(TEXT,IMAGES,FRAMES,ALL)
                     This will tell the rendering engine to draw the different
-                    selection types. 
+                    selection types.
 
    */
     void setSelectionFlags(in short toggle);
 
    /*
    GetSelectionFlags used to get whether you want to see HRULES/IMAGES with border.
     also used to tell if the presshell is an editor right now. this should change
-   
-    @param short *aReturn - This will be filled with DISPLAY_(TEXT,IMAGE,FRAMES,ALL) 
+
+    @param short *aReturn - This will be filled with DISPLAY_(TEXT,IMAGE,FRAMES,ALL)
                             bit flags.
    */
     short getSelectionFlags();
 
 };
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -391,17 +391,17 @@ partial namespace ChromeUtils {
 
   /**
    * For testing purpose we need to reset this value.
    */
   [ChromeOnly]
   void resetLastExternalProtocolIframeAllowed();
 
   [ChromeOnly, Throws]
-  void registerWindowActor(DOMString aName, WindowActorOptions aOptions);
+  void registerWindowActor(DOMString aName, optional WindowActorOptions aOptions);
 
   [ChromeOnly]
   void unregisterWindowActor(DOMString aName);
 
   [ChromeOnly]
   // aError should a nsresult.
   boolean isClassifierBlockingErrorCode(unsigned long aError);
 };
@@ -616,23 +616,23 @@ dictionary WindowActorOptions {
   /**
    * Optional list of regular expressions for remoteTypes which are
    * allowed to instantiate this actor. If not passed, all content
    * processes are allowed to instantiate the actor.
    **/
   sequence<DOMString> remoteTypes;
 
   /** This fields are used for configuring individual sides of the actor. */
-  required WindowActorSidedOptions parent;
-  required WindowActorChildOptions child;
+  WindowActorSidedOptions parent = null;
+  WindowActorChildOptions child = null;
 };
 
 dictionary WindowActorSidedOptions {
   /** The module path which should be loaded for the actor on this side. */
-  required ByteString moduleURI;
+  ByteString moduleURI;
 };
 
 dictionary WindowActorChildOptions : WindowActorSidedOptions {
   /**
    * Events which this actor wants to be listening to. When these events fire,
    * it will trigger actor creation, and then forward the event to the actor.
    */
   record<DOMString, AddEventListenerOptions> events;
--- a/dom/commandhandler/nsICommandManager.idl
+++ b/dom/commandhandler/nsICommandManager.idl
@@ -69,17 +69,17 @@ interface nsICommandManager : nsISupport
    *
    * On input: aCommandParams filled in with values that the caller cares
    * about, most of which are command-specific (see the command documentation
    * for details). One boolean value, "enabled", applies to all commands,
    * and, in return will be set to indicate whether the command is enabled
    * (equivalent to calling isCommandEnabled).
    *
    * aCommandName is the name of the command that needs the state
-   * aTargetWindow is the source of command controller 
+   * aTargetWindow is the source of command controller
    *      (null means use focus controller)
    * On output: aCommandParams: values set by the caller filled in with
    * state from the command.
    */
   void        getCommandState(in string aCommandName,
                               in mozIDOMWindowProxy aTargetWindow,
                   /* inout */ in nsICommandParams aCommandParams);
 
--- a/dom/commandhandler/nsIControllerCommand.idl
+++ b/dom/commandhandler/nsIControllerCommand.idl
@@ -28,26 +28,26 @@ interface nsIControllerCommand : nsISupp
    *                      state.
    * @param aCommandContext    a cookie held by the nsIControllerCommandTable,
    *                  allowing the command to get some context information.
    *                  The contents of this cookie are implementation-defined.
    */
   boolean isCommandEnabled(in string aCommandName, in nsISupports aCommandContext);
 
   void getCommandStateParams(in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext);
-  
+
   /**
    * Execute the name command.
    *
    * @param aCommandName  the name of the command to execute.
-   * 
+   *
    * @param aCommandContext    a cookie held by the nsIControllerCommandTable,
    *                  allowing the command to get some context information.
    *                  The contents of this cookie are implementation-defined.
    */
   [can_run_script]
   void    doCommand(in string aCommandName, in nsISupports aCommandContext);
 
   [can_run_script]
   void    doCommandParams(in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext);
-  
+
 };
 
--- a/dom/commandhandler/nsIControllerCommandTable.idl
+++ b/dom/commandhandler/nsIControllerCommandTable.idl
@@ -7,48 +7,48 @@
 #include "nsICommandParams.idl"
 
 %{C++
 class nsControllerCommandTable;
 %}
 
 /**
  * nsIControllerCommandTable
- * 
+ *
  * An interface via which a controller can maintain a series of commands,
  * and efficiently dispatch commands to their respective handlers.
  *
  * Controllers that use an nsIControllerCommandTable should support
  * nsIInterfaceRequestor, and be able to return an interface to their
  * controller command table via getInterface().
- * 
+ *
  */
 
 [scriptable, builtinclass, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
 interface nsIControllerCommandTable : nsISupports
 {
   /**
    * Make this command table immutable, so that commands cannot
    * be registered or unregistered. Some command tables are made
-   * mutable after command registration so that they can be 
+   * mutable after command registration so that they can be
    * used as singletons.
    */
   void  makeImmutable();
-  
+
   /**
    * Register and unregister commands with the command table.
    *
    * @param aCommandName  the name of the command under which to register or
    *                      unregister the given command handler.
    *
    * @param aCommand      the handler for this command.
    */
   void    registerCommand(in string aCommandName, in nsIControllerCommand aCommand);
   void    unregisterCommand(in string aCommandName, in nsIControllerCommand aCommand);
-  
+
   /**
    * Find the command handler which has been registered to handle the named command.
    *
    * @param aCommandName  the name of the command to find the handler for.
    */
   nsIControllerCommand findCommandHandler(in string aCommandName);
 
   /**
--- a/dom/commandhandler/nsIControllerContext.idl
+++ b/dom/commandhandler/nsIControllerContext.idl
@@ -1,13 +1,13 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
+
 #include "nsISupports.idl"
 #include "nsIControllerCommandTable.idl"
 
 [scriptable, builtinclass, uuid(47B82B60-A36F-4167-8072-6F421151ED50)]
 interface nsIControllerContext : nsISupports
 {
   /**
    *  Set a context on this controller, which is passed
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -192,16 +192,17 @@ NS_INTERFACE_MAP_END
 /* mozilla::EventStateManager                                     */
 /******************************************************************/
 
 static uint32_t sESMInstanceCount = 0;
 
 int32_t EventStateManager::sUserInputEventDepth = 0;
 int32_t EventStateManager::sUserKeyboardEventDepth = 0;
 bool EventStateManager::sNormalLMouseEventInProcess = false;
+int16_t EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
 EventStateManager* EventStateManager::sActiveESM = nullptr;
 Document* EventStateManager::sMouseOverDocument = nullptr;
 AutoWeakFrame EventStateManager::sLastDragOverFrame = nullptr;
 LayoutDeviceIntPoint EventStateManager::sPreLockPoint =
     LayoutDeviceIntPoint(0, 0);
 LayoutDeviceIntPoint EventStateManager::sLastRefPoint = kInvalidRefPoint;
 CSSIntPoint EventStateManager::sLastScreenPoint = CSSIntPoint(0, 0);
 LayoutDeviceIntPoint EventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
@@ -6275,27 +6276,36 @@ AutoHandlingUserInputStatePusher::AutoHa
     NS_ENSURE_TRUE_VOID(fm);
     // If it's in modal state, mouse button event handling may be nested.
     // E.g., a modal dialog is opened at mousedown or mouseup event handler
     // and the dialog is clicked.  Therefore, we should store current
     // mouse button event handling document if nsFocusManager already has it.
     mMouseButtonEventHandlingDocument =
         fm->SetMouseButtonHandlingDocument(aDocument);
   }
+  if (NeedsToUpdateCurrentMouseBtnState()) {
+    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
+    if (mouseEvent) {
+      EventStateManager::sCurrentMouseBtn = mouseEvent->mButton;
+    }
+  }
 }
 
 AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
   if (!mIsHandlingUserInput) {
     return;
   }
   EventStateManager::StopHandlingUserInput(mMessage);
   if (mMessage == eMouseDown) {
     PresShell::AllowMouseCapture(false);
   }
   if (NeedsToResetFocusManagerMouseButtonHandlingState()) {
     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     NS_ENSURE_TRUE_VOID(fm);
     nsCOMPtr<Document> handlingDocument =
         fm->SetMouseButtonHandlingDocument(mMouseButtonEventHandlingDocument);
   }
+  if (NeedsToUpdateCurrentMouseBtnState()) {
+    EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
+  }
 }
 
 }  // namespace mozilla
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -1257,16 +1257,17 @@ class EventStateManager : public nsSuppo
   // events.  sUserKeyboardEventDepth is the number of keyboard input events.
   // Incremented whenever we start handling a user input, decremented when we
   // have finished handling a user input. This depth is *not* reset in case
   // of nested event loops.
   static int32_t sUserInputEventDepth;
   static int32_t sUserKeyboardEventDepth;
 
   static bool sNormalLMouseEventInProcess;
+  static int16_t sCurrentMouseBtn;
 
   static EventStateManager* sActiveESM;
 
   static void ClearGlobalActiveContent(EventStateManager* aClearer);
 
   // Functions used for click hold context menus
   nsCOMPtr<nsITimer> mClickHoldTimer;
   void CreateClickHoldTimer(nsPresContext* aPresContext, nsIFrame* aDownFrame,
@@ -1293,16 +1294,21 @@ class MOZ_RAII AutoHandlingUserInputStat
  protected:
   RefPtr<dom::Document> mMouseButtonEventHandlingDocument;
   EventMessage mMessage;
   bool mIsHandlingUserInput;
 
   bool NeedsToResetFocusManagerMouseButtonHandlingState() const {
     return mMessage == eMouseDown || mMessage == eMouseUp;
   }
+
+  bool NeedsToUpdateCurrentMouseBtnState() const {
+    return mMessage == eMouseDown || mMessage == eMouseUp ||
+           mMessage == ePointerDown || mMessage == ePointerUp;
+  }
 };
 
 }  // namespace mozilla
 
 // Click and double-click events need to be handled even for content that
 // has no frame. This is required for Web compatibility.
 #define NS_EVENT_NEEDS_FRAME(event)               \
   (!(event)->HasPluginActivationEventMessage() && \
--- a/dom/html/nsIImageDocument.idl
+++ b/dom/html/nsIImageDocument.idl
@@ -39,9 +39,9 @@ interface nsIImageDocument : nsISupports
 
   /* A helper method for switching between states.
    * The switching logic is as follows. If the image has been resized
    * restore image original size, otherwise if the image is overflowing
    * current visible area resize the image to fit the area.
    */
   [binaryname(DOMToggleImageSize)]
   void toggleImageSize();
-};  
+};
--- a/dom/html/test/file_fullscreen-denied.html
+++ b/dom/html/test/file_fullscreen-denied.html
@@ -106,24 +106,59 @@ function testLongRunningEventHandler() {
     var end = (new Date()).getTime() + 2000;
     while ((new Date()).getTime() < end) {
       ; // Wait...
     }
     document.documentElement.requestFullscreen();
   }
   addFullscreenErrorContinuation(() => {
     ok(!document.fullscreenElement,
-       "Should not grant request in long-running event handler.");
-    // Restore the pref environment we changed before
-    // entering testNonTrustContext.
-    SpecialPowers.popPrefEnv(finish);
+      "Should not grant request in long-running event handler.");
+    SimpleTest.executeSoon(testFullscreenMouseBtn);
   });
   window.addEventListener("keypress", longRunningHandler);
   sendString("a");
 }
 
+function requestFullscreenMouseBtn(event, button) {
+  let clickEl = document.createElement("p");
+  clickEl.innerText = "Click Me";
+
+  function eventHandler(event) {
+    document.body.requestFullscreen();
+    event.target.removeEventListener(event, this);
+  }
+
+  clickEl.addEventListener(event, eventHandler);
+  document.body.appendChild(clickEl);
+  synthesizeMouseAtCenter(clickEl, { button });
+}
+
+async function testFullscreenMouseBtn(event, button, next) {
+  await SpecialPowers.pushPrefEnv({
+    "set": [["full-screen-api.mouse-event-allow-left-button-only", true]]
+  });
+  let fsRequestEvents = ["mousedown", "mouseup", "pointerdown", "pointerup"];
+  let mouseButtons = [1, 2];
+
+  for (let i = 0; i < fsRequestEvents.length; i++) {
+    let event = fsRequestEvents[i];
+    for (let j = 0; j < mouseButtons.length; j++) {
+      let mouseButton = mouseButtons[j];
+      let fsDenied = addFullscreenErrorContinuation();
+      requestFullscreenMouseBtn(event, mouseButton);
+      await fsDenied;
+      ok(!document.fullscreenElement, `Should not grant request on '${event}' triggered by mouse button ${mouseButton}`);
+    }
+  }
+  // Restore the pref environment we changed before
+  // entering testNonTrustContext.
+  await SpecialPowers.popPrefEnv();
+  finish();
+}
+
 function finish() {
   opener.nextTest();
 }
 
 </script>
 </body>
 </html>
--- a/dom/html/test/file_fullscreen-utils.js
+++ b/dom/html/test/file_fullscreen-utils.js
@@ -67,22 +67,29 @@ function addFullscreenChangeContinuation
     }
     topWin.addEventListener("resize", onResize);
   }
   doc.addEventListener("fullscreenchange", onFullscreenChange);
 }
 
 // Calls |callback| when the next fullscreenerror is dispatched to inDoc||document.
 function addFullscreenErrorContinuation(callback, inDoc) {
-  var doc = inDoc || document;
-  var listener = function(event) {
-    doc.removeEventListener("fullscreenerror", listener);
-    setTimeout(function(){callback(event);}, 0);
-  };
-  doc.addEventListener("fullscreenerror", listener);
+  return new Promise((resolve) => {
+    let doc = inDoc || document;
+    let listener = function(event) {
+      doc.removeEventListener("fullscreenerror", listener);
+      setTimeout(function(){
+        if(callback) {
+          callback(event);
+        }
+        resolve();
+      }, 0);
+    };
+    doc.addEventListener("fullscreenerror", listener);
+  })
 }
 
 // Waits until the window has both the load event and a MozAfterPaint called on
 // it, and then invokes the callback
 function waitForLoadAndPaint(win, callback) {
   win.addEventListener("MozAfterPaint", function() {
     // The load event may have fired before the MozAfterPaint, in which case
     // listening for it now will hang. Instead we check the readyState to see if
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -204,19 +204,19 @@ interface nsIDOMWindowUtils : nsISupport
    *
    * Setting a new resolution does *not* trigger reflow.  This API is
    * entirely separate from textZoom and fullZoom; a resolution scale
    * can be applied together with both textZoom and fullZoom.
    *
    * The effect of this API is for gfx code to allocate more or fewer
    * pixels for rescalable content by a factor of |resolution| in
    * both dimensions.
-   * 
+   *
    * In addition, the content is scaled by the amount of the resolution,
-   * so that it is displayed at a correspondingly larger or smaller size, 
+   * so that it is displayed at a correspondingly larger or smaller size,
    * without the need for the caller to set an additional transform.
    *
    * This can be used to implement a non-reflowing scale-zoom, e.g.
    * for pinch-zoom on mobile platforms.
    *
    * The caller of this method must have chrome privileges.
    */
   void setResolutionAndScaleTo(in float aResolution);
--- a/dom/interfaces/base/nsIRemoteTab.idl
+++ b/dom/interfaces/base/nsIRemoteTab.idl
@@ -91,17 +91,17 @@ interface nsIRemoteTab : nsISupports
   /**
    * The frame element which currently embeds this nsIRemoteTab object.
    */
   readonly attribute Element ownerElement;
 
   /**
    * Notify APZ to start autoscrolling.
    * (aAnchorX, aAnchorY) are the coordinates of the autoscroll anchor,
-   * in CSS coordinates relative to the screen. aScrollId and 
+   * in CSS coordinates relative to the screen. aScrollId and
    * aPresShellId identify the scroll frame that content chose to scroll.
    * Returns whether we were successfully able to notify APZ.
    * If this function returns true, APZ (which may live in another process)
    * may still reject the autoscroll, but it's then APZ's reponsibility
    * to notify content via an "autoscroll-rejected-by-apz" message.
    */
   boolean startApzAutoscroll(in float aAnchorX, in float aAnchorY,
                              in nsViewID aScrollId, in uint32_t aPresShellId);
--- a/dom/interfaces/events/nsIDOMEventListener.idl
+++ b/dom/interfaces/events/nsIDOMEventListener.idl
@@ -6,27 +6,27 @@
 #include "domstubs.idl"
 
 webidl Event;
 
 /**
  * The nsIDOMEventListener interface is a callback interface for
  * listening to events in the Document Object Model.
  *
- * For more information on this interface please see 
+ * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Events/
  */
 
 [uuid(df31c120-ded6-11d1-bd85-00805f8ae3f4)]
 interface nsIDOMEventListener : nsISupports
 {
   /**
-   * This method is called whenever an event occurs of the type for which 
+   * This method is called whenever an event occurs of the type for which
    * the EventListener interface was registered.
    *
-   * @param   evt The Event contains contextual information about the 
-   *              event. It also contains the stopPropagation and 
-   *              preventDefault methods which are used in determining the 
+   * @param   evt The Event contains contextual information about the
+   *              event. It also contains the stopPropagation and
+   *              preventDefault methods which are used in determining the
    *              event's flow and default action.
    */
   [can_run_script]
   void                      handleEvent(in Event event);
 };
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl
+++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl
@@ -237,17 +237,17 @@ interface nsIContentSecurityPolicy : nsI
   [noscript] readonly attribute AString referrer;
   [noscript, notxpcom, nostdcall] readonly attribute unsigned long long innerWindowID;
 
   /**
    *  Ensure we have a nsIEventTarget to use to label CSPReportSenderRunnable
    */
   [noscript] void ensureEventTarget(in nsIEventTarget aEventTarget);
 
- 
+
   /**
    * Verifies ancestry as permitted by the policy.
    *
    * NOTE: Calls to this may trigger violation reports when queried, so this
    * value should not be cached.
    *
    * @param docShell
    *    containing the protected resource
--- a/dom/interfaces/sidebar/nsIWebProtocolHandlerRegistrar.idl
+++ b/dom/interfaces/sidebar/nsIWebProtocolHandlerRegistrar.idl
@@ -5,23 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIURI;
 
 /**
  * nsIWebProtocolHandlerRegistrar
- * 
+ *
  * Applications wishing to use web protocol handlers need to implement this
  * interface. Typically they will prompt the user to confirm adding an entry
- * to the local list. 
+ * to the local list.
  *
  * The component must have the contract id defined below so that the Navigator
- * implementation can invoke it. 
+ * implementation can invoke it.
  */
 
 [scriptable, uuid(1ce9ef8d-f462-49ca-b8e9-c946c4f37d6e)]
 interface nsIWebProtocolHandlerRegistrar : nsISupports
 {
   /**
    * See documentation in Navigator.webidl
    * The additional contentWindow param for this method represents the dom
--- a/dom/interfaces/xul/nsIDOMXULButtonElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULButtonElement.idl
@@ -7,15 +7,15 @@
 
 [scriptable, uuid(6ed53cfb-9e59-424c-af8d-e74582381951)]
 interface nsIDOMXULButtonElement : nsIDOMXULControlElement {
   attribute AString type;
   attribute AString dlgType;
 
   // For buttons of type="menu" only.
   attribute boolean open;
-  
+
   // For buttons of type="checkbox" only.
   attribute boolean checked;
 
   // For buttons of type="radio" only.
   attribute AString group;
 };
--- a/dom/interfaces/xul/nsIDOMXULControlElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULControlElement.idl
@@ -5,17 +5,17 @@
 
 #include "nsISupports.idl"
 
 interface nsIControllers;
 
 [scriptable, uuid(bdc1d047-6d22-4813-bc50-638ccb349c7d)]
 interface nsIDOMXULControlElement : nsISupports {
   attribute boolean disabled;
-  
+
 // XXX defined in XULElement, but should be defined here
 //  readonly attribute nsIControllers controllers;
-  
+
 //  void focus();
 //  void blur();
 };
 
 
--- a/dom/interfaces/xul/nsIDOMXULMenuListElement.idl
+++ b/dom/interfaces/xul/nsIDOMXULMenuListElement.idl
@@ -6,19 +6,19 @@
 #include "nsIDOMXULSelectCntrlEl.idl"
 
 webidl Element;
 
 [scriptable, uuid(36c16a17-c0e9-4b35-951b-81a147314ef1)]
 interface nsIDOMXULMenuListElement : nsIDOMXULSelectControlElement {
   attribute boolean editable;
   attribute boolean open;
-  
+
   // label of selected option or value of textfield for editable menu lists
   readonly attribute AString label;
 
   attribute AString crop;
   attribute AString image;
-  
+
   // For editable menu lists only.
   readonly attribute Element inputField;
 };
 
--- a/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl
+++ b/dom/interfaces/xul/nsIDOMXULMultSelectCntrlEl.idl
@@ -12,26 +12,26 @@ webidl NodeList;
 interface nsIDOMXULMultiSelectControlElement : nsIDOMXULSelectControlElement
 {
   attribute AString selType;
 
   attribute Element currentItem;
   attribute long currentIndex;
 
   readonly attribute NodeList selectedItems;
-  
+
   void addItemToSelection(in nsIDOMXULSelectControlItemElement item);
   void removeItemFromSelection(in nsIDOMXULSelectControlItemElement item);
   void toggleItemSelection(in nsIDOMXULSelectControlItemElement item);
 
   void selectItem(in nsIDOMXULSelectControlItemElement item);
   void selectItemRange(in nsIDOMXULSelectControlItemElement startItem, in nsIDOMXULSelectControlItemElement item);
 
   void selectAll();
   void invertSelection();
   void clearSelection();
 
-  // XXX - temporary, pending implementation of scriptable, 
+  // XXX - temporary, pending implementation of scriptable,
   //       mutable NodeList for selectedItems
   readonly attribute long selectedCount;
   [binaryname(MultiGetSelectedItem)]
   Element getSelectedItem(in long index);
 };
--- a/dom/interfaces/xul/nsIDOMXULSelectCntrlItemEl.idl
+++ b/dom/interfaces/xul/nsIDOMXULSelectCntrlItemEl.idl
@@ -11,20 +11,20 @@ webidl Element;
 [scriptable, uuid(5c6be58f-17df-4750-88a5-4a59ac28adc9)]
 interface nsIDOMXULSelectControlItemElement : nsISupports {
   attribute boolean disabled;
   attribute AString crop;
   attribute AString image;
   attribute AString label;
   attribute AString accessKey;
   attribute AString command;
-  
+
   attribute AString value;
-  
+
   readonly attribute boolean selected;
-  
+
   readonly attribute Element control;
-  
+
   // XXX defined in XULElement, but should be defined here
   // void doCommand();
 };
 
 
--- a/dom/ipc/JSWindowActorService.cpp
+++ b/dom/ipc/JSWindowActorService.cpp
@@ -42,17 +42,17 @@ JSWindowActorProtocol::FromIPC(const JSW
 
   RefPtr<JSWindowActorProtocol> proto = new JSWindowActorProtocol(aInfo.name());
   // Content processes cannot load chrome browsing contexts, so this flag is
   // irrelevant and not propagated.
   proto->mIncludeChrome = false;
   proto->mAllFrames = aInfo.allFrames();
   proto->mMatches = aInfo.matches();
   proto->mRemoteTypes = aInfo.remoteTypes();
-  proto->mChild.mModuleURI.Assign(aInfo.url());
+  proto->mChild.mModuleURI = aInfo.url();
 
   proto->mChild.mEvents.SetCapacity(aInfo.events().Length());
   for (auto& ipc : aInfo.events()) {
     auto* event = proto->mChild.mEvents.AppendElement();
     event->mName.Assign(ipc.name());
     event->mFlags.mCapture = ipc.capture();
     event->mFlags.mInSystemGroup = ipc.systemGroup();
     event->mFlags.mAllowUntrustedEvents = ipc.allowUntrusted();
@@ -106,18 +106,23 @@ JSWindowActorProtocol::FromWebIDLOptions
     proto->mMatches = aOptions.mMatches.Value();
   }
 
   if (aOptions.mRemoteTypes.WasPassed()) {
     MOZ_ASSERT(aOptions.mRemoteTypes.Value().Length());
     proto->mRemoteTypes = aOptions.mRemoteTypes.Value();
   }
 
-  proto->mParent.mModuleURI = aOptions.mParent.mModuleURI;
-  proto->mChild.mModuleURI = aOptions.mChild.mModuleURI;
+  if (aOptions.mParent.mModuleURI.WasPassed()) {
+    proto->mParent.mModuleURI.emplace(aOptions.mParent.mModuleURI.Value());
+  }
+
+  if (aOptions.mChild.mModuleURI.WasPassed()) {
+    proto->mChild.mModuleURI.emplace(aOptions.mChild.mModuleURI.Value());
+  }
 
   // For each event declared in the source dictionary, initialize the
   // corresponding envent declaration entry in the JSWindowActorProtocol.
   if (aOptions.mChild.mEvents.WasPassed()) {
     auto& entries = aOptions.mChild.mEvents.Value().Entries();
     proto->mChild.mEvents.SetCapacity(entries.Length());
 
     for (auto& entry : entries) {
--- a/dom/ipc/JSWindowActorService.h
+++ b/dom/ipc/JSWindowActorService.h
@@ -46,17 +46,17 @@ class JSWindowActorProtocol final : publ
       const JSWindowActorInfo& aInfo);
   JSWindowActorInfo ToIPC();
 
   static already_AddRefed<JSWindowActorProtocol> FromWebIDLOptions(
       const nsAString& aName, const WindowActorOptions& aOptions,
       ErrorResult& aRv);
 
   struct Sided {
-    nsCString mModuleURI;
+    Maybe<nsCString> mModuleURI;
   };
 
   struct ParentSide : public Sided {};
 
   struct EventDecl {
     nsString mName;
     EventListenerFlags mFlags;
     Optional<bool> mPassive;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -222,17 +222,17 @@ struct JSWindowActorEventDecl
   bool allowUntrusted;
   bool? passive;
 };
 
 struct JSWindowActorInfo
 {
   nsString name;
   bool allFrames;
-  nsCString url;
+  nsCString? url;
 
   JSWindowActorEventDecl[] events;
   nsCString[] observers;
   nsString[] matches;
   nsString[] remoteTypes;
 };
 
 struct GMPAPITags
--- a/dom/ipc/WindowGlobalActor.cpp
+++ b/dom/ipc/WindowGlobalActor.cpp
@@ -4,16 +4,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/. */
 
 #include "mozilla/dom/WindowGlobalActor.h"
 
 #include "mozJSComponentLoader.h"
 #include "mozilla/Logging.h"
 #include "mozilla/dom/JSWindowActorService.h"
+#include "mozilla/dom/JSWindowActorParent.h"
+#include "mozilla/dom/JSWindowActorChild.h"
 
 namespace mozilla {
 namespace dom {
 
 void WindowGlobalActor::ConstructActor(const nsAString& aName,
                                        JS::MutableHandleObject aActor,
                                        ErrorResult& aRv) {
   JSWindowActor::Type actorType = GetSide();
@@ -52,17 +54,38 @@ void WindowGlobalActor::ConstructActor(c
 
   const JSWindowActorProtocol::Sided* side;
   if (actorType == JSWindowActor::Type::Parent) {
     side = &proto->Parent();
   } else {
     side = &proto->Child();
   }
 
-  aRv = loader->Import(cx, side->mModuleURI, &global, &exports);
+  // Support basic functionally such as SendAsyncMessage and SendQuery for
+  // unspecified moduleURI.
+  if (!side->mModuleURI) {
+    RefPtr<JSWindowActor> actor;
+    if (actorType == JSWindowActor::Type::Parent) {
+      actor = new JSWindowActorParent();
+    } else {
+      actor = new JSWindowActorChild();
+    }
+
+    JS::Rooted<JS::Value> wrapper(cx);
+    if (!ToJSValue(cx, actor, &wrapper)) {
+      aRv.NoteJSContextException(cx);
+      return;
+    }
+
+    MOZ_ASSERT(wrapper.isObject());
+    aActor.set(&wrapper.toObject());
+    return;
+  }
+
+  aRv = loader->Import(cx, side->mModuleURI.ref(), &global, &exports);
   if (aRv.Failed()) {
     return;
   }
 
   MOZ_ASSERT(exports, "null exports!");
 
   // Load the specific property from our module.
   JS::RootedValue ctor(cx);
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -58,16 +58,17 @@ FormValidationStepMismatch=Please select
 FormValidationStepMismatchOneValue=Please select a valid value. The nearest valid value is %S.
 FormValidationBadInputNumber=Please enter a number.
 EnablePrivilegeWarning=Use of enablePrivilege is deprecated.  Please use code that runs with the system principal (e.g. an extension) instead.
 FullscreenDeniedDisabled=Request for fullscreen was denied because Fullscreen API is disabled by user preference.
 FullscreenDeniedFocusedPlugin=Request for fullscreen was denied because a windowed plugin is focused.
 FullscreenDeniedHidden=Request for fullscreen was denied because the document is no longer visible.
 FullscreenDeniedContainerNotAllowed=Request for fullscreen was denied because at least one of the document’s containing elements is not an iframe or does not have an “allowfullscreen” attribute.
 FullscreenDeniedNotInputDriven=Request for fullscreen was denied because Element.requestFullscreen() was not called from inside a short running user-generated event handler.
+FullscreenDeniedMouseEventOnlyLeftBtn=Request for fullscreen was denied because Element.requestFullscreen() was called from inside a mouse event handler not triggered by left mouse button.
 FullscreenDeniedNotHTMLSVGOrMathML=Request for fullscreen was denied because requesting element is not <svg>, <math>, or an HTML element.
 FullscreenDeniedNotInDocument=Request for fullscreen was denied because requesting element is no longer in its document.
 FullscreenDeniedMovedDocument=Request for fullscreen was denied because requesting element has moved document.
 FullscreenDeniedLostWindow=Request for fullscreen was denied because we no longer have a window.
 FullscreenDeniedSubDocFullscreen=Request for fullscreen was denied because a subdocument of the document requesting fullscreen is already fullscreen.
 FullscreenDeniedNotDescendant=Request for fullscreen was denied because requesting element is not a descendant of the current fullscreen element.
 FullscreenDeniedNotFocusedTab=Request for fullscreen was denied because requesting element is not in the currently focused tab.
 FullscreenDeniedFeaturePolicy=Request for fullscreen was denied because of FeaturePolicy directives.
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -753,17 +753,18 @@ void DecodedStream::SendVideo(bool aIsSa
   TimeUnit currentPosition = GetPosition(&currentTime);
 
   if (mData->mLastVideoTimeStamp.IsNull()) {
     mData->mLastVideoTimeStamp = currentTime;
   }
 
   for (uint32_t i = 0; i < video.Length(); ++i) {
     VideoData* v = video[i];
-    TimeUnit lastStart = mData->mLastVideoStartTime.valueOr(mStartTime.ref());
+    TimeUnit lastStart = mData->mLastVideoStartTime.valueOr(
+        mStartTime.ref() - TimeUnit::FromMicroseconds(1));
     TimeUnit lastEnd = mData->mLastVideoEndTime.valueOr(mStartTime.ref());
 
     if (lastEnd < v->mTime) {
       // Write last video frame to catch up. mLastVideoImage can be null here
       // which is fine, it just means there's no video.
 
       // TODO: |mLastVideoImage| should come from the last image rendered
       // by the state machine. This will avoid the black frame when capture
@@ -772,17 +773,20 @@ void DecodedStream::SendVideo(bool aIsSa
       // and capture happens at 15 sec, we'll have to append a black frame
       // that is 15 sec long.
       TimeStamp t =
           std::max(mData->mLastVideoTimeStamp,
                    currentTime + (lastEnd - currentPosition).ToTimeDuration());
       mData->WriteVideoToSegment(mData->mLastVideoImage, lastEnd, v->mTime,
                                  mData->mLastVideoImageDisplaySize, t, &output,
                                  aPrincipalHandle);
-    } else if (lastStart < v->mTime) {
+      lastEnd = v->mTime;
+    }
+
+    if (lastStart < v->mTime) {
       // This frame starts after the last frame's start. Note that this could be
       // before the last frame's end time for some videos. This only matters for
       // the track's lifetime in the MSG, as rendering is based on timestamps,
       // aka frame start times.
       TimeStamp t =
           std::max(mData->mLastVideoTimeStamp,
                    currentTime + (lastEnd - currentPosition).ToTimeDuration());
       TimeUnit end = std::max(
--- a/dom/media/test/manifest.js
+++ b/dom/media/test/manifest.js
@@ -273,17 +273,17 @@ var gPlayTests = [
   { name:"test-2-stereo.opus", type:"audio/ogg; codecs=opus", duration:2.925 },
   { name:"test-3-LCR.opus", type:"audio/ogg; codecs=opus", duration:4.214 },
   { name:"test-4-quad.opus", type:"audio/ogg; codecs=opus", duration:6.234 },
   { name:"test-5-5.0.opus", type:"audio/ogg; codecs=opus", duration:7.558 },
   { name:"test-6-5.1.opus", type:"audio/ogg; codecs=opus", duration:10.333 },
   { name:"test-7-6.1.opus", type:"audio/ogg; codecs=opus", duration:11.690 },
   { name:"test-8-7.1.opus", type:"audio/ogg; codecs=opus", duration:13.478 },
 
-  { name:"gizmo-short.mp4", type:"video/mp4", duration:0.27 },
+  { name:"gizmo-short.mp4", type:"video/mp4", duration:0.27, contentDuration:0.267 },
   // Test playback of a MP4 file with a non-zero start time (and audio starting
   // a second later).
   { name:"bipbop-lateaudio.mp4", type:"video/mp4" },
   // Ambisonics AAC, requires AAC extradata to be set when creating decoder (see bug 1431169)
   // Also test 4.0 decoding.
   { name:"ambisonics.mp4", type:"audio/mp4", duration:16.48 },
   // Opus in MP4 channel mapping=0 sample file (content shorter due to preskip)
   { name:"opus-sample.mp4", type:"audio/mp4; codecs=opus", duration:10.92, contentDuration:10.09 },
--- a/dom/messagechannel/MessageChannel.cpp
+++ b/dom/messagechannel/MessageChannel.cpp
@@ -73,13 +73,21 @@ already_AddRefed<MessageChannel> Message
   channel->mPort2 = MessagePort::Create(aGlobal, portUUID2, portUUID1, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   channel->mPort1->UnshippedEntangle(channel->mPort2);
   channel->mPort2->UnshippedEntangle(channel->mPort1);
 
+  // MessagePorts should not work if created from a disconnected window.
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
+  if (window && !window->GetDocShell()) {
+    // The 2 ports are entangled. We can close one of them to close the other
+    // too.
+    channel->mPort1->CloseForced();
+  }
+
   return channel.forget();
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/messagechannel/tests/mochitest.ini
+++ b/dom/messagechannel/tests/mochitest.ini
@@ -24,8 +24,9 @@ skip-if = (os == "win" && processor == "
 [test_messageChannel_selfTransferring.html]
 [test_messageChannel_sharedWorker.html]
 [test_messageChannel_sharedWorker2.html]
 [test_messageChannel_any.html]
 [test_messageChannel_forceClose.html]
 [test_messageChannel_bug1178076.html]
 [test_messageChannel_bug1224825.html]
 [test_messageChannel_worker_forceClose.html]
+[test_removedWindow.html]
new file mode 100644
--- /dev/null
+++ b/dom/messagechannel/tests/test_removedWindow.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>MessagePort should not work when created from a disconnected window</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<body>
+<script>
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+runTest();
+
+async function runTest() {
+  let ifr = document.createElement('iframe');
+  await new Promise(resolve => {
+    ifr.onload = resolve;
+    ifr.src = 'support/empty.html';
+    document.body.appendChild(ifr);
+  });
+
+  let w = ifr.contentWindow;
+
+  let pre = new w.MessageChannel();
+  ok(!!pre, "We have a channel");
+
+  ifr.remove();
+
+  let post = new w.MessageChannel();
+  ok(!!post, "We have a channel");
+
+  // This should silently fail.
+  pre.port1.postMessage(42);
+  pre.port2.onmessage = e => {
+    ok(false, "No messages should be received!");
+  }
+
+  // This should silently fail.
+  post.port1.postMessage(42);
+  post.port2.onmessage = e => {
+    ok(false, "No messages should be received!");
+  }
+
+  // Let's use another MessagePort just to be sure no messages are received by
+  // port2.
+
+  let mc = new MessageChannel();
+  mc.port1.postMessage(42);
+  mc.port2.onmessage = e => {
+    ok(true, "Ready to complete the test");
+    SimpleTest.finish();
+  }
+}
+
+</script>
+</body>
--- a/dom/plugins/base/nsIHTTPHeaderListener.idl
+++ b/dom/plugins/base/nsIHTTPHeaderListener.idl
@@ -11,17 +11,17 @@
  * nsIPluginHost::{GetURL,PostURL}() call. <P>
  */
 
 [scriptable, uuid(ea51e0b8-871c-4b85-92da-6f400394c5ec)]
 interface nsIHTTPHeaderListener : nsISupports
 {
   /**
    * Called for each HTTP Response header.
-   * NOTE: You must copy the values of the params.  
+   * NOTE: You must copy the values of the params.
    */
   void newResponseHeader(in string headerName, in string headerValue);
 
   /**
    * Called once for the HTTP Response status line.
    * Value does NOT include a terminating newline.
    * NOTE: You must copy this value.
    */
--- a/dom/plugins/base/nsIPluginInstanceOwner.idl
+++ b/dom/plugins/base/nsIPluginInstanceOwner.idl
@@ -58,17 +58,17 @@ interface nsIPluginInstanceOwner : nsISu
 
 %{C++
   /**
    * Called when there is a valid target so that the proper
    * frame can be updated with new content. will not be called
    * with nullptr aTarget.
    */
   NS_IMETHOD
-  GetURL(const char *aURL, const char *aTarget, 
+  GetURL(const char *aURL, const char *aTarget,
          nsIInputStream *aPostStream,
          void *aHeadersData, uint32_t aHeadersDataLen,
          bool aDoCheckLoadURIChecks) = 0;
 %}
 
   /**
    * Get the associated document.
    */
--- a/dom/xul/nsIController.idl
+++ b/dom/xul/nsIController.idl
@@ -16,24 +16,24 @@ interface nsIController : nsISupports {
   void onEvent(in string eventName);
 };
 
 
 /*
 
   Enhanced controller interface that allows for passing of parameters
   to commands.
-  
+
 */
 
 interface nsICommandParams;
 
 [scriptable, uuid(EEC0B435-7F53-44FE-B00A-CF3EED65C01A)]
 interface nsICommandController : nsISupports
 {
-  
+
   void        getCommandStateWithParams( in string command, in nsICommandParams aCommandParams);
-    
+
   [can_run_script]
   void        doCommandWithParams(in string command, in nsICommandParams aCommandParams);
 
   Array<ACString> getSupportedCommands();
 };
--- a/dom/xul/nsIControllers.idl
+++ b/dom/xul/nsIControllers.idl
@@ -24,11 +24,11 @@ interface nsIControllers : nsISupports
         Return an ID for this controller which is unique to this
         nsIControllers.
     */
     unsigned long getControllerId(in nsIController controller);
     /*
         Get the controller specified by the given ID.
     */
     nsIController getControllerById(in unsigned long controllerID);
-    
+
 	unsigned long getControllerCount();
 };
--- a/intl/locale/nsICollation.idl
+++ b/intl/locale/nsICollation.idl
@@ -26,20 +26,20 @@ interface nsICollationFactory : nsISuppo
 };
 
 [scriptable, uuid(b0132cc0-3786-4557-9874-910d7def5f93)]
 interface nsICollation : nsISupports {
 
   // use the primary comparison for the given locale - no flags
   const long kCollationStrengthDefault = 0;
 
-  // do not consider case differences when doing the comparison i.e. A=a) 
+  // do not consider case differences when doing the comparison i.e. A=a)
   const long kCollationCaseInsensitiveAscii = 1;
 
-  // do not consider accent differences when doing the comparison a=á) 
+  // do not consider accent differences when doing the comparison a=á)
   const long kCollationAccentInsenstive = 2;
 
   // case sensitive collation (default)
   const long kCollationCaseSensitive = kCollationStrengthDefault;
 
   // case insensitive collation
   const long kCollationCaseInSensitive = (kCollationCaseInsensitiveAscii | kCollationAccentInsenstive);
 
@@ -47,17 +47,17 @@ interface nsICollation : nsISupports {
   void initialize(in ACString locale);
 
   // compare two strings
   // result is same as strcmp
   long compareString(in long strength, in AString string1, in AString string2);
 
   // allocate sort key from input string
   // returns newly allocated key, and its band its byte length
-  [noscript] void allocateRawSortKey(in long strength, 
+  [noscript] void allocateRawSortKey(in long strength,
                                      in AString stringIn,
                                      [array,size_is(outLen)] out octet key,
                                      out unsigned long outLen);
 
   // compare two sort keys
   // length is a byte length, result is same as strcmp
   [noscript] long compareRawSortKey([const,array,size_is(len1)] in octet key1, in unsigned long len1,
                                     [const,array,size_is(len2)] in octet key2, in unsigned long len2);
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -766,17 +766,17 @@ struct RealmStats {
   // zero.
 #define FOR_EACH_SIZE(MACRO)                                  \
   MACRO(Private, MallocHeap, objectsPrivate)                  \
   MACRO(Other, GCHeapUsed, scriptsGCHeap)                     \
   MACRO(Other, MallocHeap, scriptsMallocHeapData)             \
   MACRO(Other, MallocHeap, baselineData)                      \
   MACRO(Other, MallocHeap, baselineStubsFallback)             \
   MACRO(Other, MallocHeap, ionData)                           \
-  MACRO(Other, MallocHeap, typeInferenceTypeScripts)          \
+  MACRO(Other, MallocHeap, jitScripts)                        \
   MACRO(Other, MallocHeap, typeInferenceAllocationSiteTables) \
   MACRO(Other, MallocHeap, typeInferenceArrayTypeTables)      \
   MACRO(Other, MallocHeap, typeInferenceObjectTypeTables)     \
   MACRO(Other, MallocHeap, realmObject)                       \
   MACRO(Other, MallocHeap, realmTables)                       \
   MACRO(Other, MallocHeap, innerViewsTable)                   \
   MACRO(Other, MallocHeap, lazyArrayBuffersTable)             \
   MACRO(Other, MallocHeap, objectMetadataTable)               \
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -2526,17 +2526,17 @@ void Zone::prepareForCompacting() {
 
 void GCRuntime::sweepTypesAfterCompacting(Zone* zone) {
   zone->beginSweepTypes();
 
   AutoClearTypeInferenceStateOnOOM oom(zone);
 
   for (auto script = zone->cellIterUnsafe<JSScript>(); !script.done();
        script.next()) {
-    AutoSweepTypeScript sweep(script);
+    AutoSweepJitScript sweep(script);
   }
   for (auto group = zone->cellIterUnsafe<ObjectGroup>(); !group.done();
        group.next()) {
     AutoSweepObjectGroup sweep(group);
   }
 
   zone->types.endSweep(rt);
 }
@@ -5911,17 +5911,17 @@ void GCRuntime::drainMarkStack() {
 }
 
 static void SweepThing(Shape* shape) {
   if (!shape->isMarkedAny()) {
     shape->sweep();
   }
 }
 
-static void SweepThing(JSScript* script) { AutoSweepTypeScript sweep(script); }
+static void SweepThing(JSScript* script) { AutoSweepJitScript sweep(script); }
 
 static void SweepThing(ObjectGroup* group) {
   AutoSweepObjectGroup sweep(group);
 }
 
 template <typename T>
 static bool SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget) {
   while (Arena* arena = *arenasToSweep) {
@@ -8097,17 +8097,17 @@ void GCRuntime::mergeRealms(Realm* sourc
 
   // Fixup realm pointers in source to refer to target, and make sure
   // type information generations are in sync.
 
   for (auto script = source->zone()->cellIterUnsafe<JSScript>(); !script.done();
        script.next()) {
     MOZ_ASSERT(script->realm() == source);
     script->realm_ = target;
-    MOZ_ASSERT(!script->types());
+    MOZ_ASSERT(!script->jitScript());
   }
 
   GlobalObject* global = target->maybeGlobal();
   MOZ_ASSERT(global);
 
   for (auto group = source->zone()->cellIterUnsafe<ObjectGroup>();
        !group.done(); group.next()) {
     // Replace placeholder object prototypes with the correct prototype in
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -11,18 +11,19 @@
 #ifndef gc_GCEnum_h
 #define gc_GCEnum_h
 
 #include <stdint.h>
 
 namespace js {
 namespace gc {
 
-// Mark colors to pass to markIfUnmarked.
-enum class MarkColor : uint32_t { Black = 0, Gray };
+// Mark colors. Order is important here: the greater value the 'more marked' a
+// cell is.
+enum class MarkColor : uint8_t { Gray = 1, Black = 2 };
 
 // The phases of an incremental GC.
 #define GCSTATES(D) \
   D(NotActive)      \
   D(MarkRoots)      \
   D(Mark)           \
   D(Sweep)          \
   D(Finalize)       \
--- a/js/src/gc/Verifier.h
+++ b/js/src/gc/Verifier.h
@@ -12,19 +12,22 @@
 #define gc_Verifier_h
 
 #include "gc/Cell.h"
 
 namespace js {
 namespace gc {
 
 // Like gc::MarkColor but allows the possibility of the cell being
-// unmarked. Order is important here, with white being 'least marked'
-// and black being 'most marked'.
-enum class CellColor : uint8_t { White = 0, Gray = 1, Black = 2 };
+// unmarked.
+enum class CellColor : uint8_t {
+  White = 0,
+  Gray = uint8_t(MarkColor::Gray),
+  Black = uint8_t(MarkColor::Black)
+};
 
 static constexpr CellColor AllCellColors[] = {
   CellColor::White, CellColor::Gray, CellColor::Black
 };
 
 static constexpr CellColor MarkedCellColors[] = {
   CellColor::Gray, CellColor::Black
 };
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -202,38 +202,38 @@ void Zone::discardJitCode(FreeOp* fop,
   }
 
   if (isPreservingCode()) {
     return;
   }
 
   if (discardBaselineCode || releaseTypes) {
 #ifdef DEBUG
-    // Assert no TypeScripts are marked as active.
+    // Assert no JitScripts are marked as active.
     for (auto script = cellIter<JSScript>(); !script.done(); script.next()) {
-      if (TypeScript* types = script.unbarrieredGet()->types()) {
-        MOZ_ASSERT(!types->active());
+      if (JitScript* jitScript = script.unbarrieredGet()->jitScript()) {
+        MOZ_ASSERT(!jitScript->active());
       }
     }
 #endif
 
-    // Mark TypeScripts on the stack as active.
-    jit::MarkActiveTypeScripts(this);
+    // Mark JitScripts on the stack as active.
+    jit::MarkActiveJitScripts(this);
   }
 
   // Invalidate all Ion code in this zone.
   jit::InvalidateAll(fop, this);
 
   for (auto script = cellIterUnsafe<JSScript>(); !script.done();
        script.next()) {
     jit::FinishInvalidation(fop, script);
 
     // Discard baseline script if it's not marked as active.
     if (discardBaselineCode && script->hasBaselineScript()) {
-      if (script->types()->active()) {
+      if (script->jitScript()->active()) {
         // ICs will be purged so the script will need to warm back up before it
         // can be inlined during Ion compilation.
         script->baselineScript()->clearIonCompiledOrInlined();
       } else {
         jit::FinishDiscardBaselineScript(fop, script);
       }
     }
 
@@ -243,34 +243,32 @@ void Zone::discardJitCode(FreeOp* fop,
     script->resetWarmUpCounterForGC();
 
     // Clear the BaselineScript's control flow graph. The LifoAlloc is purged
     // below.
     if (script->hasBaselineScript()) {
       script->baselineScript()->setControlFlowGraph(nullptr);
     }
 
-    // Try to release the script's TypeScript. This should happen after
+    // Try to release the script's JitScript. This should happen after
     // releasing JIT code because we can't do this when the script still has
     // JIT code.
     if (releaseTypes) {
-      script->maybeReleaseTypes();
+      script->maybeReleaseJitScript();
     }
 
-    // The optimizedStubSpace will be purged below so make sure ICScript
-    // doesn't point into it. We do this after (potentially) releasing types
-    // because TypeScript contains the ICScript* and there's no need to
-    // purge stubs if we just destroyed the Typescript.
-    if (discardBaselineCode && script->hasICScript()) {
-      script->icScript()->purgeOptimizedStubs(script);
-    }
+    if (JitScript* jitScript = script->jitScript()) {
+      // If we did not release the JitScript, we need to purge optimized IC
+      // stubs because the optimizedStubSpace will be purged below.
+      if (discardBaselineCode) {
+        jitScript->purgeOptimizedStubs(script);
+      }
 
-    // Finally, reset the active flag.
-    if (TypeScript* types = script->types()) {
-      types->resetActive();
+      // Finally, reset the active flag.
+      jitScript->resetActive();
     }
   }
 
   /*
    * When scripts contains pointers to nursery things, the store buffer
    * can contain entries that point into the optimized stub space. Since
    * this method can be called outside the context of a GC, this situation
    * could result in us trying to mark invalid store buffer entries.
@@ -522,20 +520,21 @@ void MemoryTracker::adopt(MemoryTracker&
   other.map.clear();
 #endif
 }
 
 #ifdef DEBUG
 
 static const char* MemoryUseName(MemoryUse use) {
   switch (use) {
-#define DEFINE_CASE(Name) \
-    case MemoryUse::Name: return #Name;
-JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
-#undef DEFINE_CASE
+#  define DEFINE_CASE(Name) \
+    case MemoryUse::Name:   \
+      return #Name;
+    JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
+#  undef DEFINE_CASE
   }
 
   MOZ_CRASH("Unknown memory use");
 }
 
 MemoryTracker::MemoryTracker() : mutex(mutexid::MemoryTracker) {}
 
 MemoryTracker::~MemoryTracker() {
@@ -546,18 +545,17 @@ MemoryTracker::~MemoryTracker() {
 
   if (map.empty()) {
     MOZ_ASSERT(bytes() == 0);
     return;
   }
 
   fprintf(stderr, "Missing calls to JS::RemoveAssociatedMemory:\n");
   for (auto r = map.all(); !r.empty(); r.popFront()) {
-    fprintf(stderr, "  %p 0x%zx %s\n", r.front().key().cell,
-            r.front().value(),
+    fprintf(stderr, "  %p 0x%zx %s\n", r.front().key().cell, r.front().value(),
             MemoryUseName(r.front().key().use));
   }
 
   MOZ_CRASH();
 }
 
 void MemoryTracker::trackMemory(Cell* cell, size_t nbytes, MemoryUse use) {
   MOZ_ASSERT(cell->isTenured());
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1068,17 +1068,17 @@ static bool InitFromBailout(JSContext* c
     op = JSOp(*pc);
     if (skippedLoopEntry && script->trackRecordReplayProgress()) {
       mozilla::recordreplay::AdvanceExecutionProgressCounter();
     }
   }
 
   const uint32_t pcOff = script->pcToOffset(pc);
   BaselineScript* baselineScript = script->baselineScript();
-  ICScript* icScript = script->icScript();
+  JitScript* jitScript = script->jitScript();
 
 #ifdef DEBUG
   uint32_t expectedDepth;
   bool reachablePC;
   if (!ReconstructStackDepth(cx, script, resumeAfter ? GetNextPc(pc) : pc,
                              &expectedDepth, &reachablePC)) {
     return false;
   }
@@ -1131,34 +1131,34 @@ static bool InitFromBailout(JSContext* c
     // If the bailout was a resumeAfter, and the opcode is monitored,
     // then the bailed out state should be in a position to enter
     // into the ICTypeMonitor chain for the op.
     bool enterMonitorChain = false;
     if (resumeAfter && (CodeSpec[op].format & JOF_TYPESET)) {
       // Not every monitored op has a monitored fallback stub, e.g.
       // JSOP_NEWOBJECT, which always returns the same type for a
       // particular script/pc location.
-      ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
+      ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
       ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
       if (fallbackStub->isMonitoredFallback()) {
         enterMonitorChain = true;
       }
     }
 
     uint32_t numUses = js::StackUses(pc);
 
     if (resumeAfter && !enterMonitorChain) {
       pc = GetNextPc(pc);
     }
 
     builder.setResumePC(pc);
     builder.setResumeFramePtr(prevFramePtr);
 
     if (enterMonitorChain) {
-      ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
+      ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
       ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
       MOZ_ASSERT(fallbackStub->isMonitoredFallback());
       JitSpew(JitSpew_BaselineBailouts, "      [TYPE-MONITOR CHAIN]");
 
       ICTypeMonitor_Fallback* typeMonitorFallback =
           fallbackStub->toMonitoredFallbackStub()->getFallbackMonitorStub(
               cx, script);
       if (!typeMonitorFallback) {
@@ -1332,17 +1332,17 @@ static bool InitFromBailout(JSContext* c
       (uint32_t)builder.framePushed(), FrameType::BaselineJS,
       BaselineStubFrameLayout::Size());
   if (!builder.writeWord(baselineFrameDescr, "Descriptor")) {
     return false;
   }
 
   // Calculate and write out return address.
   // The icEntry in question MUST have an inlinable fallback stub.
-  ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
+  ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
   MOZ_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
 
   RetAddrEntry& retAddrEntry =
       baselineScript->retAddrEntryFromPCOffset(pcOff, RetAddrEntry::Kind::IC);
   if (!builder.writePtr(baselineScript->returnAddressForEntry(retAddrEntry),
                         "ReturnAddr")) {
     return false;
   }
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -157,18 +157,18 @@ MethodStatus BaselineCompiler::compile()
   JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%u:%u",
           script->filename(), script->lineno(), script->column());
 
   TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
   TraceLoggerEvent scriptEvent(TraceLogger_AnnotateScripts, script);
   AutoTraceLog logScript(logger, scriptEvent);
   AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
 
-  AutoKeepTypeScripts keepTypes(cx);
-  if (!script->ensureHasTypes(cx, keepTypes)) {
+  AutoKeepJitScripts keepJitScript(cx);
+  if (!script->ensureHasJitScript(cx, keepJitScript)) {
     return Method_Error;
   }
 
   // When code coverage is only enabled for optimizations, or when a Debugger
   // set the collectCoverageInfo flag, we have to create the ScriptCounts if
   // they do not exist.
   if (!script->hasScriptCounts() && cx->realm()->collectCoverage()) {
     if (!script->initScriptCounts(cx)) {
@@ -537,28 +537,28 @@ bool BaselineCodeGen<Handler>::emitOutOf
 
   masm.popValue(R0);
   masm.ret();
   return true;
 }
 
 template <>
 bool BaselineCompilerCodeGen::emitNextIC() {
-  // Emit a call to an IC stored in ICScript. Calls to this must match the
-  // ICEntry order in ICScript: first the non-op IC entries for |this| and
+  // Emit a call to an IC stored in JitScript. Calls to this must match the
+  // ICEntry order in JitScript: first the non-op IC entries for |this| and
   // formal arguments, then the for-op IC entries for JOF_IC ops.
 
   JSScript* script = handler.script();
   uint32_t pcOffset = script->pcToOffset(handler.pc());
 
   // We don't use every ICEntry and we can skip unreachable ops, so we have
   // to loop until we find an ICEntry for the current pc.
   const ICEntry* entry;
   do {
-    entry = &script->icScript()->icEntry(handler.icEntryIndex());
+    entry = &script->jitScript()->icEntry(handler.icEntryIndex());
     handler.moveToNextICEntry();
   } while (entry->pcOffset() < pcOffset);
 
   MOZ_RELEASE_ASSERT(entry->pcOffset() == pcOffset);
   MOZ_ASSERT_IF(!entry->isForPrologue(), BytecodeOpHasIC(JSOp(*handler.pc())));
 
   CodeOffset callOffset;
   EmitCallIC(masm, entry, &callOffset);
@@ -1106,20 +1106,19 @@ void BaselineInterpreterCodeGen::emitIni
   {
     // CalleeToken_Script.
     masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), scratch1);
   }
   masm.bind(&done);
   masm.storePtr(scratch1, frame.addressOfInterpreterScript());
 
   // Initialize interpreterICEntry.
-  masm.loadPtr(Address(scratch1, JSScript::offsetOfTypes()), scratch2);
-  masm.loadPtr(Address(scratch2, TypeScript::offsetOfICScript()), scratch2);
-  masm.computeEffectiveAddress(Address(scratch2, ICScript::offsetOfICEntries()),
-                               scratch2);
+  masm.loadPtr(Address(scratch1, JSScript::offsetOfJitScript()), scratch2);
+  masm.computeEffectiveAddress(
+      Address(scratch2, JitScript::offsetOfICEntries()), scratch2);
   masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
 
   // Initialize interpreterPC.
   masm.loadPtr(Address(scratch1, JSScript::offsetOfScriptData()), scratch1);
   masm.load32(Address(scratch1, SharedScriptData::offsetOfCodeOffset()),
               scratch2);
   masm.addPtr(scratch2, scratch1);
   masm.storePtr(scratch1, frame.addressOfInterpreterPC());
@@ -5892,27 +5891,28 @@ bool BaselineCodeGen<Handler>::emitGener
   Register callee = regs.takeAny();
   masm.unboxObject(
       Address(genObj, AbstractGeneratorObject::offsetOfCalleeSlot()), callee);
 
   // Load the return value.
   ValueOperand retVal = regs.takeAnyValue();
   masm.loadValue(frame.addressOfStackValue(-1), retVal);
 
-  // Branch to interpret if the script does not have a TypeScript or
+  // Branch to interpret if the script does not have a JitScript or
   // BaselineScript (depending on whether the Baseline Interpreter is enabled).
   // Note that we don't relazify generator scripts, so the function is
   // guaranteed to be non-lazy.
   Label interpret;
   Register scratch1 = regs.takeAny();
   masm.loadPtr(Address(callee, JSFunction::offsetOfScript()), scratch1);
   Address baselineAddr(scratch1, JSScript::offsetOfBaselineScript());
   if (JitOptions.baselineInterpreter) {
-    Address typesAddr(scratch1, JSScript::offsetOfTypes());
-    masm.branchPtr(Assembler::Equal, typesAddr, ImmPtr(nullptr), &interpret);
+    Address jitScriptAddr(scratch1, JSScript::offsetOfJitScript());
+    masm.branchPtr(Assembler::Equal, jitScriptAddr, ImmPtr(nullptr),
+                   &interpret);
   } else {
     masm.branchPtr(Assembler::BelowOrEqual, baselineAddr,
                    ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
   }
 
 #ifdef JS_TRACE_LOGGING
   if (JS::TraceLoggerSupported()) {
     masm.loadPtr(baselineAddr, scratch1);
@@ -6121,17 +6121,17 @@ bool BaselineCodeGen<Handler>::emitGener
 #endif
     masm.jump(code);
 
     // Pop arguments and frame pointer (pushed by prepareVMCall) from
     // framePushed.
     masm.implicitPop((fun.explicitStackSlots() + 1) * sizeof(void*));
   }
 
-  // Call into the VM to run in the C++ interpreter if there's no TypeScript or
+  // Call into the VM to run in the C++ interpreter if there's no JitScript or
   // BaselineScript.
   masm.bind(&interpret);
 
   prepareVMCall();
   if (resumeKind == GeneratorResumeKind::Next) {
     pushArg(ImmGCPtr(cx->names().next));
   } else if (resumeKind == GeneratorResumeKind::Throw) {
     pushArg(ImmGCPtr(cx->names().throw_));
@@ -6259,20 +6259,19 @@ bool BaselineInterpreterCodeGen::emit_JS
   // scratch1 := scratch1 * sizeof(ICEntry)
   static_assert(sizeof(ICEntry) == 8 || sizeof(ICEntry) == 16,
                 "shift below depends on ICEntry size");
   uint32_t shift = (sizeof(ICEntry) == 16) ? 4 : 3;
   masm.lshiftPtr(Imm32(shift), scratch1);
 
   // Compute ICEntry* and store to frame->interpreterICEntry.
   loadScript(scratch2);
-  masm.loadPtr(Address(scratch2, JSScript::offsetOfTypes()), scratch2);
-  masm.loadPtr(Address(scratch2, TypeScript::offsetOfICScript()), scratch2);
+  masm.loadPtr(Address(scratch2, JSScript::offsetOfJitScript()), scratch2);
   masm.computeEffectiveAddress(
-      BaseIndex(scratch2, scratch1, TimesOne, ICScript::offsetOfICEntries()),
+      BaseIndex(scratch2, scratch1, TimesOne, JitScript::offsetOfICEntries()),
       scratch2);
   masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
   return true;
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_CHECKCLASSHERITAGE() {
   frame.syncStack(0);
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -521,17 +521,17 @@ class BaselineCompilerHandler {
   CompilerFrameInfo frame_;
   TempAllocator& alloc_;
   BytecodeAnalysis analysis_;
   FixedList<Label> labels_;
   RetAddrEntryVector retAddrEntries_;
   JSScript* script_;
   jsbytecode* pc_;
 
-  // Index of the current ICEntry in the script's ICScript.
+  // Index of the current ICEntry in the script's JitScript.
   uint32_t icEntryIndex_;
 
   bool compileDebugInstrumentation_;
   bool ionCompileable_;
 
  public:
   using FrameInfoT = CompilerFrameInfo;
 
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -610,17 +610,17 @@ static bool RecompileBaselineScriptForDe
   if (oldBaselineScript->hasDebugInstrumentation() == observing) {
     return true;
   }
 
   JitSpew(JitSpew_BaselineDebugModeOSR, "Recompiling (%s:%u:%u) for %s",
           script->filename(), script->lineno(), script->column(),
           observing ? "DEBUGGING" : "NORMAL EXECUTION");
 
-  AutoKeepTypeScripts keepTypes(cx);
+  AutoKeepJitScripts keepJitScripts(cx);
   script->setBaselineScript(cx->runtime(), nullptr);
 
   MethodStatus status =
       BaselineCompile(cx, script, /* forceDebugMode = */ observing);
   if (status != Method_Compiled) {
     // We will only fail to recompile for debug mode due to OOM. Restore
     // the old baseline script in case something doesn't properly
     // propagate OOM.
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -105,19 +105,19 @@ bool BaselineFrame::initFunctionEnvironm
 }
 
 bool BaselineFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) {
   return js::PushVarEnvironmentObject(cx, scope, this);
 }
 
 void BaselineFrame::setInterpreterPC(jsbytecode* pc) {
   uint32_t pcOffset = script()->pcToOffset(pc);
-  ICScript* icScript = script()->icScript();
+  JitScript* jitScript = script()->jitScript();
   interpreterPC_ = pc;
-  interpreterICEntry_ = icScript->interpreterICEntryFromPCOffset(pcOffset);
+  interpreterICEntry_ = jitScript->interpreterICEntryFromPCOffset(pcOffset);
 }
 
 bool BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues) {
   mozilla::PodZero(this);
 
   envChain_ = fp->environmentChain();
 
   if (fp->hasInitialEnvironmentUnchecked()) {
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -151,55 +151,44 @@ class MOZ_RAII FallbackStubAllocator {
   template <typename T, typename... Args>
   T* newStub(BaselineICFallbackKind kind, Args&&... args) {
     TrampolinePtr addr = code_.addr(kind);
     return ICStub::NewFallback<T>(cx_, &stubSpace_, addr,
                                   std::forward<Args>(args)...);
   }
 };
 
-/* static */
-UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
+}  // namespace jit
+
+bool JitScript::initICEntries(JSContext* cx, JSScript* script) {
   MOZ_ASSERT(cx->realm()->jitRealm());
   MOZ_ASSERT(jit::IsBaselineEnabled(cx));
 
-  const uint32_t numICEntries = script->numICEntries();
-
-  // Allocate the ICScript.
-  UniquePtr<ICScript> icScript(
-      script->zone()->pod_malloc_with_extra<ICScript, ICEntry>(numICEntries));
-  if (!icScript) {
-    ReportOutOfMemory(cx);
-    return nullptr;
-  }
-  new (icScript.get()) ICScript(numICEntries);
-
-  // We need to call prepareForDestruction on ICScript before we |delete| it.
-  auto prepareForDestruction = mozilla::MakeScopeExit(
-      [&] { icScript->prepareForDestruction(cx->zone()); });
-
-  FallbackStubAllocator alloc(cx, icScript->fallbackStubSpace_);
+  MOZ_ASSERT(numICEntries() == script->numICEntries());
+
+  // TODO(bug 1551796): move JitScript into jit namespace so we don't need this.
+  using namespace js::jit;
+
+  FallbackStubAllocator alloc(cx, fallbackStubSpace_);
 
   // Index of the next ICEntry to initialize.
   uint32_t icEntryIndex = 0;
 
   using Kind = BaselineICFallbackKind;
 
-  ICScript* icScriptPtr = icScript.get();
-  auto addIC = [cx, icScriptPtr, &icEntryIndex, script](jsbytecode* pc,
-                                                        ICStub* stub) {
+  auto addIC = [cx, this, &icEntryIndex, script](jsbytecode* pc, ICStub* stub) {
     if (!stub) {
       MOZ_ASSERT(cx->isExceptionPending());
       mozilla::Unused << cx;  // Silence -Wunused-lambda-capture in opt builds.
       return false;
     }
 
     // Initialize the ICEntry.
     uint32_t offset = pc ? script->pcToOffset(pc) : ICEntry::ProloguePCOffset;
-    ICEntry& entryRef = icScriptPtr->icEntry(icEntryIndex);
+    ICEntry& entryRef = icEntry(icEntryIndex);
     icEntryIndex++;
     new (&entryRef) ICEntry(stub, offset);
 
     // Fix up pointers from fallback stubs to the ICEntry.
     if (stub->isFallback()) {
       stub->toFallbackStub()->fixupICEntry(&entryRef);
     } else {
       stub->toTypeMonitor_Fallback()->fixupICEntry(&entryRef);
@@ -210,24 +199,24 @@ UniquePtr<ICScript> ICScript::create(JSC
 
   // Add ICEntries and fallback stubs for this/argument type checks.
   // Note: we pass a nullptr pc to indicate this is a non-op IC.
   // See ICEntry::NonOpPCOffset.
   if (JSFunction* fun = script->functionNonDelazifying()) {
     ICStub* stub =
         alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr, 0);
     if (!addIC(nullptr, stub)) {
-      return nullptr;
+      return false;
     }
 
     for (size_t i = 0; i < fun->nargs(); i++) {
       ICStub* stub = alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor,
                                                            nullptr, i + 1);
       if (!addIC(nullptr, stub)) {
-        return nullptr;
+        return false;
       }
     }
   }
 
   jsbytecode const* pcEnd = script->codeEnd();
 
   // Add ICEntries and fallback stubs for JOF_IC bytecode ops.
   for (jsbytecode* pc = script->code(); pc < pcEnd; pc = GetNextPc(pc)) {
@@ -243,27 +232,27 @@ UniquePtr<ICScript> ICScript::create(JSC
     switch (op) {
       case JSOP_NOT:
       case JSOP_AND:
       case JSOP_OR:
       case JSOP_IFEQ:
       case JSOP_IFNE: {
         ICStub* stub = alloc.newStub<ICToBool_Fallback>(Kind::ToBool);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_BITNOT:
       case JSOP_NEG:
       case JSOP_INC:
       case JSOP_DEC: {
         ICStub* stub = alloc.newStub<ICUnaryArith_Fallback>(Kind::UnaryArith);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_BITOR:
       case JSOP_BITXOR:
       case JSOP_BITAND:
       case JSOP_LSH:
       case JSOP_RSH:
@@ -271,258 +260,258 @@ UniquePtr<ICScript> ICScript::create(JSC
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_MUL:
       case JSOP_DIV:
       case JSOP_MOD:
       case JSOP_POW: {
         ICStub* stub = alloc.newStub<ICBinaryArith_Fallback>(Kind::BinaryArith);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_EQ:
       case JSOP_NE:
       case JSOP_LT:
       case JSOP_LE:
       case JSOP_GT:
       case JSOP_GE:
       case JSOP_STRICTEQ:
       case JSOP_STRICTNE: {
         ICStub* stub = alloc.newStub<ICCompare_Fallback>(Kind::Compare);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_LOOPENTRY: {
         ICStub* stub =
             alloc.newStub<ICWarmUpCounter_Fallback>(Kind::WarmUpCounter);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_NEWARRAY: {
         ObjectGroup* group =
             ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
         if (!group) {
-          return nullptr;
+          return false;
         }
         ICStub* stub =
             alloc.newStub<ICNewArray_Fallback>(Kind::NewArray, group);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_NEWOBJECT:
       case JSOP_NEWINIT: {
         ICStub* stub = alloc.newStub<ICNewObject_Fallback>(Kind::NewObject);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_INITELEM:
       case JSOP_INITHIDDENELEM:
       case JSOP_INITELEM_ARRAY:
       case JSOP_INITELEM_INC:
       case JSOP_SETELEM:
       case JSOP_STRICTSETELEM: {
         ICStub* stub = alloc.newStub<ICSetElem_Fallback>(Kind::SetElem);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_INITPROP:
       case JSOP_INITLOCKEDPROP:
       case JSOP_INITHIDDENPROP:
       case JSOP_INITGLEXICAL:
       case JSOP_SETPROP:
       case JSOP_STRICTSETPROP:
       case JSOP_SETNAME:
       case JSOP_STRICTSETNAME:
       case JSOP_SETGNAME:
       case JSOP_STRICTSETGNAME: {
         ICStub* stub = alloc.newStub<ICSetProp_Fallback>(Kind::SetProp);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETPROP:
       case JSOP_CALLPROP:
       case JSOP_LENGTH:
       case JSOP_GETBOUNDNAME: {
         ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetProp);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETPROP_SUPER: {
         ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetPropSuper);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETELEM:
       case JSOP_CALLELEM: {
         ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElem);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETELEM_SUPER: {
         ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElemSuper);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_IN: {
         ICStub* stub = alloc.newStub<ICIn_Fallback>(Kind::In);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_HASOWN: {
         ICStub* stub = alloc.newStub<ICHasOwn_Fallback>(Kind::HasOwn);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETNAME:
       case JSOP_GETGNAME: {
         ICStub* stub = alloc.newStub<ICGetName_Fallback>(Kind::GetName);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_BINDNAME:
       case JSOP_BINDGNAME: {
         ICStub* stub = alloc.newStub<ICBindName_Fallback>(Kind::BindName);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETALIASEDVAR:
       case JSOP_GETIMPORT: {
         ICStub* stub =
             alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_GETINTRINSIC: {
         ICStub* stub =
             alloc.newStub<ICGetIntrinsic_Fallback>(Kind::GetIntrinsic);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_CALL:
       case JSOP_CALL_IGNORES_RV:
       case JSOP_CALLITER:
       case JSOP_FUNCALL:
       case JSOP_FUNAPPLY:
       case JSOP_EVAL:
       case JSOP_STRICTEVAL: {
         ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::Call);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_SUPERCALL:
       case JSOP_NEW: {
         ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::CallConstructing);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_SPREADCALL:
       case JSOP_SPREADEVAL:
       case JSOP_STRICTSPREADEVAL: {
         ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::SpreadCall);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_SPREADSUPERCALL:
       case JSOP_SPREADNEW: {
         ICStub* stub =
             alloc.newStub<ICCall_Fallback>(Kind::SpreadCallConstructing);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_INSTANCEOF: {
         ICStub* stub = alloc.newStub<ICInstanceOf_Fallback>(Kind::InstanceOf);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_TYPEOF:
       case JSOP_TYPEOFEXPR: {
         ICStub* stub = alloc.newStub<ICTypeOf_Fallback>(Kind::TypeOf);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_ITER: {
         ICStub* stub = alloc.newStub<ICGetIterator_Fallback>(Kind::GetIterator);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       case JSOP_REST: {
         ArrayObject* templateObject = ObjectGroup::newArrayObject(
             cx, nullptr, 0, TenuredObject,
             ObjectGroup::NewArrayKind::UnknownIndex);
         if (!templateObject) {
-          return nullptr;
+          return false;
         }
         ICStub* stub =
             alloc.newStub<ICRest_Fallback>(Kind::Rest, templateObject);
         if (!addIC(pc, stub)) {
-          return nullptr;
+          return false;
         }
         break;
       }
       default:
         MOZ_CRASH("JOF_IC op not handled");
     }
   }
 
   // Assert all ICEntries have been initialized.
-  MOZ_ASSERT(icEntryIndex == numICEntries);
-
-  prepareForDestruction.release();
-
-  return icScript;
+  MOZ_ASSERT(icEntryIndex == numICEntries());
+
+  return true;
 }
 
+namespace jit {
+
 ICStubConstIterator& ICStubConstIterator::operator++() {
   MOZ_ASSERT(currentStub_ != nullptr);
   currentStub_ = currentStub_->next();
   return *this;
 }
 
 ICStubIterator::ICStubIterator(ICFallbackStub* fallbackStub, bool end)
     : icEntry_(fallbackStub->icEntry()),
@@ -1093,17 +1082,17 @@ ICMonitoredStub::ICMonitoredStub(Kind ki
       firstMonitorStub_->toTypeMonitor_Fallback()->firstMonitorStub() ==
           firstMonitorStub_);
 }
 
 bool ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx,
                                                   JSScript* script) {
   MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
 
-  ICStubSpace* space = script->icScript()->fallbackStubSpace();
+  ICStubSpace* space = script->jitScript()->fallbackStubSpace();
   FallbackStubAllocator alloc(cx, *space);
   auto* stub = alloc.newStub<ICTypeMonitor_Fallback>(
       BaselineICFallbackKind::TypeMonitor, this);
   if (!stub) {
     return false;
   }
 
   fallbackMonitorStub_ = stub;
@@ -1122,19 +1111,19 @@ bool ICMonitoredFallbackStub::addMonitor
   return typeMonitorFallback->addMonitorStubForValue(cx, frame, types, val);
 }
 
 static MOZ_MUST_USE bool TypeMonitorResult(JSContext* cx,
                                            ICMonitoredFallbackStub* stub,
                                            BaselineFrame* frame,
                                            HandleScript script, jsbytecode* pc,
                                            HandleValue val) {
-  AutoSweepTypeScript sweep(script);
-  StackTypeSet* types = script->types()->bytecodeTypes(sweep, script, pc);
-  TypeScript::MonitorBytecodeType(cx, script, pc, types, val);
+  AutoSweepJitScript sweep(script);
+  StackTypeSet* types = script->jitScript()->bytecodeTypes(sweep, script, pc);
+  JitScript::MonitorBytecodeType(cx, script, pc, types, val);
 
   return stub->addMonitorStubForValue(cx, frame, types, val);
 }
 
 bool ICCacheIR_Updated::initUpdatingChain(JSContext* cx, ICStubSpace* space) {
   MOZ_ASSERT(firstUpdateStub_ == nullptr);
 
   FallbackStubAllocator alloc(cx, *space);
@@ -1147,17 +1136,17 @@ bool ICCacheIR_Updated::initUpdatingChai
   firstUpdateStub_ = stub;
   return true;
 }
 
 /* static */
 ICStubSpace* ICStubCompiler::StubSpaceForStub(bool makesGCCalls,
                                               JSScript* script) {
   if (makesGCCalls) {
-    return script->icScript()->fallbackStubSpace();
+    return script->jitScript()->fallbackStubSpace();
   }
   return script->zone()->jitZone()->optimizedStubSpace();
 }
 
 static void InitMacroAssemblerForICStub(StackMacroAssembler& masm) {
 #ifndef JS_USE_LINK_REGISTER
   // The first value contains the return addres,
   // which we pull into ICTailCallReg for tail calls.
@@ -1292,25 +1281,29 @@ void ICStubCompilerBase::pushStubPayload
 }
 
 void ICStubCompilerBase::PushStubPayload(MacroAssembler& masm,
                                          Register scratch) {
   pushStubPayload(masm, scratch);
   masm.adjustFrame(sizeof(intptr_t));
 }
 
-void ICScript::noteAccessedGetter(uint32_t pcOffset) {
-  ICEntry& entry = icEntryFromPCOffset(pcOffset);
-  ICFallbackStub* stub = entry.fallbackStub();
+}  // namespace jit
+
+void JitScript::noteAccessedGetter(uint32_t pcOffset) {
+  jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
+  jit::ICFallbackStub* stub = entry.fallbackStub();
 
   if (stub->isGetProp_Fallback()) {
     stub->toGetProp_Fallback()->noteAccessedGetter();
   }
 }
 
+namespace jit {
+
 // TypeMonitor_Fallback
 //
 
 bool ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx,
                                                     BaselineFrame* frame,
                                                     StackTypeSet* types,
                                                     HandleValue val) {
   MOZ_ASSERT(types);
@@ -1509,39 +1502,39 @@ bool DoTypeMonitorFallback(JSContext* cx
     // In derived class constructors (including nested arrows/eval), the
     // |this| argument or GETALIASEDVAR can return the magic TDZ value.
     MOZ_ASSERT(value.isMagic(JS_UNINITIALIZED_LEXICAL));
     MOZ_ASSERT(frame->isFunctionFrame() || frame->isEvalFrame());
     MOZ_ASSERT(stub->monitorsThis() || *GetNextPc(pc) == JSOP_CHECKTHIS ||
                *GetNextPc(pc) == JSOP_CHECKTHISREINIT ||
                *GetNextPc(pc) == JSOP_CHECKRETURN);
     if (stub->monitorsThis()) {
-      TypeScript::MonitorThisType(cx, script, TypeSet::UnknownType());
+      JitScript::MonitorThisType(cx, script, TypeSet::UnknownType());
     } else {
-      TypeScript::MonitorBytecodeType(cx, script, pc, TypeSet::UnknownType());
+      JitScript::MonitorBytecodeType(cx, script, pc, TypeSet::UnknownType());
     }
     return true;
   }
 
-  TypeScript* typeScript = script->types();
-  AutoSweepTypeScript sweep(script);
+  JitScript* jitScript = script->jitScript();
+  AutoSweepJitScript sweep(script);
 
   StackTypeSet* types;
   uint32_t argument;
   if (stub->monitorsArgument(&argument)) {
     MOZ_ASSERT(pc == script->code());
-    types = typeScript->argTypes(sweep, script, argument);
-    TypeScript::MonitorArgType(cx, script, argument, value);
+    types = jitScript->argTypes(sweep, script, argument);
+    JitScript::MonitorArgType(cx, script, argument, value);
   } else if (stub->monitorsThis()) {
     MOZ_ASSERT(pc == script->code());
-    types = typeScript->thisTypes(sweep, script);
-    TypeScript::MonitorThisType(cx, script, value);
+    types = jitScript->thisTypes(sweep, script);
+    JitScript::MonitorThisType(cx, script, value);
   } else {
-    types = typeScript->bytecodeTypes(sweep, script, pc);
-    TypeScript::MonitorBytecodeType(cx, script, pc, types, value);
+    types = jitScript->bytecodeTypes(sweep, script, pc);
+    JitScript::MonitorBytecodeType(cx, script, pc, types, value);
   }
 
   return stub->addMonitorStubForValue(cx, frame, types, value);
 }
 
 bool FallbackICCodeCompiler::emit_TypeMonitor() {
   MOZ_ASSERT(R0 == JSReturnOperand);
 
@@ -2488,25 +2481,29 @@ bool FallbackICCodeCompiler::emit_SetEle
   masm.push(ICStubReg);
   pushStubPayload(masm, R0.scratchReg());
 
   using Fn = bool (*)(JSContext*, BaselineFrame*, ICSetElem_Fallback*, Value*,
                       HandleValue, HandleValue, HandleValue);
   return tailCallVM<Fn, DoSetElemFallback>(masm);
 }
 
-void ICScript::noteHasDenseAdd(uint32_t pcOffset) {
-  ICEntry& entry = icEntryFromPCOffset(pcOffset);
-  ICFallbackStub* stub = entry.fallbackStub();
+}  // namespace jit
+
+void JitScript::noteHasDenseAdd(uint32_t pcOffset) {
+  jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
+  jit::ICFallbackStub* stub = entry.fallbackStub();
 
   if (stub->isSetElem_Fallback()) {
     stub->toSetElem_Fallback()->noteHasDenseAdd();
   }
 }
 
+namespace jit {
+
 template <typename T>
 void StoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
                        const ValueOperand& value, const T& dest,
                        Register scratch, Label* failure) {
   Label done;
 
   if (type == Scalar::Float32 || type == Scalar::Float64) {
     masm.ensureDouble(value, FloatReg0, failure);
@@ -2774,17 +2771,17 @@ bool DoGetIntrinsicFallback(JSContext* c
   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::MonitorBytecodeType(cx, script, pc, res);
+  JitScript::MonitorBytecodeType(cx, script, pc, res);
 
   TryAttachStub<GetIntrinsicIRGenerator>("GetIntrinsic", cx, frame, stub,
                                          BaselineCacheIRStubKind::Regular, res);
 
   return true;
 }
 
 bool FallbackICCodeCompiler::emit_GetIntrinsic() {
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -264,112 +264,16 @@ class ICEntry {
 
   inline ICStub** addressOfFirstStub() { return &firstStub_; }
 
   bool isForPrologue() const { return pcOffset_ == ProloguePCOffset; }
 
   void trace(JSTracer* trc);
 };
 
-// [SMDOC] ICScript
-//
-// ICScript contains IC data used by Baseline (Ion has its own IC chains, stored
-// in IonScript).
-//
-// For each IC we store an ICEntry, which points to the first ICStub in the
-// chain. Note that multiple stubs in the same zone can share Baseline IC code.
-// This works because the stub data is stored in the ICStub instead of baked in
-// in the stub code.
-//
-// Storing this separate from BaselineScript simplifies debug mode OSR because
-// the ICScript can be reused when we replace the BaselineScript. It also makes
-// it easier to experiment with interpreter ICs in the future because the
-// interpreter and Baseline JIT will be able to use exactly the same IC data.
-//
-// ICScript contains the following:
-//
-// * Fallback stub space: this stores all fallback stubs and the "can GC" stubs.
-//   These stubs are never purged before destroying the ICScript. (Other stubs
-//   are stored in the optimized stub space stored in JitZone and can be
-//   discarded more eagerly. See ICScript::purgeOptimizedStubs.)
-//
-// * List of IC entries, in the following order:
-//
-//   - Type monitor IC for |this|.
-//   - Type monitor IC for each formal argument.
-//   - IC for each JOF_IC bytecode op.
-//
-// ICScript is stored in TypeScript and allocated/destroyed at the same time.
-class ICScript {
-  // Allocated space for fallback stubs.
-  FallbackICStubSpace fallbackStubSpace_ = {};
-
-  uint32_t numICEntries_;
-
-  explicit ICScript(uint32_t numICEntries) : numICEntries_(numICEntries) {}
-
-  ICEntry* icEntryList() {
-    return (ICEntry*)(reinterpret_cast<uint8_t*>(this) + sizeof(ICScript));
-  }
-
- public:
-  static MOZ_MUST_USE js::UniquePtr<ICScript> create(JSContext* cx,
-                                                     JSScript* script);
-
-  ~ICScript() {
-    // The contents of the fallback stub space are removed and freed
-    // separately after the next minor GC. See prepareForDestruction.
-    MOZ_ASSERT(fallbackStubSpace_.isEmpty());
-  }
-  void prepareForDestruction(Zone* zone) {
-    // When the script contains pointers to nursery things, the store buffer can
-    // contain entries that point into the fallback stub space. Since we can
-    // destroy scripts outside the context of a GC, this situation could result
-    // in us trying to mark invalid store buffer entries.
-    //
-    // Defer freeing any allocated blocks until after the next minor GC.
-    fallbackStubSpace_.freeAllAfterMinorGC(zone);
-  }
-
-  FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; }
-
-  void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
-                              size_t* fallbackStubs) const {
-    *data += mallocSizeOf(this);
-
-    // |data| already includes the ICStubSpace itself, so use
-    // sizeOfExcludingThis.
-    *fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
-  }
-
-  size_t numICEntries() const { return numICEntries_; }
-
-  ICEntry& icEntry(size_t index) {
-    MOZ_ASSERT(index < numICEntries());
-    return icEntryList()[index];
-  }
-
-  void noteAccessedGetter(uint32_t pcOffset);
-  void noteHasDenseAdd(uint32_t pcOffset);
-
-  void trace(JSTracer* trc);
-  void purgeOptimizedStubs(JSScript* script);
-
-  ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset);
-
-  ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
-  ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
-                                    ICEntry* prevLookedUpEntry);
-
-  ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
-  ICEntry& icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry);
-
-  static constexpr size_t offsetOfICEntries() { return sizeof(ICScript); }
-};
-
 class ICMonitoredStub;
 class ICMonitoredFallbackStub;
 
 // Constant iterator that traverses arbitrary chains of ICStubs.
 // No requirements are made of the ICStub used to construct this
 // iterator, aside from that the stub be part of a nullptr-terminated
 // chain.
 // The iterator is considered to be at its end once it has been
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -122,49 +122,47 @@ static bool GetCacheIRReceiverForNativeS
                             CacheOp::StoreDynamicSlot)) {
     return false;
   }
 
   *receiver = ReceiverGuard(group, shape);
   return true;
 }
 
-ICScript* BaselineInspector::icScript() const { return script->icScript(); }
+JitScript* BaselineInspector::jitScript() const {
+  MOZ_ASSERT(script->hasJitScript());
+  return script->jitScript();
+}
 
 ICEntry& BaselineInspector::icEntryFromPC(jsbytecode* pc) {
   ICEntry* entry = maybeICEntryFromPC(pc);
   MOZ_ASSERT(entry);
   return *entry;
 }
 
 ICEntry* BaselineInspector::maybeICEntryFromPC(jsbytecode* pc) {
-  MOZ_ASSERT(hasICScript());
   MOZ_ASSERT(isValidPC(pc));
-  ICEntry* ent = icScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
-                                                      prevLookedUpEntry);
+  ICEntry* ent = jitScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
+                                                       prevLookedUpEntry);
   if (!ent) {
     return nullptr;
   }
 
   MOZ_ASSERT(!ent->isForPrologue());
   prevLookedUpEntry = ent;
   return ent;
 }
 
 bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
                                                ReceiverVector& receivers) {
   // Return a list of the receivers seen by the baseline IC for the current
   // op. Empty lists indicate no receivers are known, or there was an
   // uncacheable access.
   MOZ_ASSERT(receivers.empty());
 
-  if (!hasICScript()) {
-    return true;
-  }
-
   MOZ_ASSERT(isValidPC(pc));
   const ICEntry& entry = icEntryFromPC(pc);
 
   ICStub* stub = entry.firstStub();
   while (stub->next()) {
     ReceiverGuard receiver;
     if (stub->isCacheIR_Monitored()) {
       if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(),
@@ -198,20 +196,16 @@ bool BaselineInspector::maybeInfoForProp
   if (receivers.length() > 5) {
     receivers.clear();
   }
 
   return true;
 }
 
 ICStub* BaselineInspector::monomorphicStub(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   // IonBuilder::analyzeNewLoopTypes may call this (via expectedResultType
   // below) on code that's unreachable, according to BytecodeAnalysis. Use
   // maybeICEntryFromPC to handle this.
   const ICEntry* entry = maybeICEntryFromPC(pc);
   if (!entry) {
     return nullptr;
   }
 
@@ -222,20 +216,16 @@ ICStub* BaselineInspector::monomorphicSt
     return nullptr;
   }
 
   return stub;
 }
 
 bool BaselineInspector::dimorphicStub(jsbytecode* pc, ICStub** pfirst,
                                       ICStub** psecond) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
 
   ICStub* stub = entry.firstStub();
   ICStub* next = stub->next();
   ICStub* after = next ? next->next() : nullptr;
 
   if (!after || !after->isFallback()) {
     return false;
@@ -570,20 +560,16 @@ static bool TryToSpecializeBinaryArithOp
   }
 
   MOZ_ASSERT(sawInt32);
   *result = MIRType::Int32;
   return true;
 }
 
 MIRType BaselineInspector::expectedBinaryArithSpecialization(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return MIRType::None;
-  }
-
   MIRType result;
   ICStub* stubs[2];
 
   if (JSOp(*pc) == JSOP_POS) {
     // +x expanding to x*1, but no corresponding IC.
     return MIRType::None;
   }
 
@@ -605,61 +591,45 @@ MIRType BaselineInspector::expectedBinar
       return result;
     }
   }
 
   return MIRType::None;
 }
 
 bool BaselineInspector::hasSeenNonIntegerIndex(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* stub = entry.fallbackStub();
 
   MOZ_ASSERT(stub->isGetElem_Fallback());
 
   return stub->toGetElem_Fallback()->sawNonIntegerIndex();
 }
 
 bool BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* stub = entry.fallbackStub();
 
   if (stub->isGetElem_Fallback()) {
     return stub->toGetElem_Fallback()->hasNegativeIndex();
   }
   return false;
 }
 
 bool BaselineInspector::hasSeenAccessedGetter(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* stub = entry.fallbackStub();
 
   if (stub->isGetProp_Fallback()) {
     return stub->toGetProp_Fallback()->hasAccessedGetter();
   }
   return false;
 }
 
 bool BaselineInspector::hasSeenDoubleResult(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* stub = entry.fallbackStub();
 
   MOZ_ASSERT(stub->isUnaryArith_Fallback() || stub->isBinaryArith_Fallback());
 
   if (stub->isUnaryArith_Fallback()) {
     return stub->toUnaryArith_Fallback()->sawDoubleResult();
   }
@@ -715,20 +685,16 @@ JSObject* MaybeTemplateObject(ICStub* st
       argReader->metaKind<MetaTwoByteKind>() != kind ||
       !filter(*argReader, stubInfo)) {
     return nullptr;
   }
   return stubInfo->getStubField<JSObject*>(stub, argReader->stubOffset());
 }
 
 JSObject* BaselineInspector::getTemplateObject(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     switch (stub->kind()) {
       case ICStub::NewArray_Fallback:
         return stub->toNewArray_Fallback()->templateObject();
       case ICStub::NewObject_Fallback:
         return stub->toNewObject_Fallback()->templateObject();
       case ICStub::Rest_Fallback:
@@ -755,40 +721,32 @@ JSObject* BaselineInspector::getTemplate
         break;
     }
   }
 
   return nullptr;
 }
 
 ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     switch (stub->kind()) {
       case ICStub::NewArray_Fallback:
         return stub->toNewArray_Fallback()->templateGroup();
       default:
         break;
     }
   }
 
   return nullptr;
 }
 
 JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
   MOZ_ASSERT(*pc == JSOP_NEW);
 
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* stub = entry.firstStub();
 
   if (entry.fallbackStub()->state().hasFailures()) {
     return nullptr;
   }
 
   if (stub->next() != entry.fallbackStub()) {
@@ -810,20 +768,16 @@ JSFunction* BaselineInspector::getSingle
     // The callee is the first stub field in a ScriptedTemplateObject meta op.
     return stubInfo->getStubField<JSFunction*>(stub, argReader->stubOffset());
   }
   return nullptr;
 }
 
 JSObject* BaselineInspector::getTemplateObjectForNative(jsbytecode* pc,
                                                         Native native) {
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     if (stub->isCall_Native() &&
         stub->toCall_Native()->callee()->native() == native) {
       return stub->toCall_Native()->templateObject();
     }
     if (ICStub::IsCacheIRKind(stub->kind())) {
       auto filter = [stub, native](CacheIRReader& reader,
@@ -840,20 +794,16 @@ JSObject* BaselineInspector::getTemplate
     }
   }
 
   return nullptr;
 }
 
 JSObject* BaselineInspector::getTemplateObjectForClassHook(jsbytecode* pc,
                                                            const Class* clasp) {
-  if (!hasICScript()) {
-    return nullptr;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     if (stub->isCall_ClassHook() &&
         stub->toCall_ClassHook()->clasp() == clasp) {
       return stub->toCall_ClassHook()->templateObject();
     }
     if (ICStub::IsCacheIRKind(stub->kind())) {
       auto filter = [stub, clasp](CacheIRReader& args,
@@ -1199,20 +1149,16 @@ static bool AddCacheIRGetPropFunction(
   *isOwnProperty = false;
   return true;
 }
 
 bool BaselineInspector::commonGetPropFunction(
     jsbytecode* pc, jsid id, bool innerized, JSObject** holder,
     Shape** holderShape, JSFunction** commonGetter, Shape** globalShape,
     bool* isOwnProperty, ReceiverVector& receivers) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   MOZ_ASSERT(IsGetPropPC(pc) || IsGetElemPC(pc) || JSOp(*pc) == JSOP_GETGNAME);
   MOZ_ASSERT(receivers.empty());
 
   // Only GetElem operations need to guard against a specific property id.
   if (!IsGetElemPC(pc)) {
     id = JSID_EMPTY;
   }
 
@@ -1281,20 +1227,16 @@ static JSFunction* GetMegamorphicGetterS
 
   JSObject* obj =
       isGetter ? propShape->getterObject() : propShape->setterObject();
   return &obj->as<JSFunction>();
 }
 
 bool BaselineInspector::megamorphicGetterSetterFunction(
     jsbytecode* pc, jsid id, bool isGetter, JSFunction** getterOrSetter) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   MOZ_ASSERT(IsGetPropPC(pc) || IsGetElemPC(pc) || IsSetPropPC(pc) ||
              JSOp(*pc) == JSOP_GETGNAME || JSOp(*pc) == JSOP_INITGLEXICAL ||
              JSOp(*pc) == JSOP_INITPROP || JSOp(*pc) == JSOP_INITLOCKEDPROP ||
              JSOp(*pc) == JSOP_INITHIDDENPROP);
 
   // Only GetElem operations need to guard against a specific property id.
   if (!IsGetElemPC(pc)) {
     id = JSID_EMPTY;
@@ -1446,20 +1388,16 @@ static bool AddCacheIRSetPropFunction(
   return true;
 }
 
 bool BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder,
                                               Shape** holderShape,
                                               JSFunction** commonSetter,
                                               bool* isOwnProperty,
                                               ReceiverVector& receivers) {
-  if (!hasICScript()) {
-    return false;
-  }
-
   MOZ_ASSERT(IsSetPropPC(pc) || JSOp(*pc) == JSOP_INITGLEXICAL ||
              JSOp(*pc) == JSOP_INITPROP || JSOp(*pc) == JSOP_INITLOCKEDPROP ||
              JSOp(*pc) == JSOP_INITHIDDENPROP);
   MOZ_ASSERT(receivers.empty());
 
   *commonSetter = nullptr;
   const ICEntry& entry = icEntryFromPC(pc);
 
@@ -1546,20 +1484,16 @@ bool BaselineInspector::maybeInfoForProt
                                                   ReceiverVector& receivers,
                                                   JSObject** holder) {
   // This is like maybeInfoForPropertyOp, but for when the property exists on
   // the prototype.
 
   MOZ_ASSERT(receivers.empty());
   MOZ_ASSERT(!*holder);
 
-  if (!hasICScript()) {
-    return true;
-  }
-
   MOZ_ASSERT(isValidPC(pc));
   const ICEntry& entry = icEntryFromPC(pc);
 
   ICStub* stub = entry.firstStub();
   while (stub->next()) {
     ReceiverGuard receiver;
     if (stub->isCacheIR_Monitored()) {
       if (!GetCacheIRReceiverForProtoReadSlot(stub->toCacheIR_Monitored(),
@@ -1609,20 +1543,16 @@ static MIRType GetCacheIRExpectedInputTy
     return MIRTypeFromValueType(JSValueType(type));
   }
 
   MOZ_ASSERT_UNREACHABLE("Unexpected instruction");
   return MIRType::Value;
 }
 
 MIRType BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc) {
-  if (!hasICScript()) {
-    return MIRType::Value;
-  }
-
   const ICEntry& entry = icEntryFromPC(pc);
   MIRType type = MIRType::None;
 
   for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
     MIRType stubType = MIRType::None;
     if (stub->isCacheIR_Monitored()) {
       stubType = GetCacheIRExpectedInputType(stub->toCacheIR_Monitored());
       if (stubType == MIRType::Value) {
@@ -1648,19 +1578,16 @@ MIRType BaselineInspector::expectedPrope
 
   return (type == MIRType::None) ? MIRType::Value : type;
 }
 
 bool BaselineInspector::instanceOfData(jsbytecode* pc, Shape** shape,
                                        uint32_t* slot,
                                        JSObject** prototypeObject) {
   MOZ_ASSERT(*pc == JSOP_INSTANCEOF);
-  if (!hasICScript()) {
-    return false;
-  }
 
   const ICEntry& entry = icEntryFromPC(pc);
   ICStub* firstStub = entry.firstStub();
 
   // Ensure singleton instanceof stub
   if (!firstStub->next() || !firstStub->isCacheIR_Regular() ||
       !firstStub->next()->isInstanceOf_Fallback() ||
       firstStub->next()->toInstanceOf_Fallback()->state().hasFailures()) {
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -42,36 +42,31 @@ class BaselineInspector {
   ICEntry* prevLookedUpEntry;
 
  public:
   explicit BaselineInspector(JSScript* script)
       : script(script), prevLookedUpEntry(nullptr) {
     MOZ_ASSERT(script);
   }
 
-  bool hasICScript() const { return script->hasICScript(); }
-
-  ICScript* icScript() const;
+  JitScript* jitScript() const;
 
  private:
 #ifdef DEBUG
   bool isValidPC(jsbytecode* pc) { return script->containsPC(pc); }
 #endif
 
   ICEntry& icEntryFromPC(jsbytecode* pc);
   ICEntry* maybeICEntryFromPC(jsbytecode* pc);
 
   template <typename ICInspectorType>
   ICInspectorType makeICInspector(jsbytecode* pc,
                                   ICStub::Kind expectedFallbackKind) {
-    ICEntry* ent = nullptr;
-    if (hasICScript()) {
-      ent = &icEntryFromPC(pc);
-      MOZ_ASSERT(ent->fallbackStub()->kind() == expectedFallbackKind);
-    }
+    ICEntry* ent = &icEntryFromPC(pc);
+    MOZ_ASSERT(ent->fallbackStub()->kind() == expectedFallbackKind);
     return ICInspectorType(this, pc, ent);
   }
 
   ICStub* monomorphicStub(jsbytecode* pc);
   MOZ_MUST_USE bool dimorphicStub(jsbytecode* pc, ICStub** pfirst,
                                   ICStub** psecond);
 
  public:
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -315,17 +315,17 @@ static MethodStatus CanEnterBaselineJIT(
   return BaselineCompile(cx, script, forceDebugInstrumentation);
 }
 
 static MethodStatus CanEnterBaselineInterpreter(JSContext* cx,
                                                 HandleScript script) {
   MOZ_ASSERT(jit::IsBaselineEnabled(cx));
   MOZ_ASSERT(JitOptions.baselineInterpreter);
 
-  if (script->types()) {
+  if (script->jitScript()) {
     return Method_Compiled;
   }
 
   if (script->hasForceInterpreterOp()) {
     return Method_CantCompile;
   }
 
   // Check script warm-up counter.
@@ -333,18 +333,18 @@ static MethodStatus CanEnterBaselineInte
       JitOptions.baselineInterpreterWarmUpThreshold) {
     return Method_Skipped;
   }
 
   if (!cx->realm()->ensureJitRealmExists(cx)) {
     return Method_Error;
   }
 
-  AutoKeepTypeScripts keepTypes(cx);
-  if (!script->ensureHasTypes(cx, keepTypes)) {
+  AutoKeepJitScripts keepJitScript(cx);
+  if (!script->ensureHasJitScript(cx, keepJitScript)) {
     return Method_Error;
   }
 
   return Method_Compiled;
 }
 
 template <BaselineTier Tier>
 MethodStatus jit::CanEnterBaselineAtBranch(JSContext* cx,
@@ -512,17 +512,17 @@ BaselineScript* BaselineScript::New(
   return script;
 }
 
 void BaselineScript::trace(JSTracer* trc) {
   TraceEdge(trc, &method_, "baseline-method");
   TraceNullableEdge(trc, &templateEnv_, "baseline-template-environment");
 }
 
-void ICScript::trace(JSTracer* trc) {
+void JitScript::trace(JSTracer* trc) {
   // Mark all IC stub codes hanging off the IC stub entries.
   for (size_t i = 0; i < numICEntries(); i++) {
     ICEntry& ent = icEntry(i);
     ent.trace(trc);
   }
 }
 
 /* static */
@@ -615,22 +615,22 @@ CompactBufferReader BaselineScript::pcMa
       (indexEntry == numPCMappingIndexEntries() - 1)
           ? pcMappingData() + pcMappingSize_
           : pcMappingData() + pcMappingIndexEntry(indexEntry + 1).bufferOffset;
 
   return CompactBufferReader(dataStart, dataEnd);
 }
 
 struct ICEntries {
-  ICScript* const icScript_;
+  JitScript* const jitScript_;
 
-  explicit ICEntries(ICScript* icScript) : icScript_(icScript) {}
+  explicit ICEntries(JitScript* jitScript) : jitScript_(jitScript) {}
 
-  size_t numEntries() const { return icScript_->numICEntries(); }
-  ICEntry& operator[](size_t index) const { return icScript_->icEntry(index); }
+  size_t numEntries() const { return jitScript_->numICEntries(); }
+  ICEntry& operator[](size_t index) const { return jitScript_->icEntry(index); }
 };
 
 struct RetAddrEntries {
   BaselineScript* const baseline_;
 
   explicit RetAddrEntries(BaselineScript* baseline) : baseline_(baseline) {}
 
   size_t numEntries() const { return baseline_->numRetAddrEntries(); }
@@ -707,41 +707,41 @@ static bool ComputeBinarySearchMid(RetAd
       },
       loc);
 }
 
 uint8_t* BaselineScript::returnAddressForEntry(const RetAddrEntry& ent) {
   return method()->raw() + ent.returnOffset().offset();
 }
 
-ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
+ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
   // This method ignores prologue IC entries. There can be at most one
   // non-prologue IC per bytecode op.
 
   size_t mid;
   if (!ComputeBinarySearchMid(ICEntries(this), pcOffset, &mid)) {
     return nullptr;
   }
 
   MOZ_ASSERT(mid < numICEntries());
 
   ICEntry& entry = icEntry(mid);
   MOZ_ASSERT(!entry.isForPrologue());
   MOZ_ASSERT(entry.pcOffset() == pcOffset);
   return &entry;
 }
 
-ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset) {
+ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset) {
   ICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
   MOZ_RELEASE_ASSERT(entry);
   return *entry;
 }
 
-ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
-                                            ICEntry* prevLookedUpEntry) {
+ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
+                                             ICEntry* prevLookedUpEntry) {
   // Do a linear forward search from the last queried PC offset, or fallback to
   // a binary search if the last offset is too far away.
   if (prevLookedUpEntry && pcOffset >= prevLookedUpEntry->pcOffset() &&
       (pcOffset - prevLookedUpEntry->pcOffset()) <= 10) {
     ICEntry* firstEntry = &icEntry(0);
     ICEntry* lastEntry = &icEntry(numICEntries() - 1);
     ICEntry* curEntry = prevLookedUpEntry;
     while (curEntry >= firstEntry && curEntry <= lastEntry) {
@@ -751,24 +751,24 @@ ICEntry* ICScript::maybeICEntryFromPCOff
       curEntry++;
     }
     return nullptr;
   }
 
   return maybeICEntryFromPCOffset(pcOffset);
 }
 
-ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset,
-                                       ICEntry* prevLookedUpEntry) {
+ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset,
+                                        ICEntry* prevLookedUpEntry) {
   ICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
   MOZ_RELEASE_ASSERT(entry);
   return *entry;
 }
 
-ICEntry* ICScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
+ICEntry* JitScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
   // We have to return the entry to store in BaselineFrame::interpreterICEntry
   // when resuming in the Baseline Interpreter at pcOffset. The bytecode op at
   // pcOffset does not necessarily have an ICEntry, so we want to return the
   // first ICEntry for which the following is true:
   //
   //    !entry.isForPrologue() && entry.pcOffset() >= pcOffset
   //
   // Fortunately, ComputeBinarySearchMid returns exactly this entry.
@@ -1192,18 +1192,18 @@ void BaselineInterpreter::toggleCodeCove
   if (coverage::IsLCovEnabled()) {
     // Instrumentation is enabled no matter what.
     return;
   }
 
   toggleCodeCoverageInstrumentationUnchecked(enable);
 }
 
-void ICScript::purgeOptimizedStubs(JSScript* script) {
-  MOZ_ASSERT(script->icScript() == this);
+void JitScript::purgeOptimizedStubs(JSScript* script) {
+  MOZ_ASSERT(script->jitScript() == this);
 
   Zone* zone = script->zone();
   if (zone->isGCSweeping() && IsAboutToBeFinalizedDuringSweep(*script)) {
     // We're sweeping and the script is dead. Don't purge optimized stubs
     // because (1) accessing CacheIRStubInfo pointers in ICStubs is invalid
     // because we may have swept them already when we started (incremental)
     // sweeping and (2) it's unnecessary because this script will be finalized
     // soon anyway.
@@ -1289,28 +1289,28 @@ bool HasEnteredCounters(ICEntry& entry) 
       return true;
     }
     stub = stub->next();
   }
   return false;
 }
 
 void jit::JitSpewBaselineICStats(JSScript* script, const char* dumpReason) {
-  MOZ_ASSERT(script->hasICScript());
+  MOZ_ASSERT(script->hasJitScript());
   JSContext* cx = TlsContext.get();
   AutoStructuredSpewer spew(cx, SpewChannel::BaselineICStats, script);
   if (!spew) {
     return;
   }
 
-  ICScript* icScript = script->icScript();
+  JitScript* jitScript = script->jitScript();
   spew->property("reason", dumpReason);
   spew->beginListProperty("entries");
-  for (size_t i = 0; i < icScript->numICEntries(); i++) {
-    ICEntry& entry = icScript->icEntry(i);
+  for (size_t i = 0; i < jitScript->numICEntries(); i++) {
+    ICEntry& entry = jitScript->icEntry(i);
     if (!HasEnteredCounters(entry)) {
       continue;
     }
 
     uint32_t pcOffset = entry.pcOffset();
     jsbytecode* pc = entry.pc(script);
 
     unsigned column;
@@ -1338,32 +1338,26 @@ void jit::JitSpewBaselineICStats(JSScrip
     spew->endObject();
   }
   spew->endList();
 }
 #endif
 
 void jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script) {
   MOZ_ASSERT(script->hasBaselineScript());
-  MOZ_ASSERT(!script->types()->active());
+  MOZ_ASSERT(!script->jitScript()->active());
 
   BaselineScript* baseline = script->baselineScript();
   script->setBaselineScript(fop->runtime(), nullptr);
   BaselineScript::Destroy(fop, baseline);
 }
 
 void jit::AddSizeOfBaselineData(JSScript* script,
                                 mozilla::MallocSizeOf mallocSizeOf,
-                                size_t* data, size_t* fallbackStubs) {
-  if (script->hasICScript()) {
-    // ICScript is stored in TypeScript but we report its size here and not
-    // in TypeScript::sizeOfIncludingThis.
-    script->icScript()->addSizeOfIncludingThis(mallocSizeOf, data,
-                                               fallbackStubs);
-  }
+                                size_t* data) {
   if (script->hasBaselineScript()) {
     script->baselineScript()->addSizeOfIncludingThis(mallocSizeOf, data);
   }
 }
 
 void jit::ToggleBaselineProfiling(JSRuntime* runtime, bool enable) {
   JitRuntime* jrt = runtime->jitRuntime();
   if (!jrt) {
@@ -1411,57 +1405,57 @@ void jit::ToggleBaselineTraceLoggerEngin
         continue;
       }
       script->baselineScript()->toggleTraceLoggerEngine(enable);
     }
   }
 }
 #endif
 
-static void MarkActiveTypeScripts(JSContext* cx,
-                                  const JitActivationIterator& activation) {
+static void MarkActiveJitScripts(JSContext* cx,
+                                 const JitActivationIterator& activation) {
   for (OnlyJSJitFrameIter iter(activation); !iter.done(); ++iter) {
     const JSJitFrameIter& frame = iter.frame();
     switch (frame.type()) {
       case FrameType::BaselineJS:
-        frame.script()->types()->setActive();
+        frame.script()->jitScript()->setActive();
         break;
       case FrameType::Exit:
         if (frame.exitFrame()->is<LazyLinkExitFrameLayout>()) {
           LazyLinkExitFrameLayout* ll =
               frame.exitFrame()->as<LazyLinkExitFrameLayout>();
           JSScript* script =
               ScriptFromCalleeToken(ll->jsFrame()->calleeToken());
-          script->types()->setActive();
+          script->jitScript()->setActive();
         }
         break;
       case FrameType::Bailout:
       case FrameType::IonJS: {
-        // Keep the TypeScript and BaselineScript around, since bailouts from
+        // Keep the JitScript and BaselineScript around, since bailouts from
         // the ion jitcode need to re-enter into the Baseline code.
-        frame.script()->types()->setActive();
+        frame.script()->jitScript()->setActive();
         for (InlineFrameIterator inlineIter(cx, &frame); inlineIter.more();
              ++inlineIter) {
-          inlineIter.script()->types()->setActive();
+          inlineIter.script()->jitScript()->setActive();
         }
         break;
       }
       default:;
     }
   }
 }
 
-void jit::MarkActiveTypeScripts(Zone* zone) {
+void jit::MarkActiveJitScripts(Zone* zone) {
   if (zone->isAtomsZone()) {
     return;
   }
   JSContext* cx = TlsContext.get();
   for (JitActivationIterator iter(cx); !iter.done(); ++iter) {
     if (iter->compartment()->zone() == zone) {
-      MarkActiveTypeScripts(cx, iter);
+      MarkActiveJitScripts(cx, iter);
     }
   }
 }
 
 void BaselineInterpreter::init(JitCode* code, uint32_t interpretOpOffset,
                                uint32_t profilerEnterToggleOffset,
                                uint32_t profilerExitToggleOffset,
                                uint32_t debuggeeCheckOffset,
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -570,17 +570,17 @@ JitExecStatus EnterBaselineAtBranch(JSCo
 // |res| is set to the native code address in the BaselineScript to jump to, or
 // nullptr if we were unable to compile this script.
 bool BaselineCompileFromBaselineInterpreter(JSContext* cx, BaselineFrame* frame,
                                             uint8_t** res);
 
 void FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
 
 void AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf,
-                           size_t* data, size_t* fallbackStubs);
+                           size_t* data);
 
 void ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
 
 void ToggleBaselineTraceLoggerScripts(JSRuntime* runtime, bool enable);
 void ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable);
 
 struct BaselineBailoutInfo {
   // Pointer into the current C stack, where overwriting will start.
@@ -633,19 +633,19 @@ struct BaselineBailoutInfo {
   BailoutKind bailoutKind;
 };
 
 MOZ_MUST_USE bool BailoutIonToBaseline(
     JSContext* cx, JitActivation* activation, const JSJitFrameIter& iter,
     bool invalidate, BaselineBailoutInfo** bailoutInfo,
     const ExceptionBailoutInfo* exceptionInfo);
 
-// Mark TypeScripts on the stack as active, so that they are not discarded
+// Mark JitScripts on the stack as active, so that they are not discarded
 // during GC.
-void MarkActiveTypeScripts(Zone* zone);
+void MarkActiveJitScripts(Zone* zone);
 
 MethodStatus BaselineCompile(JSContext* cx, JSScript* script,
                              bool forceDebugInstrumentation = false);
 
 #ifdef JS_STRUCTURED_SPEW
 void JitSpewBaselineICStats(JSScript* script, const char* dumpReason);
 #endif
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -3141,18 +3141,18 @@ void jit::TraceJitScripts(JSTracer* trc,
   if (script->hasIonScript()) {
     jit::IonScript::Trace(trc, script->ionScript());
   }
 
   if (script->hasBaselineScript()) {
     jit::BaselineScript::Trace(trc, script->baselineScript());
   }
 
-  if (script->hasICScript()) {
-    script->icScript()->trace(trc);
+  if (script->hasJitScript()) {
+    script->jitScript()->trace(trc);
   }
 }
 
 bool jit::JitSupportsFloatingPoint() {
   return js::jit::MacroAssembler::SupportsFloatingPoint();
 }
 
 bool jit::JitSupportsUnalignedAccesses() {
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4549,17 +4549,17 @@ bool jit::AnalyzeNewScriptDefiniteProper
     if (status == Method_Error) {
       return false;
     }
     if (status != Method_Compiled) {
       return true;
     }
   }
 
-  TypeScript::MonitorThisType(cx, script, TypeSet::ObjectType(group));
+  JitScript::MonitorThisType(cx, script, TypeSet::ObjectType(group));
 
   MIRGraph graph(&temp);
   InlineScriptTree* inlineScriptTree =
       InlineScriptTree::New(&temp, nullptr, nullptr, script);
   if (!inlineScriptTree) {
     return false;
   }
 
@@ -4795,18 +4795,18 @@ bool jit::AnalyzeArgumentsUsage(JSContex
   if (!jit::CanLikelyAllocateMoreExecutableMemory()) {
     return true;
   }
 
   if (!cx->realm()->ensureJitRealmExists(cx)) {
     return false;
   }
 
-  AutoKeepTypeScripts keepTypes(cx);
-  if (!script->ensureHasTypes(cx, keepTypes)) {
+  AutoKeepJitScripts keepJitScript(cx);
+  if (!script->ensureHasJitScript(cx, keepJitScript)) {
     return false;
   }
 
   TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
   TraceLoggerEvent event(TraceLogger_AnnotateScripts, script);
   AutoTraceLog logScript(logger, event);
   AutoTraceLog logCompile(logger, TraceLogger_IonAnalysis);
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -750,35 +750,35 @@ AbortReasonOr<Ok> IonBuilder::analyzeNew
     }
   }
   return Ok();
 }
 
 AbortReasonOr<Ok> IonBuilder::init() {
   {
     LifoAlloc::AutoFallibleScope fallibleAllocator(alloc().lifoAlloc());
-    if (!TypeScript::FreezeTypeSets(constraints(), script(), &thisTypes,
-                                    &argTypes, &typeArray)) {
+    if (!JitScript::FreezeTypeSets(constraints(), script(), &thisTypes,
+                                   &argTypes, &typeArray)) {
       return abort(AbortReason::Alloc);
     }
   }
 
   if (!alloc().ensureBallast()) {
     return abort(AbortReason::Alloc);
   }
 
   if (inlineCallInfo_) {
     // If we're inlining, the actual this/argument types are not necessarily
     // a subset of the script's observed types. |argTypes| is never accessed
     // for inlined scripts, so we just null it.
     thisTypes = inlineCallInfo_->thisArg()->resultTypeSet();
     argTypes = nullptr;
   }
 
-  bytecodeTypeMap = script()->types()->bytecodeTypeMap();
+  bytecodeTypeMap = script()->jitScript()->bytecodeTypeMap();
 
   return Ok();
 }
 
 AbortReasonOr<Ok> IonBuilder::build() {
   // Spew IC info for inlined script, but only when actually compiling,
   // not when analyzing it.
 #ifdef JS_STRUCTURED_SPEW
@@ -4045,18 +4045,19 @@ IonBuilder::InliningResult IonBuilder::i
   callInfo.popCallStack(current);
   current->push(callInfo.fun());
 
   JSScript* calleeScript = target->nonLazyScript();
   BaselineInspector inspector(calleeScript);
 
   // Improve type information of |this| when not set.
   if (callInfo.constructing() && !callInfo.thisArg()->resultTypeSet()) {
-    AutoSweepTypeScript sweep(calleeScript);
-    StackTypeSet* types = calleeScript->types()->thisTypes(sweep, calleeScript);
+    AutoSweepJitScript sweep(calleeScript);
+    StackTypeSet* types =
+        calleeScript->jitScript()->thisTypes(sweep, calleeScript);
     if (!types->unknown()) {
       TemporaryTypeSet* clonedTypes = types->clone(alloc_->lifoAlloc());
       if (!clonedTypes) {
         return abort(AbortReason::Alloc);
       }
       MTypeBarrier* barrier =
           MTypeBarrier::New(alloc(), callInfo.thisArg(), clonedTypes);
       current->add(barrier);
@@ -5327,23 +5328,23 @@ MDefinition* IonBuilder::createThisScrip
   TypeSet::ObjectKey* templateObjectKey =
       TypeSet::ObjectKey::get(templateObject->group());
   if (templateObjectKey->hasFlags(constraints(),
                                   OBJECT_FLAG_NEW_SCRIPT_CLEARED)) {
     return nullptr;
   }
 
   JSScript* targetScript = target->nonLazyScript();
-  TypeScript* typeScript = targetScript->types();
-  if (!typeScript) {
+  JitScript* jitScript = targetScript->jitScript();
+  if (!jitScript) {
     return nullptr;
   }
 
-  AutoSweepTypeScript sweep(targetScript);
-  StackTypeSet* thisTypes = typeScript->thisTypes(sweep, targetScript);
+  AutoSweepJitScript sweep(targetScript);
+  StackTypeSet* thisTypes = jitScript->thisTypes(sweep, targetScript);
   if (!thisTypes->hasType(TypeSet::ObjectType(templateObject))) {
     return nullptr;
   }
 
   // Generate an inline path to create a new |this| object with
   // the given singleton prototype.
   MConstant* templateConst =
       MConstant::NewConstraintlessObject(alloc(), templateObject);
@@ -5397,23 +5398,23 @@ MDefinition* IonBuilder::createThisScrip
   TypeSet::ObjectKey* templateObjectKey =
       TypeSet::ObjectKey::get(templateObject->group());
   if (templateObjectKey->hasFlags(constraints(),
                                   OBJECT_FLAG_NEW_SCRIPT_CLEARED)) {
     return nullptr;
   }
 
   JSScript* targetScript = target->nonLazyScript();
-  TypeScript* typeScript = targetScript->types();
-  if (!typeScript) {
+  JitScript* jitScript = targetScript->jitScript();
+  if (!jitScript) {
     return nullptr;
   }
 
-  AutoSweepTypeScript sweep(targetScript);
-  StackTypeSet* thisTypes = typeScript->thisTypes(sweep, targetScript);
+  AutoSweepJitScript sweep(targetScript);
+  StackTypeSet* thisTypes = jitScript->thisTypes(sweep, targetScript);
   if (!thisTypes->hasType(TypeSet::ObjectType(templateObject))) {
     return nullptr;
   }
 
   // Shape guard.
   callee = addShapeGuard(callee, target->lastProperty(), Bailout_ShapeGuard);
 
   // Guard callee.prototype == proto.
@@ -6090,35 +6091,35 @@ bool IonBuilder::testNeedsArgumentCheck(
     return false;
   }
 
   if (!target->hasScript()) {
     return true;
   }
 
   JSScript* targetScript = target->nonLazyScript();
-  TypeScript* typeScript = targetScript->types();
-  if (!typeScript) {
+  JitScript* jitScript = targetScript->jitScript();
+  if (!jitScript) {
     return true;
   }
 
-  AutoSweepTypeScript sweep(targetScript);
+  AutoSweepJitScript sweep(targetScript);
   if (!ArgumentTypesMatch(callInfo.thisArg(),
-                          typeScript->thisTypes(sweep, targetScript))) {
+                          jitScript->thisTypes(sweep, targetScript))) {
     return true;
   }
   uint32_t expected_args = Min<uint32_t>(callInfo.argc(), target->nargs());
   for (size_t i = 0; i < expected_args; i++) {
     if (!ArgumentTypesMatch(callInfo.getArg(i),
-                            typeScript->argTypes(sweep, targetScript, i))) {
+                            jitScript->argTypes(sweep, targetScript, i))) {
       return true;
     }
   }
   for (size_t i = callInfo.argc(); i < target->nargs(); i++) {
-    StackTypeSet* types = typeScript->argTypes(sweep, targetScript, i);
+    StackTypeSet* types = jitScript->argTypes(sweep, targetScript, i);
     if (!types->mightBeMIRType(MIRType::Undefined)) {
       return true;
     }
   }
 
   return false;
 }
 
@@ -13580,18 +13581,18 @@ MInstruction* IonBuilder::addGuardReceiv
 
 MInstruction* IonBuilder::addSharedTypedArrayGuard(MDefinition* obj) {
   MGuardSharedTypedArray* guard = MGuardSharedTypedArray::New(alloc(), obj);
   current->add(guard);
   return guard;
 }
 
 TemporaryTypeSet* IonBuilder::bytecodeTypes(jsbytecode* pc) {
-  return TypeScript::BytecodeTypes(script(), pc, bytecodeTypeMap,
-                                   &typeArrayHint, typeArray);
+  return JitScript::BytecodeTypes(script(), pc, bytecodeTypeMap, &typeArrayHint,
+                                  typeArray);
 }
 
 TypedObjectPrediction IonBuilder::typedObjectPrediction(MDefinition* typedObj) {
   // Extract TypedObjectPrediction directly if we can
   if (typedObj->isNewDerivedTypedObject()) {
     return typedObj->toNewDerivedTypedObject()->prediction();
   }
 
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -223,17 +223,17 @@ bool IonGetPropertyIC::update(JSContext*
     if (!GetElementOperation(cx, JSOp(*ic->pc()), val, idVal, res)) {
       return false;
     }
   }
 
   if (!ic->idempotent()) {
     // Monitor changes to cache entry.
     if (!ic->monitoredResult()) {
-      TypeScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
+      JitScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
     }
   }
 
   return true;
 }
 
 /* static */
 bool IonGetPropSuperIC::update(JSContext* cx, HandleScript outerScript,
@@ -258,17 +258,17 @@ bool IonGetPropSuperIC::update(JSContext
     return false;
   }
 
   if (!GetProperty(cx, obj, receiver, id, res)) {
     return false;
   }
 
   // Monitor changes to cache entry.
-  TypeScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
+  JitScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
   return true;
 }
 
 /* static */
 bool IonSetPropertyIC::update(JSContext* cx, HandleScript outerScript,
                               IonSetPropertyIC* ic, HandleObject obj,
                               HandleValue idVal, HandleValue rhs) {
   using DeferType = SetPropIRGenerator::DeferType;
@@ -420,17 +420,17 @@ bool IonGetNameIC::update(JSContext* cx,
       return false;
     }
   } else {
     if (!FetchName<GetNameMode::Normal>(cx, obj, holder, name, prop, res)) {
       return false;
     }
   }
 
-  // No need to call TypeScript::Monitor, IonBuilder always inserts a type
+  // No need to call JitScript::Monitor, IonBuilder always inserts a type
   // barrier after GetName ICs.
 
   return true;
 }
 
 /* static */
 JSObject* IonBindNameIC::update(JSContext* cx, HandleScript outerScript,
                                 IonBindNameIC* ic, HandleObject envChain) {
--- a/js/src/jit/Jit.cpp
+++ b/js/src/jit/Jit.cpp
@@ -136,17 +136,17 @@ static EnterJitStatus JS_HAZ_JSNATIVE_CA
 EnterJitStatus js::jit::MaybeEnterJit(JSContext* cx, RunState& state) {
   JSScript* script = state.script();
 
   uint8_t* code = script->jitCodeRaw();
   do {
     // Make sure we can enter Baseline Interpreter or JIT code. Note that
     // the prologue has warm-up checks to tier up if needed.
     if (JitOptions.baselineInterpreter) {
-      if (script->types()) {
+      if (script->jitScript()) {
         break;
       }
     } else {
       if (script->hasBaselineScript()) {
         break;
       }
     }
 
copy from js/src/vm/TypeInference-inl.h
copy to js/src/jit/JitScript-inl.h
--- a/js/src/vm/TypeInference-inl.h
+++ b/js/src/jit/JitScript-inl.h
@@ -1,623 +1,51 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* Inline members for javascript type inference. */
+#ifndef jit_JitScript_inl_h
+#define jit_JitScript_inl_h
 
-#ifndef vm_TypeInference_inl_h
-#define vm_TypeInference_inl_h
-
-#include "vm/TypeInference.h"
+#include "jit/JitScript.h"
 
 #include "mozilla/BinarySearch.h"
-#include "mozilla/Casting.h"
-#include "mozilla/PodOperations.h"
 
-#include <utility>  // for ::std::swap
-
-#include "builtin/Symbol.h"
-#include "gc/GC.h"
-#include "jit/BaselineJIT.h"
-#include "js/HeapAPI.h"
-#include "vm/ArrayObject.h"
-#include "vm/BooleanObject.h"
-#include "vm/JSFunction.h"
-#include "vm/NativeObject.h"
-#include "vm/NumberObject.h"
-#include "vm/ObjectGroup.h"
-#include "vm/Shape.h"
-#include "vm/SharedArrayObject.h"
-#include "vm/StringObject.h"
-#include "vm/TypedArrayObject.h"
+#include "vm/JSScript.h"
+#include "vm/TypeInference.h"
 
 #include "vm/JSContext-inl.h"
-#include "vm/ObjectGroup-inl.h"
 
 namespace js {
 
-/////////////////////////////////////////////////////////////////////
-// RecompileInfo
-/////////////////////////////////////////////////////////////////////
-
-jit::IonScript* RecompileInfo::maybeIonScriptToInvalidate(
-    const TypeZone& zone) const {
-  MOZ_ASSERT(script_->zone() == zone.zone());
-
-  // Make sure this is not called under CodeGenerator::link (before the
-  // IonScript is created).
-  MOZ_ASSERT_IF(zone.currentCompilationId(),
-                zone.currentCompilationId().ref() != id_);
-
-  if (!script_->hasIonScript() ||
-      script_->ionScript()->compilationId() != id_) {
-    return nullptr;
-  }
-
-  return script_->ionScript();
-}
-
-inline bool RecompileInfo::shouldSweep(const TypeZone& zone) {
-  if (IsAboutToBeFinalizedUnbarriered(&script_)) {
-    return true;
-  }
-
-  MOZ_ASSERT(script_->zone() == zone.zone());
-
-  // Don't sweep if we're called under CodeGenerator::link, before the
-  // IonScript is created.
-  if (zone.currentCompilationId() && zone.currentCompilationId().ref() == id_) {
-    return false;
-  }
-
-  return maybeIonScriptToInvalidate(zone) == nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Types
-/////////////////////////////////////////////////////////////////////
-
-/* static */ inline TypeSet::ObjectKey* TypeSet::ObjectKey::get(JSObject* obj) {
-  MOZ_ASSERT(obj);
-  if (obj->isSingleton()) {
-    return (ObjectKey*)(uintptr_t(obj) | 1);
-  }
-  return (ObjectKey*)obj->group();
-}
-
-/* static */ inline TypeSet::ObjectKey* TypeSet::ObjectKey::get(
-    ObjectGroup* group) {
-  MOZ_ASSERT(group);
-  if (group->singleton()) {
-    return (ObjectKey*)(uintptr_t(group->singleton()) | 1);
-  }
-  return (ObjectKey*)group;
-}
-
-inline ObjectGroup* TypeSet::ObjectKey::groupNoBarrier() {
-  MOZ_ASSERT(isGroup());
-  return (ObjectGroup*)this;
-}
-
-inline JSObject* TypeSet::ObjectKey::singletonNoBarrier() {
-  MOZ_ASSERT(isSingleton());
-  return (JSObject*)(uintptr_t(this) & ~1);
-}
-
-inline ObjectGroup* TypeSet::ObjectKey::group() {
-  ObjectGroup* res = groupNoBarrier();
-  ObjectGroup::readBarrier(res);
-  return res;
-}
-
-inline JSObject* TypeSet::ObjectKey::singleton() {
-  JSObject* res = singletonNoBarrier();
-  JSObject::readBarrier(res);
-  return res;
-}
-
-inline JS::Compartment* TypeSet::ObjectKey::maybeCompartment() {
-  if (isSingleton()) {
-    return singletonNoBarrier()->compartment();
-  }
-
-  return groupNoBarrier()->compartment();
-}
-
-/* static */ inline TypeSet::Type TypeSet::ObjectType(const JSObject* obj) {
-  if (obj->isSingleton()) {
-    return Type(uintptr_t(obj) | 1);
-  }
-  return Type(uintptr_t(obj->group()));
-}
-
-/* static */ inline TypeSet::Type TypeSet::ObjectType(
-    const ObjectGroup* group) {
-  if (group->singleton()) {
-    return Type(uintptr_t(group->singleton()) | 1);
-  }
-  return Type(uintptr_t(group));
-}
-
-/* static */ inline TypeSet::Type TypeSet::ObjectType(const ObjectKey* obj) {
-  return Type(uintptr_t(obj));
-}
-
-inline TypeSet::Type TypeSet::GetValueType(const Value& val) {
-  if (val.isDouble()) {
-    return TypeSet::DoubleType();
-  }
-  if (val.isObject()) {
-    return TypeSet::ObjectType(&val.toObject());
-  }
-  return TypeSet::PrimitiveType(val.extractNonDoubleType());
-}
-
-inline bool TypeSet::IsUntrackedValue(const Value& val) {
-  return val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
-                           val.whyMagic() == JS_UNINITIALIZED_LEXICAL);
-}
-
-inline TypeSet::Type TypeSet::GetMaybeUntrackedValueType(const Value& val) {
-  return IsUntrackedValue(val) ? UnknownType() : GetValueType(val);
-}
-
-inline TypeFlags PrimitiveTypeFlag(ValueType type) {
-  switch (type) {
-    case ValueType::Undefined:
-      return TYPE_FLAG_UNDEFINED;
-    case ValueType::Null:
-      return TYPE_FLAG_NULL;
-    case ValueType::Boolean:
-      return TYPE_FLAG_BOOLEAN;
-    case ValueType::Int32:
-      return TYPE_FLAG_INT32;
-    case ValueType::Double:
-      return TYPE_FLAG_DOUBLE;
-    case ValueType::String:
-      return TYPE_FLAG_STRING;
-    case ValueType::Symbol:
-      return TYPE_FLAG_SYMBOL;
-    case ValueType::BigInt:
-      return TYPE_FLAG_BIGINT;
-    case ValueType::Magic:
-      return TYPE_FLAG_LAZYARGS;
-    case ValueType::PrivateGCThing:
-    case ValueType::Object:
-      break;
-  }
-
-  MOZ_CRASH("Bad ValueType");
-}
-
-inline JSValueType TypeFlagPrimitive(TypeFlags flags) {
-  switch (flags) {
-    case TYPE_FLAG_UNDEFINED:
-      return JSVAL_TYPE_UNDEFINED;
-    case TYPE_FLAG_NULL:
-      return JSVAL_TYPE_NULL;
-    case TYPE_FLAG_BOOLEAN:
-      return JSVAL_TYPE_BOOLEAN;
-    case TYPE_FLAG_INT32:
-      return JSVAL_TYPE_INT32;
-    case TYPE_FLAG_DOUBLE:
-      return JSVAL_TYPE_DOUBLE;
-    case TYPE_FLAG_STRING:
-      return JSVAL_TYPE_STRING;
-    case TYPE_FLAG_SYMBOL:
-      return JSVAL_TYPE_SYMBOL;
-    case TYPE_FLAG_BIGINT:
-      return JSVAL_TYPE_BIGINT;
-    case TYPE_FLAG_LAZYARGS:
-      return JSVAL_TYPE_MAGIC;
-    default:
-      MOZ_CRASH("Bad TypeFlags");
-  }
-}
-
-/*
- * Get the canonical representation of an id to use when doing inference.  This
- * maintains the constraint that if two different jsids map to the same property
- * in JS (e.g. 3 and "3"), they have the same type representation.
- */
-inline jsid IdToTypeId(jsid id) {
-  MOZ_ASSERT(!JSID_IS_EMPTY(id));
-
-  // All properties which can be stored in an object's dense elements must
-  // map to the aggregate property for index types.
-  return JSID_IS_INT(id) ? JSID_VOID : id;
-}
-
-const char* TypeIdStringImpl(jsid id);
-
-/* Convert an id for printing during debug. */
-static inline const char* TypeIdString(jsid id) {
-#ifdef DEBUG
-  return TypeIdStringImpl(id);
-#else
-  return "(missing)";
-#endif
-}
-
-// New script properties analyses overview.
-//
-// When constructing objects using 'new' on a script, we attempt to determine
-// the properties which that object will eventually have. This is done via two
-// analyses. One of these, the definite properties analysis, is static, and the
-// other, the acquired properties analysis, is dynamic. As objects are
-// constructed using 'new' on some script to create objects of group G, our
-// analysis strategy is as follows:
-//
-// - When the first objects are created, no analysis is immediately performed.
-//   Instead, all objects of group G are accumulated in an array.
-//
-// - After a certain number of such objects have been created, the definite
-//   properties analysis is performed. This analyzes the body of the
-//   constructor script and any other functions it calls to look for properties
-//   which will definitely be added by the constructor in a particular order,
-//   creating an object with shape S.
-//
-// - The properties in S are compared with the greatest common prefix P of the
-//   shapes of the objects that have been created. If P has more properties
-//   than S, the acquired properties analysis is performed.
-//
-// - The acquired properties analysis marks all properties in P as definite
-//   in G, and creates a new group IG for objects which are partially
-//   initialized. Objects of group IG are initially created with shape S, and if
-//   they are later given shape P, their group can be changed to G.
-//
-// For objects which are rarely created, the definite properties analysis can
-// be triggered after only one or a few objects have been allocated, when code
-// being Ion compiled might access them. In this case type information in the
-// constructor might not be good enough for the definite properties analysis to
-// compute useful information, but the acquired properties analysis will still
-// be able to identify definite properties in this case.
-//
-// This layered approach is designed to maximize performance on easily
-// analyzable code, while still allowing us to determine definite properties
-// robustly when code consistently adds the same properties to objects, but in
-// complex ways which can't be understood statically.
-class TypeNewScript {
- private:
-  // Scripted function which this information was computed for.
-  HeapPtr<JSFunction*> function_ = {};
-
-  // Any preliminary objects with the type. The analyses are not performed
-  // until this array is cleared.
-  PreliminaryObjectArray* preliminaryObjects = nullptr;
-
-  // After the new script properties analyses have been performed, a template
-  // object to use for newly constructed objects. The shape of this object
-  // reflects all definite properties the object will have, and the
-  // allocation kind to use.
-  HeapPtr<PlainObject*> templateObject_ = {};
-
-  // Order in which definite properties become initialized. We need this in
-  // case the definite properties are invalidated (such as by adding a setter
-  // to an object on the prototype chain) while an object is in the middle of
-  // being initialized, so we can walk the stack and fixup any objects which
-  // look for in-progress objects which were prematurely set with an incorrect
-  // shape. Property assignments in inner frames are preceded by a series of
-  // SETPROP_FRAME entries specifying the stack down to the frame containing
-  // the write.
-  TypeNewScriptInitializer* initializerList = nullptr;
-
-  // If there are additional properties found by the acquired properties
-  // analysis which were not found by the definite properties analysis, this
-  // shape contains all such additional properties (plus the definite
-  // properties). When an object of this group acquires this shape, it is
-  // fully initialized and its group can be changed to initializedGroup.
-  HeapPtr<Shape*> initializedShape_ = {};
-
-  // Group with definite properties set for all properties found by
-  // both the definite and acquired properties analyses.
-  HeapPtr<ObjectGroup*> initializedGroup_ = {};
-
- public:
-  TypeNewScript() = default;
-
-  ~TypeNewScript() {
-    js_delete(preliminaryObjects);
-    js_free(initializerList);
-  }
-
-  void clear() {
-    function_ = nullptr;
-    templateObject_ = nullptr;
-    initializedShape_ = nullptr;
-    initializedGroup_ = nullptr;
-  }
-
-  static void writeBarrierPre(TypeNewScript* newScript);
-
-  bool analyzed() const { return preliminaryObjects == nullptr; }
-
-  PlainObject* templateObject() const { return templateObject_; }
-
-  Shape* initializedShape() const { return initializedShape_; }
-
-  ObjectGroup* initializedGroup() const { return initializedGroup_; }
-
-  JSFunction* function() const { return function_; }
-
-  void trace(JSTracer* trc);
-  void sweep();
-
-  void registerNewObject(PlainObject* res);
-  bool maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
-                    bool force = false);
-
-  bool rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* group);
-
-  static bool make(JSContext* cx, ObjectGroup* group, JSFunction* fun);
-
-  size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
-
-  static size_t offsetOfPreliminaryObjects() {
-    return offsetof(TypeNewScript, preliminaryObjects);
-  }
-};
-
-inline bool ObjectGroup::hasUnanalyzedPreliminaryObjects() {
-  return (newScriptDontCheckGeneration() &&
-          !newScriptDontCheckGeneration()->analyzed()) ||
-         maybePreliminaryObjectsDontCheckGeneration();
-}
-
-/*
- * Structure for type inference entry point functions. All functions which can
- * change type information must use this, and functions which depend on
- * intermediate types (i.e. JITs) can use this to ensure that intermediate
- * information is not collected and does not change.
- *
- * Ensures that GC cannot occur. Does additional sanity checking that inference
- * is not reentrant and that recompilations occur properly.
- */
-struct MOZ_RAII AutoEnterAnalysis {
-  // Prevent GC activity in the middle of analysis.
-  gc::AutoSuppressGC suppressGC;
-
-  // Allow clearing inference info on OOM during incremental sweeping. This is
-  // constructed for the outermost AutoEnterAnalysis on the stack.
-  mozilla::Maybe<AutoClearTypeInferenceStateOnOOM> oom;
-
-  // Pending recompilations to perform before execution of JIT code can resume.
-  RecompileInfoVector pendingRecompiles;
-
-  // Prevent us from calling the objectMetadataCallback.
-  js::AutoSuppressAllocationMetadataBuilder suppressMetadata;
-
-  FreeOp* freeOp;
-  Zone* zone;
-
-  explicit AutoEnterAnalysis(JSContext* cx)
-      : suppressGC(cx), suppressMetadata(cx) {
-    init(cx->defaultFreeOp(), cx->zone());
-  }
-
-  AutoEnterAnalysis(FreeOp* fop, Zone* zone)
-      : suppressGC(TlsContext.get()), suppressMetadata(zone) {
-    init(fop, zone);
-  }
-
-  ~AutoEnterAnalysis() {
-    if (this != zone->types.activeAnalysis) {
-      return;
-    }
-
-    zone->types.activeAnalysis = nullptr;
-
-    if (!pendingRecompiles.empty()) {
-      zone->types.processPendingRecompiles(freeOp, pendingRecompiles);
-    }
-  }
-
- private:
-  void init(FreeOp* fop, Zone* zone) {
-#ifdef JS_CRASH_DIAGNOSTICS
-    MOZ_RELEASE_ASSERT(CurrentThreadCanAccessZone(zone));
-#endif
-    this->freeOp = fop;
-    this->zone = zone;
-
-    if (!zone->types.activeAnalysis) {
-      oom.emplace(zone);
-      zone->types.activeAnalysis = this;
-    }
-  }
-};
-
-/////////////////////////////////////////////////////////////////////
-// Interface functions
-/////////////////////////////////////////////////////////////////////
-
-void TypeMonitorCallSlow(JSContext* cx, JSObject* callee, const CallArgs& args,
-                         bool constructing);
-
-/*
- * Monitor a javascript call, either on entry to the interpreter or made
- * from within the interpreter.
- */
-inline void TypeMonitorCall(JSContext* cx, const js::CallArgs& args,
-                            bool constructing) {
-  if (args.callee().is<JSFunction>()) {
-    JSFunction* fun = &args.callee().as<JSFunction>();
-    if (fun->isInterpreted() && fun->nonLazyScript()->types()) {
-      TypeMonitorCallSlow(cx, &args.callee(), args, constructing);
-    }
-  }
-}
-
-MOZ_ALWAYS_INLINE bool TrackPropertyTypes(JSObject* obj, jsid id) {
-  if (obj->hasLazyGroup() ||
-      obj->group()->unknownPropertiesDontCheckGeneration()) {
-    return false;
-  }
-
-  if (obj->isSingleton() &&
-      !obj->group()->maybeGetPropertyDontCheckGeneration(id)) {
-    return false;
-  }
-
-  return true;
-}
-
-void EnsureTrackPropertyTypes(JSContext* cx, JSObject* obj, jsid id);
-
-inline bool CanHaveEmptyPropertyTypesForOwnProperty(JSObject* obj) {
-  // Per the comment on TypeSet::propertySet, property type sets for global
-  // objects may be empty for 'own' properties if the global property still
-  // has its initial undefined value.
-  return obj->is<GlobalObject>();
-}
-
-inline bool PropertyHasBeenMarkedNonConstant(JSObject* obj, jsid id) {
-  // Non-constant properties are only relevant for singleton objects.
-  if (!obj->isSingleton()) {
-    return true;
-  }
-
-  // EnsureTrackPropertyTypes must have been called on this object.
-  AutoSweepObjectGroup sweep(obj->group());
-  if (obj->group()->unknownProperties(sweep)) {
-    return true;
-  }
-  HeapTypeSet* types = obj->group()->maybeGetProperty(sweep, IdToTypeId(id));
-  return types->nonConstantProperty();
-}
-
-MOZ_ALWAYS_INLINE bool HasTrackedPropertyType(JSObject* obj, jsid id,
-                                              TypeSet::Type type) {
-  MOZ_ASSERT(id == IdToTypeId(id));
-  MOZ_ASSERT(TrackPropertyTypes(obj, id));
-
-  if (HeapTypeSet* types =
-          obj->group()->maybeGetPropertyDontCheckGeneration(id)) {
-    if (!types->hasType(type)) {
-      return false;
-    }
-    // Non-constant properties are only relevant for singleton objects.
-    if (obj->isSingleton() && !types->nonConstantProperty()) {
-      return false;
-    }
-    return true;
-  }
-
-  return false;
-}
-
-MOZ_ALWAYS_INLINE bool HasTypePropertyId(JSObject* obj, jsid id,
-                                         TypeSet::Type type) {
-  id = IdToTypeId(id);
-  if (!TrackPropertyTypes(obj, id)) {
-    return true;
-  }
-
-  return HasTrackedPropertyType(obj, id, type);
-}
-
-MOZ_ALWAYS_INLINE bool HasTypePropertyId(JSObject* obj, jsid id,
-                                         const Value& value) {
-  return HasTypePropertyId(obj, id, TypeSet::GetValueType(value));
-}
-
-void AddTypePropertyId(JSContext* cx, ObjectGroup* group, JSObject* obj,
-                       jsid id, TypeSet::Type type);
-void AddTypePropertyId(JSContext* cx, ObjectGroup* group, JSObject* obj,
-                       jsid id, const Value& value);
-
-/* Add a possible type for a property of obj. */
-MOZ_ALWAYS_INLINE void AddTypePropertyId(JSContext* cx, JSObject* obj, jsid id,
-                                         TypeSet::Type type) {
-  id = IdToTypeId(id);
-  if (TrackPropertyTypes(obj, id) && !HasTrackedPropertyType(obj, id, type)) {
-    AddTypePropertyId(cx, obj->group(), obj, id, type);
-  }
-}
-
-MOZ_ALWAYS_INLINE void AddTypePropertyId(JSContext* cx, JSObject* obj, jsid id,
-                                         const Value& value) {
-  return AddTypePropertyId(cx, obj, id, TypeSet::GetValueType(value));
-}
-
-inline void MarkObjectGroupFlags(JSContext* cx, JSObject* obj,
-                                 ObjectGroupFlags flags) {
-  if (obj->hasLazyGroup()) {
-    return;
-  }
-
-  AutoSweepObjectGroup sweep(obj->group());
-  if (!obj->group()->hasAllFlags(sweep, flags)) {
-    obj->group()->setFlags(sweep, cx, flags);
-  }
-}
-
-inline void MarkObjectGroupUnknownProperties(JSContext* cx, ObjectGroup* obj) {
-  AutoSweepObjectGroup sweep(obj);
-  if (!obj->unknownProperties(sweep)) {
-    obj->markUnknown(sweep, cx);
-  }
-}
-
-inline void MarkTypePropertyNonData(JSContext* cx, JSObject* obj, jsid id) {
-  id = IdToTypeId(id);
-  if (TrackPropertyTypes(obj, id)) {
-    obj->group()->markPropertyNonData(cx, obj, id);
-  }
-}
-
-inline void MarkTypePropertyNonWritable(JSContext* cx, JSObject* obj, jsid id) {
-  id = IdToTypeId(id);
-  if (TrackPropertyTypes(obj, id)) {
-    obj->group()->markPropertyNonWritable(cx, obj, id);
-  }
-}
-
-/* Mark a state change on a particular object. */
-inline void MarkObjectStateChange(JSContext* cx, JSObject* obj) {
-  if (obj->hasLazyGroup()) {
-    return;
-  }
-
-  AutoSweepObjectGroup sweep(obj->group());
-  if (!obj->group()->unknownProperties(sweep)) {
-    obj->group()->markStateChange(sweep, cx);
-  }
-}
-
-/////////////////////////////////////////////////////////////////////
-// Script interface functions
-/////////////////////////////////////////////////////////////////////
-
-inline StackTypeSet* TypeScript::thisTypes(const AutoSweepTypeScript& sweep,
-                                           JSScript* script) {
+inline StackTypeSet* JitScript::thisTypes(const AutoSweepJitScript& sweep,
+                                          JSScript* script) {
   return typeArray(sweep) + script->numBytecodeTypeSets();
 }
 
 /*
  * Note: for non-escaping arguments, argTypes reflect only the initial type of
  * the variable (e.g. passed values for argTypes, or undefined for localTypes)
  * and not types from subsequent assignments.
  */
 
-inline StackTypeSet* TypeScript::argTypes(const AutoSweepTypeScript& sweep,
-                                          JSScript* script, unsigned i) {
+inline StackTypeSet* JitScript::argTypes(const AutoSweepJitScript& sweep,
+                                         JSScript* script, unsigned i) {
   MOZ_ASSERT(i < script->functionNonDelazifying()->nargs());
   return typeArray(sweep) + script->numBytecodeTypeSets() + 1 /* this */ + i;
 }
 
 template <typename TYPESET>
-/* static */ inline TYPESET* TypeScript::BytecodeTypes(JSScript* script,
-                                                       jsbytecode* pc,
-                                                       uint32_t* bytecodeMap,
-                                                       uint32_t* hint,
-                                                       TYPESET* typeArray) {
+/* static */ inline TYPESET* JitScript::BytecodeTypes(JSScript* script,
+                                                      jsbytecode* pc,
+                                                      uint32_t* bytecodeMap,
+                                                      uint32_t* hint,
+                                                      TYPESET* typeArray) {
   MOZ_ASSERT(CodeSpec[*pc].format & JOF_TYPESET);
   uint32_t offset = script->pcToOffset(pc);
 
   // See if this pc is the next typeset opcode after the last one looked up.
   size_t numBytecodeTypeSets = script->numBytecodeTypeSets();
   if ((*hint + 1) < numBytecodeTypeSets && bytecodeMap[*hint + 1] == offset) {
     (*hint)++;
     return typeArray + *hint;
@@ -640,759 +68,39 @@ template <typename TYPESET>
     MOZ_ASSERT(numBytecodeTypeSets == JSScript::MaxBytecodeTypeSets);
     loc = numBytecodeTypeSets - 1;
   }
 
   *hint = mozilla::AssertedCast<uint32_t>(loc);
   return typeArray + *hint;
 }
 
-inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
-                                               JSScript* script,
-                                               jsbytecode* pc) {
+inline StackTypeSet* JitScript::bytecodeTypes(const AutoSweepJitScript& sweep,
+                                              JSScript* script,
+                                              jsbytecode* pc) {
   MOZ_ASSERT(CurrentThreadCanAccessZone(script->zone()));
   return BytecodeTypes(script, pc, bytecodeTypeMap(), bytecodeTypeMapHint(),
                        typeArray(sweep));
 }
 
-/* static */ inline void TypeScript::MonitorBytecodeType(
-    JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
-    const js::Value& rval) {
-  TypeSet::Type type = TypeSet::GetValueType(rval);
-  if (!types->hasType(type)) {
-    MonitorBytecodeTypeSlow(cx, script, pc, types, type);
-  }
-}
-
-/* static */ inline void TypeScript::MonitorAssign(JSContext* cx,
-                                                   HandleObject obj, jsid id) {
-  if (!obj->isSingleton()) {
-    /*
-     * Mark as unknown any object which has had dynamic assignments to
-     * non-integer properties at SETELEM opcodes. This avoids making large
-     * numbers of type properties for hashmap-style objects. We don't need
-     * to do this for objects with singleton type, because type properties
-     * are only constructed for them when analyzed scripts depend on those
-     * specific properties.
-     */
-    uint32_t i;
-    if (IdIsIndex(id, &i)) {
-      return;
-    }
-
-    // But if we don't have too many properties yet, don't do anything.  The
-    // idea here is that normal object initialization should not trigger
-    // deoptimization in most cases, while actual usage as a hashmap should.
-    ObjectGroup* group = obj->group();
-    if (group->basePropertyCountDontCheckGeneration() < 128) {
-      return;
-    }
-    MarkObjectGroupUnknownProperties(cx, group);
-  }
-}
-
-/* static */ inline void TypeScript::MonitorThisType(JSContext* cx,
-                                                     JSScript* script,
-                                                     TypeSet::Type type) {
-  cx->check(script, type);
-
-  TypeScript* typeScript = script->types();
-  if (!typeScript) {
-    return;
-  }
-
-  AutoSweepTypeScript sweep(script);
-  StackTypeSet* types = typeScript->thisTypes(sweep, script);
-
-  if (!types->hasType(type)) {
-    AutoEnterAnalysis enter(cx);
-
-    InferSpew(ISpewOps, "externalType: setThis %p: %s", script,
-              TypeSet::TypeString(type).get());
-    types->addType(sweep, cx, type);
-  }
-}
-
-/* static */ inline void TypeScript::MonitorThisType(JSContext* cx,
-                                                     JSScript* script,
-                                                     const js::Value& value) {
-  MonitorThisType(cx, script, TypeSet::GetValueType(value));
-}
-
-/* static */ inline void TypeScript::MonitorArgType(JSContext* cx,
-                                                    JSScript* script,
-                                                    unsigned arg,
-                                                    TypeSet::Type type) {
-  cx->check(script->compartment(), type);
-
-  TypeScript* typeScript = script->types();
-  if (!typeScript) {
-    return;
-  }
-
-  AutoSweepTypeScript sweep(script);
-  StackTypeSet* types = typeScript->argTypes(sweep, script, arg);
-
-  if (!types->hasType(type)) {
-    AutoEnterAnalysis enter(cx);
-
-    InferSpew(ISpewOps, "externalType: setArg %p %u: %s", script, arg,
-              TypeSet::TypeString(type).get());
-    types->addType(sweep, cx, type);
-  }
-}
-
-/* static */ inline void TypeScript::MonitorArgType(JSContext* cx,
-                                                    JSScript* script,
-                                                    unsigned arg,
-                                                    const js::Value& value) {
-  MonitorArgType(cx, script, arg, TypeSet::GetValueType(value));
-}
-
-inline AutoKeepTypeScripts::AutoKeepTypeScripts(JSContext* cx)
-    : zone_(cx->zone()->types), prev_(zone_.keepTypeScripts) {
-  zone_.keepTypeScripts = true;
-}
-
-inline AutoKeepTypeScripts::~AutoKeepTypeScripts() {
-  MOZ_ASSERT(zone_.keepTypeScripts);
-  zone_.keepTypeScripts = prev_;
+inline AutoKeepJitScripts::AutoKeepJitScripts(JSContext* cx)
+    : zone_(cx->zone()->types), prev_(zone_.keepJitScripts) {
+  zone_.keepJitScripts = true;
 }
 
-/////////////////////////////////////////////////////////////////////
-// TypeHashSet
-/////////////////////////////////////////////////////////////////////
-
-// Hashing code shared by objects in TypeSets and properties in ObjectGroups.
-struct TypeHashSet {
-  // The sets of objects in a type set grow monotonically, are usually empty,
-  // almost always small, and sometimes big. For empty or singleton sets, the
-  // the pointer refers directly to the value.  For sets fitting into
-  // SET_ARRAY_SIZE, an array of this length is used to store the elements.
-  // For larger sets, a hash table filled to 25%-50% of capacity is used,
-  // with collisions resolved by linear probing.
-  static const unsigned SET_ARRAY_SIZE = 8;
-  static const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
-
-  // Get the capacity of a set with the given element count.
-  static inline unsigned Capacity(unsigned count) {
-    MOZ_ASSERT(count >= 2);
-    MOZ_ASSERT(count < SET_CAPACITY_OVERFLOW);
-
-    if (count <= SET_ARRAY_SIZE) {
-      return SET_ARRAY_SIZE;
-    }
-
-    return 1u << (mozilla::FloorLog2(count) + 2);
-  }
-
-  // Compute the FNV hash for the low 32 bits of v.
-  template <class T, class KEY>
-  static inline uint32_t HashKey(T v) {
-    uint32_t nv = KEY::keyBits(v);
-
-    uint32_t hash = 84696351 ^ (nv & 0xff);
-    hash = (hash * 16777619) ^ ((nv >> 8) & 0xff);
-    hash = (hash * 16777619) ^ ((nv >> 16) & 0xff);
-    return (hash * 16777619) ^ ((nv >> 24) & 0xff);
-  }
-
-  // Insert space for an element into the specified set and grow its capacity
-  // if needed. returned value is an existing or new entry (nullptr if new).
-  template <class T, class U, class KEY>
-  static U** InsertTry(LifoAlloc& alloc, U**& values, unsigned& count, T key) {
-    unsigned capacity = Capacity(count);
-    unsigned insertpos = HashKey<T, KEY>(key) & (capacity - 1);
-
-    MOZ_RELEASE_ASSERT(uintptr_t(values[-1]) == capacity);
-
-    // Whether we are converting from a fixed array to hashtable.
-    bool converting = (count == SET_ARRAY_SIZE);
-
-    if (!converting) {
-      while (values[insertpos] != nullptr) {
-        if (KEY::getKey(values[insertpos]) == key) {
-          return &values[insertpos];
-        }
-        insertpos = (insertpos + 1) & (capacity - 1);
-      }
-    }
-
-    if (count >= SET_CAPACITY_OVERFLOW) {
-      return nullptr;
-    }
-
-    count++;
-    unsigned newCapacity = Capacity(count);
-
-    if (newCapacity == capacity) {
-      MOZ_ASSERT(!converting);
-      return &values[insertpos];
-    }
-
-    // Allocate an extra word right before the array storing the capacity,
-    // for sanity checks.
-    U** newValues = alloc.newArray<U*>(newCapacity + 1);
-    if (!newValues) {
-      return nullptr;
-    }
-    mozilla::PodZero(newValues, newCapacity + 1);
-
-    newValues[0] = (U*)uintptr_t(newCapacity);
-    newValues++;
-
-    for (unsigned i = 0; i < capacity; i++) {
-      if (values[i]) {
-        unsigned pos =
-            HashKey<T, KEY>(KEY::getKey(values[i])) & (newCapacity - 1);
-        while (newValues[pos] != nullptr) {
-          pos = (pos + 1) & (newCapacity - 1);
-        }
-        newValues[pos] = values[i];
-      }
-    }
-
-    values = newValues;
-
-    insertpos = HashKey<T, KEY>(key) & (newCapacity - 1);
-    while (values[insertpos] != nullptr) {
-      insertpos = (insertpos + 1) & (newCapacity - 1);
-    }
-    return &values[insertpos];
-  }
-
-  // Insert an element into the specified set if it is not already there,
-  // returning an entry which is nullptr if the element was not there.
-  template <class T, class U, class KEY>
-  static inline U** Insert(LifoAlloc& alloc, U**& values, unsigned& count,
-                           T key) {
-    if (count == 0) {
-      MOZ_ASSERT(values == nullptr);
-      count++;
-      return (U**)&values;
-    }
-
-    if (count == 1) {
-      U* oldData = (U*)values;
-      if (KEY::getKey(oldData) == key) {
-        return (U**)&values;
-      }
-
-      // Allocate an extra word right before the array storing the
-      // capacity, for sanity checks.
-      values = alloc.newArray<U*>(SET_ARRAY_SIZE + 1);
-      if (!values) {
-        values = (U**)oldData;
-        return nullptr;
-      }
-      mozilla::PodZero(values, SET_ARRAY_SIZE + 1);
-
-      values[0] = (U*)uintptr_t(SET_ARRAY_SIZE);
-      values++;
-
-      count++;
-
-      values[0] = oldData;
-      return &values[1];
-    }
-
-    if (count <= SET_ARRAY_SIZE) {
-      MOZ_RELEASE_ASSERT(uintptr_t(values[-1]) == SET_ARRAY_SIZE);
-
-      for (unsigned i = 0; i < count; i++) {
-        if (KEY::getKey(values[i]) == key) {
-          return &values[i];
-        }
-      }
-
-      if (count < SET_ARRAY_SIZE) {
-        count++;
-        return &values[count - 1];
-      }
-    }
-
-    return InsertTry<T, U, KEY>(alloc, values, count, key);
-  }
-
-  // Lookup an entry in a hash set, return nullptr if it does not exist.
-  template <class T, class U, class KEY>
-  static MOZ_ALWAYS_INLINE U* Lookup(U** values, unsigned count, T key) {
-    if (count == 0) {
-      return nullptr;
-    }
-
-    if (count == 1) {
-      return (KEY::getKey((U*)values) == key) ? (U*)values : nullptr;
-    }
-
-    if (count <= SET_ARRAY_SIZE) {
-      MOZ_RELEASE_ASSERT(uintptr_t(values[-1]) == SET_ARRAY_SIZE);
-      for (unsigned i = 0; i < count; i++) {
-        if (KEY::getKey(values[i]) == key) {
-          return values[i];
-        }
-      }
-      return nullptr;
-    }
-
-    unsigned capacity = Capacity(count);
-    unsigned pos = HashKey<T, KEY>(key) & (capacity - 1);
-
-    MOZ_RELEASE_ASSERT(uintptr_t(values[-1]) == capacity);
-
-    while (values[pos] != nullptr) {
-      if (KEY::getKey(values[pos]) == key) {
-        return values[pos];
-      }
-      pos = (pos + 1) & (capacity - 1);
-    }
-
-    return nullptr;
-  }
-
-  template <class T, class U, class Key, typename Fun>
-  static void MapEntries(U**& values, unsigned count, Fun f) {
-    // No element.
-    if (count == 0) {
-      MOZ_RELEASE_ASSERT(!values);
-      return;
-    }
-
-    // Simple functions to read and mutate the mark bit of pointers.
-    auto markBit = [](U* elem) -> bool {
-      return bool(reinterpret_cast<uintptr_t>(elem) & U::TypeHashSetMarkBit);
-    };
-    auto toggleMarkBit = [](U* elem) -> U* {
-      return reinterpret_cast<U*>(reinterpret_cast<uintptr_t>(elem) ^
-                                  U::TypeHashSetMarkBit);
-    };
-
-    // When we have a single element it is stored in-place of the function
-    // array pointer.
-    if (count == 1) {
-      U* elem = f(reinterpret_cast<U*>(values));
-      MOZ_ASSERT(!markBit(elem));
-      values = reinterpret_cast<U**>(elem);
-      return;
-    }
-
-    // When we have SET_ARRAY_SIZE or fewer elements, the values is an
-    // unorderred array.
-    if (count <= SET_ARRAY_SIZE) {
-      for (unsigned i = 0; i < count; i++) {
-        U* elem = f(values[i]);
-        MOZ_ASSERT(!markBit(elem));
-        values[i] = elem;
-      }
-      return;
-    }
-
-    // This code applies the function f and relocates the values based on
-    // the new pointers.
-    //
-    // To avoid allocations, we reuse the same structure but distinguish the
-    // elements to be rellocated from the rellocated elements with the
-    // mark bit.
-    unsigned capacity = Capacity(count);
-    MOZ_RELEASE_ASSERT(uintptr_t(values[-1]) == capacity);
-    unsigned found = 0;
-    for (unsigned i = 0; i < capacity; i++) {
-      if (!values[i]) {
-        continue;
-      }
-      MOZ_ASSERT(found <= count);
-      U* elem = f(values[i]);
-      values[i] = nullptr;
-      MOZ_ASSERT(!markBit(elem));
-      values[found++] = toggleMarkBit(elem);
-    }
-    MOZ_ASSERT(found == count);
-
-    // Follow the same rule as InsertTry, except that for each cell we identify
-    // empty cell content with either a nullptr or the value of the mark bit:
-    //
-    //   nullptr    empty cell.
-    //   0b...0.    inserted element.
-    //   0b...1.    empty cell - element to be inserted.
-    unsigned mask = capacity - 1;
-    for (unsigned i = 0; i < count; i++) {
-      U* elem = values[i];
-      if (!markBit(elem)) {
-        // If this is a newly inserted element, this implies that one of
-        // the previous objects was moved to this position.
-        continue;
-      }
-      values[i] = nullptr;
-      while (elem) {
-        MOZ_ASSERT(markBit(elem));
-        elem = toggleMarkBit(elem);
-        unsigned pos = HashKey<T, Key>(Key::getKey(elem)) & mask;
-        while (values[pos] != nullptr && !markBit(values[pos])) {
-          pos = (pos + 1) & mask;
-        }
-        // The replaced element is either a nullptr, which stops this
-        // loop, or an element to be inserted, which would be inserted
-        // by this loop.
-        std::swap(values[pos], elem);
-      }
-    }
-#ifdef DEBUG
-    unsigned inserted = 0;
-    for (unsigned i = 0; i < capacity; i++) {
-      if (!values[i]) {
-        continue;
-      }
-      inserted++;
-    }
-    MOZ_ASSERT(inserted == count);
-#endif
-  }
-};
-
-/////////////////////////////////////////////////////////////////////
-// TypeSet
-/////////////////////////////////////////////////////////////////////
-
-inline TypeSet::ObjectKey* TypeSet::Type::objectKey() const {
-  MOZ_ASSERT(isObject());
-  return (ObjectKey*)data;
-}
-
-inline JSObject* TypeSet::Type::singleton() const {
-  return objectKey()->singleton();
-}
-
-inline ObjectGroup* TypeSet::Type::group() const {
-  return objectKey()->group();
-}
-
-inline JSObject* TypeSet::Type::singletonNoBarrier() const {
-  return objectKey()->singletonNoBarrier();
+inline AutoKeepJitScripts::~AutoKeepJitScripts() {
+  MOZ_ASSERT(zone_.keepJitScripts);
+  zone_.keepJitScripts = prev_;
 }
 
-inline ObjectGroup* TypeSet::Type::groupNoBarrier() const {
-  return objectKey()->groupNoBarrier();
-}
-
-inline void TypeSet::Type::trace(JSTracer* trc) {
-  if (isSingletonUnchecked()) {
-    JSObject* obj = singletonNoBarrier();
-    TraceManuallyBarrieredEdge(trc, &obj, "TypeSet::Object");
-    *this = TypeSet::ObjectType(obj);
-  } else if (isGroupUnchecked()) {
-    ObjectGroup* group = groupNoBarrier();
-    TraceManuallyBarrieredEdge(trc, &group, "TypeSet::Group");
-    *this = TypeSet::ObjectType(group);
-  }
-}
-
-inline JS::Compartment* TypeSet::Type::maybeCompartment() {
-  if (isSingletonUnchecked()) {
-    return singletonNoBarrier()->compartment();
-  }
-
-  if (isGroupUnchecked()) {
-    return groupNoBarrier()->compartment();
-  }
-
-  return nullptr;
-}
-
-MOZ_ALWAYS_INLINE bool TypeSet::hasType(Type type) const {
-  if (unknown()) {
-    return true;
-  }
-
-  if (type.isUnknown()) {
-    return false;
-  } else if (type.isPrimitive()) {
-    return !!(flags & PrimitiveTypeFlag(type.primitive()));
-  } else if (type.isAnyObject()) {
-    return !!(flags & TYPE_FLAG_ANYOBJECT);
-  } else {
-    return !!(flags & TYPE_FLAG_ANYOBJECT) ||
-           TypeHashSet::Lookup<ObjectKey*, ObjectKey, ObjectKey>(
-               objectSet, baseObjectCount(), type.objectKey()) != nullptr;
-  }
-}
-
-inline void TypeSet::setBaseObjectCount(uint32_t count) {
-  MOZ_ASSERT(count <= TYPE_FLAG_DOMOBJECT_COUNT_LIMIT);
-  flags = (flags & ~TYPE_FLAG_OBJECT_COUNT_MASK) |
-          (count << TYPE_FLAG_OBJECT_COUNT_SHIFT);
-}
-
-inline void HeapTypeSet::newPropertyState(const AutoSweepObjectGroup& sweep,
-                                          JSContext* cx) {
-  checkMagic();
-
-  /* Propagate the change to all constraints. */
-  if (!cx->helperThread()) {
-    TypeConstraint* constraint = constraintList(sweep);
-    while (constraint) {
-      constraint->newPropertyState(cx, this);
-      constraint = constraint->next();
-    }
-  } else {
-    MOZ_ASSERT(!constraintList(sweep));
-  }
-}
-
-inline void HeapTypeSet::setNonDataProperty(const AutoSweepObjectGroup& sweep,
-                                            JSContext* cx) {
-  checkMagic();
-
-  if (flags & TYPE_FLAG_NON_DATA_PROPERTY) {
-    return;
-  }
-
-  flags |= TYPE_FLAG_NON_DATA_PROPERTY;
-  newPropertyState(sweep, cx);
-}
-
-inline void HeapTypeSet::setNonWritableProperty(
-    const AutoSweepObjectGroup& sweep, JSContext* cx) {
-  checkMagic();
-
-  if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY) {
-    return;
-  }
-
-  flags |= TYPE_FLAG_NON_WRITABLE_PROPERTY;
-  newPropertyState(sweep, cx);
-}
-
-inline void HeapTypeSet::setNonConstantProperty(
-    const AutoSweepObjectGroup& sweep, JSContext* cx) {
-  checkMagic();
-
-  if (flags & TYPE_FLAG_NON_CONSTANT_PROPERTY) {
-    return;
-  }
-
-  flags |= TYPE_FLAG_NON_CONSTANT_PROPERTY;
-  newPropertyState(sweep, cx);
-}
-
-inline unsigned TypeSet::getObjectCount() const {
-  MOZ_ASSERT(!unknownObject());
-  uint32_t count = baseObjectCount();
-  if (count > TypeHashSet::SET_ARRAY_SIZE) {
-    return TypeHashSet::Capacity(count);
-  }
-  return count;
-}
-
-inline TypeSet::ObjectKey* TypeSet::getObject(unsigned i) const {
-  MOZ_ASSERT(i < getObjectCount());
-  if (baseObjectCount() == 1) {
-    MOZ_ASSERT(i == 0);
-    return (ObjectKey*)objectSet;
-  }
-  return objectSet[i];
-}
-
-inline JSObject* TypeSet::getSingleton(unsigned i) const {
-  ObjectKey* key = getObject(i);
-  return (key && key->isSingleton()) ? key->singleton() : nullptr;
-}
-
-inline ObjectGroup* TypeSet::getGroup(unsigned i) const {
-  ObjectKey* key = getObject(i);
-  return (key && key->isGroup()) ? key->group() : nullptr;
-}
-
-inline JSObject* TypeSet::getSingletonNoBarrier(unsigned i) const {
-  ObjectKey* key = getObject(i);
-  return (key && key->isSingleton()) ? key->singletonNoBarrier() : nullptr;
-}
-
-inline ObjectGroup* TypeSet::getGroupNoBarrier(unsigned i) const {
-  ObjectKey* key = getObject(i);
-  return (key && key->isGroup()) ? key->groupNoBarrier() : nullptr;
-}
-
-inline bool TypeSet::hasGroup(unsigned i) const { return getGroupNoBarrier(i); }
-
-inline bool TypeSet::hasSingleton(unsigned i) const {
-  return getSingletonNoBarrier(i);
-}
-
-inline const Class* TypeSet::getObjectClass(unsigned i) const {
-  if (JSObject* object = getSingleton(i)) {
-    return object->getClass();
-  }
-  if (ObjectGroup* group = getGroup(i)) {
-    return group->clasp();
-  }
-  return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////
-// ObjectGroup
-/////////////////////////////////////////////////////////////////////
-
-inline uint32_t ObjectGroup::basePropertyCountDontCheckGeneration() {
-  uint32_t flags = flagsDontCheckGeneration();
-  return (flags & OBJECT_FLAG_PROPERTY_COUNT_MASK) >>
-         OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
-}
-
-inline uint32_t ObjectGroup::basePropertyCount(
-    const AutoSweepObjectGroup& sweep) {
-  MOZ_ASSERT(sweep.group() == this);
-  return basePropertyCountDontCheckGeneration();
-}
-
-inline void ObjectGroup::setBasePropertyCount(const AutoSweepObjectGroup& sweep,
-                                              uint32_t count) {
-  // Note: Callers must ensure they are performing threadsafe operations.
-  MOZ_ASSERT(count <= OBJECT_FLAG_PROPERTY_COUNT_LIMIT);
-  flags_ = (flags(sweep) & ~OBJECT_FLAG_PROPERTY_COUNT_MASK) |
-           (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
-}
-
-inline HeapTypeSet* ObjectGroup::getProperty(const AutoSweepObjectGroup& sweep,
-                                             JSContext* cx, JSObject* obj,
-                                             jsid id) {
-  MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) ||
-             JSID_IS_SYMBOL(id));
-  MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
-  MOZ_ASSERT(!unknownProperties(sweep));
-  MOZ_ASSERT_IF(obj, obj->group() == this);
-  MOZ_ASSERT_IF(singleton(), obj);
-  MOZ_ASSERT(cx->compartment() == compartment());
-
-  if (HeapTypeSet* types = maybeGetProperty(sweep, id)) {
-    return types;
-  }
-
-  Property* base = cx->typeLifoAlloc().new_<Property>(id);
-  if (!base) {
-    markUnknown(sweep, cx);
-    return nullptr;
-  }
-
-  uint32_t propertyCount = basePropertyCount(sweep);
-  Property** pprop = TypeHashSet::Insert<jsid, Property, Property>(
-      cx->typeLifoAlloc(), propertySet, propertyCount, id);
-  if (!pprop) {
-    markUnknown(sweep, cx);
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!*pprop);
-
-  setBasePropertyCount(sweep, propertyCount);
-  *pprop = base;
-
-  updateNewPropertyTypes(sweep, cx, obj, id, &base->types);
-
-  if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
-    // We hit the maximum number of properties the object can have, mark
-    // the object unknown so that new properties will not be added in the
-    // future.
-    markUnknown(sweep, cx);
-  }
-
-  base->types.checkMagic();
-  return &base->types;
-}
-
-MOZ_ALWAYS_INLINE HeapTypeSet* ObjectGroup::maybeGetPropertyDontCheckGeneration(
-    jsid id) {
-  MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) ||
-             JSID_IS_SYMBOL(id));
-  MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
-  MOZ_ASSERT(!unknownPropertiesDontCheckGeneration());
-
-  Property* prop = TypeHashSet::Lookup<jsid, Property, Property>(
-      propertySet, basePropertyCountDontCheckGeneration(), id);
-
-  if (!prop) {
-    return nullptr;
-  }
-
-  prop->types.checkMagic();
-  return &prop->types;
-}
-
-MOZ_ALWAYS_INLINE HeapTypeSet* ObjectGroup::maybeGetProperty(
-    const AutoSweepObjectGroup& sweep, jsid id) {
-  MOZ_ASSERT(sweep.group() == this);
-  return maybeGetPropertyDontCheckGeneration(id);
-}
-
-inline unsigned ObjectGroup::getPropertyCount(
-    const AutoSweepObjectGroup& sweep) {
-  uint32_t count = basePropertyCount(sweep);
-  if (count > TypeHashSet::SET_ARRAY_SIZE) {
-    return TypeHashSet::Capacity(count);
-  }
-  return count;
-}
-
-inline ObjectGroup::Property* ObjectGroup::getProperty(
-    const AutoSweepObjectGroup& sweep, unsigned i) {
-  MOZ_ASSERT(i < getPropertyCount(sweep));
-  Property* result;
-  if (basePropertyCount(sweep) == 1) {
-    MOZ_ASSERT(i == 0);
-    result = (Property*)propertySet;
-  } else {
-    result = propertySet[i];
-  }
-  if (result) {
-    result->types.checkMagic();
-  }
-  return result;
-}
-
-inline AutoSweepObjectGroup::AutoSweepObjectGroup(ObjectGroup* group)
-#ifdef DEBUG
-    : group_(group)
-#endif
-{
-  if (group->needsSweep()) {
-    group->sweep(*this);
-  }
-}
-
-#ifdef DEBUG
-inline AutoSweepObjectGroup::~AutoSweepObjectGroup() {
-  // This should still hold.
-  MOZ_ASSERT(!group_->needsSweep());
-}
-#endif
-
-inline AutoSweepTypeScript::AutoSweepTypeScript(JSScript* script)
-#ifdef DEBUG
-    : zone_(script->zone()),
-      typeScript_(script->types())
-#endif
-{
-  if (TypeScript* types = script->types()) {
-    Zone* zone = script->zone();
-    if (types->typesNeedsSweep(zone)) {
-      types->sweepTypes(*this, zone);
-    }
-  }
-}
-
-#ifdef DEBUG
-inline AutoSweepTypeScript::~AutoSweepTypeScript() {
-  // This should still hold.
-  MOZ_ASSERT_IF(typeScript_, !typeScript_->typesNeedsSweep(zone_));
-}
-#endif
-
-inline bool TypeScript::typesNeedsSweep(Zone* zone) const {
+inline bool JitScript::typesNeedsSweep(Zone* zone) const {
   MOZ_ASSERT(!js::TlsContext.get()->inUnsafeCallWithABI);
   return typesGeneration() != zone->types.generation;
 }
 
 }  // namespace js
 
-inline bool JSScript::ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&) {
-  return types() || makeTypes(cx);
+inline bool JSScript::ensureHasJitScript(JSContext* cx,
+                                         js::AutoKeepJitScripts&) {
+  return jitScript() || createJitScript(cx);
 }
 
-#endif /* vm_TypeInference_inl_h */
+#endif /* jit_JitScript_inl_h */
copy from js/src/vm/TypeInference.cpp
copy to js/src/jit/JitScript.cpp
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/jit/JitScript.cpp
@@ -1,4652 +1,191 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "vm/TypeInference-inl.h"
+#include "jit/JitScript-inl.h"
 
-#include "mozilla/DebugOnly.h"
 #include "mozilla/IntegerPrintfMacros.h"
-#include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
-#include "mozilla/PodOperations.h"
 #include "mozilla/ScopeExit.h"
-#include "mozilla/Sprintf.h"
 
-#include <new>
-
-#include "jsapi.h"
-#include "builtin/String.h"
-
-#include "gc/HashUtil.h"
 #include "jit/BaselineIC.h"
-#include "jit/BaselineJIT.h"
-#include "jit/CompileInfo.h"
-#include "jit/Ion.h"
-#include "jit/IonAnalysis.h"
-#include "jit/JitRealm.h"
-#include "jit/OptimizationTracking.h"
-#include "js/MemoryMetrics.h"
-#include "js/UniquePtr.h"
-#include "vm/HelperThreads.h"
-#include "vm/JSContext.h"
-#include "vm/JSObject.h"
 #include "vm/JSScript.h"
-#include "vm/Opcodes.h"
-#include "vm/Printer.h"
-#include "vm/Shape.h"
-#include "vm/Time.h"
+#include "vm/TypeInference.h"
 
-#include "gc/Marking-inl.h"
-#include "gc/PrivateIterators-inl.h"
-#include "vm/JSAtom-inl.h"
 #include "vm/JSScript-inl.h"
-#include "vm/NativeObject-inl.h"
+#include "vm/TypeInference-inl.h"
 
 using namespace js;
-
-using mozilla::DebugOnly;
-using mozilla::Maybe;
-using mozilla::PodArrayZero;
-using mozilla::PodCopy;
-using mozilla::PodZero;
-
-#ifdef DEBUG
-
-static inline jsid id___proto__(JSContext* cx) {
-  return NameToId(cx->names().proto);
-}
-
-static inline jsid id_constructor(JSContext* cx) {
-  return NameToId(cx->names().constructor);
-}
-
-static inline jsid id_caller(JSContext* cx) {
-  return NameToId(cx->names().caller);
-}
-
-const char* js::TypeIdStringImpl(jsid id) {
-  if (JSID_IS_VOID(id)) {
-    return "(index)";
-  }
-  if (JSID_IS_EMPTY(id)) {
-    return "(new)";
-  }
-  if (JSID_IS_SYMBOL(id)) {
-    return "(symbol)";
-  }
-  static char bufs[4][100];
-  static unsigned which = 0;
-  which = (which + 1) & 3;
-  PutEscapedString(bufs[which], 100, JSID_TO_FLAT_STRING(id), 0);
-  return bufs[which];
-}
-
-#endif
-
-/////////////////////////////////////////////////////////////////////
-// Logging
-/////////////////////////////////////////////////////////////////////
-
-/* static */ const char* TypeSet::NonObjectTypeString(TypeSet::Type type) {
-  if (type.isPrimitive()) {
-    switch (type.primitive()) {
-      case ValueType::Undefined:
-        return "void";
-      case ValueType::Null:
-        return "null";
-      case ValueType::Boolean:
-        return "bool";
-      case ValueType::Int32:
-        return "int";
-      case ValueType::Double:
-        return "float";
-      case ValueType::String:
-        return "string";
-      case ValueType::Symbol:
-        return "symbol";
-      case ValueType::BigInt:
-        return "BigInt";
-      case ValueType::Magic:
-        return "lazyargs";
-      case ValueType::PrivateGCThing:
-      case ValueType::Object:
-        MOZ_CRASH("Bad type");
-    }
-  }
-  if (type.isUnknown()) {
-    return "unknown";
-  }
-
-  MOZ_ASSERT(type.isAnyObject());
-  return "object";
-}
-
-static UniqueChars MakeStringCopy(const char* s) {
-  AutoEnterOOMUnsafeRegion oomUnsafe;
-  char* copy = strdup(s);
-  if (!copy) {
-    oomUnsafe.crash("Could not copy string");
-  }
-  return UniqueChars(copy);
-}
-
-/* static */
-UniqueChars TypeSet::TypeString(const TypeSet::Type type) {
-  if (type.isPrimitive() || type.isUnknown() || type.isAnyObject()) {
-    return MakeStringCopy(NonObjectTypeString(type));
-  }
-
-  char buf[100];
-  if (type.isSingleton()) {
-    JSObject* singleton = type.singletonNoBarrier();
-    SprintfLiteral(buf, "<%s %#" PRIxPTR ">", singleton->getClass()->name,
-                   uintptr_t(singleton));
-  } else {
-    SprintfLiteral(buf, "[%s * %#" PRIxPTR "]",
-                   type.groupNoBarrier()->clasp()->name,
-                   uintptr_t(type.groupNoBarrier()));
-  }
-
-  return MakeStringCopy(buf);
-}
-
-/* static */
-UniqueChars TypeSet::ObjectGroupString(const ObjectGroup* group) {
-  return TypeString(TypeSet::ObjectType(group));
-}
-
-#ifdef DEBUG
-
-bool js::InferSpewActive(TypeSpewChannel channel) {
-  static bool active[SPEW_COUNT];
-  static bool checked = false;
-  if (!checked) {
-    checked = true;
-    PodArrayZero(active);
-    if (mozilla::recordreplay::IsRecordingOrReplaying()) {
-      return false;
-    }
-    const char* env = getenv("INFERFLAGS");
-    if (!env) {
-      return false;
-    }
-    if (strstr(env, "ops")) {
-      active[ISpewOps] = true;
-    }
-    if (strstr(env, "result")) {
-      active[ISpewResult] = true;
-    }
-    if (strstr(env, "full")) {
-      for (unsigned i = 0; i < SPEW_COUNT; i++) {
-        active[i] = true;
-      }
-    }
-  }
-  return active[channel];
-}
-
-static bool InferSpewColorable() {
-  /* Only spew colors on xterm-color to not screw up emacs. */
-  static bool colorable = false;
-  static bool checked = false;
-  if (!checked) {
-    checked = true;
-    if (mozilla::recordreplay::IsRecordingOrReplaying()) {
-      return false;
-    }
-    const char* env = getenv("TERM");
-    if (!env) {
-      return false;
-    }
-    if (strcmp(env, "xterm-color") == 0 || strcmp(env, "xterm-256color") == 0) {
-      colorable = true;
-    }
-  }
-  return colorable;
-}
-
-const char* js::InferSpewColorReset() {
-  if (!InferSpewColorable()) {
-    return "";
-  }
-  return "\x1b[0m";
-}
-
-const char* js::InferSpewColor(TypeConstraint* constraint) {
-  /* Type constraints are printed out using foreground colors. */
-  static const char* const colors[] = {"\x1b[31m", "\x1b[32m", "\x1b[33m",
-                                       "\x1b[34m", "\x1b[35m", "\x1b[36m",
-                                       "\x1b[37m"};
-  if (!InferSpewColorable()) {
-    return "";
-  }
-  return colors[DefaultHasher<TypeConstraint*>::hash(constraint) % 7];
-}
-
-const char* js::InferSpewColor(TypeSet* types) {
-  /* Type sets are printed out using bold colors. */
-  static const char* const colors[] = {"\x1b[1;31m", "\x1b[1;32m", "\x1b[1;33m",
-                                       "\x1b[1;34m", "\x1b[1;35m", "\x1b[1;36m",
-                                       "\x1b[1;37m"};
-  if (!InferSpewColorable()) {
-    return "";
-  }
-  return colors[DefaultHasher<TypeSet*>::hash(types) % 7];
-}
-
-#  ifdef DEBUG
-void js::InferSpewImpl(const char* fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  fprintf(stderr, "[infer] ");
-  vfprintf(stderr, fmt, ap);
-  fprintf(stderr, "\n");
-  va_end(ap);
-}
-#  endif
-
-MOZ_NORETURN MOZ_COLD static void MOZ_FORMAT_PRINTF(2, 3)
-    TypeFailure(JSContext* cx, const char* fmt, ...) {
-  char msgbuf[1024]; /* Larger error messages will be truncated */
-  char errbuf[1024];
-
-  va_list ap;
-  va_start(ap, fmt);
-  VsprintfLiteral(errbuf, fmt, ap);
-  va_end(ap);
-
-  SprintfLiteral(msgbuf, "[infer failure] %s", errbuf);
-
-  /* Dump type state, even if INFERFLAGS is unset. */
-  PrintTypes(cx, cx->compartment(), true);
-
-  MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
-  MOZ_CRASH();
-}
-
-bool js::ObjectGroupHasProperty(JSContext* cx, ObjectGroup* group, jsid id,
-                                const Value& value) {
-  /*
-   * Check the correctness of the type information in the object's property
-   * against an actual value.
-   */
-  AutoSweepObjectGroup sweep(group);
-  if (!group->unknownProperties(sweep) && !value.isUndefined()) {
-    id = IdToTypeId(id);
-
-    /* Watch for properties which inference does not monitor. */
-    if (id == id___proto__(cx) || id == id_constructor(cx) ||
-        id == id_caller(cx)) {
-      return true;
-    }
-
-    TypeSet::Type type = TypeSet::GetValueType(value);
-
-    AutoEnterAnalysis enter(cx);
-
-    /*
-     * We don't track types for properties inherited from prototypes which
-     * haven't yet been accessed during analysis of the inheriting object.
-     * Don't do the property instantiation now.
-     */
-    TypeSet* types = group->maybeGetProperty(sweep, id);
-    if (!types) {
-      return true;
-    }
-
-    // Type set guards might miss when an object's group changes and its
-    // properties become unknown.
-    if (value.isObject()) {
-      if (types->unknownObject()) {
-        return true;
-      }
-      for (size_t i = 0; i < types->getObjectCount(); i++) {
-        if (TypeSet::ObjectKey* key = types->getObject(i)) {
-          if (key->unknownProperties()) {
-            return true;
-          }
-        }
-      }
-    }
-
-    if (!types->hasType(type)) {
-      TypeFailure(cx, "Missing type in object %s %s: %s",
-                  TypeSet::ObjectGroupString(group).get(), TypeIdString(id),
-                  TypeSet::TypeString(type).get());
-    }
-  }
-  return true;
-}
-
-#endif
-
-/////////////////////////////////////////////////////////////////////
-// TypeSet
-/////////////////////////////////////////////////////////////////////
-
-TemporaryTypeSet::TemporaryTypeSet(LifoAlloc* alloc, Type type) {
-  if (type.isUnknown()) {
-    flags |= TYPE_FLAG_BASE_MASK;
-    return;
-  }
-  if (type.isPrimitive()) {
-    flags = PrimitiveTypeFlag(type.primitive());
-    if (flags == TYPE_FLAG_DOUBLE) {
-      flags |= TYPE_FLAG_INT32;
-    }
-    return;
-  }
-  if (type.isAnyObject()) {
-    flags |= TYPE_FLAG_ANYOBJECT;
-    return;
-  }
-  if (type.isGroup()) {
-    AutoSweepObjectGroup sweep(type.group());
-    if (type.group()->unknownProperties(sweep)) {
-      flags |= TYPE_FLAG_ANYOBJECT;
-      return;
-    }
-  }
-  setBaseObjectCount(1);
-  objectSet = reinterpret_cast<ObjectKey**>(type.objectKey());
-
-  if (type.isGroup()) {
-    ObjectGroup* ngroup = type.group();
-    AutoSweepObjectGroup sweep(ngroup);
-    if (ngroup->newScript(sweep) &&
-        ngroup->newScript(sweep)->initializedGroup()) {
-      addType(ObjectType(ngroup->newScript(sweep)->initializedGroup()), alloc);
-    }
-  }
-}
-
-bool TypeSet::mightBeMIRType(jit::MIRType type) const {
-  if (unknown()) {
-    return true;
-  }
-
-  if (type == jit::MIRType::Object) {
-    return unknownObject() || baseObjectCount() != 0;
-  }
-
-  switch (type) {
-    case jit::MIRType::Undefined:
-      return baseFlags() & TYPE_FLAG_UNDEFINED;
-    case jit::MIRType::Null:
-      return baseFlags() & TYPE_FLAG_NULL;
-    case jit::MIRType::Boolean:
-      return baseFlags() & TYPE_FLAG_BOOLEAN;
-    case jit::MIRType::Int32:
-      return baseFlags() & TYPE_FLAG_INT32;
-    case jit::MIRType::Float32:  // Fall through, there's no JSVAL for Float32.
-    case jit::MIRType::Double:
-      return baseFlags() & TYPE_FLAG_DOUBLE;
-    case jit::MIRType::String:
-      return baseFlags() & TYPE_FLAG_STRING;
-    case jit::MIRType::Symbol:
-      return baseFlags() & TYPE_FLAG_SYMBOL;
-    case jit::MIRType::BigInt:
-      return baseFlags() & TYPE_FLAG_BIGINT;
-    case jit::MIRType::MagicOptimizedArguments:
-      return baseFlags() & TYPE_FLAG_LAZYARGS;
-    case jit::MIRType::MagicHole:
-    case jit::MIRType::MagicIsConstructing:
-      // These magic constants do not escape to script and are not observed
-      // in the type sets.
-      //
-      // The reason we can return false here is subtle: if Ion is asking the
-      // type set if it has seen such a magic constant, then the MIR in
-      // question is the most generic type, MIRType::Value. A magic constant
-      // could only be emitted by a MIR of MIRType::Value if that MIR is a
-      // phi, and we check that different magic constants do not flow to the
-      // same join point in GuessPhiType.
-      return false;
-    default:
-      MOZ_CRASH("Bad MIR type");
-  }
-}
-
-bool TypeSet::objectsAreSubset(TypeSet* other) {
-  if (other->unknownObject()) {
-    return true;
-  }
-
-  if (unknownObject()) {
-    return false;
-  }
-
-  for (unsigned i = 0; i < getObjectCount(); i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-    if (!other->hasType(ObjectType(key))) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool TypeSet::isSubset(const TypeSet* other) const {
-  if ((baseFlags() & other->baseFlags()) != baseFlags()) {
-    return false;
-  }
-
-  if (unknownObject()) {
-    MOZ_ASSERT(other->unknownObject());
-  } else {
-    for (unsigned i = 0; i < getObjectCount(); i++) {
-      ObjectKey* key = getObject(i);
-      if (!key) {
-        continue;
-      }
-      if (!other->hasType(ObjectType(key))) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-bool TypeSet::objectsIntersect(const TypeSet* other) const {
-  if (unknownObject() || other->unknownObject()) {
-    return true;
-  }
-
-  for (unsigned i = 0; i < getObjectCount(); i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-    if (other->hasType(ObjectType(key))) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-template <class TypeListT>
-bool TypeSet::enumerateTypes(TypeListT* list) const {
-  /* If any type is possible, there's no need to worry about specifics. */
-  if (flags & TYPE_FLAG_UNKNOWN) {
-    return list->append(UnknownType());
-  }
-
-  /* Enqueue type set members stored as bits. */
-  for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
-    if (flags & flag) {
-      Type type = PrimitiveType(TypeFlagPrimitive(flag));
-      if (!list->append(type)) {
-        return false;
-      }
-    }
-  }
-
-  /* If any object is possible, skip specifics. */
-  if (flags & TYPE_FLAG_ANYOBJECT) {
-    return list->append(AnyObjectType());
-  }
-
-  /* Enqueue specific object types. */
-  unsigned count = getObjectCount();
-  for (unsigned i = 0; i < count; i++) {
-    ObjectKey* key = getObject(i);
-    if (key) {
-      if (!list->append(ObjectType(key))) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-template bool TypeSet::enumerateTypes<TypeSet::TypeList>(TypeList* list) const;
-template bool TypeSet::enumerateTypes<jit::TempTypeList>(
-    jit::TempTypeList* list) const;
-
-inline bool TypeSet::addTypesToConstraint(JSContext* cx,
-                                          TypeConstraint* constraint) {
-  /*
-   * Build all types in the set into a vector before triggering the
-   * constraint, as doing so may modify this type set.
-   */
-  TypeList types;
-  if (!enumerateTypes(&types)) {
-    return false;
-  }
-
-  for (unsigned i = 0; i < types.length(); i++) {
-    constraint->newType(cx, this, types[i]);
-  }
-
-  return true;
-}
-
-#ifdef DEBUG
-static inline bool CompartmentsMatch(Compartment* a, Compartment* b) {
-  return !a || !b || a == b;
-}
-#endif
-
-bool ConstraintTypeSet::addConstraint(JSContext* cx, TypeConstraint* constraint,
-                                      bool callExisting) {
-  checkMagic();
-
-  if (!constraint) {
-    /* OOM failure while constructing the constraint. */
-    return false;
-  }
-
-  MOZ_RELEASE_ASSERT(cx->zone()->types.activeAnalysis);
-  MOZ_ASSERT(
-      CompartmentsMatch(maybeCompartment(), constraint->maybeCompartment()));
-
-  InferSpew(ISpewOps, "addConstraint: %sT%p%s %sC%p%s %s", InferSpewColor(this),
-            this, InferSpewColorReset(), InferSpewColor(constraint), constraint,
-            InferSpewColorReset(), constraint->kind());
-
-  MOZ_ASSERT(constraint->next() == nullptr);
-  constraint->setNext(constraintList_);
-  constraintList_ = constraint;
-
-  if (callExisting) {
-    return addTypesToConstraint(cx, constraint);
-  }
-  return true;
-}
-
-void TypeSet::clearObjects() {
-  setBaseObjectCount(0);
-  objectSet = nullptr;
-}
-
-Compartment* TypeSet::maybeCompartment() {
-  if (unknownObject()) {
-    return nullptr;
-  }
-
-  unsigned objectCount = getObjectCount();
-  for (unsigned i = 0; i < objectCount; i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-
-    Compartment* comp = key->maybeCompartment();
-    if (comp) {
-      return comp;
-    }
-  }
-
-  return nullptr;
-}
-
-void TypeSet::addType(Type type, LifoAlloc* alloc) {
-  MOZ_ASSERT(CompartmentsMatch(maybeCompartment(), type.maybeCompartment()));
-
-  if (unknown()) {
-    return;
-  }
-
-  if (type.isUnknown()) {
-    flags |= TYPE_FLAG_BASE_MASK;
-    clearObjects();
-    MOZ_ASSERT(unknown());
-    return;
-  }
-
-  if (type.isPrimitive()) {
-    TypeFlags flag = PrimitiveTypeFlag(type.primitive());
-    if (flags & flag) {
-      return;
-    }
-
-    /* If we add float to a type set it is also considered to contain int. */
-    if (flag == TYPE_FLAG_DOUBLE) {
-      flag |= TYPE_FLAG_INT32;
-    }
-
-    flags |= flag;
-    return;
-  }
-
-  if (flags & TYPE_FLAG_ANYOBJECT) {
-    return;
-  }
-  if (type.isAnyObject()) {
-    goto unknownObject;
-  }
-
-  {
-    uint32_t objectCount = baseObjectCount();
-    ObjectKey* key = type.objectKey();
-    ObjectKey** pentry = TypeHashSet::Insert<ObjectKey*, ObjectKey, ObjectKey>(
-        *alloc, objectSet, objectCount, key);
-    if (!pentry) {
-      goto unknownObject;
-    }
-    if (*pentry) {
-      return;
-    }
-    *pentry = key;
-
-    setBaseObjectCount(objectCount);
-
-    // Limit the number of objects we track. There is a different limit
-    // depending on whether the set only contains DOM objects, which can
-    // have many different classes and prototypes but are still optimizable
-    // by IonMonkey.
-    if (objectCount >= TYPE_FLAG_OBJECT_COUNT_LIMIT) {
-      JS_STATIC_ASSERT(TYPE_FLAG_DOMOBJECT_COUNT_LIMIT >=
-                       TYPE_FLAG_OBJECT_COUNT_LIMIT);
-      // Examining the entire type set is only required when we first hit
-      // the normal object limit.
-      if (objectCount == TYPE_FLAG_OBJECT_COUNT_LIMIT) {
-        for (unsigned i = 0; i < objectCount; i++) {
-          const Class* clasp = getObjectClass(i);
-          if (clasp && !clasp->isDOMClass()) {
-            goto unknownObject;
-          }
-        }
-      }
-
-      // Make sure the newly added object is also a DOM object.
-      if (!key->clasp()->isDOMClass()) {
-        goto unknownObject;
-      }
-
-      // Limit the number of DOM objects.
-      if (objectCount == TYPE_FLAG_DOMOBJECT_COUNT_LIMIT) {
-        goto unknownObject;
-      }
-    }
-  }
-
-  if (type.isGroup()) {
-    ObjectGroup* ngroup = type.group();
-    MOZ_ASSERT(!ngroup->singleton());
-    AutoSweepObjectGroup sweep(ngroup);
-    if (ngroup->unknownProperties(sweep)) {
-      goto unknownObject;
-    }
-
-    // If we add a partially initialized group to a type set, add the
-    // corresponding fully initialized group, as an object's group may change
-    // from the former to the latter via the acquired properties analysis.
-    if (ngroup->newScript(sweep) &&
-        ngroup->newScript(sweep)->initializedGroup()) {
-      addType(ObjectType(ngroup->newScript(sweep)->initializedGroup()), alloc);
-    }
-  }
-
-  if (false) {
-  unknownObject:
-    flags |= TYPE_FLAG_ANYOBJECT;
-    clearObjects();
-  }
-}
-
-// This class is used for post barriers on type set contents. The only times
-// when type sets contain nursery references is when a nursery object has its
-// group dynamically changed to a singleton. In such cases the type set will
-// need to be traced at the next minor GC.
-//
-// There is no barrier used for TemporaryTypeSets. These type sets are only
-// used during Ion compilation, and if some ConstraintTypeSet contains nursery
-// pointers then any number of TemporaryTypeSets might as well. Thus, if there
-// are any such ConstraintTypeSets in existence, all off thread Ion
-// compilations are canceled by the next minor GC.
-class TypeSetRef : public gc::BufferableRef {
-  Zone* zone;
-  ConstraintTypeSet* types;
-#ifdef DEBUG
-  uint64_t minorGCNumberAtCreation;
-#endif
-
- public:
-  TypeSetRef(Zone* zone, ConstraintTypeSet* types)
-      : zone(zone),
-        types(types)
-#ifdef DEBUG
-        ,
-        minorGCNumberAtCreation(
-            zone->runtimeFromMainThread()->gc.minorGCCount())
-#endif
-  {
-  }
-
-  void trace(JSTracer* trc) override {
-    MOZ_ASSERT(trc->runtime()->gc.minorGCCount() == minorGCNumberAtCreation);
-    types->trace(zone, trc);
-  }
-};
-
-void ConstraintTypeSet::postWriteBarrier(JSContext* cx, Type type) {
-  if (type.isSingletonUnchecked()) {
-    if (gc::StoreBuffer* sb = type.singletonNoBarrier()->storeBuffer()) {
-      sb->putGeneric(TypeSetRef(cx->zone(), this));
-      sb->setShouldCancelIonCompilations();
-    }
-  }
-}
-
-void ConstraintTypeSet::addType(const AutoSweepBase& sweep, JSContext* cx,
-                                Type type) {
-  checkMagic();
-
-  MOZ_RELEASE_ASSERT(cx->zone()->types.activeAnalysis);
-
-  if (hasType(type)) {
-    return;
-  }
-
-  TypeSet::addType(type, &cx->typeLifoAlloc());
-
-  if (type.isObjectUnchecked() && unknownObject()) {
-    type = AnyObjectType();
-  }
-
-  postWriteBarrier(cx, type);
-
-  InferSpew(ISpewOps, "addType: %sT%p%s %s", InferSpewColor(this), this,
-            InferSpewColorReset(), TypeString(type).get());
-
-  /* Propagate the type to all constraints. */
-  if (!cx->helperThread()) {
-    TypeConstraint* constraint = constraintList(sweep);
-    while (constraint) {
-      constraint->newType(cx, this, type);
-      constraint = constraint->next();
-    }
-  } else {
-    MOZ_ASSERT(!constraintList_);
-  }
-}
-
-void TypeSet::print(FILE* fp) {
-  bool fromDebugger = !fp;
-  if (!fp) {
-    fp = stderr;
-  }
-
-  if (flags & TYPE_FLAG_NON_DATA_PROPERTY) {
-    fprintf(fp, " [non-data]");
-  }
-
-  if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY) {
-    fprintf(fp, " [non-writable]");
-  }
-
-  if (definiteProperty()) {
-    fprintf(fp, " [definite:%d]", definiteSlot());
-  }
-
-  if (baseFlags() == 0 && !baseObjectCount()) {
-    fprintf(fp, " missing");
-    return;
-  }
-
-  if (flags & TYPE_FLAG_UNKNOWN) {
-    fprintf(fp, " unknown");
-  }
-  if (flags & TYPE_FLAG_ANYOBJECT) {
-    fprintf(fp, " object");
-  }
-
-  if (flags & TYPE_FLAG_UNDEFINED) {
-    fprintf(fp, " void");
-  }
-  if (flags & TYPE_FLAG_NULL) {
-    fprintf(fp, " null");
-  }
-  if (flags & TYPE_FLAG_BOOLEAN) {
-    fprintf(fp, " bool");
-  }
-  if (flags & TYPE_FLAG_INT32) {
-    fprintf(fp, " int");
-  }
-  if (flags & TYPE_FLAG_DOUBLE) {
-    fprintf(fp, " float");
-  }
-  if (flags & TYPE_FLAG_STRING) {
-    fprintf(fp, " string");
-  }
-  if (flags & TYPE_FLAG_SYMBOL) {
-    fprintf(fp, " symbol");
-  }
-  if (flags & TYPE_FLAG_BIGINT) {
-    fprintf(fp, " BigInt");
-  }
-  if (flags & TYPE_FLAG_LAZYARGS) {
-    fprintf(fp, " lazyargs");
-  }
-
-  uint32_t objectCount = baseObjectCount();
-  if (objectCount) {
-    fprintf(fp, " object[%u]", objectCount);
-
-    unsigned count = getObjectCount();
-    for (unsigned i = 0; i < count; i++) {
-      ObjectKey* key = getObject(i);
-      if (key) {
-        fprintf(fp, " %s", TypeString(ObjectType(key)).get());
-      }
-    }
-  }
-
-  if (fromDebugger) {
-    fprintf(fp, "\n");
-  }
-}
-
-/* static */
-void TypeSet::readBarrier(const TypeSet* types) {
-  if (types->unknownObject()) {
-    return;
-  }
-
-  for (unsigned i = 0; i < types->getObjectCount(); i++) {
-    if (ObjectKey* key = types->getObject(i)) {
-      if (key->isSingleton()) {
-        (void)key->singleton();
-      } else {
-        (void)key->group();
-      }
-    }
-  }
-}
-
-/* static */
-bool TypeSet::IsTypeMarked(JSRuntime* rt, TypeSet::Type* v) {
-  bool rv;
-  if (v->isSingletonUnchecked()) {
-    JSObject* obj = v->singletonNoBarrier();
-    rv = IsMarkedUnbarriered(rt, &obj);
-    *v = TypeSet::ObjectType(obj);
-  } else if (v->isGroupUnchecked()) {
-    ObjectGroup* group = v->groupNoBarrier();
-    rv = IsMarkedUnbarriered(rt, &group);
-    *v = TypeSet::ObjectType(group);
-  } else {
-    rv = true;
-  }
-  return rv;
-}
-
-static inline bool IsObjectKeyAboutToBeFinalized(TypeSet::ObjectKey** keyp) {
-  TypeSet::ObjectKey* key = *keyp;
-  bool isAboutToBeFinalized;
-  if (key->isGroup()) {
-    ObjectGroup* group = key->groupNoBarrier();
-    isAboutToBeFinalized = IsAboutToBeFinalizedUnbarriered(&group);
-    if (!isAboutToBeFinalized) {
-      *keyp = TypeSet::ObjectKey::get(group);
-    }
-  } else {
-    MOZ_ASSERT(key->isSingleton());
-    JSObject* singleton = key->singletonNoBarrier();
-    isAboutToBeFinalized = IsAboutToBeFinalizedUnbarriered(&singleton);
-    if (!isAboutToBeFinalized) {
-      *keyp = TypeSet::ObjectKey::get(singleton);
-    }
-  }
-  return isAboutToBeFinalized;
-}
-
-bool TypeSet::IsTypeAboutToBeFinalized(TypeSet::Type* v) {
-  bool isAboutToBeFinalized;
-  if (v->isObjectUnchecked()) {
-    TypeSet::ObjectKey* key = v->objectKey();
-    isAboutToBeFinalized = IsObjectKeyAboutToBeFinalized(&key);
-    if (!isAboutToBeFinalized) {
-      *v = TypeSet::ObjectType(key);
-    }
-  } else {
-    isAboutToBeFinalized = false;
-  }
-  return isAboutToBeFinalized;
-}
-
-bool TypeSet::cloneIntoUninitialized(LifoAlloc* alloc,
-                                     TemporaryTypeSet* result) const {
-  unsigned objectCount = baseObjectCount();
-  unsigned capacity =
-      (objectCount >= 2) ? TypeHashSet::Capacity(objectCount) : 0;
-
-  ObjectKey** newSet;
-  if (capacity) {
-    // We allocate an extra word right before the array that stores the
-    // capacity, so make sure we clone that as well.
-    newSet = alloc->newArray<ObjectKey*>(capacity + 1);
-    if (!newSet) {
-      return false;
-    }
-    newSet++;
-    PodCopy(newSet - 1, objectSet - 1, capacity + 1);
-  }
-
-  new (result) TemporaryTypeSet(flags, capacity ? newSet : objectSet);
-  return true;
-}
-
-TemporaryTypeSet* TypeSet::clone(LifoAlloc* alloc) const {
-  TemporaryTypeSet* res = alloc->pod_malloc<TemporaryTypeSet>();
-  if (!res || !cloneIntoUninitialized(alloc, res)) {
-    return nullptr;
-  }
-  return res;
-}
-
-TemporaryTypeSet* TypeSet::cloneObjectsOnly(LifoAlloc* alloc) {
-  TemporaryTypeSet* res = clone(alloc);
-  if (!res) {
-    return nullptr;
-  }
-
-  res->flags &= ~TYPE_FLAG_BASE_MASK | TYPE_FLAG_ANYOBJECT;
-
-  return res;
-}
-
-TemporaryTypeSet* TypeSet::cloneWithoutObjects(LifoAlloc* alloc) {
-  TemporaryTypeSet* res = alloc->new_<TemporaryTypeSet>();
-  if (!res) {
-    return nullptr;
-  }
-
-  res->flags = flags & ~TYPE_FLAG_ANYOBJECT;
-  res->setBaseObjectCount(0);
-  return res;
-}
-
-/* static */
-TemporaryTypeSet* TypeSet::unionSets(TypeSet* a, TypeSet* b, LifoAlloc* alloc) {
-  TemporaryTypeSet* res = alloc->new_<TemporaryTypeSet>(
-      a->baseFlags() | b->baseFlags(), static_cast<ObjectKey**>(nullptr));
-  if (!res) {
-    return nullptr;
-  }
-
-  if (!res->unknownObject()) {
-    for (size_t i = 0; i < a->getObjectCount() && !res->unknownObject(); i++) {
-      if (ObjectKey* key = a->getObject(i)) {
-        res->addType(ObjectType(key), alloc);
-      }
-    }
-    for (size_t i = 0; i < b->getObjectCount() && !res->unknownObject(); i++) {
-      if (ObjectKey* key = b->getObject(i)) {
-        res->addType(ObjectType(key), alloc);
-      }
-    }
-  }
-
-  return res;
-}
-
-/* static */
-TemporaryTypeSet* TypeSet::removeSet(TemporaryTypeSet* input,
-                                     TemporaryTypeSet* removal,
-                                     LifoAlloc* alloc) {
-  // Only allow removal of primitives and the "AnyObject" flag.
-  MOZ_ASSERT(!removal->unknown());
-  MOZ_ASSERT_IF(!removal->unknownObject(), removal->getObjectCount() == 0);
-
-  uint32_t flags = input->baseFlags() & ~removal->baseFlags();
-  TemporaryTypeSet* res =
-      alloc->new_<TemporaryTypeSet>(flags, static_cast<ObjectKey**>(nullptr));
-  if (!res) {
-    return nullptr;
-  }
-
-  res->setBaseObjectCount(0);
-  if (removal->unknownObject() || input->unknownObject()) {
-    return res;
-  }
-
-  for (size_t i = 0; i < input->getObjectCount(); i++) {
-    if (!input->getObject(i)) {
-      continue;
-    }
-
-    res->addType(TypeSet::ObjectType(input->getObject(i)), alloc);
-  }
-
-  return res;
-}
-
-/* static */
-TemporaryTypeSet* TypeSet::intersectSets(TemporaryTypeSet* a,
-                                         TemporaryTypeSet* b,
-                                         LifoAlloc* alloc) {
-  TemporaryTypeSet* res;
-  res = alloc->new_<TemporaryTypeSet>(a->baseFlags() & b->baseFlags(),
-                                      static_cast<ObjectKey**>(nullptr));
-  if (!res) {
-    return nullptr;
-  }
-
-  res->setBaseObjectCount(0);
-  if (res->unknownObject()) {
-    return res;
-  }
-
-  MOZ_ASSERT(!a->unknownObject() || !b->unknownObject());
-
-  if (a->unknownObject()) {
-    for (size_t i = 0; i < b->getObjectCount(); i++) {
-      if (b->getObject(i)) {
-        res->addType(ObjectType(b->getObject(i)), alloc);
-      }
-    }
-    return res;
-  }
-
-  if (b->unknownObject()) {
-    for (size_t i = 0; i < a->getObjectCount(); i++) {
-      if (a->getObject(i)) {
-        res->addType(ObjectType(a->getObject(i)), alloc);
-      }
-    }
-    return res;
-  }
-
-  MOZ_ASSERT(!a->unknownObject() && !b->unknownObject());
-
-  for (size_t i = 0; i < a->getObjectCount(); i++) {
-    for (size_t j = 0; j < b->getObjectCount(); j++) {
-      if (b->getObject(j) != a->getObject(i)) {
-        continue;
-      }
-      if (!b->getObject(j)) {
-        continue;
-      }
-      res->addType(ObjectType(b->getObject(j)), alloc);
-      break;
-    }
-  }
-
-  return res;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Compiler constraints
-/////////////////////////////////////////////////////////////////////
-
-// Compiler constraints overview
-//
-// Constraints generated during Ion compilation capture assumptions made about
-// heap properties that will trigger invalidation of the resulting Ion code if
-// the constraint is violated. Constraints can only be attached to type sets on
-// the main thread, so to allow compilation to occur almost entirely off thread
-// the generation is split into two phases.
-//
-// During compilation, CompilerConstraint values are constructed in a list,
-// recording the heap property type set which was read from and its expected
-// contents, along with the assumption made about those contents.
-//
-// At the end of compilation, when linking the result on the main thread, the
-// list of compiler constraints are read and converted to type constraints and
-// attached to the type sets. If the property type sets have changed so that the
-// assumptions no longer hold then the compilation is aborted and its result
-// discarded.
-
-// Superclass of all constraints generated during Ion compilation. These may
-// be allocated off thread, using the current JIT context's allocator.
-class CompilerConstraint {
- public:
-  // Property being queried by the compiler.
-  HeapTypeSetKey property;
-
-  // Contents of the property at the point when the query was performed. This
-  // may differ from the actual property types later in compilation as the
-  // main thread performs side effects.
-  TemporaryTypeSet* expected;
-
-  CompilerConstraint(LifoAlloc* alloc, const HeapTypeSetKey& property)
-      : property(property),
-        expected(property.maybeTypes() ? property.maybeTypes()->clone(alloc)
-                                       : nullptr) {}
-
-  // Generate the type constraint recording the assumption made by this
-  // compilation. Returns true if the assumption originally made still holds.
-  virtual bool generateTypeConstraint(JSContext* cx,
-                                      RecompileInfo recompileInfo) = 0;
-};
-
-class js::CompilerConstraintList {
- public:
-  struct FrozenScript {
-    JSScript* script;
-    TemporaryTypeSet* thisTypes;
-    TemporaryTypeSet* argTypes;
-    TemporaryTypeSet* bytecodeTypes;
-  };
-
- private:
-  // OOM during generation of some constraint.
-  bool failed_;
-
-  // Allocator used for constraints.
-  LifoAlloc* alloc_;
-
-  // Constraints generated on heap properties.
-  Vector<CompilerConstraint*, 0, jit::JitAllocPolicy> constraints;
-
-  // Scripts whose stack type sets were frozen for the compilation.
-  Vector<FrozenScript, 1, jit::JitAllocPolicy> frozenScripts;
-
- public:
-  explicit CompilerConstraintList(jit::TempAllocator& alloc)
-      : failed_(false),
-        alloc_(alloc.lifoAlloc()),
-        constraints(alloc),
-        frozenScripts(alloc) {}
-
-  void add(CompilerConstraint* constraint) {
-    if (!constraint || !constraints.append(constraint)) {
-      setFailed();
-    }
-  }
-
-  void freezeScript(JSScript* script, TemporaryTypeSet* thisTypes,
-                    TemporaryTypeSet* argTypes,
-                    TemporaryTypeSet* bytecodeTypes) {
-    FrozenScript entry;
-    entry.script = script;
-    entry.thisTypes = thisTypes;
-    entry.argTypes = argTypes;
-    entry.bytecodeTypes = bytecodeTypes;
-    if (!frozenScripts.append(entry)) {
-      setFailed();
-    }
-  }
-
-  size_t length() { return constraints.length(); }
-
-  CompilerConstraint* get(size_t i) { return constraints[i]; }
-
-  size_t numFrozenScripts() { return frozenScripts.length(); }
-
-  const FrozenScript& frozenScript(size_t i) { return frozenScripts[i]; }
-
-  bool failed() { return failed_; }
-  void setFailed() { failed_ = true; }
-  LifoAlloc* alloc() const { return alloc_; }
-};
-
-CompilerConstraintList* js::NewCompilerConstraintList(
-    jit::TempAllocator& alloc) {
-  return alloc.lifoAlloc()->new_<CompilerConstraintList>(alloc);
-}
-
-/* static */
-bool TypeScript::FreezeTypeSets(CompilerConstraintList* constraints,
-                                JSScript* script, TemporaryTypeSet** pThisTypes,
-                                TemporaryTypeSet** pArgTypes,
-                                TemporaryTypeSet** pBytecodeTypes) {
-  LifoAlloc* alloc = constraints->alloc();
-  AutoSweepTypeScript sweep(script);
-  TypeScript* typeScript = script->types();
-  StackTypeSet* existing = typeScript->typeArray(sweep);
-
-  size_t count = typeScript->numTypeSets();
-  TemporaryTypeSet* types =
-      alloc->newArrayUninitialized<TemporaryTypeSet>(count);
-  if (!types) {
-    return false;
-  }
-
-  for (size_t i = 0; i < count; i++) {
-    if (!existing[i].cloneIntoUninitialized(alloc, &types[i])) {
-      return false;
-    }
-  }
-
-  size_t thisTypesIndex = typeScript->thisTypes(sweep, script) - existing;
-  *pThisTypes = types + thisTypesIndex;
-
-  if (script->functionNonDelazifying() &&
-      script->functionNonDelazifying()->nargs() > 0) {
-    size_t firstArgIndex = typeScript->argTypes(sweep, script, 0) - existing;
-    *pArgTypes = types + firstArgIndex;
-  } else {
-    *pArgTypes = nullptr;
-  }
-
-  *pBytecodeTypes = types;
-
-  constraints->freezeScript(script, *pThisTypes, *pArgTypes, *pBytecodeTypes);
-  return true;
-}
-
-namespace {
-
-template <typename T>
-class CompilerConstraintInstance : public CompilerConstraint {
-  T data;
-
- public:
-  CompilerConstraintInstance<T>(LifoAlloc* alloc,
-                                const HeapTypeSetKey& property, const T& data)
-      : CompilerConstraint(alloc, property), data(data) {}
-
-  bool generateTypeConstraint(JSContext* cx,
-                              RecompileInfo recompileInfo) override;
-};
-
-// Constraint generated from a CompilerConstraint when linking the compilation.
-template <typename T>
-class TypeCompilerConstraint : public TypeConstraint {
-  // Compilation which this constraint may invalidate.
-  RecompileInfo compilation;
-
-  T data;
-
- public:
-  TypeCompilerConstraint<T>(RecompileInfo compilation, const T& data)
-      : compilation(compilation), data(data) {}
-
-  const char* kind() override { return data.kind(); }
-
-  void newType(JSContext* cx, TypeSet* source, TypeSet::Type type) override {
-    if (data.invalidateOnNewType(type)) {
-      cx->zone()->types.addPendingRecompile(cx, compilation);
-    }
-  }
-
-  void newPropertyState(JSContext* cx, TypeSet* source) override {
-    if (data.invalidateOnNewPropertyState(source)) {
-      cx->zone()->types.addPendingRecompile(cx, compilation);
-    }
-  }
-
-  void newObjectState(JSContext* cx, ObjectGroup* group) override {
-    // Note: Once the object has unknown properties, no more notifications
-    // will be sent on changes to its state, so always invalidate any
-    // associated compilations.
-    AutoSweepObjectGroup sweep(group);
-    if (group->unknownProperties(sweep) ||
-        data.invalidateOnNewObjectState(sweep, group)) {
-      cx->zone()->types.addPendingRecompile(cx, compilation);
-    }
-  }
-
-  bool sweep(TypeZone& zone, TypeConstraint** res) override {
-    if (data.shouldSweep() || compilation.shouldSweep(zone)) {
-      return false;
-    }
-    *res = zone.typeLifoAlloc().new_<TypeCompilerConstraint<T> >(compilation,
-                                                                 data);
-    return true;
-  }
-
-  Compartment* maybeCompartment() override { return data.maybeCompartment(); }
-};
-
-template <typename T>
-bool CompilerConstraintInstance<T>::generateTypeConstraint(
-    JSContext* cx, RecompileInfo recompileInfo) {
-  // This should only be called in suppress-GC contexts, but the static
-  // analysis doesn't know this.
-  MOZ_ASSERT(cx->suppressGC);
-  JS::AutoSuppressGCAnalysis suppress;
-
-  if (property.object()->unknownProperties()) {
-    return false;
-  }
-
-  if (!property.instantiate(cx)) {
-    return false;
-  }
-
-  AutoSweepObjectGroup sweep(property.object()->maybeGroup());
-  if (!data.constraintHolds(sweep, cx, property, expected)) {
-    return false;
-  }
-
-  return property.maybeTypes()->addConstraint(
-      cx,
-      cx->typeLifoAlloc().new_<TypeCompilerConstraint<T> >(recompileInfo, data),
-      /* callExisting = */ false);
-}
-
-} /* anonymous namespace */
-
-const Class* TypeSet::ObjectKey::clasp() {
-  return isGroup() ? group()->clasp() : singleton()->getClass();
-}
-
-TaggedProto TypeSet::ObjectKey::proto() {
-  return isGroup() ? group()->proto() : singleton()->taggedProto();
-}
-
-TypeNewScript* TypeSet::ObjectKey::newScript() {
-  if (isGroup()) {
-    AutoSweepObjectGroup sweep(group());
-    if (group()->newScript(sweep)) {
-      return group()->newScript(sweep);
-    }
-  }
-  return nullptr;
-}
-
-ObjectGroup* TypeSet::ObjectKey::maybeGroup() {
-  if (isGroup()) {
-    return group();
-  }
-  if (!singleton()->hasLazyGroup()) {
-    return singleton()->group();
-  }
-  return nullptr;
-}
-
-bool TypeSet::ObjectKey::unknownProperties() {
-  if (ObjectGroup* group = maybeGroup()) {
-    AutoSweepObjectGroup sweep(group);
-    return group->unknownProperties(sweep);
-  }
-  return false;
-}
-
-HeapTypeSetKey TypeSet::ObjectKey::property(jsid id) {
-  MOZ_ASSERT(!unknownProperties());
-
-  HeapTypeSetKey property;
-  property.object_ = this;
-  property.id_ = id;
-  if (ObjectGroup* group = maybeGroup()) {
-    AutoSweepObjectGroup sweep(group);
-    property.maybeTypes_ = group->maybeGetProperty(sweep, id);
-  }
-
-  return property;
-}
-
-void TypeSet::ObjectKey::ensureTrackedProperty(JSContext* cx, jsid id) {
-  // If we are accessing a lazily defined property which actually exists in
-  // the VM and has not been instantiated yet, instantiate it now if we are
-  // on the main thread and able to do so.
-  if (!JSID_IS_VOID(id) && !JSID_IS_EMPTY(id)) {
-    MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
-    if (isSingleton()) {
-      JSObject* obj = singleton();
-      if (obj->isNative() && obj->as<NativeObject>().containsPure(id)) {
-        EnsureTrackPropertyTypes(cx, obj, id);
-      }
-    }
-  }
-}
-
-void js::EnsureTrackPropertyTypes(JSContext* cx, JSObject* obj, jsid id) {
-  id = IdToTypeId(id);
-
-  if (obj->isSingleton()) {
-    AutoEnterAnalysis enter(cx);
-    if (obj->hasLazyGroup()) {
-      AutoEnterOOMUnsafeRegion oomUnsafe;
-      RootedObject objRoot(cx, obj);
-      if (!JSObject::getGroup(cx, objRoot)) {
-        oomUnsafe.crash(
-            "Could not allocate ObjectGroup in EnsureTrackPropertyTypes");
-      }
-    }
-    ObjectGroup* group = obj->group();
-    AutoSweepObjectGroup sweep(group);
-    if (!group->unknownProperties(sweep) &&
-        !group->getProperty(sweep, cx, obj, id)) {
-      MOZ_ASSERT(group->unknownProperties(sweep));
-      return;
-    }
-  }
-
-  MOZ_ASSERT(obj->group()->unknownPropertiesDontCheckGeneration() ||
-             TrackPropertyTypes(obj, id));
-}
-
-bool HeapTypeSetKey::instantiate(JSContext* cx) {
-  if (maybeTypes()) {
-    return true;
-  }
-  if (object()->isSingleton()) {
-    RootedObject obj(cx, object()->singleton());
-    if (!JSObject::getGroup(cx, obj)) {
-      cx->clearPendingException();
-      return false;
-    }
-  }
-  JSObject* obj = object()->isSingleton() ? object()->singleton() : nullptr;
-  AutoSweepObjectGroup sweep(object()->maybeGroup());
-  maybeTypes_ = object()->maybeGroup()->getProperty(sweep, cx, obj, id());
-  return maybeTypes_ != nullptr;
-}
-
-static bool CheckFrozenTypeSet(const AutoSweepTypeScript& sweep, JSContext* cx,
-                               TemporaryTypeSet* frozen, StackTypeSet* actual) {
-  // Return whether the types frozen for a script during compilation are
-  // still valid. Also check for any new types added to the frozen set during
-  // compilation, and add them to the actual stack type sets. These new types
-  // indicate places where the compiler relaxed its possible inputs to be
-  // more tolerant of potential new types.
-
-  if (!actual->isSubset(frozen)) {
-    return false;
-  }
-
-  if (!frozen->isSubset(actual)) {
-    TypeSet::TypeList list;
-    frozen->enumerateTypes(&list);
-
-    for (size_t i = 0; i < list.length(); i++) {
-      actual->addType(sweep, cx, list[i]);
-    }
-  }
-
-  return true;
-}
-
-namespace {
-
-/*
- * As for TypeConstraintFreeze, but describes an implicit freeze constraint
- * added for stack types within a script. Applies to all compilations of the
- * script, not just a single one.
- */
-class TypeConstraintFreezeStack : public TypeConstraint {
-  JSScript* script_;
-
- public:
-  explicit TypeConstraintFreezeStack(JSScript* script) : script_(script) {}
-
-  const char* kind() override { return "freezeStack"; }
-
-  void newType(JSContext* cx, TypeSet* source, TypeSet::Type type) override {
-    /*
-     * Unlike TypeConstraintFreeze, triggering this constraint once does
-     * not disable it on future changes to the type set.
-     */
-    cx->zone()->types.addPendingRecompile(cx, script_);
-  }
-
-  bool sweep(TypeZone& zone, TypeConstraint** res) override {
-    if (IsAboutToBeFinalizedUnbarriered(&script_)) {
-      return false;
-    }
-    *res = zone.typeLifoAlloc().new_<TypeConstraintFreezeStack>(script_);
-    return true;
-  }
-
-  Compartment* maybeCompartment() override { return script_->compartment(); }
-};
-
-} /* anonymous namespace */
-
-bool js::FinishCompilation(JSContext* cx, HandleScript script,
-                           CompilerConstraintList* constraints,
-                           IonCompilationId compilationId, bool* isValidOut) {
-  MOZ_ASSERT(*cx->zone()->types.currentCompilationId() == compilationId);
-
-  if (constraints->failed()) {
-    return false;
-  }
-
-  RecompileInfo recompileInfo(script, compilationId);
-
-  bool succeeded = true;
-
-  for (size_t i = 0; i < constraints->length(); i++) {
-    CompilerConstraint* constraint = constraints->get(i);
-    if (!constraint->generateTypeConstraint(cx, recompileInfo)) {
-      succeeded = false;
-    }
-  }
-
-  for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
-    const CompilerConstraintList::FrozenScript& entry =
-        constraints->frozenScript(i);
-    TypeScript* types = entry.script->types();
-    if (!types) {
-      succeeded = false;
-      break;
-    }
-
-    // It could happen that one of the compiled scripts was made a
-    // debuggee mid-compilation (e.g., via setting a breakpoint). If so,
-    // throw away the compilation.
-    if (entry.script->isDebuggee()) {
-      succeeded = false;
-      break;
-    }
-
-    AutoSweepTypeScript sweep(entry.script);
-    TypeScript* typeScript = entry.script->types();
-    if (!CheckFrozenTypeSet(sweep, cx, entry.thisTypes,
-                            typeScript->thisTypes(sweep, entry.script))) {
-      succeeded = false;
-    }
-    unsigned nargs = entry.script->functionNonDelazifying()
-                         ? entry.script->functionNonDelazifying()->nargs()
-                         : 0;
-    for (size_t i = 0; i < nargs; i++) {
-      if (!CheckFrozenTypeSet(sweep, cx, &entry.argTypes[i],
-                              typeScript->argTypes(sweep, entry.script, i))) {
-        succeeded = false;
-      }
-    }
-    for (size_t i = 0; i < entry.script->numBytecodeTypeSets(); i++) {
-      if (!CheckFrozenTypeSet(sweep, cx, &entry.bytecodeTypes[i],
-                              &types->typeArray(sweep)[i])) {
-        succeeded = false;
-      }
-    }
-
-    // Add this compilation to the inlinedCompilations list of each inlined
-    // script, so we can invalidate it on changes to stack type sets.
-    if (entry.script != script) {
-      if (!types->addInlinedCompilation(sweep, recompileInfo)) {
-        succeeded = false;
-      }
-    }
-
-    // If necessary, add constraints to trigger invalidation on the script
-    // after any future changes to the stack type sets.
-    if (types->hasFreezeConstraints(sweep)) {
-      continue;
-    }
-
-    size_t count = types->numTypeSets();
-    StackTypeSet* array = types->typeArray(sweep);
-    for (size_t i = 0; i < count; i++) {
-      if (!array[i].addConstraint(
-              cx,
-              cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(entry.script),
-              false)) {
-        succeeded = false;
-      }
-    }
-
-    if (succeeded) {
-      types->setHasFreezeConstraints(sweep);
-    }
-  }
-
-  if (!succeeded) {
-    script->resetWarmUpCounterToDelayIonCompilation();
-    *isValidOut = false;
-    return true;
-  }
-
-  *isValidOut = true;
-  return true;
-}
-
-static void CheckDefinitePropertiesTypeSet(const AutoSweepTypeScript& sweep,
-                                           JSContext* cx,
-                                           TemporaryTypeSet* frozen,
-                                           StackTypeSet* actual) {
-  // The definite properties analysis happens on the main thread, so no new
-  // types can have been added to actual. The analysis may have updated the
-  // contents of |frozen| though with new speculative types, and these need
-  // to be reflected in |actual| for AddClearDefiniteFunctionUsesInScript
-  // to work.
-  if (!frozen->isSubset(actual)) {
-    TypeSet::TypeList list;
-    frozen->enumerateTypes(&list);
-
-    for (size_t i = 0; i < list.length(); i++) {
-      actual->addType(sweep, cx, list[i]);
-    }
-  }
-}
-
-void js::FinishDefinitePropertiesAnalysis(JSContext* cx,
-                                          CompilerConstraintList* constraints) {
-#ifdef DEBUG
-  // Assert no new types have been added to the StackTypeSets. Do this before
-  // calling CheckDefinitePropertiesTypeSet, as it may add new types to the
-  // StackTypeSets and break these invariants if a script is inlined more
-  // than once. See also CheckDefinitePropertiesTypeSet.
-  for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
-    const CompilerConstraintList::FrozenScript& entry =
-        constraints->frozenScript(i);
-    JSScript* script = entry.script;
-    TypeScript* typeScript = script->types();
-    MOZ_ASSERT(typeScript);
-
-    AutoSweepTypeScript sweep(script);
-    MOZ_ASSERT(typeScript->thisTypes(sweep, script)->isSubset(entry.thisTypes));
-
-    unsigned nargs = entry.script->functionNonDelazifying()
-                         ? entry.script->functionNonDelazifying()->nargs()
-                         : 0;
-    for (size_t j = 0; j < nargs; j++) {
-      StackTypeSet* argTypes = typeScript->argTypes(sweep, script, j);
-      MOZ_ASSERT(argTypes->isSubset(&entry.argTypes[j]));
-    }
-
-    for (size_t j = 0; j < script->numBytecodeTypeSets(); j++) {
-      MOZ_ASSERT(script->types()->typeArray(sweep)[j].isSubset(
-          &entry.bytecodeTypes[j]));
-    }
-  }
-#endif
-
-  for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
-    const CompilerConstraintList::FrozenScript& entry =
-        constraints->frozenScript(i);
-    JSScript* script = entry.script;
-    TypeScript* types = script->types();
-    if (!types) {
-      MOZ_CRASH();
-    }
-
-    AutoSweepTypeScript sweep(script);
-    CheckDefinitePropertiesTypeSet(sweep, cx, entry.thisTypes,
-                                   types->thisTypes(sweep, script));
-
-    unsigned nargs = script->functionNonDelazifying()
-                         ? script->functionNonDelazifying()->nargs()
-                         : 0;
-    for (size_t j = 0; j < nargs; j++) {
-      StackTypeSet* argTypes = types->argTypes(sweep, script, j);
-      CheckDefinitePropertiesTypeSet(sweep, cx, &entry.argTypes[j], argTypes);
-    }
-
-    for (size_t j = 0; j < script->numBytecodeTypeSets(); j++) {
-      CheckDefinitePropertiesTypeSet(sweep, cx, &entry.bytecodeTypes[j],
-                                     &types->typeArray(sweep)[j]);
-    }
-  }
-}
-
-namespace {
-
-// Constraint which triggers recompilation of a script if any type is added to a
-// type set. */
-class ConstraintDataFreeze {
- public:
-  ConstraintDataFreeze() {}
-
-  const char* kind() { return "freeze"; }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return true; }
-  bool invalidateOnNewPropertyState(TypeSet* property) { return true; }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    return false;
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return expected ? property.maybeTypes()->isSubset(expected)
-                    : property.maybeTypes()->empty();
-  }
-
-  bool shouldSweep() { return false; }
-
-  Compartment* maybeCompartment() { return nullptr; }
-};
-
-} /* anonymous namespace */
-
-void HeapTypeSetKey::freeze(CompilerConstraintList* constraints) {
-  LifoAlloc* alloc = constraints->alloc();
-  LifoAlloc::AutoFallibleScope fallibleAllocator(alloc);
-
-  typedef CompilerConstraintInstance<ConstraintDataFreeze> T;
-  constraints->add(alloc->new_<T>(alloc, *this, ConstraintDataFreeze()));
-}
-
-static inline jit::MIRType GetMIRTypeFromTypeFlags(TypeFlags flags) {
-  switch (flags) {
-    case TYPE_FLAG_UNDEFINED:
-      return jit::MIRType::Undefined;
-    case TYPE_FLAG_NULL:
-      return jit::MIRType::Null;
-    case TYPE_FLAG_BOOLEAN:
-      return jit::MIRType::Boolean;
-    case TYPE_FLAG_INT32:
-      return jit::MIRType::Int32;
-    case (TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE):
-      return jit::MIRType::Double;
-    case TYPE_FLAG_STRING:
-      return jit::MIRType::String;
-    case TYPE_FLAG_SYMBOL:
-      return jit::MIRType::Symbol;
-    case TYPE_FLAG_BIGINT:
-      return jit::MIRType::BigInt;
-    case TYPE_FLAG_LAZYARGS:
-      return jit::MIRType::MagicOptimizedArguments;
-    case TYPE_FLAG_ANYOBJECT:
-      return jit::MIRType::Object;
-    default:
-      return jit::MIRType::Value;
-  }
-}
-
-jit::MIRType TemporaryTypeSet::getKnownMIRType() {
-  TypeFlags flags = baseFlags();
-  jit::MIRType type;
-
-  if (baseObjectCount()) {
-    type = flags ? jit::MIRType::Value : jit::MIRType::Object;
-  } else {
-    type = GetMIRTypeFromTypeFlags(flags);
-  }
-
-  /*
-   * If the type set is totally empty then it will be treated as unknown,
-   * but we still need to record the dependency as adding a new type can give
-   * it a definite type tag. This is not needed if there are enough types
-   * that the exact tag is unknown, as it will stay unknown as more types are
-   * added to the set.
-   */
-  DebugOnly<bool> empty = flags == 0 && baseObjectCount() == 0;
-  MOZ_ASSERT_IF(empty, type == jit::MIRType::Value);
-
-  return type;
-}
-
-jit::MIRType HeapTypeSetKey::knownMIRType(CompilerConstraintList* constraints) {
-  TypeSet* types = maybeTypes();
-
-  if (!types || types->unknown()) {
-    return jit::MIRType::Value;
-  }
-
-  TypeFlags flags = types->baseFlags() & ~TYPE_FLAG_ANYOBJECT;
-  jit::MIRType type;
-
-  if (types->unknownObject() || types->getObjectCount()) {
-    type = flags ? jit::MIRType::Value : jit::MIRType::Object;
-  } else {
-    type = GetMIRTypeFromTypeFlags(flags);
-  }
-
-  if (type != jit::MIRType::Value) {
-    freeze(constraints);
-  }
-
-  /*
-   * If the type set is totally empty then it will be treated as unknown,
-   * but we still need to record the dependency as adding a new type can give
-   * it a definite type tag. This is not needed if there are enough types
-   * that the exact tag is unknown, as it will stay unknown as more types are
-   * added to the set.
-   */
-  MOZ_ASSERT_IF(types->empty(), type == jit::MIRType::Value);
-
-  return type;
-}
-
-bool HeapTypeSetKey::isOwnProperty(CompilerConstraintList* constraints,
-                                   bool allowEmptyTypesForGlobal /* = false*/) {
-  if (maybeTypes() &&
-      (!maybeTypes()->empty() || maybeTypes()->nonDataProperty())) {
-    return true;
-  }
-  if (object()->isSingleton()) {
-    JSObject* obj = object()->singleton();
-    MOZ_ASSERT(CanHaveEmptyPropertyTypesForOwnProperty(obj) ==
-               obj->is<GlobalObject>());
-    if (!allowEmptyTypesForGlobal) {
-      if (CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
-        return true;
-      }
-    }
-  }
-  freeze(constraints);
-  return false;
-}
-
-bool HeapTypeSetKey::knownSubset(CompilerConstraintList* constraints,
-                                 const HeapTypeSetKey& other) {
-  if (!maybeTypes() || maybeTypes()->empty()) {
-    freeze(constraints);
-    return true;
-  }
-  if (!other.maybeTypes() || !maybeTypes()->isSubset(other.maybeTypes())) {
-    return false;
-  }
-  freeze(constraints);
-  return true;
-}
-
-JSObject* TemporaryTypeSet::maybeSingleton() {
-  if (baseFlags() != 0 || baseObjectCount() != 1) {
-    return nullptr;
-  }
-
-  return getSingleton(0);
-}
-
-TemporaryTypeSet::ObjectKey* TemporaryTypeSet::maybeSingleObject() {
-  if (baseFlags() != 0 || baseObjectCount() != 1) {
-    return nullptr;
-  }
-
-  return getObject(0);
-}
-
-JSObject* HeapTypeSetKey::singleton(CompilerConstraintList* constraints) {
-  HeapTypeSet* types = maybeTypes();
-
-  if (!types || types->nonDataProperty() || types->baseFlags() != 0 ||
-      types->getObjectCount() != 1) {
-    return nullptr;
-  }
-
-  JSObject* obj = types->getSingleton(0);
-
-  if (obj) {
-    freeze(constraints);
-  }
-
-  return obj;
-}
-
-bool HeapTypeSetKey::needsBarrier(CompilerConstraintList* constraints) {
-  TypeSet* types = maybeTypes();
-  if (!types) {
-    return false;
-  }
-  bool result = types->unknownObject() || types->getObjectCount() > 0 ||
-                types->hasAnyFlag(TYPE_FLAG_PRIMITIVE_GCTHING);
-  if (!result) {
-    freeze(constraints);
-  }
-  return result;
-}
-
-namespace {
-
-// Constraint which triggers recompilation if an object acquires particular
-// flags.
-class ConstraintDataFreezeObjectFlags {
- public:
-  // Flags we are watching for on this object.
-  ObjectGroupFlags flags;
-
-  explicit ConstraintDataFreezeObjectFlags(ObjectGroupFlags flags)
-      : flags(flags) {
-    MOZ_ASSERT(flags);
-  }
-
-  const char* kind() { return "freezeObjectFlags"; }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return false; }
-  bool invalidateOnNewPropertyState(TypeSet* property) { return false; }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    return group->hasAnyFlags(sweep, flags);
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return !invalidateOnNewObjectState(sweep, property.object()->maybeGroup());
-  }
-
-  bool shouldSweep() { return false; }
-
-  Compartment* maybeCompartment() { return nullptr; }
-};
-
-} /* anonymous namespace */
-
-bool TypeSet::ObjectKey::hasFlags(CompilerConstraintList* constraints,
-                                  ObjectGroupFlags flags) {
-  MOZ_ASSERT(flags);
-
-  if (ObjectGroup* group = maybeGroup()) {
-    AutoSweepObjectGroup sweep(group);
-    if (group->hasAnyFlags(sweep, flags)) {
-      return true;
-    }
-  }
-
-  HeapTypeSetKey objectProperty = property(JSID_EMPTY);
-  LifoAlloc* alloc = constraints->alloc();
-
-  typedef CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> T;
-  constraints->add(alloc->new_<T>(alloc, objectProperty,
-                                  ConstraintDataFreezeObjectFlags(flags)));
-  return false;
-}
-
-bool TypeSet::ObjectKey::hasStableClassAndProto(
-    CompilerConstraintList* constraints) {
-  return !hasFlags(constraints, OBJECT_FLAG_UNKNOWN_PROPERTIES);
-}
-
-bool TemporaryTypeSet::hasObjectFlags(CompilerConstraintList* constraints,
-                                      ObjectGroupFlags flags) {
-  if (unknownObject()) {
-    return true;
-  }
-
-  /*
-   * Treat type sets containing no objects as having all object flags,
-   * to spare callers from having to check this.
-   */
-  if (baseObjectCount() == 0) {
-    return true;
-  }
-
-  unsigned count = getObjectCount();
-  for (unsigned i = 0; i < count; i++) {
-    ObjectKey* key = getObject(i);
-    if (key && key->hasFlags(constraints, flags)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-gc::InitialHeap ObjectGroup::initialHeap(CompilerConstraintList* constraints) {
-  // If this object is not required to be pretenured but could be in the
-  // future, add a constraint to trigger recompilation if the requirement
-  // changes.
-
-  AutoSweepObjectGroup sweep(this);
-  if (shouldPreTenure(sweep)) {
-    return gc::TenuredHeap;
-  }
-
-  if (!canPreTenure(sweep)) {
-    return gc::DefaultHeap;
-  }
-
-  HeapTypeSetKey objectProperty =
-      TypeSet::ObjectKey::get(this)->property(JSID_EMPTY);
-  LifoAlloc* alloc = constraints->alloc();
-
-  typedef CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> T;
-  constraints->add(
-      alloc->new_<T>(alloc, objectProperty,
-                     ConstraintDataFreezeObjectFlags(OBJECT_FLAG_PRE_TENURE)));
-
-  return gc::DefaultHeap;
-}
-
-namespace {
-
-// Constraint which triggers recompilation when a typed array's data becomes
-// invalid.
-class ConstraintDataFreezeObjectForTypedArrayData {
-  NativeObject* obj;
-
-  void* viewData;
-  uint32_t length;
-
- public:
-  explicit ConstraintDataFreezeObjectForTypedArrayData(TypedArrayObject& tarray)
-      : obj(&tarray),
-        viewData(tarray.dataPointerUnshared()),
-        length(tarray.length()) {
-    MOZ_ASSERT(tarray.isSingleton());
-    MOZ_ASSERT(!tarray.isSharedMemory());
-  }
-
-  const char* kind() { return "freezeObjectForTypedArrayData"; }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return false; }
-  bool invalidateOnNewPropertyState(TypeSet* property) { return false; }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    MOZ_ASSERT(obj->group() == group);
-    TypedArrayObject& tarr = obj->as<TypedArrayObject>();
-    return tarr.dataPointerUnshared() != viewData || tarr.length() != length;
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return !invalidateOnNewObjectState(sweep, property.object()->maybeGroup());
-  }
-
-  bool shouldSweep() {
-    // Note: |viewData| is only used for equality testing.
-    return IsAboutToBeFinalizedUnbarriered(&obj);
-  }
-
-  Compartment* maybeCompartment() { return obj->compartment(); }
-};
-
-} /* anonymous namespace */
-
-void TypeSet::ObjectKey::watchStateChangeForTypedArrayData(
-    CompilerConstraintList* constraints) {
-  TypedArrayObject& tarray = singleton()->as<TypedArrayObject>();
-  HeapTypeSetKey objectProperty = property(JSID_EMPTY);
-  LifoAlloc* alloc = constraints->alloc();
-
-  typedef CompilerConstraintInstance<
-      ConstraintDataFreezeObjectForTypedArrayData>
-      T;
-  constraints->add(
-      alloc->new_<T>(alloc, objectProperty,
-                     ConstraintDataFreezeObjectForTypedArrayData(tarray)));
-}
-
-static void ObjectStateChange(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                              ObjectGroup* group, bool markingUnknown) {
-  if (group->unknownProperties(sweep)) {
-    return;
-  }
-
-  /* All constraints listening to state changes are on the empty id. */
-  HeapTypeSet* types = group->maybeGetProperty(sweep, JSID_EMPTY);
-
-  /* Mark as unknown after getting the types, to avoid assertion. */
-  if (markingUnknown) {
-    group->addFlags(sweep,
-                    OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES);
-  }
-
-  if (types) {
-    if (!cx->helperThread()) {
-      TypeConstraint* constraint = types->constraintList(sweep);
-      while (constraint) {
-        constraint->newObjectState(cx, group);
-        constraint = constraint->next();
-      }
-    } else {
-      MOZ_ASSERT(!types->constraintList(sweep));
-    }
-  }
-}
-
-namespace {
-
-class ConstraintDataFreezePropertyState {
- public:
-  enum Which { NON_DATA, NON_WRITABLE } which;
-
-  explicit ConstraintDataFreezePropertyState(Which which) : which(which) {}
-
-  const char* kind() {
-    return (which == NON_DATA) ? "freezeNonDataProperty"
-                               : "freezeNonWritableProperty";
-  }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return false; }
-  bool invalidateOnNewPropertyState(TypeSet* property) {
-    return (which == NON_DATA) ? property->nonDataProperty()
-                               : property->nonWritableProperty();
-  }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    return false;
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return !invalidateOnNewPropertyState(property.maybeTypes());
-  }
-
-  bool shouldSweep() { return false; }
-
-  Compartment* maybeCompartment() { return nullptr; }
-};
-
-} /* anonymous namespace */
-
-bool HeapTypeSetKey::nonData(CompilerConstraintList* constraints) {
-  if (maybeTypes() && maybeTypes()->nonDataProperty()) {
-    return true;
-  }
-
-  LifoAlloc* alloc = constraints->alloc();
-
-  typedef CompilerConstraintInstance<ConstraintDataFreezePropertyState> T;
-  constraints->add(
-      alloc->new_<T>(alloc, *this,
-                     ConstraintDataFreezePropertyState(
-                         ConstraintDataFreezePropertyState::NON_DATA)));
-  return false;
-}
-
-bool HeapTypeSetKey::nonWritable(CompilerConstraintList* constraints) {
-  if (maybeTypes() && maybeTypes()->nonWritableProperty()) {
-    return true;
-  }
-
-  LifoAlloc* alloc = constraints->alloc();
-
-  typedef CompilerConstraintInstance<ConstraintDataFreezePropertyState> T;
-  constraints->add(
-      alloc->new_<T>(alloc, *this,
-                     ConstraintDataFreezePropertyState(
-                         ConstraintDataFreezePropertyState::NON_WRITABLE)));
-  return false;
-}
-
-namespace {
-
-class ConstraintDataConstantProperty {
- public:
-  explicit ConstraintDataConstantProperty() {}
-
-  const char* kind() { return "constantProperty"; }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return false; }
-  bool invalidateOnNewPropertyState(TypeSet* property) {
-    return property->nonConstantProperty();
-  }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    return false;
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return !invalidateOnNewPropertyState(property.maybeTypes());
-  }
-
-  bool shouldSweep() { return false; }
-
-  Compartment* maybeCompartment() { return nullptr; }
-};
-
-} /* anonymous namespace */
-
-bool HeapTypeSetKey::constant(CompilerConstraintList* constraints,
-                              Value* valOut) {
-  if (nonData(constraints)) {
-    return false;
-  }
-
-  // Only singleton object properties can be marked as constants.
-  JSObject* obj = object()->singleton();
-  if (!obj || !obj->isNative()) {
-    return false;
-  }
-
-  if (maybeTypes() && maybeTypes()->nonConstantProperty()) {
-    return false;
-  }
-
-  // Get the current value of the property.
-  Shape* shape = obj->as<NativeObject>().lookupPure(id());
-  if (!shape || !shape->isDataProperty() || shape->hadOverwrite()) {
-    return false;
-  }
-
-  Value val = obj->as<NativeObject>().getSlot(shape->slot());
-
-  // If the value is a pointer to an object in the nursery, don't optimize.
-  if (val.isGCThing() && IsInsideNursery(val.toGCThing())) {
-    return false;
-  }
-
-  // If the value is a string that's not atomic, don't optimize.
-  if (val.isString() && !val.toString()->isAtom()) {
-    return false;
-  }
-
-  *valOut = val;
-
-  LifoAlloc* alloc = constraints->alloc();
-  typedef CompilerConstraintInstance<ConstraintDataConstantProperty> T;
-  constraints->add(
-      alloc->new_<T>(alloc, *this, ConstraintDataConstantProperty()));
-  return true;
-}
-
-// A constraint that never triggers recompilation.
-class ConstraintDataInert {
- public:
-  explicit ConstraintDataInert() {}
-
-  const char* kind() { return "inert"; }
-
-  bool invalidateOnNewType(TypeSet::Type type) { return false; }
-  bool invalidateOnNewPropertyState(TypeSet* property) { return false; }
-  bool invalidateOnNewObjectState(const AutoSweepObjectGroup& sweep,
-                                  ObjectGroup* group) {
-    return false;
-  }
-
-  bool constraintHolds(const AutoSweepObjectGroup& sweep, JSContext* cx,
-                       const HeapTypeSetKey& property,
-                       TemporaryTypeSet* expected) {
-    return true;
-  }
-
-  bool shouldSweep() { return false; }
-
-  Compartment* maybeCompartment() { return nullptr; }
-};
-
-bool HeapTypeSetKey::couldBeConstant(CompilerConstraintList* constraints) {
-  // Only singleton object properties can be marked as constants.
-  if (!object()->isSingleton()) {
-    return false;
-  }
-
-  if (!maybeTypes() || !maybeTypes()->nonConstantProperty()) {
-    return true;
-  }
-
-  // It is possible for a property that was not marked as constant to
-  // 'become' one, if we throw away the type property during a GC and
-  // regenerate it with the constant flag set. ObjectGroup::sweep only removes
-  // type properties if they have no constraints attached to them, so add
-  // inert constraints to pin these properties in place.
-
-  LifoAlloc* alloc = constraints->alloc();
-  typedef CompilerConstraintInstance<ConstraintDataInert> T;
-  constraints->add(alloc->new_<T>(alloc, *this, ConstraintDataInert()));
-
-  return false;
-}
-
-bool TemporaryTypeSet::filtersType(const TemporaryTypeSet* other,
-                                   Type filteredType) const {
-  if (other->unknown()) {
-    return unknown();
-  }
-
-  for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
-    Type type = PrimitiveType(TypeFlagPrimitive(flag));
-    if (type != filteredType && other->hasType(type) && !hasType(type)) {
-      return false;
-    }
-  }
-
-  if (other->unknownObject()) {
-    return unknownObject();
-  }
-
-  for (size_t i = 0; i < other->getObjectCount(); i++) {
-    ObjectKey* key = other->getObject(i);
-    if (key) {
-      Type type = ObjectType(key);
-      if (type != filteredType && !hasType(type)) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-TemporaryTypeSet::DoubleConversion TemporaryTypeSet::convertDoubleElements(
-    CompilerConstraintList* constraints) {
-  if (unknownObject() || !getObjectCount()) {
-    return AmbiguousDoubleConversion;
-  }
-
-  bool alwaysConvert = true;
-  bool maybeConvert = false;
-  bool dontConvert = false;
-
-  for (unsigned i = 0; i < getObjectCount(); i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-
-    if (key->unknownProperties()) {
-      alwaysConvert = false;
-      continue;
-    }
-
-    HeapTypeSetKey property = key->property(JSID_VOID);
-    property.freeze(constraints);
-
-    // We can't convert to double elements for objects which do not have
-    // double in their element types (as the conversion may render the type
-    // information incorrect), nor for non-array objects (as their elements
-    // may point to emptyObjectElements or emptyObjectElementsShared, which
-    // cannot be converted).
-    if (!property.maybeTypes() ||
-        !property.maybeTypes()->hasType(DoubleType()) ||
-        key->clasp() != &ArrayObject::class_) {
-      dontConvert = true;
-      alwaysConvert = false;
-      continue;
-    }
-
-    // Only bother with converting known packed arrays whose possible
-    // element types are int or double. Other arrays require type tests
-    // when elements are accessed regardless of the conversion.
-    if (property.knownMIRType(constraints) == jit::MIRType::Double &&
-        !key->hasFlags(constraints, OBJECT_FLAG_NON_PACKED)) {
-      maybeConvert = true;
-    } else {
-      alwaysConvert = false;
-    }
-  }
-
-  MOZ_ASSERT_IF(alwaysConvert, maybeConvert);
-
-  if (maybeConvert && dontConvert) {
-    return AmbiguousDoubleConversion;
-  }
-  if (alwaysConvert) {
-    return AlwaysConvertToDoubles;
-  }
-  if (maybeConvert) {
-    return MaybeConvertToDoubles;
-  }
-  return DontConvertToDoubles;
-}
-
-const Class* TemporaryTypeSet::getKnownClass(
-    CompilerConstraintList* constraints) {
-  if (unknownObject()) {
-    return nullptr;
-  }
-
-  const Class* clasp = nullptr;
-  unsigned count = getObjectCount();
-
-  for (unsigned i = 0; i < count; i++) {
-    const Class* nclasp = getObjectClass(i);
-    if (!nclasp) {
-      continue;
-    }
-
-    if (getObject(i)->unknownProperties()) {
-      return nullptr;
-    }
-
-    if (clasp && clasp != nclasp) {
-      return nullptr;
-    }
-    clasp = nclasp;
-  }
-
-  if (clasp) {
-    for (unsigned i = 0; i < count; i++) {
-      ObjectKey* key = getObject(i);
-      if (key && !key->hasStableClassAndProto(constraints)) {
-        return nullptr;
-      }
-    }
-  }
-
-  return clasp;
-}
-
-Realm* TemporaryTypeSet::getKnownRealm(CompilerConstraintList* constraints) {
-  if (unknownObject()) {
-    return nullptr;
-  }
-
-  Realm* realm = nullptr;
-  unsigned count = getObjectCount();
-
-  for (unsigned i = 0; i < count; i++) {
-    const Class* clasp = getObjectClass(i);
-    if (!clasp) {
-      continue;
-    }
-
-    // If clasp->isProxy(), this might be a cross-compartment wrapper and
-    // CCWs don't have a (single) realm, so we give up. If the object has
-    // unknownProperties(), hasStableClassAndProto (called below) will
-    // return |false| so fail now before attaching any constraints.
-    if (clasp->isProxy() || getObject(i)->unknownProperties()) {
-      return nullptr;
-    }
-
-    MOZ_ASSERT(hasSingleton(i) || hasGroup(i));
-
-    Realm* nrealm =
-        hasSingleton(i) ? getSingleton(i)->nonCCWRealm() : getGroup(i)->realm();
-    MOZ_ASSERT(nrealm);
-    if (!realm) {
-      realm = nrealm;
-      continue;
-    }
-    if (realm != nrealm) {
-      return nullptr;
-    }
-  }
-
-  if (realm) {
-    for (unsigned i = 0; i < count; i++) {
-      ObjectKey* key = getObject(i);
-      if (key && !key->hasStableClassAndProto(constraints)) {
-        return nullptr;
-      }
-    }
-  }
-
-  return realm;
-}
-
-void TemporaryTypeSet::getTypedArraySharedness(
-    CompilerConstraintList* constraints, TypedArraySharedness* sharedness) {
-  // In the future this will inspect the object set.
-  *sharedness = UnknownSharedness;
-}
-
-TemporaryTypeSet::ForAllResult TemporaryTypeSet::forAllClasses(
-    CompilerConstraintList* constraints, bool (*func)(const Class* clasp)) {
-  if (unknownObject()) {
-    return ForAllResult::MIXED;
-  }
-
-  unsigned count = getObjectCount();
-  if (count == 0) {
-    return ForAllResult::EMPTY;
-  }
-
-  bool true_results = false;
-  bool false_results = false;
-  for (unsigned i = 0; i < count; i++) {
-    const Class* clasp = getObjectClass(i);
-    if (!clasp) {
-      continue;
-    }
-    if (!getObject(i)->hasStableClassAndProto(constraints)) {
-      return ForAllResult::MIXED;
-    }
-    if (func(clasp)) {
-      true_results = true;
-      if (false_results) {
-        return ForAllResult::MIXED;
-      }
-    } else {
-      false_results = true;
-      if (true_results) {
-        return ForAllResult::MIXED;
-      }
-    }
-  }
-
-  MOZ_ASSERT(true_results != false_results);
-
-  return true_results ? ForAllResult::ALL_TRUE : ForAllResult::ALL_FALSE;
-}
-
-Scalar::Type TemporaryTypeSet::getTypedArrayType(
-    CompilerConstraintList* constraints, TypedArraySharedness* sharedness) {
-  const Class* clasp = getKnownClass(constraints);
-
-  if (clasp && IsTypedArrayClass(clasp)) {
-    if (sharedness) {
-      getTypedArraySharedness(constraints, sharedness);
-    }
-    return GetTypedArrayClassType(clasp);
-  }
-  return Scalar::MaxTypedArrayViewType;
-}
-
-bool TemporaryTypeSet::isDOMClass(CompilerConstraintList* constraints,
-                                  DOMObjectKind* kind) {
-  if (unknownObject()) {
-    return false;
-  }
-
-  *kind = DOMObjectKind::Unknown;
-  bool isFirst = true;
-
-  unsigned count = getObjectCount();
-  for (unsigned i = 0; i < count; i++) {
-    const Class* clasp = getObjectClass(i);
-    if (!clasp) {
-      continue;
-    }
-    if (!clasp->isDOMClass() ||
-        !getObject(i)->hasStableClassAndProto(constraints)) {
-      return false;
-    }
-
-    DOMObjectKind thisKind =
-        clasp->isProxy() ? DOMObjectKind::Proxy : DOMObjectKind::Native;
-    if (isFirst) {
-      *kind = thisKind;
-      isFirst = false;
-      continue;
-    }
-    if (*kind != thisKind) {
-      *kind = DOMObjectKind::Unknown;
-    }
-  }
-
-  return count > 0;
-}
-
-bool TemporaryTypeSet::maybeCallable(CompilerConstraintList* constraints) {
-  if (!maybeObject()) {
-    return false;
-  }
-
-  if (unknownObject()) {
-    return true;
-  }
-
-  unsigned count = getObjectCount();
-  for (unsigned i = 0; i < count; i++) {
-    const Class* clasp = getObjectClass(i);
-    if (!clasp) {
-      continue;
-    }
-    if (clasp->isProxy() || clasp->nonProxyCallable()) {
-      return true;
-    }
-    if (!getObject(i)->hasStableClassAndProto(constraints)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool TemporaryTypeSet::maybeEmulatesUndefined(
-    CompilerConstraintList* constraints) {
-  if (!maybeObject()) {
-    return false;
-  }
-
-  if (unknownObject()) {
-    return true;
-  }
-
-  unsigned count = getObjectCount();
-  for (unsigned i = 0; i < count; i++) {
-    // The object emulates undefined if clasp->emulatesUndefined() or if
-    // it's a WrapperObject, see EmulatesUndefined. Since all wrappers are
-    // proxies, we can just check for that.
-    const Class* clasp = getObjectClass(i);
-    if (!clasp) {
-      continue;
-    }
-    if (clasp->emulatesUndefined() || clasp->isProxy()) {
-      return true;
-    }
-    if (!getObject(i)->hasStableClassAndProto(constraints)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool TemporaryTypeSet::getCommonPrototype(CompilerConstraintList* constraints,
-                                          JSObject** proto) {
-  if (unknownObject()) {
-    return false;
-  }
-
-  *proto = nullptr;
-  bool isFirst = true;
-  unsigned count = getObjectCount();
-
-  for (unsigned i = 0; i < count; i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-
-    if (key->unknownProperties()) {
-      return false;
-    }
-
-    TaggedProto nproto = key->proto();
-    if (isFirst) {
-      if (nproto.isDynamic()) {
-        return false;
-      }
-      *proto = nproto.toObjectOrNull();
-      isFirst = false;
-    } else {
-      if (nproto != TaggedProto(*proto)) {
-        return false;
-      }
-    }
-  }
-
-  // Guard against mutating __proto__.
-  for (unsigned i = 0; i < count; i++) {
-    if (ObjectKey* key = getObject(i)) {
-      MOZ_ALWAYS_TRUE(key->hasStableClassAndProto(constraints));
-    }
-  }
-
-  return true;
-}
-
-bool TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList* constraints,
-                                            jsid id) {
-  if (unknownObject()) {
-    return true;
-  }
-
-  for (unsigned i = 0; i < getObjectCount(); i++) {
-    ObjectKey* key = getObject(i);
-    if (!key) {
-      continue;
-    }
-
-    if (key->unknownProperties()) {
-      return true;
-    }
-
-    HeapTypeSetKey property = key->property(id);
-    if (property.needsBarrier(constraints)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool js::ClassCanHaveExtraProperties(const Class* clasp) {
-  return clasp->getResolve() || clasp->getOpsLookupProperty() ||
-         clasp->getOpsGetProperty() || IsTypedArrayClass(clasp);
-}
-
-void TypeZone::processPendingRecompiles(FreeOp* fop,
-                                        RecompileInfoVector& recompiles) {
-  MOZ_ASSERT(!recompiles.empty());
-
-  // Steal the list of scripts to recompile, to make sure we don't try to
-  // recursively recompile them. Note: the move constructor will not reset the
-  // length if the Vector is using inline storage, so we also use clear().
-  RecompileInfoVector pending(std::move(recompiles));
-  recompiles.clear();
-
-  jit::Invalidate(*this, fop, pending);
-
-  MOZ_ASSERT(recompiles.empty());
-}
-
-void TypeZone::addPendingRecompile(JSContext* cx, const RecompileInfo& info) {
-  InferSpew(ISpewOps, "addPendingRecompile: %p:%s:%u", info.script(),
-            info.script()->filename(), info.script()->lineno());
-
-  AutoEnterOOMUnsafeRegion oomUnsafe;
-  RecompileInfoVector& vector =
-      cx->zone()->types.activeAnalysis->pendingRecompiles;
-  if (!vector.append(info)) {
-    // BUG 1536159: For diagnostics, compute the size of the failed allocation.
-    // This presumes the vector growth strategy is to double. This is only used
-    // for crash reporting so not a problem if we get it wrong.
-    size_t allocSize = 2 * sizeof(RecompileInfo) * vector.capacity();
-    oomUnsafe.crash(allocSize, "Could not update pendingRecompiles");
-  }
-}
-
-void TypeZone::addPendingRecompile(JSContext* cx, JSScript* script) {
-  MOZ_ASSERT(script);
-
-  CancelOffThreadIonCompile(script);
-
-  // Let the script warm up again before attempting another compile.
-  script->resetWarmUpCounterToDelayIonCompilation();
-
-  if (script->hasIonScript()) {
-    addPendingRecompile(
-        cx, RecompileInfo(script, script->ionScript()->compilationId()));
-  }
-
-  // Trigger recompilation of any callers inlining this script.
-  if (TypeScript* types = script->types()) {
-    AutoSweepTypeScript sweep(script);
-    for (const RecompileInfo& info : types->inlinedCompilations(sweep)) {
-      addPendingRecompile(cx, info);
-    }
-    types->inlinedCompilations(sweep).clearAndFree();
-  }
-}
-
-#ifdef JS_CRASH_DIAGNOSTICS
-void js::ReportMagicWordFailure(uintptr_t actual, uintptr_t expected) {
-  MOZ_CRASH_UNSAFE_PRINTF("Got 0x%" PRIxPTR " expected magic word 0x%" PRIxPTR,
-                          actual, expected);
-}
-
-void js::ReportMagicWordFailure(uintptr_t actual, uintptr_t expected,
-                                uintptr_t flags, uintptr_t objectSet) {
-  MOZ_CRASH_UNSAFE_PRINTF("Got 0x%" PRIxPTR " expected magic word 0x%" PRIxPTR
-                          " flags 0x%" PRIxPTR " objectSet 0x%" PRIxPTR,
-                          actual, expected, flags, objectSet);
-}
-#endif
-
-void js::PrintTypes(JSContext* cx, Compartment* comp, bool force) {
-#ifdef DEBUG
-  gc::AutoSuppressGC suppressGC(cx);
-
-  Zone* zone = comp->zone();
-  AutoEnterAnalysis enter(nullptr, zone);
-
-  if (!force && !InferSpewActive(ISpewResult)) {
-    return;
-  }
-
-  RootedScript script(cx);
-  for (auto iter = zone->cellIter<JSScript>(); !iter.done(); iter.next()) {
-    script = iter;
-    if (TypeScript* types = script->types()) {
-      types->printTypes(cx, script);
-    }
-  }
-
-  for (auto group = zone->cellIter<ObjectGroup>(); !group.done();
-       group.next()) {
-    AutoSweepObjectGroup sweep(group);
-    group->print(sweep);
-  }
-#endif
-}
-
-/////////////////////////////////////////////////////////////////////
-// ObjectGroup
-/////////////////////////////////////////////////////////////////////
-
-static inline void UpdatePropertyType(const AutoSweepObjectGroup& sweep,
-                                      JSContext* cx, HeapTypeSet* types,
-                                      NativeObject* obj, Shape* shape,
-                                      bool indexed) {
-  MOZ_ASSERT(obj->isSingleton() && !obj->hasLazyGroup());
-
-  if (!shape->writable()) {
-    types->setNonWritableProperty(sweep, cx);
-  }
-
-  if (shape->hasGetterValue() || shape->hasSetterValue()) {
-    types->setNonDataProperty(sweep, cx);
-    types->TypeSet::addType(TypeSet::UnknownType(), &cx->typeLifoAlloc());
-  } else if (shape->isDataProperty()) {
-    if (!indexed && types->canSetDefinite(shape->slot())) {
-      types->setDefinite(shape->slot());
-    }
-
-    const Value& value = obj->getSlot(shape->slot());
-
-    /*
-     * Don't add initial undefined types for properties of global objects
-     * that are not collated into the JSID_VOID property (see propertySet
-     * comment).
-     *
-     * Also don't add untracked values (initial uninitialized lexical magic
-     * values and optimized out values) as appearing in CallObjects, module
-     * environments or the global lexical scope.
-     */
-    MOZ_ASSERT_IF(TypeSet::IsUntrackedValue(value),
-                  obj->is<CallObject>() || obj->is<ModuleEnvironmentObject>() ||
-                      IsExtensibleLexicalEnvironment(obj));
-    if ((indexed || !value.isUndefined() ||
-         !CanHaveEmptyPropertyTypesForOwnProperty(obj)) &&
-        !TypeSet::IsUntrackedValue(value)) {
-      TypeSet::Type type = TypeSet::GetValueType(value);
-      types->TypeSet::addType(type, &cx->typeLifoAlloc());
-      types->postWriteBarrier(cx, type);
-    }
-
-    if (indexed || shape->hadOverwrite()) {
-      types->setNonConstantProperty(sweep, cx);
-    } else {
-      InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s - setConstant",
-                InferSpewColor(types), types, InferSpewColorReset(),
-                TypeSet::ObjectGroupString(obj->group()).get(),
-                TypeIdString(shape->propid()));
-    }
-  }
-}
-
-void ObjectGroup::updateNewPropertyTypes(const AutoSweepObjectGroup& sweep,
-                                         JSContext* cx, JSObject* objArg,
-                                         jsid id, HeapTypeSet* types) {
-  InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s", InferSpewColor(types),
-            types, InferSpewColorReset(),
-            TypeSet::ObjectGroupString(this).get(), TypeIdString(id));
-
-  MOZ_ASSERT_IF(objArg, objArg->group() == this);
-  MOZ_ASSERT_IF(singleton(), objArg);
-
-  if (!singleton() || !objArg->isNative()) {
-    types->setNonConstantProperty(sweep, cx);
-    return;
-  }
-
-  NativeObject* obj = &objArg->as<NativeObject>();
-
-  /*
-   * Fill the property in with any type the object already has in an own
-   * property. We are only interested in plain native properties and
-   * dense elements which don't go through a barrier when read by the VM
-   * or jitcode.
-   */
-
-  if (JSID_IS_VOID(id)) {
-    /* Go through all shapes on the object to get integer-valued properties. */
-    RootedShape shape(cx, obj->lastProperty());
-    while (!shape->isEmptyShape()) {
-      if (JSID_IS_VOID(IdToTypeId(shape->propid()))) {
-        UpdatePropertyType(sweep, cx, types, obj, shape, true);
-      }
-      shape = shape->previous();
-    }
-
-    /* Also get values of any dense elements in the object. */
-    for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
-      const Value& value = obj->getDenseElement(i);
-      if (!value.isMagic(JS_ELEMENTS_HOLE)) {
-        TypeSet::Type type = TypeSet::GetValueType(value);
-        types->TypeSet::addType(type, &cx->typeLifoAlloc());
-        types->postWriteBarrier(cx, type);
-      }
-    }
-  } else if (!JSID_IS_EMPTY(id)) {
-    RootedId rootedId(cx, id);
-    Shape* shape = obj->lookup(cx, rootedId);
-    if (shape) {
-      UpdatePropertyType(sweep, cx, types, obj, shape, false);
-    }
-  }
-}
-
-void ObjectGroup::addDefiniteProperties(JSContext* cx, Shape* shape) {
-  AutoSweepObjectGroup sweep(this);
-  if (unknownProperties(sweep)) {
-    return;
-  }
-
-  // Mark all properties of shape as definite properties of this group.
-  AutoEnterAnalysis enter(cx);
-
-  while (!shape->isEmptyShape()) {
-    jsid id = IdToTypeId(shape->propid());
-    if (!JSID_IS_VOID(id)) {
-      MOZ_ASSERT_IF(shape->slot() >= shape->numFixedSlots(),
-                    shape->numFixedSlots() == NativeObject::MAX_FIXED_SLOTS);
-      TypeSet* types = getProperty(sweep, cx, nullptr, id);
-      if (!types) {
-        MOZ_ASSERT(unknownProperties(sweep));
-        return;
-      }
-      if (types->canSetDefinite(shape->slot())) {
-        types->setDefinite(shape->slot());