Merge autoland to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Fri, 14 Feb 2020 17:50:46 +0200
changeset 513901 f8ec5d8b4718a6456446b56c40ea32c50c631d48
parent 513866 ca97340e64722330f45043b3fa8a819ad7c59835 (current diff)
parent 513900 832f445b534776525ea11b36c42bbcda249b27ac (diff)
child 514170 02b1aa498dd2269ea45fb47e7e50f3d45d26bd3c
push id37124
push usercsabou@mozilla.com
push dateFri, 14 Feb 2020 15:51:24 +0000
treeherdermozilla-central@f8ec5d8b4718 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone75.0a1
first release with
nightly linux32
f8ec5d8b4718 / 75.0a1 / 20200214155124 / files
nightly linux64
f8ec5d8b4718 / 75.0a1 / 20200214155124 / files
nightly mac
f8ec5d8b4718 / 75.0a1 / 20200214155124 / files
nightly win32
f8ec5d8b4718 / 75.0a1 / 20200214155124 / files
nightly win64
f8ec5d8b4718 / 75.0a1 / 20200214155124 / 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
js/src/jit/moz.build
testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html
toolkit/library/moz.build
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1949,20 +1949,18 @@ pref("devtools.inspector.three-pane-enab
 // Enable the 3 pane mode in the chrome inspector
 pref("devtools.inspector.chrome.three-pane-enabled", false);
 // Collapse pseudo-elements by default in the rule-view
 pref("devtools.inspector.show_pseudo_elements", false);
 // The default size for image preview tooltips in the rule-view/computed-view/markup-view
 pref("devtools.inspector.imagePreviewTooltipSize", 300);
 // Enable user agent style inspection in rule-view
 pref("devtools.inspector.showUserAgentStyles", false);
-// Show all native anonymous content
+// Show native anonymous content and user agent shadow roots
 pref("devtools.inspector.showAllAnonymousContent", false);
-// Show user agent shadow roots
-pref("devtools.inspector.showUserAgentShadowRoots", false);
 // Enable the new Rules View
 pref("devtools.inspector.new-rulesview.enabled", false);
 // Enable the compatibility tool in the inspector.
 pref("devtools.inspector.compatibility.enabled", false);
 // Enable the new Box Model Highlighter with renderer in parent process
 pref("devtools.inspector.use-new-box-model-highlighter", false);
 // Enable color scheme simulation in the inspector.
 pref("devtools.inspector.color-scheme-simulation.enabled", false);
--- a/browser/components/urlbar/tests/browser/browser_search_tips.js
+++ b/browser/components/urlbar/tests/browser/browser_search_tips.js
@@ -710,23 +710,36 @@ async function checkTip(win, expectedTip
   if (closeView) {
     await UrlbarTestUtils.promisePopupClose(win);
   }
 }
 
 async function checkTab(win, url, expectedTip, reset = true) {
   // BrowserTestUtils.withNewTab always waits for tab load, which hangs on
   // about:newtab for some reason, so don't use it.
+  let shownCount;
+  if (expectedTip) {
+    shownCount = UrlbarPrefs.get(`searchTips.${expectedTip}.shownCount`);
+  }
+
   let tab = await BrowserTestUtils.openNewForegroundTab({
     gBrowser: win.gBrowser,
     url,
     waitForLoad: url != "about:newtab",
   });
 
   await checkTip(win, expectedTip, true);
+  if (expectedTip) {
+    Assert.equal(
+      UrlbarPrefs.get(`searchTips.${expectedTip}.shownCount`),
+      shownCount + 1,
+      "The shownCount pref should have been incremented by one."
+    );
+  }
+
   if (reset) {
     resetProvider();
   }
 
   BrowserTestUtils.removeTab(tab);
 }
 
 /**
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_ua_widgets.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_ua_widgets.js
@@ -5,82 +5,80 @@
 
 const TEST_URL = `data:text/html;charset=utf-8,
   <video id="with-children" controls>
     <div>some content</div>
   </video>
   <video id="no-children" controls></video>`;
 
 add_task(async function() {
-  info(
-    "Test a <video> element with no children, showUserAgentShadowRoots=true"
-  );
-  const { inspector, markup } = await setup({ showUserAgentShadowRoots: true });
+  info("Test a <video> element with no children, showAllAnonymousContent=true");
+  const { inspector, markup } = await setup({ showAllAnonymousContent: true });
 
   info("Find the #no-children element.");
   const hostFront = await getNodeFront("#no-children", inspector);
   const hostContainer = markup.getContainer(hostFront);
   ok(
     hostContainer.canExpand,
     "<video controls/> has children in the markup view"
   );
 
   info("Expand the <video> element");
   await expandContainer(inspector, hostContainer);
-  is(hostContainer.getChildContainers().length, 1, "video has 1 child");
+  is(hostContainer.getChildContainers().length, 3, "video has 3 children");
 
   const shadowRootContainer = hostContainer.getChildContainers()[0];
   assertContainerHasText(shadowRootContainer, "#shadow-root");
 });
 
 add_task(async function() {
-  info("Test a <video> element with children, showUserAgentShadowRoots=true");
-  const { inspector, markup } = await setup({ showUserAgentShadowRoots: true });
+  info("Test a <video> element with children, showAllAnonymousContent=true");
+  const { inspector, markup } = await setup({ showAllAnonymousContent: true });
 
   info("Find the #with-children element.");
   const hostFront = await getNodeFront("#with-children", inspector);
   const hostContainer = markup.getContainer(hostFront);
   ok(
     hostContainer.canExpand,
     "<video controls/> has children in the markup view"
   );
 
   info("Expand the <video> element");
   await expandContainer(inspector, hostContainer);
-  is(hostContainer.getChildContainers().length, 2, "video has 2 children");
+  is(hostContainer.getChildContainers().length, 4, "video has 4 children");
 
   const shadowRootContainer = hostContainer.getChildContainers()[0];
   assertContainerHasText(shadowRootContainer, "#shadow-root");
 
   const divContainer = hostContainer.getChildContainers()[1];
   assertContainerHasText(divContainer, "some content");
 });
 
 add_task(async function() {
   info(
-    "Test a <video> element with no children, showUserAgentShadowRoots=false"
+    "Test a <video> element with no children, showAllAnonymousContent=false"
   );
   const { inspector, markup } = await setup({
-    showUserAgentShadowRoots: false,
+    showAllAnonymousContent: false,
   });
 
   info("Find the #no-children element.");
   const hostFront = await getNodeFront("#no-children", inspector);
   const hostContainer = markup.getContainer(hostFront);
   ok(!hostContainer.getChildContainers(), "video has no children");
   ok(
     !hostContainer.canExpand,
     "<video controls/> shows no children in the markup view"
   );
 });
 
 add_task(async function() {
-  info("Test a <video> element with children, showUserAgentShadowRoots=false");
+  info("Test a <video> element with children, showAllAnonymousContent=false");
   const { inspector, markup } = await setup({
-    showUserAgentShadowRoots: false,
+    showAllAnonymousContent: false,
   });
 
   info("Find the #with-children element.");
   const hostFront = await getNodeFront("#with-children", inspector);
   const hostContainer = markup.getContainer(hostFront);
   ok(
     hostContainer.canExpand,
     "<video controls/> has children in the markup view"
@@ -89,18 +87,18 @@ add_task(async function() {
   info("Expand the <video> element");
   await expandContainer(inspector, hostContainer);
   is(hostContainer.getChildContainers().length, 1, "video has 1 child");
 
   const divContainer = hostContainer.getChildContainers()[0];
   assertContainerHasText(divContainer, "some content");
 });
 
-async function setup({ showUserAgentShadowRoots }) {
+async function setup({ showAllAnonymousContent }) {
   await pushPref(
-    "devtools.inspector.showUserAgentShadowRoots",
-    showUserAgentShadowRoots
+    "devtools.inspector.showAllAnonymousContent",
+    showAllAnonymousContent
   );
 
   const { inspector } = await openInspectorForURL(TEST_URL);
   const { markup } = inspector;
   return { inspector, markup };
 }
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_ua_widgets_with_nac.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_ua_widgets_with_nac.js
@@ -9,51 +9,34 @@ const TEST_URL =
   <video id="video-with-subtitles" style="border: 4px solid red">
     <track label="en" kind="subtitles" srclang="en" src="data:text/vtt,WEBVTT" default>
   </video>`);
 
 const TEST_ID = "#video-with-subtitles";
 
 // Test that Inspector can show Native Anonymous Content (nac) in user agent widgets, as
 // siblings of the ua widget closed shadow-root.
-
-add_task(async function testWithoutShowAllAnonymousContent() {
-  info(
-    "Test a <video> element with subtitles, without showAllAnonymousContent"
-  );
-  const { inspector } = await setup({ showAllAnonymousContent: false });
-
-  // We should only see the shadow root and the authored <track> element.
-  const tree = `
-  video
-    #shadow-root!ignore-children
-    track`;
-  await assertMarkupViewAsTree(tree, TEST_ID, inspector);
-});
-
-add_task(async function testWithShowAllAnonymousContent() {
+add_task(async function testMarkupView() {
   info(
     "Test a <video> element with subtitles, expect to see native anonymous content"
   );
-  const { inspector } = await setup({ showAllAnonymousContent: true });
+  const { inspector } = await setup();
 
   // We should only see the shadow root, the <track> and two NAC elements <img> and <div>.
   const tree = `
   video
     #shadow-root!ignore-children
     track
     img
     class="caption-box"`;
   await assertMarkupViewAsTree(tree, TEST_ID, inspector);
 });
 
 add_task(async function testElementPicker() {
-  const { inspector, markup, toolbox, testActor } = await setup({
-    showAllAnonymousContent: true,
-  });
+  const { inspector, markup, toolbox, testActor } = await setup();
 
   info("Waiting for element picker to become active.");
   await startPicker(toolbox);
 
   info("Move mouse over the video element and pick");
   await hoverElement(inspector, testActor, TEST_ID, 50, 50);
   await pickElement(inspector, testActor, TEST_ID, 50, 50);
 
@@ -73,19 +56,15 @@ add_task(async function testElementPicke
 
   const moreNodesLink = markup.doc.querySelector(".more-nodes");
   ok(
     !moreNodesLink,
     "There is no 'more nodes' button displayed in the markup view"
   );
 });
 
-async function setup({ showAllAnonymousContent }) {
-  await pushPref("devtools.inspector.showUserAgentShadowRoots", true);
-  await pushPref(
-    "devtools.inspector.showAllAnonymousContent",
-    showAllAnonymousContent
-  );
+async function setup() {
+  await pushPref("devtools.inspector.showAllAnonymousContent", true);
 
   const { inspector, testActor, toolbox } = await openInspectorForURL(TEST_URL);
   const { markup } = inspector;
   return { inspector, markup, testActor, toolbox };
 }
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -736,19 +736,15 @@ select.playback-rate-selector.devtools-b
   content: "";
   height: 100%;
   position: absolute;
   transform: translateX(-1px);
   width: 1px;
 }
 
 /* No Animation Panel */
-.animation-error-message {
-  overflow: auto;
-}
-
 .animation-error-message > p {
-  white-space: pre;
+  white-space: pre-wrap;
 }
 
 .animation-element-picker::before {
   background-image: url("chrome://devtools/skin/images/command-pick.svg");
 }
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -271,33 +271,31 @@ var WalkerActor = protocol.ActorClassWit
   /**
    * Create the WalkerActor
    * @param {DebuggerServerConnection} conn
    *        The server connection.
    * @param {TargetActor} targetActor
    *        The top-level Actor for this tab.
    * @param {Object} options
    *        - {Boolean} showAllAnonymousContent: Show all native anonymous content
-   *        - {Boolean} showUserAgentShadowRoots: Show shadow roots for user-agent widgets
    */
   initialize: function(conn, targetActor, options) {
     protocol.Actor.prototype.initialize.call(this, conn);
     this.targetActor = targetActor;
     this.rootWin = targetActor.window;
     this.rootDoc = this.rootWin.document;
     this._refMap = new Map();
     this._pendingMutations = [];
     this._activePseudoClassLocks = new Set();
     this._mutationBreakpoints = new WeakMap();
     this.customElementWatcher = new CustomElementWatcher(
       targetActor.chromeEventHandler
     );
 
     this.showAllAnonymousContent = options.showAllAnonymousContent;
-    this.showUserAgentShadowRoots = options.showUserAgentShadowRoots;
 
     this.walkerSearch = new WalkerSearch(this);
 
     // Nodes which have been removed from the client's known
     // ownership tree are considered "orphaned", and stored in
     // this set.
     this._orphaned = new Set();
 
@@ -936,19 +934,19 @@ var WalkerActor = protocol.ActorClassWit
     const shadowHost = isShadowHost(node.rawNode);
     const shadowRoot = isShadowRoot(node.rawNode);
 
     // UA Widgets are internal Firefox widgets such as videocontrols implemented
     // using shadow DOM. By default, their shadow root should be hidden for web
     // developers.
     const isUAWidget =
       shadowHost && node.rawNode.openOrClosedShadowRoot.isUAWidget();
-    const hideShadowRoot = isUAWidget && !this.showUserAgentShadowRoots;
+    const hideShadowRoot = isUAWidget && !this.showAllAnonymousContent;
     const showNativeAnonymousChildren =
-      isUAWidget && this.showUserAgentShadowRoots;
+      isUAWidget && this.showAllAnonymousContent;
 
     const templateElement = isTemplateElement(node.rawNode);
     if (templateElement) {
       // <template> tags should have a single child pointing to the element's template
       // content.
       const documentFragment = node.rawNode.content;
       const nodes = [documentFragment];
       return { hasFirst: true, hasLast: true, nodes };
--- a/devtools/server/tests/browser/browser_inspector-shadow.js
+++ b/devtools/server/tests/browser/browser_inspector-shadow.js
@@ -176,45 +176,45 @@ add_task(async function() {
   is(
     slotted._form.nodeValue,
     originalSlot._form.nodeValue,
     "Slotted content is the same as original's"
   );
 });
 
 add_task(async function() {
-  info("Test UA widgets when showUserAgentShadowRoots is true");
+  info("Test UA widgets when showAllAnonymousContent is true");
   await SpecialPowers.pushPrefEnv({
-    set: [["devtools.inspector.showUserAgentShadowRoots", true]],
+    set: [["devtools.inspector.showAllAnonymousContent", true]],
   });
 
   const { walker } = await initInspectorFront(URL);
 
   let el = await walker.querySelector(walker.rootNode, "#video-controls");
   let hostChildren = await walker.children(el);
-  is(hostChildren.nodes.length, 1, "#video-controls tag has one child");
+  is(hostChildren.nodes.length, 3, "#video-controls tag has 3 children");
   const shadowRoot = hostChildren.nodes[0];
   ok(shadowRoot.isShadowRoot, "#video-controls has a shadow-root child");
 
   el = await walker.querySelector(
     walker.rootNode,
     "#video-controls-with-children"
   );
   hostChildren = await walker.children(el);
   is(
     hostChildren.nodes.length,
-    2,
-    "#video-controls-with-children has two children"
+    4,
+    "#video-controls-with-children has 4 children"
   );
 });
 
 add_task(async function() {
-  info("Test UA widgets when showUserAgentShadowRoots is false");
+  info("Test UA widgets when showAllAnonymousContent is false");
   await SpecialPowers.pushPrefEnv({
-    set: [["devtools.inspector.showUserAgentShadowRoots", false]],
+    set: [["devtools.inspector.showAllAnonymousContent", false]],
   });
 
   const { walker } = await initInspectorFront(URL);
 
   let el = await walker.querySelector(walker.rootNode, "#video-controls");
   let hostChildren = await walker.children(el);
   is(hostChildren.nodes.length, 0, "#video-controls tag has no children");
 
--- a/devtools/shared/fronts/inspector.js
+++ b/devtools/shared/fronts/inspector.js
@@ -13,17 +13,16 @@ const {
 const { inspectorSpec } = require("devtools/shared/specs/inspector");
 loader.lazyRequireGetter(this, "flags", "devtools/shared/flags");
 
 const TELEMETRY_EYEDROPPER_OPENED = "DEVTOOLS_EYEDROPPER_OPENED_COUNT";
 const TELEMETRY_EYEDROPPER_OPENED_MENU =
   "DEVTOOLS_MENU_EYEDROPPER_OPENED_COUNT";
 const SHOW_ALL_ANONYMOUS_CONTENT_PREF =
   "devtools.inspector.showAllAnonymousContent";
-const SHOW_UA_SHADOW_ROOTS_PREF = "devtools.inspector.showUserAgentShadowRoots";
 const CONTENT_FISSION_ENABLED_PREF = "devtools.contenttoolbox.fission";
 const USE_NEW_BOX_MODEL_HIGHLIGHTER_PREF =
   "devtools.inspector.use-new-box-model-highlighter";
 
 const telemetry = new Telemetry();
 
 /**
  * Client side of the inspector actor, which is used to create
@@ -59,22 +58,23 @@ class InspectorFront extends FrontClassW
 
     return this._isContentFissionEnabled;
   }
 
   async _getWalker() {
     const showAllAnonymousContent = Services.prefs.getBoolPref(
       SHOW_ALL_ANONYMOUS_CONTENT_PREF
     );
-    const showUserAgentShadowRoots = Services.prefs.getBoolPref(
-      SHOW_UA_SHADOW_ROOTS_PREF
-    );
     this.walker = await this.getWalker({
       showAllAnonymousContent,
-      showUserAgentShadowRoots,
+      // Backward compatibility for Firefox 74 or older.
+      // getWalker() now uses a single boolean flag to drive the display of
+      // both anonymous content and user-agent shadow roots.
+      // Older servers used separate flags. See Bug 1613773.
+      showUserAgentShadowRoots: showAllAnonymousContent,
     });
 
     // We need to reparent the RootNode of remote iframe Walkers
     // so that their parent is the NodeFront of the <iframe>
     // element, coming from another process/target/WalkerFront.
     await this.walker.reparentRemoteFrame();
   }
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -90,16 +90,20 @@
 
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
 
 #if defined(XP_LINUX)
 #  include "mozilla/Hal.h"
 #endif
 
+#if defined(XP_WIN)
+#  include "mozilla/WindowsVersion.h"
+#endif
+
 #include "mozilla/EMEUtils.h"
 #include "mozilla/DetailedPromise.h"
 #include "mozilla/Unused.h"
 
 #include "mozilla/webgpu/Instance.h"
 #include "mozilla/dom/WindowGlobalChild.h"
 
 namespace mozilla {
@@ -1704,16 +1708,29 @@ bool Navigator::HasUserMediaSupport(JSCo
   // Emulate [SecureContext] unless media.devices.insecure.enabled=true
   return (StaticPrefs::media_navigator_enabled() ||
           StaticPrefs::media_peerconnection_enabled()) &&
          (IsSecureContextOrObjectIsFromSecureContext(cx, obj) ||
           StaticPrefs::media_devices_insecure_enabled());
 }
 
 /* static */
+bool Navigator::HasShareSupport(JSContext* cx, JSObject* obj) {
+  if (!Preferences::GetBool("dom.webshare.enabled")) {
+    return false;
+  }
+#if defined(XP_WIN) && !defined(__MINGW32__)
+  // The first public build that supports ShareCanceled API
+  return IsWindows10BuildOrLater(18956);
+#else
+  return true;
+#endif
+}
+
+/* static */
 already_AddRefed<nsPIDOMWindowInner> Navigator::GetWindowFromGlobal(
     JSObject* aGlobal) {
   nsCOMPtr<nsPIDOMWindowInner> win = xpc::WindowOrNull(aGlobal);
   return win.forget();
 }
 
 nsresult Navigator::GetPlatform(nsAString& aPlatform,
                                 nsIPrincipal* aCallerPrincipal,
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -223,16 +223,17 @@ class Navigator final : public nsISuppor
   dom::MediaCapabilities* MediaCapabilities();
   dom::MediaSession* MediaSession();
 
   AddonManager* GetMozAddonManager(ErrorResult& aRv);
 
   // WebIDL helper methods
   static bool HasUserMediaSupport(JSContext* /* unused */,
                                   JSObject* /* unused */);
+  static bool HasShareSupport(JSContext* /* unused */, JSObject* /* unused */);
 
   nsPIDOMWindowInner* GetParentObject() const { return GetWindow(); }
 
   virtual JSObject* WrapObject(JSContext* cx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   // GetWindowFromGlobal returns the inner window for this global, if
   // any, else null.
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -3103,22 +3103,44 @@ void Selection::RemoveSelectionChangeBlo
   mSelectionChangeBlockerCount--;
 }
 
 bool Selection::IsBlockingSelectionChangeEvents() const {
   return mSelectionChangeBlockerCount > 0;
 }
 
 void Selection::DeleteFromDocument(ErrorResult& aRv) {
-  if (!mFrameSelection) return;  // nothing to do
-  RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
-  nsresult rv = frameSelection->DeleteFromDocument();
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
+  if (mSelectionType != SelectionType::eNormal) {
+    return;  // Nothing to do.
+  }
+
+  // If we're already collapsed, then we do nothing (bug 719503).
+  if (IsCollapsed()) {
+    return;
   }
+
+  for (uint32_t rangeIdx = 0; rangeIdx < RangeCount(); ++rangeIdx) {
+    RefPtr<nsRange> range = GetRangeAt(rangeIdx);
+    range->DeleteContents(aRv);
+    if (aRv.Failed()) {
+      return;
+    }
+  }
+
+  // Collapse to the new location.
+  // If we deleted one character, then we move back one element.
+  // FIXME  We don't know how to do this past frame boundaries yet.
+  if (AnchorOffset() > 0) {
+    Collapse(GetAnchorNode(), AnchorOffset());
+  }
+#ifdef DEBUG
+  else {
+    printf("Don't know how to set selection back past frame boundary\n");
+  }
+#endif
 }
 
 void Selection::Modify(const nsAString& aAlter, const nsAString& aDirection,
                        const nsAString& aGranularity, ErrorResult& aRv) {
   // Silently exit if there's no selection or no focus node.
   if (!mFrameSelection || !GetAnchorFocusRange() || !GetFocusNode()) {
     return;
   }
--- a/dom/base/Selection.h
+++ b/dom/base/Selection.h
@@ -287,16 +287,18 @@ class Selection final : public nsSupport
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void ExtendJS(nsINode& aContainer, uint32_t aOffset,
                 mozilla::ErrorResult& aRv);
 
   void SelectAllChildrenJS(nsINode& aNode, mozilla::ErrorResult& aRv);
 
   /**
    * Deletes this selection from document the nodes belong to.
+   * Only if this has `SelectionType::eNormal`.
+   * TODO: mark as `MOZ_CAN_RUN_SCRIPT`.
    */
   void DeleteFromDocument(mozilla::ErrorResult& aRv);
 
   uint32_t RangeCount() const { return mRanges.Length(); }
 
   void GetType(nsAString& aOutType) const;
 
   nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv);
@@ -405,20 +407,24 @@ class Selection final : public nsSupport
   /**
    * Collapses the selection to a single point, at the specified offset
    * in the given node. When the selection is collapsed, and the content
    * is focused and editable, the caret will blink there.
    * @param aContainer The given node where the selection will be set
    * @param offset      Where in given dom node to place the selection (the
    *                    offset into the given node)
    */
+  // TODO: mark as `MOZ_CAN_RUN_SCRIPT`
+  // (https://bugzilla.mozilla.org/show_bug.cgi?id=1615296).
   void Collapse(nsINode& aContainer, uint32_t aOffset, ErrorResult& aRv) {
     Collapse(RawRangeBoundary(&aContainer, aOffset), aRv);
   }
 
+  // TODO: this should be `MOZ_CAN_RUN_SCRIPT` instead
+  // (https://bugzilla.mozilla.org/show_bug.cgi?id=1615296).
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void Collapse(const RawRangeBoundary& aPoint, ErrorResult& aRv);
 
   /**
    * Collapses the whole selection to a single point at the start
    * of the current selection (irrespective of direction).  If content
    * is focused and editable, the caret will blink there.
    */
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -4958,58 +4958,50 @@ void nsGlobalWindowOuter::PrintOuter(Err
                                  ? GetCurrentInnerWindowInternal()->mDoc.get()
                                  : nullptr);
 
     nsCOMPtr<nsIPrintSettingsService> printSettingsService =
         do_GetService("@mozilla.org/gfx/printsettings-service;1");
 
     nsCOMPtr<nsIPrintSettings> printSettings;
     if (printSettingsService) {
-      bool printSettingsAreGlobal =
-          Preferences::GetBool("print.use_global_printsettings", false);
-
-      if (printSettingsAreGlobal) {
-        printSettingsService->GetGlobalPrintSettings(
-            getter_AddRefs(printSettings));
-
-        nsAutoString printerName;
-        printSettings->GetPrinterName(printerName);
-
-        bool shouldGetDefaultPrinterName = printerName.IsEmpty();
+      printSettingsService->GetGlobalPrintSettings(
+          getter_AddRefs(printSettings));
+
+      nsAutoString printerName;
+      printSettings->GetPrinterName(printerName);
+
+      bool shouldGetDefaultPrinterName = printerName.IsEmpty();
 #  ifdef MOZ_X11
-        // In Linux, GTK backend does not support per printer settings.
-        // Calling GetDefaultPrinterName causes a sandbox violation (see Bug
-        // 1329216). The printer name is not needed anywhere else on Linux
-        // before it gets to the parent. In the parent, we will then query the
-        // default printer name if no name is set. Unless we are in the parent,
-        // we will skip this part.
-        if (!XRE_IsParentProcess()) {
-          shouldGetDefaultPrinterName = false;
-        }
+      // In Linux, GTK backend does not support per printer settings.
+      // Calling GetDefaultPrinterName causes a sandbox violation (see Bug
+      // 1329216). The printer name is not needed anywhere else on Linux
+      // before it gets to the parent. In the parent, we will then query the
+      // default printer name if no name is set. Unless we are in the parent,
+      // we will skip this part.
+      if (!XRE_IsParentProcess()) {
+        shouldGetDefaultPrinterName = false;
+      }
 #  endif
-        if (shouldGetDefaultPrinterName) {
-          printSettingsService->GetDefaultPrinterName(printerName);
-          printSettings->SetPrinterName(printerName);
-        }
-        printSettingsService->InitPrintSettingsFromPrinter(printerName,
-                                                           printSettings);
-        printSettingsService->InitPrintSettingsFromPrefs(
-            printSettings, true, nsIPrintSettings::kInitSaveAll);
-      } else {
-        printSettingsService->GetNewPrintSettings(
-            getter_AddRefs(printSettings));
+      if (shouldGetDefaultPrinterName) {
+        printSettingsService->GetDefaultPrinterName(printerName);
+        printSettings->SetPrinterName(printerName);
       }
+      printSettingsService->InitPrintSettingsFromPrinter(printerName,
+                                                         printSettings);
+      printSettingsService->InitPrintSettingsFromPrefs(
+          printSettings, true, nsIPrintSettings::kInitSaveAll);
 
       EnterModalState();
       webBrowserPrint->Print(printSettings, nullptr);
       LeaveModalState();
 
       bool savePrintSettings =
           Preferences::GetBool("print.save_print_settings", false);
-      if (printSettingsAreGlobal && savePrintSettings) {
+      if (savePrintSettings) {
         printSettingsService->SavePrintSettingsToPrefs(
             printSettings, true, nsIPrintSettings::kInitSaveAll);
         printSettingsService->SavePrintSettingsToPrefs(
             printSettings, false, nsIPrintSettings::kInitSavePrinterName);
       }
     } else {
       webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
       webBrowserPrint->Print(printSettings, nullptr);
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -9593,83 +9593,37 @@ void ClearRequestBase::DeleteFiles(Quota
     nsCString origin;
     bool persisted;
     rv = aQuotaManager->GetDirectoryMetadata2WithRestore(
         file, persistent, &timestamp, &persisted, suffix, group, origin);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
-    bool hasOtherClient = false;
-
     if (!mClientType.IsNull()) {
-      // Checking whether there is any other client in the directory is needed.
-      // If there is not, removing whole directory is needed.
-      nsCOMPtr<nsIDirectoryEnumerator> originEntries;
-      if (NS_WARN_IF(NS_FAILED(
-              file->GetDirectoryEntries(getter_AddRefs(originEntries)))) ||
-          !originEntries) {
+      nsAutoString clientDirectoryName;
+      bool ok = Client::TypeToText(mClientType.Value(), clientDirectoryName,
+                                   fallible);
+      if (NS_WARN_IF(!ok)) {
+        return;
+      }
+
+      rv = file->Append(clientDirectoryName);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
         return;
       }
 
-      nsCOMPtr<nsIFile> clientFile;
-      while (NS_SUCCEEDED((rv = originEntries->GetNextFile(
-                               getter_AddRefs(clientFile)))) &&
-             clientFile) {
-        bool isDirectory;
-        rv = clientFile->IsDirectory(&isDirectory);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return;
-        }
-
-        if (!isDirectory) {
-          continue;
-        }
-
-        nsString leafName;
-        rv = clientFile->GetLeafName(leafName);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return;
-        }
-
-        Client::Type clientType;
-        bool ok = Client::TypeFromText(leafName, clientType, fallible);
-        if (!ok) {
-          UNKNOWN_FILE_WARNING(leafName);
-          continue;
-        }
-
-        if (clientType != mClientType.Value()) {
-          hasOtherClient = true;
-          break;
-        }
-      }
-
-      if (hasOtherClient) {
-        nsAutoString clientDirectoryName;
-        bool ok = Client::TypeToText(mClientType.Value(), clientDirectoryName,
-                                     fallible);
-        if (NS_WARN_IF(!ok)) {
-          return;
-        }
-
-        rv = file->Append(clientDirectoryName);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return;
-        }
-
-        bool exists;
-        rv = file->Exists(&exists);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return;
-        }
-
-        if (!exists) {
-          continue;
-        }
+      bool exists;
+      rv = file->Exists(&exists);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+      }
+
+      if (!exists) {
+        continue;
       }
     }
 
     for (uint32_t index = 0; index < 10; index++) {
       // We can't guarantee that this will always succeed on Windows...
       if (NS_SUCCEEDED((rv = file->Remove(true)))) {
         break;
       }
@@ -9692,23 +9646,21 @@ void ClearRequestBase::DeleteFiles(Quota
 
     // If it hasn't been initialized, we don't need to update the quota and
     // notify the removing client.
     if (!initialized) {
       return;
     }
 
     if (aPersistenceType != PERSISTENCE_TYPE_PERSISTENT) {
-      if (hasOtherClient) {
-        MOZ_ASSERT(!mClientType.IsNull());
-
+      if (mClientType.IsNull()) {
+        aQuotaManager->RemoveQuotaForOrigin(aPersistenceType, group, origin);
+      } else {
         aQuotaManager->ResetUsageForClient(aPersistenceType, group, origin,
                                            mClientType.Value());
-      } else {
-        aQuotaManager->RemoveQuotaForOrigin(aPersistenceType, group, origin);
       }
     }
 
     aQuotaManager->OriginClearCompleted(aPersistenceType, origin, mClientType);
   }
 }
 
 nsresult ClearRequestBase::DoDirectoryWork(QuotaManager* aQuotaManager) {
--- a/dom/quota/test/unit/defaultStorageDirectory_shared.json
+++ b/dom/quota/test/unit/defaultStorageDirectory_shared.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/head-shared.js
+++ b/dom/quota/test/unit/head-shared.js
@@ -22,16 +22,20 @@ function log(msg) {
 function is(a, b, msg) {
   Assert.equal(a, b, msg);
 }
 
 function ok(cond, msg) {
   Assert.ok(!!cond, msg);
 }
 
+function todo(cond, msg) {
+  todo_check_true(cond);
+}
+
 function run_test() {
   runTest();
 }
 
 if (!this.runTest) {
   this.runTest = function() {
     do_get_profile();
 
@@ -587,16 +591,20 @@ function verifyStorage(packageDefinition
 
       if (expectedEntry) {
         log(`${indent}Checking common entry ${sharedEntry.name}`);
 
         if (!expectedEntry.dir || !sharedEntry.dir) {
           throw new Error("A common entry must be a directory");
         }
 
+        if (!expectedEntry.entries && !sharedEntry.entries) {
+          throw new Error("A common entry must not be a leaf");
+        }
+
         if (sharedEntry.entries) {
           if (!expectedEntry.entries) {
             expectedEntry.entries = [];
           }
 
           addSharedEntries(
             expectedEntry.entries,
             sharedEntry.entries,
--- a/dom/quota/test/unit/indexedDBDirectory_shared.json
+++ b/dom/quota/test/unit/indexedDBDirectory_shared.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "indexedDB",
         "dir": true,
         "entries": [
           { "name": "invalid+++example.com", "dir": true },
--- a/dom/quota/test/unit/persistentStorageDirectory_shared.json
+++ b/dom/quota/test/unit/persistentStorageDirectory_shared.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/test_clearStorageForPrincipal.js
+++ b/dom/quota/test/unit/test_clearStorageForPrincipal.js
@@ -43,14 +43,14 @@ async function testSteps() {
     await requestFinished(request);
 
     info("Verifying");
     file = getRelativeFile(testingOrigins[i].path + removingClient);
     ok(!file.exists(), "Client file doesn't exist");
 
     file = getRelativeFile(testingOrigins[i].path);
     if (testingOrigins[i].only_idb) {
-      ok(!file.exists(), "Origin file doesn't exist");
+      todo(!file.exists(), "Origin file doesn't exist");
     } else {
       ok(file.exists(), "Origin file does exist");
     }
   }
 }
--- a/dom/quota/test/unit/upgrades/indexedDBAndPersistentStorageDirectory_profile.json
+++ b/dom/quota/test/unit/upgrades/indexedDBAndPersistentStorageDirectory_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "indexedDB",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/indexedDBDirectory_flatOriginDirectories_profile.json
+++ b/dom/quota/test/unit/upgrades/indexedDBDirectory_flatOriginDirectories_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "indexedDB",
         "dir": true,
         "entries": [
           { "name": "1007+f+app+++system.gaiamobile.org", "dir": true },
--- a/dom/quota/test/unit/upgrades/indexedDBDirectory_profile.json
+++ b/dom/quota/test/unit/upgrades/indexedDBDirectory_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "indexedDB",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/persistentAndDefaultStorageDirectory_profile.json
+++ b/dom/quota/test/unit/upgrades/persistentAndDefaultStorageDirectory_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/persistentStorageDirectory_flatOriginDirectories_profile.json
+++ b/dom/quota/test/unit/upgrades/persistentStorageDirectory_flatOriginDirectories_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/persistentStorageDirectory_originDirectories_profile.json
+++ b/dom/quota/test/unit/upgrades/persistentStorageDirectory_originDirectories_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/persistentStorageDirectory_profile.json
+++ b/dom/quota/test/unit/upgrades/persistentStorageDirectory_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/test_upgradeFromFlatOriginDirectories.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromFlatOriginDirectories.js
@@ -70,16 +70,20 @@ function* testSteps() {
   ];
 
   const metadataFileName = ".metadata";
 
   for (const setup of setups) {
     clear(continueToNextStepSync);
     yield undefined;
 
+    info("Verifying storage");
+
+    verifyStorage(setup.packages, "beforeInstall");
+
     info("Installing packages");
 
     installPackages(setup.packages);
 
     info("Verifying storage");
 
     verifyStorage(setup.packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeFromIndexedDBDirectory.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromIndexedDBDirectory.js
@@ -34,16 +34,20 @@ function* testSteps() {
     "../indexedDBDirectory_shared",
   ];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing package");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeFromIndexedDBDirectory_removeOldDirectory.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromIndexedDBDirectory_removeOldDirectory.js
@@ -19,16 +19,20 @@ async function testSteps() {
     "../persistentStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   let request = clear();
   await requestFinished(request);
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory.js
@@ -222,16 +222,20 @@ function* testSteps() {
     "../persistentStorageDirectory_shared",
   ];
 
   let metadataBuffers = [];
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory_removeOldDirectory.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory_removeOldDirectory.js
@@ -20,16 +20,20 @@ async function testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   let request = clear();
   await requestFinished(request);
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory_upgradeOriginDirectories.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeFromPersistentStorageDirectory_upgradeOriginDirectories.js
@@ -40,16 +40,20 @@ function* testSteps() {
     // directories).
     "persistentStorageDirectory_originDirectories_profile",
     "../persistentStorageDirectory_shared",
   ];
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom0_0.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom0_0.js
@@ -40,16 +40,20 @@ function* testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_removeAppsData.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_removeAppsData.js
@@ -34,16 +34,20 @@ function* testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_removeMorgueDirectory.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_removeMorgueDirectory.js
@@ -18,16 +18,20 @@ function* testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_stripObsoleteOriginAttributes.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom1_0_stripObsoleteOriginAttributes.js
@@ -50,16 +50,20 @@ function* testSteps() {
 
   let metadataBuffers = [];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_0.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_0.js
@@ -36,16 +36,20 @@ function* testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_1.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_1.js
@@ -40,16 +40,20 @@ async function testSteps() {
     "../defaultStorageDirectory_shared",
   ];
 
   info("Clearing");
 
   let request = clear();
   await requestFinished(request);
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_2.js
+++ b/dom/quota/test/unit/upgrades/test_upgradeStorageFrom2_2.js
@@ -28,16 +28,20 @@ async function testSteps() {
     conn.close();
   }
 
   info("Clearing");
 
   let request = clear();
   await requestFinished(request);
 
+  info("Verifying storage");
+
+  verifyStorage(packages, "beforeInstall");
+
   info("Installing packages");
 
   installPackages(packages);
 
   info("Verifying storage");
 
   verifyStorage(packages, "afterInstall");
 
--- a/dom/quota/test/unit/upgrades/version0_0_profile.json
+++ b/dom/quota/test/unit/upgrades/version0_0_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version1_0_appsData_profile.json
+++ b/dom/quota/test/unit/upgrades/version1_0_appsData_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version1_0_morgueDirectory_profile.json
+++ b/dom/quota/test/unit/upgrades/version1_0_morgueDirectory_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version1_0_obsoleteOriginAttributes_profile.json
+++ b/dom/quota/test/unit/upgrades/version1_0_obsoleteOriginAttributes_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version2_0_profile.json
+++ b/dom/quota/test/unit/upgrades/version2_0_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version2_1_profile.json
+++ b/dom/quota/test/unit/upgrades/version2_1_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [
       {
         "name": "storage",
         "dir": true,
         "entries": [
           {
--- a/dom/quota/test/unit/upgrades/version2_2_profile.json
+++ b/dom/quota/test/unit/upgrades/version2_2_profile.json
@@ -1,9 +1,10 @@
 [
+  { "key": "beforeInstall", "entries": [] },
   {
     "key": "afterInstall",
     "entries": [{ "name": "storage.sqlite", "dir": false }]
   },
   {
     "key": "afterInit",
     "entries": [
       {
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -322,24 +322,24 @@ interface mixin NavigatorAutomationInfor
 // https://www.w3.org/TR/clipboard-apis/#navigator-interface
 partial interface Navigator {
   [Pref="dom.events.asyncClipboard", SecureContext, SameObject]
   readonly attribute Clipboard clipboard;
 };
 
 // https://wicg.github.io/web-share/#navigator-interface
 partial interface Navigator {
-  [SecureContext, Throws, Pref="dom.webshare.enabled"]
+  [SecureContext, Throws, Func="Navigator::HasShareSupport"]
   Promise<void> share(optional ShareData data = {});
 };
 // https://wicg.github.io/web-share/#sharedata-dictionary
 dictionary ShareData {
   USVString title;
   USVString text;
   USVString url;
 };
 
 // https://w3c.github.io/mediasession/#idl-index
 [Exposed=Window]
 partial interface Navigator {
   [Pref="dom.media.mediasession.enabled", SameObject]
   readonly attribute MediaSession mediaSession;
-};
\ No newline at end of file
+};
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -3930,27 +3930,48 @@ class HTMLEditor final : public TextEdit
   nsresult CreateDOMFragmentFromPaste(
       const nsAString& aInputString, const nsAString& aContextStr,
       const nsAString& aInfoStr, nsCOMPtr<nsINode>* outFragNode,
       nsCOMPtr<nsINode>* outStartNode, nsCOMPtr<nsINode>* outEndNode,
       int32_t* outStartOffset, int32_t* outEndOffset, bool aTrustedInput);
   nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
                          Document* aTargetDoc,
                          dom::DocumentFragment** aFragment, bool aTrustedInput);
-  void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
-                                nsTArray<OwningNonNull<nsINode>>& outNodeList,
-                                nsINode* aStartContainer, int32_t aStartOffset,
-                                nsINode* aEndContainer, int32_t aEndOffset);
-  enum class StartOrEnd { start, end };
-  void GetListAndTableParents(StartOrEnd aStartOrEnd,
-                              nsTArray<OwningNonNull<nsINode>>& aNodeList,
-                              nsTArray<OwningNonNull<Element>>& outArray);
+  /**
+   * CollectTopMostChildNodesCompletelyInRange() collects topmost child nodes
+   * which are completely in the given range.
+   * For example, if the range points a node with its container node, the
+   * result is only the node (meaning does not include its descendants).
+   * If the range starts start of a node and ends end of it, and if the node
+   * does not have children, returns no nodes, otherwise, if the node has
+   * some children, the result includes its all children (not including their
+   * descendants).
+   *
+   * @param aStartPoint         Start point of the range.
+   * @param aEndPoint           End point of the range.
+   * @param aOutArrayOfNodes    [Out] Topmost children which are completely in
+   *                            the range.
+   */
+  static void CollectTopMostChildNodesCompletelyInRange(
+      const EditorRawDOMPoint& aStartPoint, const EditorRawDOMPoint& aEndPoint,
+      nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
+
+  /**
+   * CollectListAndTableRelatedElementsAt() collects list elements and
+   * table related elements from aNode (meaning aNode may be in the first of
+   * the result) to the root element.
+   */
+  static void CollectListAndTableRelatedElementsAt(
+      nsINode& aNode,
+      nsTArray<OwningNonNull<Element>>& aOutArrayOfListAndTableElements);
+
   int32_t DiscoverPartialListsAndTables(
       nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
       nsTArray<OwningNonNull<Element>>& aListsAndTables);
+  enum class StartOrEnd { start, end };
   void ReplaceOrphanedStructure(
       StartOrEnd aStartOrEnd, nsTArray<OwningNonNull<nsINode>>& aNodeArray,
       nsTArray<OwningNonNull<Element>>& aListAndTableArray,
       int32_t aHighWaterMark);
 
   /**
    * FindReplaceableTableElement() is a helper method of
    * ReplaceOrphanedStructure().  If aNodeMaybeInTableElement is a descendant
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -236,21 +236,29 @@ nsresult HTMLEditor::DoInsertHTMLWithCon
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // we need to recalculate various things based on potentially new offsets
   // this is work to be completed at a later date (probably by jfrancis)
 
-  // make a list of what nodes in docFrag we need to move
   AutoTArray<OwningNonNull<nsINode>, 64> nodeList;
-  CreateListOfNodesToPaste(*fragmentAsNode->AsDocumentFragment(), nodeList,
-                           streamStartParent, streamStartOffset,
-                           streamEndParent, streamEndOffset);
+  // If we have stream start point information, lets use it and end point.
+  // Otherwise, we should make a range all over the document fragment.
+  EditorRawDOMPoint streamStartPoint =
+      streamStartParent
+          ? EditorRawDOMPoint(streamStartParent, streamStartOffset)
+          : EditorRawDOMPoint(fragmentAsNode, 0);
+  EditorRawDOMPoint streamEndPoint =
+      streamStartParent ? EditorRawDOMPoint(streamEndParent, streamEndOffset)
+                        : EditorRawDOMPoint::AtEndOf(*fragmentAsNode);
+  HTMLEditor::CollectTopMostChildNodesCompletelyInRange(
+      EditorRawDOMPoint(streamStartParent, streamStartOffset),
+      EditorRawDOMPoint(streamEndParent, streamEndOffset), nodeList);
 
   if (nodeList.IsEmpty()) {
     // We aren't inserting anything, but if aDoDeleteSelection is set, we do
     // want to delete everything.
     // XXX What will this do? We've already called DeleteSelectionAsSubAtion()
     //     above if insertion point is specified.
     if (aDoDeleteSelection) {
       nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
@@ -385,39 +393,44 @@ nsresult HTMLEditor::DoInsertHTMLWithCon
     pointToInsert = splitNodeResult.SplitPoint();
     if (NS_WARN_IF(!pointToInsert.IsSet())) {
       return NS_ERROR_FAILURE;
     }
   }
 
   // build up list of parents of first node in list that are either
   // lists or tables.  First examine front of paste node list.
-  AutoTArray<OwningNonNull<Element>, 4> startListAndTableArray;
-  GetListAndTableParents(StartOrEnd::start, nodeList, startListAndTableArray);
-  if (!startListAndTableArray.IsEmpty()) {
-    int32_t highWaterMark =
-        DiscoverPartialListsAndTables(nodeList, startListAndTableArray);
+  AutoTArray<OwningNonNull<Element>, 4>
+      arrayOfListAndTableRelatedElementsAtStart;
+  HTMLEditor::CollectListAndTableRelatedElementsAt(
+      nodeList[0], arrayOfListAndTableRelatedElementsAtStart);
+  if (!arrayOfListAndTableRelatedElementsAtStart.IsEmpty()) {
+    int32_t highWaterMark = DiscoverPartialListsAndTables(
+        nodeList, arrayOfListAndTableRelatedElementsAtStart);
     // if we have pieces of tables or lists to be inserted, let's force the
     // paste to deal with table elements right away, so that it doesn't orphan
     // some table or list contents outside the table or list.
     if (highWaterMark >= 0) {
       ReplaceOrphanedStructure(StartOrEnd::start, nodeList,
-                               startListAndTableArray, highWaterMark);
+                               arrayOfListAndTableRelatedElementsAtStart,
+                               highWaterMark);
     }
   }
 
   // Now go through the same process again for the end of the paste node list.
-  AutoTArray<OwningNonNull<Element>, 4> endListAndTableArray;
-  GetListAndTableParents(StartOrEnd::end, nodeList, endListAndTableArray);
-  if (!endListAndTableArray.IsEmpty()) {
-    int32_t highWaterMark =
-        DiscoverPartialListsAndTables(nodeList, endListAndTableArray);
+  AutoTArray<OwningNonNull<Element>, 4> arrayOfListAndTableRelatedElementsAtEnd;
+  HTMLEditor::CollectListAndTableRelatedElementsAt(
+      nodeList.LastElement(), arrayOfListAndTableRelatedElementsAtEnd);
+  if (!arrayOfListAndTableRelatedElementsAtEnd.IsEmpty()) {
+    int32_t highWaterMark = DiscoverPartialListsAndTables(
+        nodeList, arrayOfListAndTableRelatedElementsAtEnd);
     // don't orphan partial list or table structure
     if (highWaterMark >= 0) {
-      ReplaceOrphanedStructure(StartOrEnd::end, nodeList, endListAndTableArray,
+      ReplaceOrphanedStructure(StartOrEnd::end, nodeList,
+                               arrayOfListAndTableRelatedElementsAtEnd,
                                highWaterMark);
     }
   }
 
   MOZ_ASSERT(pointToInsert.GetContainer()->GetChildAt_Deprecated(
                  pointToInsert.Offset()) == pointToInsert.GetChild());
 
   // Loop over the node list and paste the nodes:
@@ -2704,57 +2717,44 @@ nsresult HTMLEditor::ParseFragment(const
                                   ? nsIParserUtils::SanitizerAllowStyle
                                   : nsIParserUtils::SanitizerAllowComments);
     sanitizer.Sanitize(fragment);
   }
   fragment.forget(aFragment);
   return rv;
 }
 
-void HTMLEditor::CreateListOfNodesToPaste(
-    DocumentFragment& aFragment, nsTArray<OwningNonNull<nsINode>>& outNodeList,
-    nsINode* aStartContainer, int32_t aStartOffset, nsINode* aEndContainer,
-    int32_t aEndOffset) {
-  // If no info was provided about the boundary between context and stream,
-  // then assume all is stream.
-  if (!aStartContainer) {
-    aStartContainer = &aFragment;
-    aStartOffset = 0;
-    aEndContainer = &aFragment;
-    aEndOffset = aFragment.Length();
-  }
+// static
+void HTMLEditor::CollectTopMostChildNodesCompletelyInRange(
+    const EditorRawDOMPoint& aStartPoint, const EditorRawDOMPoint& aEndPoint,
+    nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes) {
+  MOZ_ASSERT(aStartPoint.IsSetAndValid());
+  MOZ_ASSERT(aEndPoint.IsSetAndValid());
 
-  RefPtr<nsRange> docFragRange = nsRange::Create(
-      aStartContainer, aStartOffset, aEndContainer, aEndOffset, IgnoreErrors());
-  if (NS_WARN_IF(!docFragRange)) {
-    MOZ_ASSERT(docFragRange);
+  RefPtr<nsRange> range =
+      nsRange::Create(aStartPoint.ToRawRangeBoundary(),
+                      aEndPoint.ToRawRangeBoundary(), IgnoreErrors());
+  if (NS_WARN_IF(!range)) {
     return;
   }
-
-  // Now use a subtree iterator over the range to create a list of nodes
   DOMSubtreeIterator iter;
-  if (NS_WARN_IF(NS_FAILED(iter.Init(*docFragRange)))) {
+  if (NS_WARN_IF(NS_FAILED(iter.Init(*range)))) {
     return;
   }
-  iter.AppendAllNodesToArray(outNodeList);
+  iter.AppendAllNodesToArray(aOutArrayOfNodes);
 }
 
-void HTMLEditor::GetListAndTableParents(
-    StartOrEnd aStartOrEnd, nsTArray<OwningNonNull<nsINode>>& aNodeList,
-    nsTArray<OwningNonNull<Element>>& outArray) {
-  MOZ_ASSERT(aNodeList.Length());
-
-  // Build up list of parents of first (or last) node in list that are either
-  // lists, or tables.
-  int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodeList.Length() - 1 : 0;
-
-  for (nsCOMPtr<nsINode> node = aNodeList[idx]; node;
-       node = node->GetParentNode()) {
-    if (HTMLEditUtils::IsList(node) || HTMLEditUtils::IsTable(node)) {
-      outArray.AppendElement(*node->AsElement());
+// static
+void HTMLEditor::CollectListAndTableRelatedElementsAt(
+    nsINode& aNode,
+    nsTArray<OwningNonNull<Element>>& aOutArrayOfListAndTableElements) {
+  for (nsIContent* content = nsIContent::FromNode(&aNode); content;
+       content = content->GetParentElement()) {
+    if (HTMLEditUtils::IsList(content) || HTMLEditUtils::IsTable(content)) {
+      aOutArrayOfListAndTableElements.AppendElement(*content->AsElement());
     }
   }
 }
 
 int32_t HTMLEditor::DiscoverPartialListsAndTables(
     nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
     nsTArray<OwningNonNull<Element>>& aListsAndTables) {
   int32_t ret = -1;
--- a/extensions/permissions/nsPermissionManager.cpp
+++ b/extensions/permissions/nsPermissionManager.cpp
@@ -129,16 +129,20 @@ bool IsPreloadPermission(const nsACStrin
 
   return false;
 }
 
 // Array of permission types which should not be isolated by origin attributes,
 // for user context and private browsing.
 // Keep this array in sync with 'STRIPPED_PERMS' in
 // 'test_permmanager_oa_strip.js'
+// Currently only preloaded permissions are supported.
+// This is because perms are sent to the content process in bulk by perm key.
+// Non-preloaded, but OA stripped permissions would not be accessible by sites
+// in private browsing / non-default user context.
 static constexpr std::array<nsLiteralCString, 1> kStripOAPermissions = {
     {NS_LITERAL_CSTRING("cookie")}};
 
 bool IsOAForceStripPermission(const nsACString& aType) {
   if (aType.IsEmpty()) {
     return false;
   }
   for (const auto& perm : kStripOAPermissions) {
@@ -3042,18 +3046,19 @@ bool nsPermissionManager::GetPermissions
   if (NS_WARN_IF(XRE_IsContentProcess())) {
     return false;
   }
 
   for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
     PermissionHashKey* entry = iter.Get();
 
     nsAutoCString permissionKey;
-    GetKeyForOrigin(entry->GetKey()->mOrigin,
-                    IsOAForceStripPermission(aPermissionKey), permissionKey);
+    // We can't check for individual OA strip perms here.
+    // Don't force strip origin attributes.
+    GetKeyForOrigin(entry->GetKey()->mOrigin, false, permissionKey);
 
     // If the keys don't match, and we aren't getting the default "" key, then
     // we can exit early. We have to keep looking if we're getting the default
     // key, as we may see a preload permission which should be transmitted.
     if (aPermissionKey != permissionKey && !aPermissionKey.IsEmpty()) {
       continue;
     }
 
@@ -3204,16 +3209,18 @@ nsTArray<nsCString> nsPermissionManager:
     nsIPrincipal* aPrincipal) {
   MOZ_ASSERT(aPrincipal);
 
   nsTArray<nsCString> keys;
   nsCOMPtr<nsIPrincipal> prin = aPrincipal;
   while (prin) {
     // Add the key to the list
     nsCString* key = keys.AppendElement();
+    // We can't check for individual OA strip perms here.
+    // Don't force strip origin attributes.
     GetKeyForPrincipal(prin, false, *key);
 
     // Get the next subdomain principal and loop back around.
     prin = GetNextSubDomainPrincipal(prin);
   }
 
   MOZ_ASSERT(keys.Length() >= 1,
              "Every principal should have at least one key.");
--- a/gfx/layers/client/ClientContainerLayer.h
+++ b/gfx/layers/client/ClientContainerLayer.h
@@ -138,17 +138,17 @@ class ClientRefLayer : public RefLayer, 
 
  protected:
   virtual ~ClientRefLayer() { MOZ_COUNT_DTOR(ClientRefLayer); }
 
  public:
   Layer* AsLayer() override { return this; }
   ShadowableLayer* AsShadowableLayer() override { return this; }
 
-  void RenderLayer() override {}
+  void RenderLayer() override { RenderMaskLayers(this); }
 
   void ComputeEffectiveTransforms(
       const gfx::Matrix4x4& aTransformToSurface) override {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 
  private:
   ClientLayerManager* ClientManager() {
--- a/js/src/builtin/FinalizationGroupObject.cpp
+++ b/js/src/builtin/FinalizationGroupObject.cpp
@@ -22,51 +22,51 @@ using namespace js;
 // FinalizationRecordObject
 
 const JSClass FinalizationRecordObject::class_ = {
     "FinalizationRecord", JSCLASS_HAS_RESERVED_SLOTS(SlotCount),
     JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC};
 
 /* static */
 FinalizationRecordObject* FinalizationRecordObject::create(
-    JSContext* cx, HandleFinalizationGroupObject group, HandleValue holdings) {
+    JSContext* cx, HandleFinalizationGroupObject group, HandleValue heldValue) {
   MOZ_ASSERT(group);
 
   auto record = NewObjectWithNullTaggedProto<FinalizationRecordObject>(cx);
   if (!record) {
     return nullptr;
   }
 
   record->initReservedSlot(GroupSlot, ObjectValue(*group));
-  record->initReservedSlot(HoldingsSlot, holdings);
+  record->initReservedSlot(HeldValueSlot, heldValue);
 
   return record;
 }
 
 FinalizationGroupObject* FinalizationRecordObject::group() const {
   Value value = getReservedSlot(GroupSlot);
   if (value.isNull()) {
     return nullptr;
   }
   return &value.toObject().as<FinalizationGroupObject>();
 }
 
-Value FinalizationRecordObject::holdings() const {
-  return getReservedSlot(HoldingsSlot);
+Value FinalizationRecordObject::heldValue() const {
+  return getReservedSlot(HeldValueSlot);
 }
 
 bool FinalizationRecordObject::wasCleared() const {
-  MOZ_ASSERT_IF(!group(), holdings().isUndefined());
+  MOZ_ASSERT_IF(!group(), heldValue().isUndefined());
   return !group();
 }
 
 void FinalizationRecordObject::clear() {
   MOZ_ASSERT(group());
   setReservedSlot(GroupSlot, NullValue());
-  setReservedSlot(HoldingsSlot, UndefinedValue());
+  setReservedSlot(HeldValueSlot, UndefinedValue());
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // FinalizationRecordVectorObject
 
 const JSClass FinalizationRecordVectorObject::class_ = {
     "FinalizationRecordVector",
     JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_BACKGROUND_FINALIZE,
@@ -226,45 +226,45 @@ bool FinalizationGroupObject::construct(
   }
 
   Rooted<UniquePtr<ObjectWeakMap>> registrations(
       cx, cx->make_unique<ObjectWeakMap>(cx));
   if (!registrations) {
     return false;
   }
 
-  Rooted<UniquePtr<FinalizationRecordVector>> holdings(
+  Rooted<UniquePtr<FinalizationRecordVector>> records(
       cx, cx->make_unique<FinalizationRecordVector>(cx->zone()));
-  if (!holdings) {
+  if (!records) {
     return false;
   }
 
   FinalizationGroupObject* group =
       NewObjectWithClassProto<FinalizationGroupObject>(cx, proto);
   if (!group) {
     return false;
   }
 
   group->initReservedSlot(CleanupCallbackSlot, ObjectValue(*cleanupCallback));
   InitReservedSlot(group, RegistrationsSlot, registrations.release(),
                    MemoryUse::FinalizationGroupRegistrations);
-  InitReservedSlot(group, RecordsToBeCleanedUpSlot, holdings.release(),
+  InitReservedSlot(group, RecordsToBeCleanedUpSlot, records.release(),
                    MemoryUse::FinalizationGroupRecordVector);
   group->initReservedSlot(IsQueuedForCleanupSlot, BooleanValue(false));
   group->initReservedSlot(IsCleanupJobActiveSlot, BooleanValue(false));
 
   args.rval().setObject(*group);
   return true;
 }
 
 /* static */
 void FinalizationGroupObject::trace(JSTracer* trc, JSObject* obj) {
   auto group = &obj->as<FinalizationGroupObject>();
-  if (FinalizationRecordVector* holdings = group->recordsToBeCleanedUp()) {
-    holdings->trace(trc);
+  if (FinalizationRecordVector* records = group->recordsToBeCleanedUp()) {
+    records->trace(trc);
   }
   if (ObjectWeakMap* registrations = group->registrations()) {
     registrations->trace(trc);
   }
 }
 
 /* static */
 void FinalizationGroupObject::finalize(JSFreeOp* fop, JSObject* obj) {
@@ -321,17 +321,17 @@ void FinalizationGroupObject::setQueuedF
   setReservedSlot(IsQueuedForCleanupSlot, BooleanValue(value));
 }
 
 void FinalizationGroupObject::setCleanupJobActive(bool value) {
   MOZ_ASSERT(value != isCleanupJobActive());
   setReservedSlot(IsCleanupJobActiveSlot, BooleanValue(value));
 }
 
-// FinalizationGroup.prototype.register(target , holdings [, unregisterToken ])
+// FinalizationGroup.prototype.register(target, heldValue [, unregisterToken ])
 // https://tc39.es/proposal-weakrefs/#sec-finalization-group.prototype.register
 /* static */
 bool FinalizationGroupObject::register_(JSContext* cx, unsigned argc,
                                         Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // 1. Let finalizationGroup be the this value.
   // 2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
@@ -353,41 +353,42 @@ bool FinalizationGroupObject::register_(
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_OBJECT_REQUIRED,
                               "target argument to FinalizationGroup.register");
     return false;
   }
 
   RootedObject target(cx, &args[0].toObject());
 
-  // 5. If SameValue(target, holdings), throw a TypeError exception.
+  // 5. If SameValue(target, heldValue), throw a TypeError exception.
   if (args.get(1).isObject() && &args.get(1).toObject() == target) {
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_HOLDINGS);
+    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                              JSMSG_BAD_HELD_VALUE);
     return false;
   }
 
-  HandleValue holdings = args.get(1);
+  HandleValue heldValue = args.get(1);
 
   // 6. If Type(unregisterToken) is not Object,
   //    a. If unregisterToken is not undefined, throw a TypeError exception.
   if (!args.get(2).isUndefined() && !args.get(2).isObject()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BAD_UNREGISTER_TOKEN,
                               "FinalizationGroup.register");
     return false;
   }
 
   RootedObject unregisterToken(cx);
   if (!args.get(2).isUndefined()) {
     unregisterToken = &args[2].toObject();
   }
 
-  // Create the finalization record representing this target and holdings.
+  // Create the finalization record representing this target and heldValue.
   Rooted<FinalizationRecordObject*> record(
-      cx, FinalizationRecordObject::create(cx, group, holdings));
+      cx, FinalizationRecordObject::create(cx, group, heldValue));
   if (!record) {
     return false;
   }
 
   if (unregisterToken && !addRegistration(cx, group, unregisterToken, record)) {
     return false;
   }
 
@@ -505,17 +506,17 @@ bool FinalizationGroupObject::unregister
     return false;
   }
 
   RootedObject unregisterToken(cx, &args[0].toObject());
 
   // 5. Let removed be false.
   bool removed = false;
 
-  // 6. For each Record { [[Target]], [[Holdings]], [[UnregisterToken]] } cell
+  // 6. For each Record { [[Target]], [[HeldValue]], [[UnregisterToken]] } cell
   //    that is an element of finalizationGroup.[[Cells]], do
   //    a. If SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
   //       i. Remove cell from finalizationGroup.[[Cells]].
   //       ii. Set removed to true.
 
   RootedObject obj(cx, group->registrations()->lookup(unregisterToken));
   if (obj) {
     auto* records = obj->as<FinalizationRecordVectorObject>().records();
@@ -775,32 +776,32 @@ bool FinalizationIteratorObject::next(JS
                               JSMSG_STALE_FINALIZATION_GROUP_ITERATOR);
     return false;
   }
 
   // 8. If finalizationGroup.[[Cells]] contains a Record cell such that
   //    cell.[[Target]] is empty,
   //    a. Choose any such cell.
   //    b. Remove cell from finalizationGroup.[[Cells]].
-  //    c. Return CreateIterResultObject(cell.[[Holdings]], false).
+  //    c. Return CreateIterResultObject(cell.[[HeldValue]], false).
   FinalizationRecordVector* records = group->recordsToBeCleanedUp();
   size_t index = iterator->index();
   MOZ_ASSERT(index <= records->length());
 
   // Advance until we find a record that hasn't been unregistered.
   while (index < records->length() && index < INT32_MAX &&
          (*records)[index]->wasCleared()) {
     index++;
     iterator->setIndex(index);
   }
 
   if (index < records->length() && index < INT32_MAX) {
     RootedFinalizationRecordObject record(cx, (*records)[index]);
-    RootedValue holdings(cx, record->holdings());
-    JSObject* result = CreateIterResultObject(cx, holdings, false);
+    RootedValue heldValue(cx, record->heldValue());
+    JSObject* result = CreateIterResultObject(cx, heldValue, false);
     if (!result) {
       return false;
     }
 
     record->clear();
     iterator->setIndex(index + 1);
 
     args.rval().setObject(*result);
--- a/js/src/builtin/FinalizationGroupObject.h
+++ b/js/src/builtin/FinalizationGroupObject.h
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 /*
  * FinalizationGroup objects allow a program to register to receive a callback
- * after a 'target' object dies. The callback is passed a 'holdings' value (that
+ * after a 'target' object dies. The callback is passed a 'held value' (that
  * hopefully doesn't entrain the target). An 'unregister token' is an object
  * which can be used to remove multiple previous registrations in one go.
  *
  * To arrange this, the following data structures are used:
  *
  *   +--------------------------------+----------------------------+
  *   |  FinalizationGroup compartment |  Target zone / compartment |
  *   |                                |                            |
@@ -31,23 +31,23 @@
  *   |  |                    |        |         |         |        |
  *   |  |             +------+        |         |         |        |
  *   |  |           * v               |         |         |        |
  *   |  |  +----------+----------+ *  |         |         |        |
  *   |  |  | FinalizationRecord  +<-----------------------+        |
  *   |  |  +---------------------+    |         |                  |
  *   |  +--+ Group               |    |         v                  |
  *   |     +---------------------+    |     +---+---------+        |
- *   |     | Holdings            |    |     |   Target    |        |
+ *   |     | Held value          |    |     |   Target    |        |
  *   |     +---------------------+    |     +-------------+        |
  *   |                                |                            |
  *   +--------------------------------+----------------------------+
  *
  * Registering a target with a FinalizationGroup creates a FinalizationRecord
- * containing the group and the holdings. This is added to a vector of records
+ * containing the group and the heldValue. This is added to a vector of records
  * associated with the target, implemented as a map on the target's Zone. All
  * finalization records are treated as GC roots.
  *
  * When a target is registered an unregister token may be supplied. If so, this
  * is also recorded by the group and is stored in a weak map of
  * registrations. The values of this map are FinalizationRecordVector
  * objects. It's necessary to have another JSObject here because our weak map
  * implementation only supports JS types as values.
@@ -55,17 +55,17 @@
  * After a target object has been registered with a finalization group it is
  * expected that its callback will be called for that object even if the
  * finalization group itself is no longer reachable from JS. Thus the values of
  * each zone's finalization record map are treated as roots and marked at the
  * start of GC.
  *
  * The finalization record maps are also swept during GC to check for any
  * targets that are dying. For such targets the associated record list is
- * processed and for each record the holdings is queued on finalization
+ * processed and for each record the heldValue is queued on finalization
  * group. At a later time this causes the client's callback to be run.
  *
  * When targets are unregistered, the registration is looked up in the weakmap
  * and the corresponding records are cleared. These are removed from the zone's
  * record map when it is next swept.
  */
 
 #ifndef builtin_FinalizationGroupObject_h
@@ -83,30 +83,30 @@ class FinalizationRecordObject;
 class ObjectWeakMap;
 
 using HandleFinalizationGroupObject = Handle<FinalizationGroupObject*>;
 using HandleFinalizationRecordObject = Handle<FinalizationRecordObject*>;
 using RootedFinalizationGroupObject = Rooted<FinalizationGroupObject*>;
 using RootedFinalizationIteratorObject = Rooted<FinalizationIteratorObject*>;
 using RootedFinalizationRecordObject = Rooted<FinalizationRecordObject*>;
 
-// A finalization record: a pair of finalization group and holdings value.
+// A finalization record: a pair of finalization group and held value.
 class FinalizationRecordObject : public NativeObject {
-  enum { GroupSlot = 0, HoldingsSlot, SlotCount };
+  enum { GroupSlot = 0, HeldValueSlot, SlotCount };
 
  public:
   static const JSClass class_;
 
   // The group can be a CCW to a FinalizationGroupObject.
   static FinalizationRecordObject* create(JSContext* cx,
                                           HandleFinalizationGroupObject group,
-                                          HandleValue holdings);
+                                          HandleValue heldValue);
 
   FinalizationGroupObject* group() const;
-  Value holdings() const;
+  Value heldValue() const;
   bool wasCleared() const;
   void clear();
 };
 
 // A vector of FinalizationRecordObjects.
 using FinalizationRecordVector =
     GCVector<HeapPtr<FinalizationRecordObject*>, 1, js::ZoneAllocPolicy>;
 
@@ -187,18 +187,18 @@ class FinalizationGroupObject : public N
 
   static void trace(JSTracer* trc, JSObject* obj);
   static void finalize(JSFreeOp* fop, JSObject* obj);
 
   static bool hasRegisteredRecordsToBeCleanedUp(
       HandleFinalizationGroupObject group);
 };
 
-// An iterator over a finalization group's queued holdings. In the spec this is
-// called FinalizationGroupCleanupIterator.
+// An iterator over a finalization group's queued held values. In the spec this
+// is called FinalizationGroupCleanupIterator.
 class FinalizationIteratorObject : public NativeObject {
   enum { FinalizationGroupSlot = 0, IndexSlot, SlotCount };
 
  public:
   static const JSClass class_;
 
   static FinalizationIteratorObject* create(
       JSContext* cx, HandleFinalizationGroupObject group);
--- a/js/src/gc/FinalizationGroup.cpp
+++ b/js/src/gc/FinalizationGroup.cpp
@@ -36,17 +36,18 @@ bool GCRuntime::registerWithFinalization
   if (!ptr->value().append(record)) {
     ReportOutOfMemory(cx);
     return false;
   }
   return true;
 }
 
 void GCRuntime::markFinalizationGroupData(JSTracer* trc) {
-  // The finalization groups and holdings for all targets are marked as roots.
+  // The finalization groups and held values for all targets are marked as
+  // roots.
   for (GCZonesIter zone(this); !zone.done(); zone.next()) {
     auto& map = zone->finalizationRecordMap();
     for (Zone::FinalizationRecordMap::Enum e(map); !e.empty(); e.popFront()) {
       e.front().value().trace(trc);
     }
   }
 }
 
@@ -57,24 +58,24 @@ static FinalizationRecordObject* UnwrapF
     // CCWs between the compartments have been nuked. The
     // FinalizationGroup's callback doesn't run in this case.
     return nullptr;
   }
   return &obj->as<FinalizationRecordObject>();
 }
 
 void GCRuntime::sweepFinalizationGroups(Zone* zone) {
-  // Queue holdings for cleanup for any entries whose target is dying and remove
-  // them from the map. Sweep remaining unregister tokens.
+  // Queue finalization records for cleanup for any entries whose target is
+  // dying and remove them from the map. Sweep remaining unregister tokens.
 
   auto& map = zone->finalizationRecordMap();
   for (Zone::FinalizationRecordMap::Enum e(map); !e.empty(); e.popFront()) {
     auto& records = e.front().value();
     if (IsAboutToBeFinalized(&e.front().mutableKey())) {
-      // Queue holdings for targets that are dying.
+      // Queue finalization records for targets that are dying.
       for (JSObject* obj : records) {
         if (FinalizationRecordObject* record = UnwrapFinalizationRecord(obj)) {
           FinalizationGroupObject* group = record->group();
           if (group) {
             group->queueRecordToBeCleanedUp(record);
             queueFinalizationGroupForCleanup(group);
           }
         }
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -319,17 +319,17 @@ class Zone : public js::ZoneAllocator, p
 
   // List of shapes that may contain nursery pointers.
   using NurseryShapeVector =
       js::Vector<js::AccessorShape*, 0, js::SystemAllocPolicy>;
   js::ZoneData<NurseryShapeVector> nurseryShapes_;
 
   // A map from finalization group targets to a list of finalization records
   // representing groups that the target is registered with and their associated
-  // holdings.
+  // held values.
   using FinalizationRecordMap =
       GCHashMap<js::HeapPtrObject, js::gc::FinalizationRecordVector,
                 js::MovableCellHasher<js::HeapPtrObject>, js::ZoneAllocPolicy>;
   js::ZoneOrGCTaskData<FinalizationRecordMap> finalizationRecordMap_;
 
   js::ZoneOrGCTaskData<js::jit::JitZone*> jitZone_;
 
   js::MainThreadData<bool> gcScheduled_;
--- a/js/src/jit-test/tests/gc/finalizationGroup-ccw.js
+++ b/js/src/jit-test/tests/gc/finalizationGroup-ccw.js
@@ -1,52 +1,50 @@
 // |jit-test| --enable-weak-refs
 
 // Test combinations of arguments in different compartments.
 
 gczeal(0);
 
-let holdings = [];
+let heldValues = [];
 let group = new FinalizationGroup(iterator => {
-    for (const holding of iterator) {
-        holdings.push(holding);
-    }
+  heldValues.push(...iterator);
 });
 
 function ccwToObject() {
     return evalcx('({})', newGlobal({newCompartment: true}));
 }
 
 function ccwToGroup() {
-    let global = newGlobal({newCompartment: true});
-    global.holdings = holdings;
-    return global.eval(
-        `new FinalizationGroup(iterator => holdings.push(...iterator))`);
+  let global = newGlobal({newCompartment: true});
+  global.heldValues = heldValues;
+  return global.eval(
+    `new FinalizationGroup(iterator => heldValues.push(...iterator))`);
 }
 
 function incrementalGC() {
-    startgc(1);
-    while (gcstate() !== "NotActive") {
-        gcslice(1000);
-    }
+  startgc(1);
+  while (gcstate() !== "NotActive") {
+    gcslice(1000);
+  }
 }
 
 for (let w of [false, true]) {
-    for (let x of [false, true]) {
-        for (let y of [false, true]) {
-            for (let z of [false, true]) {
-                let g = w ? ccwToGroup(w) : group;
-                let target = x ? ccwToObject() : {};
-                let holding = y ? ccwToObject() : {};
-                let token = z ? ccwToObject() : {};
-                g.register(target, holding, token);
-                g.unregister(token);
-                g.register(target, holding, token);
-                target = undefined;
-                incrementalGC();
-                holdings.length = 0; // Clear, don't replace.
-                g.cleanupSome();
-                assertEq(holdings.length, 1);
-                assertEq(holdings[0], holding);
-            }
-        }
+  for (let x of [false, true]) {
+    for (let y of [false, true]) {
+      for (let z of [false, true]) {
+        let g = w ? ccwToGroup(w) : group;
+        let target = x ? ccwToObject() : {};
+        let heldValue = y ? ccwToObject() : {};
+        let token = z ? ccwToObject() : {};
+        g.register(target, heldValue, token);
+        g.unregister(token);
+        g.register(target, heldValue, token);
+        target = undefined;
+        incrementalGC();
+        heldValues.length = 0; // Clear, don't replace.
+        g.cleanupSome();
+        assertEq(heldValues.length, 1);
+        assertEq(heldValues[0], heldValue);
+      }
     }
+  }
 }
--- a/js/src/jit-test/tests/gc/finalizationGroup.js
+++ b/js/src/jit-test/tests/gc/finalizationGroup.js
@@ -1,27 +1,27 @@
 // |jit-test| --enable-weak-refs
 
 function checkPropertyDescriptor(obj, property, writable, enumerable,
                                  configurable) {
-    let desc = Object.getOwnPropertyDescriptor(obj, property);
-    assertEq(typeof desc, "object");
-    assertEq(desc.writable, writable);
-    assertEq(desc.enumerable, enumerable);
-    assertEq(desc.configurable, configurable);
+  let desc = Object.getOwnPropertyDescriptor(obj, property);
+  assertEq(typeof desc, "object");
+  assertEq(desc.writable, writable);
+  assertEq(desc.enumerable, enumerable);
+  assertEq(desc.configurable, configurable);
 }
 
 function assertThrowsTypeError(thunk) {
-    let error;
-    try {
-        thunk();
-    } catch (e) {
-        error = e;
-    }
-    assertEq(error instanceof TypeError, true);
+  let error;
+  try {
+    thunk();
+  } catch (e) {
+    error = e;
+  }
+  assertEq(error instanceof TypeError, true);
 }
 
 // 3.1 The FinalizationGroup Constructor
 assertEq(typeof this.FinalizationGroup, "function");
 
 // 3.1.1 FinalizationGroup ( cleanupCallback ) 
 assertThrowsTypeError(() => new FinalizationGroup());
 assertThrowsTypeError(() => new FinalizationGroup(1));
@@ -81,170 +81,170 @@ assertEq(typeof proto.next, "function");
 
 // 3.5.2.2 %FinalizationGroupCleanupIteratorPrototype% [ @@toStringTag ]
 assertEq(proto[Symbol.toStringTag], "FinalizationGroup Cleanup Iterator");
 checkPropertyDescriptor(proto, Symbol.toStringTag, false, false, true);
 
 // 3.5.3 Properties of FinalizationGroup Cleanup Iterator Instances
 assertEq(Object.getOwnPropertyNames(iterator).length, 0);
 
-let holdings = [];
+let heldValues = [];
 group = new FinalizationGroup(iterator => {
-    for (const holding of iterator) {
-        holdings.push(holding);
-    }
+  for (const heldValue of iterator) {
+    heldValues.push(heldValue);
+  }
 });
 
 // Test a single target.
-holdings = [];
+heldValues = [];
 group.register({}, 42);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], 42);
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], 42);
 
 // Test multiple targets.
-holdings = [];
+heldValues = [];
 for (let i = 0; i < 100; i++) {
-    group.register({}, i);
+  group.register({}, i);
 }
 gc();
 drainJobQueue();
-assertEq(holdings.length, 100);
-holdings = holdings.sort((a, b) => a - b);
+assertEq(heldValues.length, 100);
+heldValues = heldValues.sort((a, b) => a - b);
 for (let i = 0; i < 100; i++) {
-    assertEq(holdings[i], i);
+  assertEq(heldValues[i], i);
 }
 
 // Test a single object in multiple groups
-holdings = [];
-let holdings2 = [];
+heldValues = [];
+let heldValues2 = [];
 let group2 = new FinalizationGroup(iterator => {
-    for (const holding of iterator) {
-        holdings2.push(holding);
-    }
+  for (const heldValue of iterator) {
+    heldValues2.push(heldValue);
+  }
 });
 {
-    let object = {};
-    group.register(object, 1);
-    group2.register(object, 2);
-    object = null;
+  let object = {};
+  group.register(object, 1);
+  group2.register(object, 2);
+  object = null;
 }
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], 1);
-assertEq(holdings2.length, 1);
-assertEq(holdings2[0], 2);
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], 1);
+assertEq(heldValues2.length, 1);
+assertEq(heldValues2[0], 2);
 
 // Unregister a single target.
-holdings = [];
+heldValues = [];
 let token = {};
 group.register({}, 1, token);
 group.unregister(token);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 0);
+assertEq(heldValues.length, 0);
 
 // Unregister multiple targets.
-holdings = [];
+heldValues = [];
 let token2 = {};
 group.register({}, 1, token);
 group.register({}, 2, token2);
 group.register({}, 3, token);
 group.register({}, 4, token2);
 group.unregister(token);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 2);
-holdings = holdings.sort((a, b) => a - b);
-assertEq(holdings[0], 2);
-assertEq(holdings[1], 4);
+assertEq(heldValues.length, 2);
+heldValues = heldValues.sort((a, b) => a - b);
+assertEq(heldValues[0], 2);
+assertEq(heldValues[1], 4);
 
 // Watch object in another global.
 let other = newGlobal({newCompartment: true});
-holdings = [];
+heldValues = [];
 group.register(evalcx('({})', other), 1);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], 1);
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], 1);
 
-// Pass holdings from another global.
-let holding = evalcx('{}', other);
-holdings = [];
-group.register({}, holding);
+// Pass heldValues from another global.
+let heldValue = evalcx('{}', other);
+heldValues = [];
+group.register({}, heldValue);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], holding);
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], heldValue);
 
 // Pass unregister token from another global.
 token = evalcx('({})', other);
-holdings = [];
+heldValues = [];
 group.register({}, 1, token);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], 1);
-holdings = [];
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], 1);
+heldValues = [];
 group.register({}, 1, token);
 group.unregister(token);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 0);
+assertEq(heldValues.length, 0);
 
 // FinalizationGroup is designed to be subclassable.
 class MyGroup extends FinalizationGroup {
-    constructor(callback) {
-        super(callback);
-    }
+  constructor(callback) {
+    super(callback);
+  }
 }
 let g2 = new MyGroup(iterator => {
-    for (const holding of iterator) {
-        holdings.push(holding);
-    }
+  for (const heldValue of iterator) {
+    heldValues.push(heldValue);
+  }
 });
-holdings = [];
+heldValues = [];
 g2.register({}, 42);
 gc();
 drainJobQueue();
-assertEq(holdings.length, 1);
-assertEq(holdings[0], 42);
+assertEq(heldValues.length, 1);
+assertEq(heldValues[0], 42);
 
 // Test trying to use iterator after the callback.
 iterator = undefined;
 let g3 = new FinalizationGroup(i => iterator = i);
 g3.register({}, 1);
 gc();
 drainJobQueue();
 assertEq(typeof iterator, 'object');
 assertThrowsTypeError(() => iterator.next());
 
 // Test trying to use the wrong iterator inside the callback.
 let g4 = new FinalizationGroup(x => {
-    assertThrowsTypeError(() => iterator.next());
+  assertThrowsTypeError(() => iterator.next());
 });
 g4.register({}, 1);
 gc();
 drainJobQueue();
 
 // Test cleanupSome.
-holdings = [];
-let g5 = new FinalizationGroup(i => holdings = [...i]);
+heldValues = [];
+let g5 = new FinalizationGroup(i => heldValues = [...i]);
 g5.register({}, 1);
 g5.register({}, 2);
 g5.register({}, 3);
 gc();
 g5.cleanupSome();
-assertEq(holdings.length, 3);
-holdings = holdings.sort((a, b) => a - b);
-assertEq(holdings[0], 1);
-assertEq(holdings[1], 2);
-assertEq(holdings[2], 3);
+assertEq(heldValues.length, 3);
+heldValues = heldValues.sort((a, b) => a - b);
+assertEq(heldValues[0], 1);
+assertEq(heldValues[1], 2);
+assertEq(heldValues[2], 3);
 
 // Test trying to call cleanupSome in callback.
 let g6 = new FinalizationGroup(x => {
-    assertThrowsTypeError(() => g6.cleanupSome());
+  assertThrowsTypeError(() => g6.cleanupSome());
 });
 g6.register({}, 1);
 gc();
 drainJobQueue();
--- a/js/src/jit/AliasAnalysis.cpp
+++ b/js/src/jit/AliasAnalysis.cpp
@@ -82,19 +82,16 @@ static inline const MDefinition* MaybeUn
          object->isConvertElementsToDoubles()) {
     MOZ_ASSERT(object->numOperands() == 1);
     object = object->getOperand(0);
   }
 
   if (object->isTypedArrayElements()) {
     return nullptr;
   }
-  if (object->isTypedObjectElements()) {
-    return nullptr;
-  }
   if (object->isConstantElements()) {
     return nullptr;
   }
 
   return object;
 }
 
 // Get the object of any load/store. Returns nullptr if not tied to
@@ -106,26 +103,21 @@ static inline const MDefinition* GetObje
 
   // Note: only return the object if that object owns that property.
   // I.e. the property isn't on the prototype chain.
   const MDefinition* object = nullptr;
   switch (ins->op()) {
     case MDefinition::Opcode::InitializedLength:
     case MDefinition::Opcode::LoadElement:
     case MDefinition::Opcode::LoadUnboxedScalar:
-    case MDefinition::Opcode::LoadUnboxedObjectOrNull:
-    case MDefinition::Opcode::LoadUnboxedString:
     case MDefinition::Opcode::StoreElement:
-    case MDefinition::Opcode::StoreUnboxedObjectOrNull:
-    case MDefinition::Opcode::StoreUnboxedString:
     case MDefinition::Opcode::StoreUnboxedScalar:
     case MDefinition::Opcode::SetInitializedLength:
     case MDefinition::Opcode::ArrayLength:
     case MDefinition::Opcode::SetArrayLength:
-    case MDefinition::Opcode::TypedObjectDescr:
     case MDefinition::Opcode::Slots:
     case MDefinition::Opcode::Elements:
     case MDefinition::Opcode::MaybeCopyElementsForWrite:
     case MDefinition::Opcode::MaybeToDoubleElement:
     case MDefinition::Opcode::TypedArrayLength:
     case MDefinition::Opcode::TypedArrayByteOffset:
     case MDefinition::Opcode::ArrayPopShift:
     case MDefinition::Opcode::ArrayPush:
@@ -140,17 +132,16 @@ static inline const MDefinition* GetObje
     case MDefinition::Opcode::GuardReceiverPolymorphic:
     case MDefinition::Opcode::GuardObjectGroup:
     case MDefinition::Opcode::GuardObjectIdentity:
     case MDefinition::Opcode::LoadSlot:
     case MDefinition::Opcode::StoreSlot:
     case MDefinition::Opcode::InArray:
     case MDefinition::Opcode::LoadElementHole:
     case MDefinition::Opcode::TypedArrayElements:
-    case MDefinition::Opcode::TypedObjectElements:
     case MDefinition::Opcode::CopyLexicalEnvironmentObject:
     case MDefinition::Opcode::IsPackedArray:
       object = ins->getOperand(0);
       break;
     case MDefinition::Opcode::GetPropertyCache:
     case MDefinition::Opcode::CallGetProperty:
     case MDefinition::Opcode::GetDOMProperty:
     case MDefinition::Opcode::GetDOMMember:
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -793,36 +793,16 @@ JSObject* BaselineInspector::getTemplate
         return result;
       }
     }
   }
 
   return nullptr;
 }
 
-JSObject* BaselineInspector::getTemplateObjectForClassHook(
-    jsbytecode* pc, const JSClass* clasp) {
-  const ICEntry& entry = icEntryFromPC(pc);
-  for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
-    if (ICStub::IsCacheIRKind(stub->kind())) {
-      auto filter = [stub, clasp](CacheIRReader& args,
-                                  const CacheIRStubInfo* info) {
-        return info->getStubField<JSClass*>(stub, args.stubOffset()) == clasp;
-      };
-      JSObject* result = MaybeTemplateObject(
-          stub, MetaTwoByteKind::ClassTemplateObject, filter);
-      if (result) {
-        return result;
-      }
-    }
-  }
-
-  return nullptr;
-}
-
 LexicalEnvironmentObject* BaselineInspector::templateNamedLambdaObject() {
   JSObject* res = jitScript()->templateEnvironment();
   if (script->bodyScope()->hasEnvironment()) {
     res = res->enclosingEnvironment();
   }
   MOZ_ASSERT(res);
 
   return &res->as<LexicalEnvironmentObject>();
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -90,17 +90,16 @@ class BaselineInspector {
 
   bool hasSeenNegativeIndexGetElement(jsbytecode* pc);
   bool hasSeenNonIntegerIndex(jsbytecode* pc);
   bool hasSeenAccessedGetter(jsbytecode* pc);
   bool hasSeenDoubleResult(jsbytecode* pc);
 
   JSObject* getTemplateObject(jsbytecode* pc);
   JSObject* getTemplateObjectForNative(jsbytecode* pc, Native native);
-  JSObject* getTemplateObjectForClassHook(jsbytecode* pc, const JSClass* clasp);
 
   // Sometimes the group a template object will have is known, even if the
   // object itself isn't.
   ObjectGroup* getTemplateObjectGroup(jsbytecode* pc);
 
   JSFunction* getSingleCallee(jsbytecode* pc);
 
   LexicalEnvironmentObject* templateNamedLambdaObject();
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5425,43 +5425,16 @@ AttachDecision CallIRGenerator::tryAttac
     trackAttached("Call native func");
   } else {
     trackAttached("Call any native func");
   }
 
   return AttachDecision::Attach;
 }
 
-bool CallIRGenerator::getTemplateObjectForClassHook(
-    HandleObject calleeObj, MutableHandleObject result) {
-  MOZ_ASSERT(IsConstructPC(pc_));
-  JSNative hook = calleeObj->constructHook();
-
-  // Don't allocate a template object for super() calls as Ion doesn't support
-  // super() yet.
-  bool isSuper = op_ == JSOp::SuperCall || op_ == JSOp::SpreadSuperCall;
-  if (isSuper) {
-    return true;
-  }
-
-  if (calleeObj->nonCCWRealm() != cx_->realm()) {
-    return true;
-  }
-
-  if (hook == TypedObject::construct) {
-    Rooted<TypeDescr*> descr(cx_, calleeObj.as<TypeDescr>());
-    result.set(TypedObject::createZeroed(cx_, descr, gc::TenuredHeap));
-    if (!result) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
 AttachDecision CallIRGenerator::tryAttachCallHook(HandleObject calleeObj) {
   if (op_ == JSOp::FunApply) {
     return AttachDecision::NoAction;
   }
 
   if (mode_ != ICState::Mode::Specialized) {
     // We do not have megamorphic call hook stubs.
     // TODO: Should we attach specialized call hook stubs in
@@ -5473,42 +5446,30 @@ AttachDecision CallIRGenerator::tryAttac
   bool isConstructing = IsConstructPC(pc_);
   CallFlags flags(isConstructing, isSpread);
   JSNative hook =
       isConstructing ? calleeObj->constructHook() : calleeObj->callHook();
   if (!hook) {
     return AttachDecision::NoAction;
   }
 
-  RootedObject templateObj(cx_);
-  if (isConstructing &&
-      !getTemplateObjectForClassHook(calleeObj, &templateObj)) {
-    cx_->clearPendingException();
-    return AttachDecision::NoAction;
-  }
-
   // Load argc.
   Int32OperandId argcId(writer.setInputOperandId(0));
 
   // Load the callee and ensure it is an object
   ValOperandId calleeValId =
       writer.loadArgumentDynamicSlot(ArgumentKind::Callee, argcId, flags);
   ObjOperandId calleeObjId = writer.guardToObject(calleeValId);
 
   // Ensure the callee's class matches the one in this stub.
-  FieldOffset classOffset =
-      writer.guardAnyClass(calleeObjId, calleeObj->getClass());
+  writer.guardAnyClass(calleeObjId, calleeObj->getClass());
 
   writer.callClassHook(calleeObjId, argcId, hook, flags);
   writer.typeMonitorResult();
 
-  if (templateObj) {
-    writer.metaClassTemplateObject(templateObj, classOffset);
-  }
-
   cacheIRStubKind_ = BaselineCacheIRStubKind::Monitored;
   trackAttached("Call native func");
 
   return AttachDecision::Attach;
 }
 
 AttachDecision CallIRGenerator::tryAttachStub() {
   AutoAssertNoPendingException aanpe(cx_);
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -660,17 +660,16 @@ enum TypedThingLayout {
 };
 
 void LoadShapeWrapperContents(MacroAssembler& masm, Register obj, Register dst,
                               Label* failure);
 
 enum class MetaTwoByteKind : uint8_t {
   NativeTemplateObject,
   ScriptedTemplateObject,
-  ClassTemplateObject,
 };
 
 #ifdef JS_SIMULATOR
 bool CallAnyNative(JSContext* cx, unsigned argc, Value* vp);
 #endif
 
 // Class to record CacheIR + some additional metadata for code generation.
 class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
@@ -1017,19 +1016,19 @@ class MOZ_RAII CacheIRWriter : public JS
 
   void guardClass(ObjOperandId obj, GuardClassKind kind) {
     static_assert(sizeof(GuardClassKind) == sizeof(uint8_t),
                   "GuardClassKind must fit in a byte");
     writeOpWithOperandId(CacheOp::GuardClass, obj);
     buffer_.writeByte(uint32_t(kind));
   }
 
-  FieldOffset guardAnyClass(ObjOperandId obj, const JSClass* clasp) {
+  void guardAnyClass(ObjOperandId obj, const JSClass* clasp) {
     writeOpWithOperandId(CacheOp::GuardAnyClass, obj);
-    return addStubField(uintptr_t(clasp), StubField::Type::RawWord);
+    addStubField(uintptr_t(clasp), StubField::Type::RawWord);
   }
 
   void guardFunctionIsNative(ObjOperandId obj) {
     writeOpWithOperandId(CacheOp::GuardFunctionIsNative, obj);
   }
 
   void guardFunctionIsConstructor(ObjOperandId obj) {
     writeOpWithOperandId(CacheOp::GuardFunctionIsConstructor, obj);
@@ -1568,24 +1567,16 @@ class MOZ_RAII CacheIRWriter : public JS
   void metaScriptedTemplateObject(JSObject* templateObject,
                                   FieldOffset calleeOffset) {
     writeOp(CacheOp::MetaTwoByte);
     buffer_.writeByte(uint32_t(MetaTwoByteKind::ScriptedTemplateObject));
     reuseStubField(calleeOffset);
     addStubField(uintptr_t(templateObject), StubField::Type::JSObject);
   }
 
-  void metaClassTemplateObject(JSObject* templateObject,
-                               FieldOffset classOffset) {
-    writeOp(CacheOp::MetaTwoByte);
-    buffer_.writeByte(uint32_t(MetaTwoByteKind::ClassTemplateObject));
-    reuseStubField(classOffset);
-    addStubField(uintptr_t(templateObject), StubField::Type::JSObject);
-  }
-
   void megamorphicLoadSlotResult(ObjOperandId obj, PropertyName* name,
                                  bool handleMissing) {
     writeOpWithOperandId(CacheOp::MegamorphicLoadSlotResult, obj);
     addStubField(uintptr_t(name), StubField::Type::String);
     buffer_.writeByte(uint32_t(handleMissing));
   }
 
   void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id,
@@ -2741,18 +2732,16 @@ class MOZ_RAII CallIRGenerator : public 
   PropertyTypeCheckInfo typeCheckInfo_;
   BaselineCacheIRStubKind cacheIRStubKind_;
 
   bool getTemplateObjectForScripted(HandleFunction calleeFunc,
                                     MutableHandleObject result,
                                     bool* skipAttach);
   bool getTemplateObjectForNative(HandleFunction calleeFunc,
                                   MutableHandleObject result);
-  bool getTemplateObjectForClassHook(HandleObject calleeObj,
-                                     MutableHandleObject result);
 
   AttachDecision tryAttachArrayPush();
   AttachDecision tryAttachArrayJoin();
   AttachDecision tryAttachIsSuspendedGenerator();
   AttachDecision tryAttachFunCall();
   AttachDecision tryAttachFunApply();
   AttachDecision tryAttachCallScripted(HandleFunction calleeFunc);
   AttachDecision tryAttachSpecialCaseCallNative(HandleFunction calleeFunc);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6394,26 +6394,16 @@ void CodeGenerator::visitNewArrayCallVM(
 
   if (ReturnReg != objReg) {
     masm.movePtr(ReturnReg, objReg);
   }
 
   restoreLive(lir);
 }
 
-void CodeGenerator::visitNewDerivedTypedObject(LNewDerivedTypedObject* lir) {
-  pushArg(ToRegister(lir->offset()));
-  pushArg(ToRegister(lir->owner()));
-  pushArg(ToRegister(lir->type()));
-
-  using Fn = JSObject* (*)(JSContext*, HandleObject type, HandleObject owner,
-                           int32_t offset);
-  callVM<Fn, CreateDerivedTypedObj>(lir);
-}
-
 void CodeGenerator::visitAtan2D(LAtan2D* lir) {
   Register temp = ToRegister(lir->temp());
   FloatRegister y = ToFloatRegister(lir->y());
   FloatRegister x = ToFloatRegister(lir->x());
 
   masm.setupUnalignedABICall(temp);
   masm.passABIArg(y, MoveOp::DOUBLE);
   masm.passABIArg(x, MoveOp::DOUBLE);
@@ -6820,34 +6810,16 @@ void CodeGenerator::visitNewObject(LNewO
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitOutOfLineNewObject(OutOfLineNewObject* ool) {
   visitNewObjectVMCall(ool->lir());
   masm.jump(ool->rejoin());
 }
 
-void CodeGenerator::visitNewTypedObject(LNewTypedObject* lir) {
-  Register object = ToRegister(lir->output());
-  Register temp = ToRegister(lir->temp());
-  InlineTypedObject* templateObject = lir->mir()->templateObject();
-  gc::InitialHeap initialHeap = lir->mir()->initialHeap();
-
-  using Fn = InlineTypedObject* (*)(JSContext*, Handle<InlineTypedObject*>,
-                                    gc::InitialHeap);
-  OutOfLineCode* ool = oolCallVM<Fn, InlineTypedObject::createCopy>(
-      lir, ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
-      StoreRegisterTo(object));
-
-  TemplateObject templateObj(templateObject);
-  masm.createGCObject(object, temp, templateObj, initialHeap, ool->entry());
-
-  masm.bind(ool->rejoin());
-}
-
 void CodeGenerator::visitNewNamedLambdaObject(LNewNamedLambdaObject* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
   const CompileInfo& info = lir->mir()->block()->info();
 
   // If we have a template object, we can inline call object creation.
   using Fn =
       js::NamedLambdaObject* (*)(JSContext*, HandleFunction, gc::InitialHeap);
@@ -7716,42 +7688,16 @@ void CodeGenerator::visitTypedArrayIndex
 
 void CodeGenerator::visitOutOfLineTypedArrayIndexToInt32(
     OutOfLineTypedArrayIndexToInt32* ool) {
   // Substitute the invalid index with an arbitrary out-of-bounds index.
   masm.move32(Imm32(-1), ToRegister(ool->lir()->output()));
   masm.jump(ool->rejoin());
 }
 
-void CodeGenerator::visitTypedObjectDescr(LTypedObjectDescr* lir) {
-  Register obj = ToRegister(lir->object());
-  Register out = ToRegister(lir->output());
-  masm.loadTypedObjectDescr(obj, out);
-}
-
-void CodeGenerator::visitTypedObjectElements(LTypedObjectElements* lir) {
-  Register obj = ToRegister(lir->object());
-  Register out = ToRegister(lir->output());
-
-  if (lir->mir()->definitelyOutline()) {
-    masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
-  } else {
-    Label inlineObject, done;
-    masm.branchIfInlineTypedObject(obj, out, &inlineObject);
-
-    masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
-    masm.jump(&done);
-
-    masm.bind(&inlineObject);
-    masm.computeEffectiveAddress(
-        Address(obj, InlineTypedObject::offsetOfDataStart()), out);
-    masm.bind(&done);
-  }
-}
-
 void CodeGenerator::visitStringLength(LStringLength* lir) {
   Register input = ToRegister(lir->string());
   Register output = ToRegister(lir->output());
 
   masm.loadStringLength(input, output);
 }
 
 void CodeGenerator::visitMinMaxI(LMinMaxI* ins) {
@@ -9782,67 +9728,16 @@ void CodeGenerator::visitOutOfLineStoreE
   using Fn = bool (*)(JSContext*, HandleNativeObject, int32_t, HandleValue,
                       bool strict);
   callVM<Fn, jit::SetDenseElement>(ins);
 
   restoreLive(ins);
   masm.jump(ool->rejoin());
 }
 
-template <typename T>
-static void StoreUnboxedPointer(MacroAssembler& masm, T address, MIRType type,
-                                const LAllocation* value, bool preBarrier) {
-  if (preBarrier) {
-    masm.guardedCallPreBarrier(address, type);
-  }
-  if (value->isConstant()) {
-    Value v = value->toConstant()->toJSValue();
-    if (v.isGCThing()) {
-      masm.storePtr(ImmGCPtr(v.toGCThing()), address);
-    } else {
-      MOZ_ASSERT(v.isNull());
-      masm.storePtr(ImmWord(0), address);
-    }
-  } else {
-    masm.storePtr(ToRegister(value), address);
-  }
-}
-
-void CodeGenerator::visitStoreUnboxedPointer(LStoreUnboxedPointer* lir) {
-  MIRType type;
-  int32_t offsetAdjustment;
-  bool preBarrier;
-  if (lir->mir()->isStoreUnboxedObjectOrNull()) {
-    type = MIRType::Object;
-    offsetAdjustment =
-        lir->mir()->toStoreUnboxedObjectOrNull()->offsetAdjustment();
-    preBarrier = lir->mir()->toStoreUnboxedObjectOrNull()->preBarrier();
-  } else if (lir->mir()->isStoreUnboxedString()) {
-    type = MIRType::String;
-    offsetAdjustment = lir->mir()->toStoreUnboxedString()->offsetAdjustment();
-    preBarrier = lir->mir()->toStoreUnboxedString()->preBarrier();
-  } else {
-    MOZ_CRASH();
-  }
-
-  Register elements = ToRegister(lir->elements());
-  const LAllocation* index = lir->index();
-  const LAllocation* value = lir->value();
-
-  if (index->isConstant()) {
-    Address address(elements,
-                    ToInt32(index) * sizeof(uintptr_t) + offsetAdjustment);
-    StoreUnboxedPointer(masm, address, type, value, preBarrier);
-  } else {
-    BaseIndex address(elements, ToRegister(index), ScalePointer,
-                      offsetAdjustment);
-    StoreUnboxedPointer(masm, address, type, value, preBarrier);
-  }
-}
-
 void CodeGenerator::emitArrayPopShift(LInstruction* lir,
                                       const MArrayPopShift* mir, Register obj,
                                       Register elementsTemp,
                                       Register lengthTemp,
                                       TypedOrValueRegister out) {
   OutOfLineCode* ool;
 
   using Fn = bool (*)(JSContext*, HandleObject, MutableHandleValue);
@@ -11634,78 +11529,16 @@ void CodeGenerator::visitLoadElementHole
     masm.branch32(Assembler::LessThan, index, Imm32(0), &negative);
     bailoutFrom(&negative, lir->snapshot());
   }
   masm.moveValue(UndefinedValue(), out);
 
   masm.bind(&done);
 }
 
-void CodeGenerator::visitLoadUnboxedPointerV(LLoadUnboxedPointerV* lir) {
-  Register elements = ToRegister(lir->elements());
-  const ValueOperand out = ToOutValue(lir);
-
-  if (lir->index()->isConstant()) {
-    int32_t offset = ToInt32(lir->index()) * sizeof(uintptr_t) +
-                     lir->mir()->offsetAdjustment();
-    masm.loadPtr(Address(elements, offset), out.scratchReg());
-  } else {
-    masm.loadPtr(BaseIndex(elements, ToRegister(lir->index()), ScalePointer,
-                           lir->mir()->offsetAdjustment()),
-                 out.scratchReg());
-  }
-
-  Label notNull, done;
-  masm.branchPtr(Assembler::NotEqual, out.scratchReg(), ImmWord(0), &notNull);
-
-  masm.moveValue(NullValue(), out);
-  masm.jump(&done);
-
-  masm.bind(&notNull);
-  masm.tagValue(JSVAL_TYPE_OBJECT, out.scratchReg(), out);
-
-  masm.bind(&done);
-}
-
-void CodeGenerator::visitLoadUnboxedPointerT(LLoadUnboxedPointerT* lir) {
-  Register elements = ToRegister(lir->elements());
-  const LAllocation* index = lir->index();
-  Register out = ToRegister(lir->output());
-
-  bool bailOnNull;
-  int32_t offsetAdjustment;
-  if (lir->mir()->isLoadUnboxedObjectOrNull()) {
-    bailOnNull = lir->mir()->toLoadUnboxedObjectOrNull()->nullBehavior() ==
-                 MLoadUnboxedObjectOrNull::BailOnNull;
-    offsetAdjustment =
-        lir->mir()->toLoadUnboxedObjectOrNull()->offsetAdjustment();
-  } else if (lir->mir()->isLoadUnboxedString()) {
-    bailOnNull = false;
-    offsetAdjustment = lir->mir()->toLoadUnboxedString()->offsetAdjustment();
-  } else {
-    MOZ_CRASH();
-  }
-
-  if (index->isConstant()) {
-    Address source(elements,
-                   ToInt32(index) * sizeof(uintptr_t) + offsetAdjustment);
-    masm.loadPtr(source, out);
-  } else {
-    BaseIndex source(elements, ToRegister(index), ScalePointer,
-                     offsetAdjustment);
-    masm.loadPtr(source, out);
-  }
-
-  if (bailOnNull) {
-    Label bail;
-    masm.branchTestPtr(Assembler::Zero, out, out, &bail);
-    bailoutFrom(&bail, lir->snapshot());
-  }
-}
-
 void CodeGenerator::visitUnboxObjectOrNull(LUnboxObjectOrNull* lir) {
   Register obj = ToRegister(lir->input());
 
   if (lir->mir()->fallible()) {
     Label bail;
     masm.branchTestPtr(Assembler::Zero, obj, obj, &bail);
     bailoutFrom(&bail, lir->snapshot());
   }
--- a/js/src/jit/InlinableNatives.h
+++ b/js/src/jit/InlinableNatives.h
@@ -148,22 +148,17 @@
                                                    \
   _(TypedArrayConstructor)                         \
   _(IntrinsicIsTypedArrayConstructor)              \
   _(IntrinsicIsTypedArray)                         \
   _(IntrinsicIsPossiblyWrappedTypedArray)          \
   _(IntrinsicTypedArrayLength)                     \
   _(IntrinsicPossiblyWrappedTypedArrayLength)      \
   _(IntrinsicTypedArrayByteOffset)                 \
-  _(IntrinsicTypedArrayElementShift)               \
-                                                   \
-  _(IntrinsicObjectIsTypedObject)                  \
-  _(IntrinsicObjectIsTypeDescr)                    \
-  _(IntrinsicTypeDescrIsSimpleType)                \
-  _(IntrinsicTypeDescrIsArrayType)
+  _(IntrinsicTypedArrayElementShift)
 
 struct JSJitInfo;
 
 namespace js {
 namespace jit {
 
 enum class InlinableNative : uint16_t {
 #define ADD_NATIVE(native) native,
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -921,26 +921,16 @@ bool OptimizeMIR(MIRGenerator* mir) {
   MIRGraph& graph = mir->graph();
   GraphSpewer& gs = mir->graphSpewer();
   TraceLoggerThread* logger = TraceLoggerForCurrentThread();
 
   if (mir->shouldCancel("Start")) {
     return false;
   }
 
-  if (!mir->compilingWasm()) {
-    if (!MakeMRegExpHoistable(mir, graph)) {
-      return false;
-    }
-
-    if (mir->shouldCancel("Make MRegExp Hoistable")) {
-      return false;
-    }
-  }
-
   gs.spewPass("BuildSSA");
   AssertBasicGraphCoherency(graph);
 
   if (!JitOptions.disablePgo && !mir->compilingWasm()) {
     AutoTraceLog log(logger, TraceLogger_PruneUnusedBranches);
     if (!PruneUnusedBranches(mir, graph)) {
       return false;
     }
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1196,20 +1196,19 @@ bool jit::EliminateDeadResumePointOperan
       // in resume points may affect the interpreter's behavior. Rather
       // than doing a more sophisticated analysis, just ignore these.
       if (ins->isUnbox() || ins->isParameter() || ins->isTypeBarrier() ||
           ins->isComputeThis() || ins->isFilterTypeSet()) {
         continue;
       }
 
       // Early intermediate values captured by resume points, such as
-      // TypedObject, ArrayState and its allocation, may be legitimately
-      // dead in Ion code, but are still needed if we bail out. They can
-      // recover on bailout.
-      if (ins->isNewDerivedTypedObject() || ins->isRecoveredOnBailout()) {
+      // ArrayState and its allocation, may be legitimately dead in Ion code,
+      // but are still needed if we bail out. They can recover on bailout.
+      if (ins->isRecoveredOnBailout()) {
         MOZ_ASSERT(ins->canRecoverOnBailout());
         continue;
       }
 
       // If the instruction's behavior has been constant folded into a
       // separate instruction, we can't determine precisely where the
       // instruction becomes dead and can't eliminate its uses.
       if (ins->isImplicitlyUsed() || ins->isUseRemoved()) {
@@ -2266,308 +2265,16 @@ bool jit::ApplyTypeInformation(MIRGenera
 
   if (!analyzer.analyze()) {
     return false;
   }
 
   return true;
 }
 
-// Check if `def` is only the N-th operand of `useDef`.
-static inline size_t IsExclusiveNthOperand(MDefinition* useDef, size_t n,
-                                           MDefinition* def) {
-  uint32_t num = useDef->numOperands();
-  if (n >= num || useDef->getOperand(n) != def) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < num; i++) {
-    if (i == n) {
-      continue;
-    }
-    if (useDef->getOperand(i) == def) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-static size_t IsExclusiveThisArg(MCall* call, MDefinition* def) {
-  return IsExclusiveNthOperand(call, MCall::IndexOfThis(), def);
-}
-
-static size_t IsExclusiveFirstArg(MCall* call, MDefinition* def) {
-  return IsExclusiveNthOperand(call, MCall::IndexOfArgument(0), def);
-}
-
-static bool IsRegExpHoistableCall(CompileRuntime* runtime, MCall* call,
-                                  MDefinition* def) {
-  if (call->isConstructing()) {
-    return false;
-  }
-
-  JSAtom* name;
-  if (WrappedFunction* fun = call->getSingleTarget()) {
-    if (!fun->isSelfHostedBuiltin()) {
-      return false;
-    }
-
-    // Avoid accessing `JSFunction.flags_` via `JSFunction::isExtended`.
-    if (!fun->isExtended()) {
-      return false;
-    }
-    name = GetClonedSelfHostedFunctionNameOffMainThread(fun->rawJSFunction());
-  } else {
-    MDefinition* funDef = call->getFunction();
-    if (funDef->isDebugCheckSelfHosted()) {
-      funDef = funDef->toDebugCheckSelfHosted()->input();
-    }
-    if (funDef->isTypeBarrier()) {
-      funDef = funDef->toTypeBarrier()->input();
-    }
-
-    if (!funDef->isCallGetIntrinsicValue()) {
-      return false;
-    }
-    name = funDef->toCallGetIntrinsicValue()->name();
-  }
-
-  // Hoistable only if the RegExp is the first argument of RegExpBuiltinExec.
-  if (name == runtime->names().RegExpBuiltinExec ||
-      name == runtime->names().UnwrapAndCallRegExpBuiltinExec ||
-      name == runtime->names().RegExpMatcher ||
-      name == runtime->names().RegExpTester ||
-      name == runtime->names().RegExpSearcher) {
-    return IsExclusiveFirstArg(call, def);
-  }
-
-  if (name == runtime->names().RegExp_prototype_Exec ||
-      name == runtime->names().CallRegExpMethodIfWrapped) {
-    return IsExclusiveThisArg(call, def);
-  }
-
-  return false;
-}
-
-static bool CanCompareRegExp(MCompare* compare, MDefinition* def) {
-  MDefinition* value;
-  if (compare->lhs() == def) {
-    value = compare->rhs();
-  } else {
-    MOZ_ASSERT(compare->rhs() == def);
-    value = compare->lhs();
-  }
-
-  // Comparing two regexp that weren't cloned will give different result
-  // than if they were cloned.
-  if (value->mightBeType(MIRType::Object)) {
-    return false;
-  }
-
-  // Make sure @@toPrimitive is not called which could notice
-  // the difference between a not cloned/cloned regexp.
-
-  JSOp op = compare->jsop();
-  // Strict equality comparison won't invoke @@toPrimitive.
-  if (op == JSOp::StrictEq || op == JSOp::StrictNe) {
-    return true;
-  }
-
-  if (op != JSOp::Eq && op != JSOp::Ne) {
-    // Relational comparison always invoke @@toPrimitive.
-    MOZ_ASSERT(IsRelationalOp(op));
-    return false;
-  }
-
-  // Loose equality comparison can invoke @@toPrimitive.
-  if (value->mightBeType(MIRType::Boolean) ||
-      value->mightBeType(MIRType::String) ||
-      value->mightBeType(MIRType::Int32) ||
-      value->mightBeType(MIRType::Double) ||
-      value->mightBeType(MIRType::Float32) ||
-      value->mightBeType(MIRType::Symbol) ||
-      value->mightBeType(MIRType::BigInt)) {
-    return false;
-  }
-
-  return true;
-}
-
-static inline void SetNotInWorklist(MDefinitionVector& worklist) {
-  for (size_t i = 0; i < worklist.length(); i++) {
-    worklist[i]->setNotInWorklist();
-  }
-}
-
-static bool IsRegExpHoistable(MIRGenerator* mir, MDefinition* regexp,
-                              MDefinitionVector& worklist, bool* hoistable) {
-  MOZ_ASSERT(worklist.length() == 0);
-
-  if (!worklist.append(regexp)) {
-    return false;
-  }
-  regexp->setInWorklist();
-
-  for (size_t i = 0; i < worklist.length(); i++) {
-    MDefinition* def = worklist[i];
-    if (mir->shouldCancel("IsRegExpHoistable outer loop")) {
-      return false;
-    }
-
-    for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
-      if (mir->shouldCancel("IsRegExpHoistable inner loop")) {
-        return false;
-      }
-
-      // Ignore resume points. At this point all uses are listed.
-      // No DCE or GVN or something has happened.
-      if (use->consumer()->isResumePoint()) {
-        continue;
-      }
-
-      MDefinition* useDef = use->consumer()->toDefinition();
-
-      // Step through a few white-listed ops.
-      if (useDef->isPhi() || useDef->isFilterTypeSet() ||
-          useDef->isGuardShape()) {
-        if (useDef->isInWorklist()) {
-          continue;
-        }
-
-        if (!worklist.append(useDef)) {
-          return false;
-        }
-        useDef->setInWorklist();
-        continue;
-      }
-
-      // Instructions that doesn't invoke unknown code that may modify
-      // RegExp instance or pass it to elsewhere.
-      if (useDef->isRegExpMatcher() || useDef->isRegExpTester() ||
-          useDef->isRegExpSearcher()) {
-        if (IsExclusiveNthOperand(useDef, 0, def)) {
-          continue;
-        }
-      } else if (useDef->isLoadFixedSlot() || useDef->isTypeOf()) {
-        continue;
-      } else if (useDef->isCompare()) {
-        if (CanCompareRegExp(useDef->toCompare(), def)) {
-          continue;
-        }
-      }
-      // Instructions that modifies `lastIndex` property.
-      else if (useDef->isStoreFixedSlot()) {
-        if (IsExclusiveNthOperand(useDef, 0, def)) {
-          MStoreFixedSlot* store = useDef->toStoreFixedSlot();
-          if (store->slot() == RegExpObject::lastIndexSlot()) {
-            continue;
-          }
-        }
-      } else if (useDef->isSetPropertyCache()) {
-        if (IsExclusiveNthOperand(useDef, 0, def)) {
-          MSetPropertyCache* setProp = useDef->toSetPropertyCache();
-          if (setProp->idval()->isConstant()) {
-            Value propIdVal = setProp->idval()->toConstant()->toJSValue();
-            if (propIdVal.isString()) {
-              CompileRuntime* runtime = mir->runtime;
-              if (propIdVal.toString() == runtime->names().lastIndex) {
-                continue;
-              }
-            }
-          }
-        }
-      }
-      // MCall is safe only for some known safe functions.
-      else if (useDef->isCall()) {
-        if (IsRegExpHoistableCall(mir->runtime, useDef->toCall(), def)) {
-          continue;
-        }
-      }
-
-      // Everything else is unsafe.
-      SetNotInWorklist(worklist);
-      worklist.clear();
-      *hoistable = false;
-
-      return true;
-    }
-  }
-
-  SetNotInWorklist(worklist);
-  worklist.clear();
-  *hoistable = true;
-  return true;
-}
-
-bool jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph) {
-  // If we are compiling try blocks, regular expressions may be observable
-  // from catch blocks (which Ion does not compile). For now just disable the
-  // pass in this case.
-  if (graph.hasTryBlock()) {
-    return true;
-  }
-
-  MDefinitionVector worklist(graph.alloc());
-
-  for (ReversePostorderIterator block(graph.rpoBegin());
-       block != graph.rpoEnd(); block++) {
-    if (mir->shouldCancel("MakeMRegExpHoistable outer loop")) {
-      return false;
-    }
-
-    for (MDefinitionIterator iter(*block); iter; iter++) {
-      if (!*iter) {
-        MOZ_CRASH("confirm bug 1263794.");
-      }
-
-      if (mir->shouldCancel("MakeMRegExpHoistable inner loop")) {
-        return false;
-      }
-
-      if (!iter->isRegExp()) {
-        continue;
-      }
-
-      MRegExp* regexp = iter->toRegExp();
-
-      bool hoistable = false;
-      if (!IsRegExpHoistable(mir, regexp, worklist, &hoistable)) {
-        return false;
-      }
-
-      if (!hoistable) {
-        continue;
-      }
-
-      // Make MRegExp hoistable
-      regexp->setMovable();
-      regexp->setDoNotClone();
-
-      // That would be incorrect for global/sticky, because lastIndex
-      // could be wrong.  Therefore setting the lastIndex to 0. That is
-      // faster than a not movable regexp.
-      RegExpObject* source = regexp->source();
-      if (source->sticky() || source->global()) {
-        if (!graph.alloc().ensureBallast()) {
-          return false;
-        }
-        MConstant* zero = MConstant::New(graph.alloc(), Int32Value(0));
-        regexp->block()->insertAfter(regexp, zero);
-
-        MStoreFixedSlot* lastIndex = MStoreFixedSlot::New(
-            graph.alloc(), regexp, RegExpObject::lastIndexSlot(), zero);
-        regexp->block()->insertAfter(zero, lastIndex);
-      }
-    }
-  }
-
-  return true;
-}
-
 void jit::RenumberBlocks(MIRGraph& graph) {
   size_t id = 0;
   for (ReversePostorderIterator block(graph.rpoBegin());
        block != graph.rpoEnd(); block++) {
     block->setId(id++);
   }
 }
 
@@ -3945,17 +3652,16 @@ bool jit::EliminateRedundantChecks(MIRGr
           break;
         case MDefinition::Opcode::TypeBarrier:
           if (!TryEliminateTypeBarrier(def->toTypeBarrier(), &eliminated)) {
             return false;
           }
           break;
         case MDefinition::Opcode::LoadFixedSlot:
         case MDefinition::Opcode::LoadSlot:
-        case MDefinition::Opcode::LoadUnboxedObjectOrNull:
           if (!TryOptimizeLoadObjectOrNull(def, &eliminateList)) {
             return false;
           }
           break;
         default:
           // Now that code motion passes have finished, replace
           // instructions which pass through one of their operands
           // (and perform additional checks) with that operand.
@@ -4040,17 +3746,16 @@ bool jit::AddKeepAliveInstructions(MIRGr
         case MDefinition::Opcode::ConstantElements:
           continue;
         case MDefinition::Opcode::ConvertElementsToDoubles:
           // EliminateRedundantChecks should have replaced all uses.
           MOZ_ASSERT(!ins->hasUses());
           continue;
         case MDefinition::Opcode::Elements:
         case MDefinition::Opcode::TypedArrayElements:
-        case MDefinition::Opcode::TypedObjectElements:
           MOZ_ASSERT(ins->numOperands() == 1);
           ownerObject = ins->getOperand(0);
           break;
         case MDefinition::Opcode::Slots:
           ownerObject = ins->toSlots()->object();
           break;
         default:
           MOZ_CRASH("Unexpected op");
--- a/js/src/jit/IonAnalysis.h
+++ b/js/src/jit/IonAnalysis.h
@@ -44,18 +44,16 @@ MOZ_MUST_USE bool MakeLoopsContiguous(MI
 
 MOZ_MUST_USE bool EliminateDeadResumePointOperands(MIRGenerator* mir,
                                                    MIRGraph& graph);
 
 MOZ_MUST_USE bool EliminateDeadCode(MIRGenerator* mir, MIRGraph& graph);
 
 MOZ_MUST_USE bool ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph);
 
-MOZ_MUST_USE bool MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph);
-
 void RenumberBlocks(MIRGraph& graph);
 
 MOZ_MUST_USE bool AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph,
                                        bool updateAliasAnalysis,
                                        bool underValueNumberer = false);
 
 MOZ_MUST_USE bool RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph,
                                        uint32_t numMarkedBlocks);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1595,21 +1595,16 @@ class MOZ_RAII PoppedValueUseChecker {
           }
           [[fallthrough]];
 
         default:
           MOZ_ASSERT(popped_[i]->isImplicitlyUsed() ||
                      // First value popped by JSOp::EndIter is not used at all,
                      // it's similar to JSOp::Pop above.
                      (op == JSOp::EndIter && i == 0) ||
-                     // MNewDerivedTypedObject instances are
-                     // often dead unless they escape from the
-                     // fn. See IonBuilder::loadTypedObjectData()
-                     // for more details.
-                     popped_[i]->isNewDerivedTypedObject() ||
                      popped_[i]->defUseCount() > poppedUses_[i]);
           break;
       }
     }
   }
 };
 #endif
 
@@ -4779,18 +4774,17 @@ MGetPropertyCache* IonBuilder::getInline
 
   return nullptr;
 }
 
 IonBuilder::InliningResult IonBuilder::inlineSingleCall(CallInfo& callInfo,
                                                         JSObject* targetArg) {
   InliningStatus status;
   if (!targetArg->is<JSFunction>()) {
-    MOZ_TRY_VAR(status, inlineNonFunctionCall(callInfo, targetArg));
-    return status;
+    return InliningStatus_NotInlined;
   }
 
   JSFunction* target = &targetArg->as<JSFunction>();
   if (target->isNative()) {
     MOZ_TRY_VAR(status, inlineNativeCall(callInfo, target));
     return status;
   }
 
@@ -8600,342 +8594,21 @@ AbortReasonOr<Ok> IonBuilder::jsop_getel
     if (emitted) {
       return Ok();
     }
 
     MOZ_TRY(getElemTryString(&emitted, obj, index));
     if (emitted) {
       return Ok();
     }
-
-    MOZ_TRY(getElemTryTypedObject(&emitted, obj, index));
-    if (emitted) {
-      return Ok();
-    }
   }
 
   return getElemAddCache(obj, index);
 }
 
-AbortReasonOr<Ok> IonBuilder::getElemTryTypedObject(bool* emitted,
-                                                    MDefinition* obj,
-                                                    MDefinition* index) {
-  MOZ_ASSERT(*emitted == false);
-
-  // The next several failures are all due to types not predicting that we
-  // are definitely doing a getelem access on a typed object.
-
-  TypedObjectPrediction objPrediction = typedObjectPrediction(obj);
-  if (objPrediction.isUseless()) {
-    return Ok();
-  }
-
-  if (!objPrediction.ofArrayKind()) {
-    return Ok();
-  }
-
-  TypedObjectPrediction elemPrediction = objPrediction.arrayElementType();
-  if (elemPrediction.isUseless()) {
-    return Ok();
-  }
-
-  uint32_t elemSize;
-  if (!elemPrediction.hasKnownSize(&elemSize)) {
-    return Ok();
-  }
-
-  switch (elemPrediction.kind()) {
-    case type::Struct:
-    case type::Array:
-      return getElemTryComplexElemOfTypedObject(
-          emitted, obj, index, objPrediction, elemPrediction, elemSize);
-    case type::Scalar:
-      return getElemTryScalarElemOfTypedObject(
-          emitted, obj, index, objPrediction, elemPrediction, elemSize);
-
-    case type::Reference:
-      return getElemTryReferenceElemOfTypedObject(
-          emitted, obj, index, objPrediction, elemPrediction);
-  }
-
-  MOZ_CRASH("Bad kind");
-}
-
-bool IonBuilder::checkTypedObjectIndexInBounds(
-    uint32_t elemSize, MDefinition* index, TypedObjectPrediction objPrediction,
-    LinearSum* indexAsByteOffset) {
-  // Ensure index is an integer.
-  MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
-  current->add(idInt32);
-
-  // If we know the length statically from the type, just embed it.
-  // Otherwise, load it from the appropriate reserved slot on the
-  // typed object.  We know it's an int32, so we can convert from
-  // Value to int32 using truncation.
-  int32_t lenOfAll;
-  MDefinition* length;
-  if (objPrediction.hasKnownArrayLength(&lenOfAll)) {
-    length = constantInt(lenOfAll);
-  } else {
-    return false;
-  }
-
-  index = addBoundsCheck(idInt32, length);
-
-  return indexAsByteOffset->add(index, AssertedCast<int32_t>(elemSize));
-}
-
-static bool CheckTypedObjectSupportedType(Scalar::Type type) {
-  // FIXME: https://bugzil.la/1536699
-  return !Scalar::isBigIntType(type);
-}
-
-AbortReasonOr<Ok> IonBuilder::getElemTryScalarElemOfTypedObject(
-    bool* emitted, MDefinition* obj, MDefinition* index,
-    TypedObjectPrediction objPrediction, TypedObjectPrediction elemPrediction,
-    uint32_t elemSize) {
-  MOZ_ASSERT(objPrediction.ofArrayKind());
-
-  // Must always be loading the same scalar type
-  ScalarTypeDescr::Type elemType = elemPrediction.scalarType();
-  MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
-
-  if (!CheckTypedObjectSupportedType(elemType)) {
-    return Ok();
-  }
-
-  LinearSum indexAsByteOffset(alloc());
-  if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction,
-                                     &indexAsByteOffset)) {
-    return Ok();
-  }
-
-  *emitted = true;
-
-  return pushScalarLoadFromTypedObject(obj, indexAsByteOffset, elemType);
-}
-
-AbortReasonOr<Ok> IonBuilder::getElemTryReferenceElemOfTypedObject(
-    bool* emitted, MDefinition* obj, MDefinition* index,
-    TypedObjectPrediction objPrediction, TypedObjectPrediction elemPrediction) {
-  MOZ_ASSERT(objPrediction.ofArrayKind());
-
-  ReferenceType elemType = elemPrediction.referenceType();
-  uint32_t elemSize = ReferenceTypeDescr::size(elemType);
-
-  LinearSum indexAsByteOffset(alloc());
-  if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction,
-                                     &indexAsByteOffset)) {
-    return Ok();
-  }
-
-  if (elemType == ReferenceType::TYPE_WASM_ANYREF) {
-    return Ok();
-  }
-
-  *emitted = true;
-
-  return pushReferenceLoadFromTypedObject(obj, indexAsByteOffset, elemType,
-                                          nullptr);
-}
-
-AbortReasonOr<Ok> IonBuilder::pushScalarLoadFromTypedObject(
-    MDefinition* obj, const LinearSum& byteOffset,
-    ScalarTypeDescr::Type elemType) {
-  uint32_t size = ScalarTypeDescr::size(elemType);
-  MOZ_ASSERT(size == ScalarTypeDescr::alignment(elemType));
-
-  // Find location within the owner object.
-  MDefinition* elements;
-  MDefinition* scaledOffset;
-  int32_t adjustment;
-  MOZ_TRY(loadTypedObjectElements(obj, byteOffset, size, &elements,
-                                  &scaledOffset, &adjustment));
-
-  // Load the element.
-  MLoadUnboxedScalar* load =
-      MLoadUnboxedScalar::New(alloc(), elements, scaledOffset, elemType,
-                              DoesNotRequireMemoryBarrier, adjustment);
-  current->add(load);
-  current->push(load);
-
-  // If we are reading in-bounds elements, we can use knowledge about
-  // the array type to determine the result type, even if the opcode has
-  // never executed. The known pushed type is only used to distinguish
-  // uint32 reads that may produce either doubles or integers.
-  TemporaryTypeSet* resultTypes = bytecodeTypes(pc);
-  bool allowDouble = resultTypes->hasType(TypeSet::DoubleType());
-
-  // Note: knownType is not necessarily in resultTypes; e.g. if we
-  // have only observed integers coming out of float array.
-  MIRType knownType = MIRTypeForTypedArrayRead(elemType, allowDouble);
-
-  // Note: we can ignore the type barrier here, we know the type must
-  // be valid and unbarriered. Also, need not set resultTypeSet,
-  // because knownType is scalar and a resultTypeSet would provide
-  // no useful additional info.
-  load->setResultType(knownType);
-
-  return Ok();
-}
-
-AbortReasonOr<Ok> IonBuilder::pushReferenceLoadFromTypedObject(
-    MDefinition* typedObj, const LinearSum& byteOffset, ReferenceType type,
-    PropertyName* name) {
-  // Find location within the owner object.
-  MDefinition* elements;
-  MDefinition* scaledOffset;
-  int32_t adjustment;
-  uint32_t alignment = ReferenceTypeDescr::alignment(type);
-  MOZ_TRY(loadTypedObjectElements(typedObj, byteOffset, alignment, &elements,
-                                  &scaledOffset, &adjustment));
-
-  TemporaryTypeSet* observedTypes = bytecodeTypes(pc);
-
-  MInstruction* load = nullptr;  // initialize to silence GCC warning
-  BarrierKind barrier = PropertyReadNeedsTypeBarrier(
-      analysisContext, alloc(), constraints(), typedObj, name, observedTypes);
-
-  switch (type) {
-    case ReferenceType::TYPE_ANY: {
-      // Make sure the barrier reflects the possibility of reading undefined.
-      bool bailOnUndefined = barrier == BarrierKind::NoBarrier &&
-                             !observedTypes->hasType(TypeSet::UndefinedType());
-      if (bailOnUndefined) {
-        barrier = BarrierKind::TypeTagOnly;
-      }
-      load = MLoadElement::New(alloc(), elements, scaledOffset, false, false,
-                               adjustment);
-      break;
-    }
-    case ReferenceType::TYPE_OBJECT: {
-      // Make sure the barrier reflects the possibility of reading null. When
-      // there is no other barrier needed we include the null bailout with
-      // MLoadUnboxedObjectOrNull, which avoids the need to box the result
-      // for a type barrier instruction.
-      MLoadUnboxedObjectOrNull::NullBehavior nullBehavior;
-      if (barrier == BarrierKind::NoBarrier &&
-          !observedTypes->hasType(TypeSet::NullType())) {
-        nullBehavior = MLoadUnboxedObjectOrNull::BailOnNull;
-      } else {
-        nullBehavior = MLoadUnboxedObjectOrNull::HandleNull;
-      }
-      load = MLoadUnboxedObjectOrNull::New(alloc(), elements, scaledOffset,
-                                           nullBehavior, adjustment);
-      break;
-    }
-    case ReferenceType::TYPE_STRING: {
-      load =
-          MLoadUnboxedString::New(alloc(), elements, scaledOffset, adjustment);
-      observedTypes->addType(TypeSet::StringType(), alloc().lifoAlloc());
-      break;
-    }
-    case ReferenceType::TYPE_WASM_ANYREF: {
-      MOZ_CRASH();
-    }
-  }
-
-  current->add(load);
-  current->push(load);
-
-  return pushTypeBarrier(load, observedTypes, barrier);
-}
-
-AbortReasonOr<Ok> IonBuilder::getElemTryComplexElemOfTypedObject(
-    bool* emitted, MDefinition* obj, MDefinition* index,
-    TypedObjectPrediction objPrediction, TypedObjectPrediction elemPrediction,
-    uint32_t elemSize) {
-  MOZ_ASSERT(objPrediction.ofArrayKind());
-
-  MDefinition* type = loadTypedObjectType(obj);
-  MDefinition* elemTypeObj = typeObjectForElementFromArrayStructType(type);
-
-  LinearSum indexAsByteOffset(alloc());
-  if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction,
-                                     &indexAsByteOffset)) {
-    return Ok();
-  }
-
-  return pushDerivedTypedObject(emitted, obj, indexAsByteOffset, elemPrediction,
-                                elemTypeObj);
-}
-
-AbortReasonOr<Ok> IonBuilder::pushDerivedTypedObject(
-    bool* emitted, MDefinition* obj, const LinearSum& baseByteOffset,
-    TypedObjectPrediction derivedPrediction, MDefinition* derivedTypeObj) {
-  // Find location within the owner object.
-  MDefinition* owner;
-  LinearSum ownerByteOffset(alloc());
-  MOZ_TRY(loadTypedObjectData(obj, &owner, &ownerByteOffset));
-  if (!ownerByteOffset.add(baseByteOffset, 1)) {
-    return abort(AbortReason::Disable,
-                 "Overflow/underflow on type object offset.");
-  }
-
-  MDefinition* offset = ConvertLinearSum(alloc(), current, ownerByteOffset,
-                                         /* convertConstant = */ true);
-
-  // Create the derived typed object.
-  MInstruction* derivedTypedObj = MNewDerivedTypedObject::New(
-      alloc(), derivedPrediction, derivedTypeObj, owner, offset);
-  current->add(derivedTypedObj);
-  current->push(derivedTypedObj);
-
-  // Determine (if possible) the class/proto that `derivedTypedObj` will
-  // have. For derived typed objects, the opacity will be the same as the
-  // incoming object from which the derived typed object is, well, derived.
-  // The prototype will be determined based on the type descriptor (and is
-  // immutable).
-  TemporaryTypeSet* objTypes = obj->resultTypeSet();
-  const JSClass* expectedClass = nullptr;
-  if (const JSClass* objClass =
-          objTypes ? objTypes->getKnownClass(constraints()) : nullptr) {
-    MOZ_ASSERT(IsTypedObjectClass(objClass));
-    expectedClass =
-        GetOutlineTypedObjectClass(IsOpaqueTypedObjectClass(objClass));
-  }
-  const TypedProto* expectedProto = derivedPrediction.getKnownPrototype();
-  MOZ_ASSERT_IF(expectedClass, IsTypedObjectClass(expectedClass));
-
-  // Determine (if possible) the class/proto that the observed type set
-  // describes.
-  TemporaryTypeSet* observedTypes = bytecodeTypes(pc);
-  const JSClass* observedClass = observedTypes->getKnownClass(constraints());
-
-  // If expectedClass/expectedProto are both non-null (and hence known), we
-  // can predict precisely what object group derivedTypedObj will have.
-  // Therefore, if we observe that this group is already contained in the set
-  // of observedTypes, we can skip the barrier.
-  //
-  // Barriers still wind up being needed in some relatively
-  // rare cases:
-  //
-  // - if multiple kinds of typed objects flow into this point,
-  //   in which case we will not be able to predict expectedClass
-  //   nor expectedProto.
-  //
-  // - if the code has never executed, in which case the set of
-  //   observed types will be incomplete.
-  //
-  // Barriers are particularly expensive here because they prevent
-  // us from optimizing the MNewDerivedTypedObject away.
-  JSObject* observedProto;
-  if (observedTypes->getCommonPrototype(constraints(), &observedProto) &&
-      observedClass && observedProto && observedClass == expectedClass &&
-      observedProto == expectedProto) {
-    derivedTypedObj->setResultTypeSet(observedTypes);
-  } else {
-    MOZ_TRY(
-        pushTypeBarrier(derivedTypedObj, observedTypes, BarrierKind::TypeSet));
-  }
-
-  *emitted = true;
-  return Ok();
-}
-
 AbortReasonOr<Ok> IonBuilder::getElemTryGetProp(bool* emitted, MDefinition* obj,
                                                 MDefinition* index) {
   // If index is a constant string or symbol, try to optimize this GetElem
   // as a GetProp.
 
   MOZ_ASSERT(*emitted == false);
 
   MConstant* indexConst = index->maybeConstantValue();
@@ -9636,21 +9309,16 @@ AbortReasonOr<Ok> IonBuilder::jsop_setel
     if (emitted) {
       return Ok();
     }
 
     MOZ_TRY(setElemTryArguments(&emitted, object));
     if (emitted) {
       return Ok();
     }
-
-    MOZ_TRY(setElemTryTypedObject(&emitted, object, index, value));
-    if (emitted) {
-      return Ok();
-    }
   }
 
   if (script()->argumentsHasVarBinding() &&
       object->mightBeType(MIRType::MagicOptimizedArguments) &&
       info().analysisMode() != Analysis_ArgumentsUsage) {
     return abort(AbortReason::Disable,
                  "Type is not definitely lazy arguments.");
   }
@@ -9664,105 +9332,16 @@ AbortReasonOr<Ok> IonBuilder::jsop_setel
   MInstruction* ins =
       MCallSetElement::New(alloc(), object, index, value, IsStrictSetPC(pc));
   current->add(ins);
   current->push(value);
 
   return resumeAfter(ins);
 }
 
-AbortReasonOr<Ok> IonBuilder::setElemTryTypedObject(bool* emitted,
-                                                    MDefinition* obj,
-                                                    MDefinition* index,
-                                                    MDefinition* value) {
-  MOZ_ASSERT(*emitted == false);
-
-  // The next several failures are all due to types not predicting that we
-  // are definitely doing a getelem access on a typed object.
-
-  TypedObjectPrediction objPrediction = typedObjectPrediction(obj);
-  if (objPrediction.isUseless()) {
-    return Ok();
-  }
-
-  if (!objPrediction.ofArrayKind()) {
-    return Ok();
-  }
-
-  TypedObjectPrediction elemPrediction = objPrediction.arrayElementType();
-  if (elemPrediction.isUseless()) {
-    return Ok();
-  }
-
-  uint32_t elemSize;
-  if (!elemPrediction.hasKnownSize(&elemSize)) {
-    return Ok();
-  }
-
-  switch (elemPrediction.kind()) {
-    case type::Reference:
-      return setElemTryReferenceElemOfTypedObject(
-          emitted, obj, index, objPrediction, value, elemPrediction);
-
-    case type::Scalar:
-      return setElemTryScalarElemOfTypedObject(
-          emitted, obj, index, objPrediction, value, elemPrediction, elemSize);
-
-    case type::Struct:
-    case type::Array:
-      // Not yet optimized.
-      return Ok();
-  }
-
-  MOZ_CRASH("Bad kind");
-}
-
-AbortReasonOr<Ok> IonBuilder::setElemTryReferenceElemOfTypedObject(
-    bool* emitted, MDefinition* obj, MDefinition* index,
-    TypedObjectPrediction objPrediction, MDefinition* value,
-    TypedObjectPrediction elemPrediction) {
-  ReferenceType elemType = elemPrediction.referenceType();
-  uint32_t elemSize = ReferenceTypeDescr::size(elemType);
-
-  LinearSum indexAsByteOffset(alloc());
-  if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction,
-                                     &indexAsByteOffset)) {
-    return Ok();
-  }
-
-  if (elemType == ReferenceType::TYPE_WASM_ANYREF) {
-    return Ok();
-  }
-
-  return setPropTryReferenceTypedObjectValue(emitted, obj, indexAsByteOffset,
-                                             elemType, value, nullptr);
-}
-
-AbortReasonOr<Ok> IonBuilder::setElemTryScalarElemOfTypedObject(
-    bool* emitted, MDefinition* obj, MDefinition* index,
-    TypedObjectPrediction objPrediction, MDefinition* value,
-    TypedObjectPrediction elemPrediction, uint32_t elemSize) {
-  // Must always be loading the same scalar type
-  ScalarTypeDescr::Type elemType = elemPrediction.scalarType();
-  MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
-
-  if (!CheckTypedObjectSupportedType(elemType)) {
-    return Ok();
-  }
-
-  LinearSum indexAsByteOffset(alloc());
-  if (!checkTypedObjectIndexInBounds(elemSize, index, objPrediction,
-                                     &indexAsByteOffset)) {
-    return Ok();
-  }
-
-  return setPropTryScalarTypedObjectValue(emitted, obj, indexAsByteOffset,
-                                          elemType, value);
-}
-
 AbortReasonOr<Ok> IonBuilder::setElemTryTypedArray(bool* emitted,
                                                    MDefinition* object,
                                                    MDefinition* index,
                                                    MDefinition* value) {
   MOZ_ASSERT(*emitted == false);
 
   Scalar::Type arrayType;
   if (!ElementAccessIsTypedArray(constraints(), object, index, &arrayType)) {
@@ -10126,34 +9705,16 @@ bool IonBuilder::jsop_length_fastPath() 
       current->add(elements);
 
       // Read length.
       MArrayLength* length = MArrayLength::New(alloc(), elements);
       current->add(length);
       current->push(length);
       return true;
     }
-
-    // Compute the length for array typed objects.
-    TypedObjectPrediction prediction = typedObjectPrediction(obj);
-    if (!prediction.isUseless()) {
-      MInstruction* length;
-      int32_t sizedLength;
-      if (prediction.hasKnownArrayLength(&sizedLength)) {
-        obj->setImplicitlyUsedUnchecked();
-        length = MConstant::New(alloc(), Int32Value(sizedLength));
-      } else {
-        return false;
-      }
-
-      current->pop();
-      current->add(length);
-      current->push(length);
-      return true;
-    }
   }
 
   return false;
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_arguments() {
   if (info().needsArgsObj()) {
     current->push(current->argumentsObject());
@@ -11009,22 +10570,16 @@ AbortReasonOr<Ok> IonBuilder::jsop_getpr
       return Ok();
     }
 
     // Try to emit loads from a module namespace.
     MOZ_TRY(getPropTryModuleNamespace(&emitted, obj, name, barrier, types));
     if (emitted) {
       return Ok();
     }
-
-    // Try to emit loads from known binary data blocks
-    MOZ_TRY(getPropTryTypedObject(&emitted, obj, name));
-    if (emitted) {
-      return Ok();
-    }
   }
 
   // Emit a polymorphic cache.
   return getPropAddCache(obj, name, barrier, types);
 }
 
 AbortReasonOr<Ok> IonBuilder::improveThisTypesForCall() {
   // After a CallProp (or CallElem) for obj.prop(), the this-value and callee
@@ -11217,102 +10772,16 @@ AbortReasonOr<Ok> IonBuilder::getPropTry
 
   obj->setImplicitlyUsedUnchecked();
   pushConstant(UndefinedValue());
 
   *emitted = true;
   return Ok();
 }
 
-AbortReasonOr<Ok> IonBuilder::getPropTryTypedObject(bool* emitted,
-                                                    MDefinition* obj,
-                                                    PropertyName* name) {
-  TypedObjectPrediction fieldPrediction;
-  size_t fieldOffset;
-  size_t fieldIndex;
-  bool fieldMutable;
-  if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction,
-                           &fieldIndex, &fieldMutable)) {
-    return Ok();
-  }
-
-  switch (fieldPrediction.kind()) {
-    case type::Struct:
-    case type::Array:
-      return getPropTryComplexPropOfTypedObject(emitted, obj, fieldOffset,
-                                                fieldPrediction, fieldIndex);
-
-    case type::Reference:
-      return getPropTryReferencePropOfTypedObject(emitted, obj, fieldOffset,
-                                                  fieldPrediction, name);
-
-    case type::Scalar:
-      return getPropTryScalarPropOfTypedObject(emitted, obj, fieldOffset,
-                                               fieldPrediction);
-  }
-
-  MOZ_CRASH("Bad kind");
-}
-
-AbortReasonOr<Ok> IonBuilder::getPropTryScalarPropOfTypedObject(
-    bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-    TypedObjectPrediction fieldPrediction) {
-  // Must always be loading the same scalar type
-  Scalar::Type fieldType = fieldPrediction.scalarType();
-
-  if (!CheckTypedObjectSupportedType(fieldType)) {
-    return Ok();
-  }
-
-  *emitted = true;
-
-  LinearSum byteOffset(alloc());
-  if (!byteOffset.add(fieldOffset)) {
-    return abort(AbortReason::Disable, "Overflow of field offsets.");
-  }
-
-  return pushScalarLoadFromTypedObject(typedObj, byteOffset, fieldType);
-}
-
-AbortReasonOr<Ok> IonBuilder::getPropTryReferencePropOfTypedObject(
-    bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-    TypedObjectPrediction fieldPrediction, PropertyName* name) {
-  ReferenceType fieldType = fieldPrediction.referenceType();
-  if (fieldType == ReferenceType::TYPE_WASM_ANYREF) {
-    return Ok();
-  }
-
-  *emitted = true;
-
-  LinearSum byteOffset(alloc());
-  if (!byteOffset.add(fieldOffset)) {
-    return abort(AbortReason::Disable, "Overflow of field offsets.");
-  }
-
-  return pushReferenceLoadFromTypedObject(typedObj, byteOffset, fieldType,
-                                          name);
-}
-
-AbortReasonOr<Ok> IonBuilder::getPropTryComplexPropOfTypedObject(
-    bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-    TypedObjectPrediction fieldPrediction, size_t fieldIndex) {
-  // Identify the type object for the field.
-  MDefinition* type = loadTypedObjectType(typedObj);
-  MDefinition* fieldTypeObj =
-      typeObjectForFieldFromStructType(type, fieldIndex);
-
-  LinearSum byteOffset(alloc());
-  if (!byteOffset.add(fieldOffset)) {
-    return abort(AbortReason::Disable, "Overflow of field offsets.");
-  }
-
-  return pushDerivedTypedObject(emitted, typedObj, byteOffset, fieldPrediction,
-                                fieldTypeObj);
-}
-
 AbortReasonOr<Ok> IonBuilder::getPropTryDefiniteSlot(bool* emitted,
                                                      MDefinition* obj,
                                                      PropertyName* name,
                                                      BarrierKind barrier,
                                                      TemporaryTypeSet* types) {
   MOZ_ASSERT(*emitted == false);
 
   uint32_t nfixed;
@@ -11955,22 +11424,16 @@ AbortReasonOr<Ok> IonBuilder::jsop_setpr
   }
 
   if (!forceInlineCaches()) {
     // Try to inline a common property setter, or make a call.
     MOZ_TRY(setPropTryCommonSetter(&emitted, obj, name, value));
     if (emitted) {
       return Ok();
     }
-
-    // Try to emit stores to known binary data blocks
-    MOZ_TRY(setPropTryTypedObject(&emitted, obj, name, value));
-    if (emitted) {
-      return Ok();
-    }
   }
 
   TemporaryTypeSet* objTypes = obj->resultTypeSet();
   bool barrier = PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
                                                &obj, name, &value,
                                                /* canModify = */ true);
 
   if (!forceInlineCaches()) {
@@ -12148,86 +11611,16 @@ AbortReasonOr<Ok> IonBuilder::setPropTry
   current->push(value);
 
   MOZ_TRY(resumeAfter(set));
 
   *emitted = true;
   return Ok();
 }
 
-AbortReasonOr<Ok> IonBuilder::setPropTryTypedObject(bool* emitted,
-                                                    MDefinition* obj,
-                                                    PropertyName* name,
-                                                    MDefinition* value) {
-  TypedObjectPrediction fieldPrediction;
-  size_t fieldOffset;
-  size_t fieldIndex;
-  bool fieldMutable = false;
-  if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction,
-                           &fieldIndex, &fieldMutable)) {
-    return Ok();
-  }
-
-  if (!fieldMutable) {
-    return Ok();
-  }
-
-  switch (fieldPrediction.kind()) {
-    case type::Reference:
-      return setPropTryReferencePropOfTypedObject(emitted, obj, fieldOffset,
-                                                  value, fieldPrediction, name);
-
-    case type::Scalar:
-      return setPropTryScalarPropOfTypedObject(emitted, obj, fieldOffset, value,
-                                               fieldPrediction);
-
-    case type::Struct:
-    case type::Array:
-      return Ok();
-  }
-
-  MOZ_CRASH("Unknown kind");
-}
-
-AbortReasonOr<Ok> IonBuilder::setPropTryReferencePropOfTypedObject(
-    bool* emitted, MDefinition* obj, int32_t fieldOffset, MDefinition* value,
-    TypedObjectPrediction fieldPrediction, PropertyName* name) {
-  ReferenceType fieldType = fieldPrediction.referenceType();
-  if (fieldType == ReferenceType::TYPE_WASM_ANYREF) {
-    return Ok();
-  }
-
-  LinearSum byteOffset(alloc());
-  if (!byteOffset.add(fieldOffset)) {
-    return abort(AbortReason::Disable, "Overflow of field offset.");
-  }
-
-  return setPropTryReferenceTypedObjectValue(emitted, obj, byteOffset,
-                                             fieldType, value, name);
-}
-
-AbortReasonOr<Ok> IonBuilder::setPropTryScalarPropOfTypedObject(
-    bool* emitted, MDefinition* obj, int32_t fieldOffset, MDefinition* value,
-    TypedObjectPrediction fieldPrediction) {
-  // Must always be loading the same scalar type
-  Scalar::Type fieldType = fieldPrediction.scalarType();
-
-  if (!CheckTypedObjectSupportedType(fieldType)) {
-    return Ok();
-  }
-
-  LinearSum byteOffset(alloc());
-  if (!byteOffset.add(fieldOffset)) {
-    return abort(AbortReason::Disable, "Overflow of field offet.");
-  }
-
-  return setPropTryScalarTypedObjectValue(emitted, obj, byteOffset, fieldType,
-                                          value);
-}
-
 AbortReasonOr<Ok> IonBuilder::setPropTryDefiniteSlot(bool* emitted,
                                                      MDefinition* obj,
                                                      PropertyName* name,
                                                      MDefinition* value,
                                                      bool barrier) {
   MOZ_ASSERT(*emitted == false);
 
   if (barrier) {
@@ -13466,332 +12859,16 @@ MInstruction* IonBuilder::addSharedTyped
   return guard;
 }
 
 TemporaryTypeSet* IonBuilder::bytecodeTypes(jsbytecode* pc) {
   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();
-  }
-
-  TemporaryTypeSet* types = typedObj->resultTypeSet();
-  return typedObjectPrediction(types);
-}
-
-TypedObjectPrediction IonBuilder::typedObjectPrediction(
-    TemporaryTypeSet* types) {
-  // Type set must be known to be an object.
-  if (!types || types->getKnownMIRType() != MIRType::Object) {
-    return TypedObjectPrediction();
-  }
-
-  // And only known objects.
-  if (types->unknownObject()) {
-    return TypedObjectPrediction();
-  }
-
-  TypedObjectPrediction out;
-  for (uint32_t i = 0; i < types->getObjectCount(); i++) {
-    ObjectGroup* group = types->getGroup(i);
-    if (!group || !IsTypedObjectClass(group->clasp())) {
-      return TypedObjectPrediction();
-    }
-
-    if (!TypeSet::ObjectKey::get(group)->hasStableClassAndProto(
-            constraints())) {
-      return TypedObjectPrediction();
-    }
-
-    out.addDescr(group->typeDescr());
-  }
-
-  return out;
-}
-
-MDefinition* IonBuilder::loadTypedObjectType(MDefinition* typedObj) {
-  // Shortcircuit derived type objects, meaning the intermediate
-  // objects created to represent `a.b` in an expression like
-  // `a.b.c`. In that case, the type object can be simply pulled
-  // from the operands of that instruction.
-  if (typedObj->isNewDerivedTypedObject()) {
-    return typedObj->toNewDerivedTypedObject()->type();
-  }
-
-  MInstruction* descr = MTypedObjectDescr::New(alloc(), typedObj);
-  current->add(descr);
-
-  return descr;
-}
-
-// Given a typed object `typedObj` and an offset `offset` into that
-// object's data, returns another typed object and adusted offset
-// where the data can be found. Often, these returned values are the
-// same as the inputs, but in cases where intermediate derived type
-// objects have been created, the return values will remove
-// intermediate layers (often rendering those derived type objects
-// into dead code).
-AbortReasonOr<Ok> IonBuilder::loadTypedObjectData(MDefinition* typedObj,
-                                                  MDefinition** owner,
-                                                  LinearSum* ownerOffset) {
-  MOZ_ASSERT(typedObj->type() == MIRType::Object);
-
-  // Shortcircuit derived type objects, meaning the intermediate
-  // objects created to represent `a.b` in an expression like
-  // `a.b.c`. In that case, the owned and a base offset can be
-  // pulled from the operands of the instruction and combined with
-  // `offset`.
-  if (typedObj->isNewDerivedTypedObject()) {
-    MNewDerivedTypedObject* ins = typedObj->toNewDerivedTypedObject();
-
-    SimpleLinearSum base = ExtractLinearSum(ins->offset());
-    if (!ownerOffset->add(base)) {
-      return abort(AbortReason::Disable,
-                   "Overflow/underflow on type object offset.");
-    }
-
-    *owner = ins->owner();
-    return Ok();
-  }
-
-  *owner = typedObj;
-  return Ok();
-}
-
-// Takes as input a typed object, an offset into that typed object's
-// memory, and the type repr of the data found at that offset. Returns
-// the elements pointer and a scaled offset. The scaled offset is
-// expressed in units of `unit`; when working with typed array MIR,
-// this is typically the alignment.
-AbortReasonOr<Ok> IonBuilder::loadTypedObjectElements(
-    MDefinition* typedObj, const LinearSum& baseByteOffset, uint32_t scale,
-    MDefinition** ownerElements, MDefinition** ownerScaledOffset,
-    int32_t* ownerByteAdjustment) {
-  MDefinition* owner;
-  LinearSum ownerByteOffset(alloc());
-  MOZ_TRY(loadTypedObjectData(typedObj, &owner, &ownerByteOffset));
-
-  if (!ownerByteOffset.add(baseByteOffset)) {
-    return abort(AbortReason::Disable,
-                 "Overflow after adding the base offset.");
-  }
-
-  TemporaryTypeSet* ownerTypes = owner->resultTypeSet();
-  const JSClass* clasp =
-      ownerTypes ? ownerTypes->getKnownClass(constraints()) : nullptr;
-  if (clasp && IsInlineTypedObjectClass(clasp)) {
-    // Perform the load directly from the owner pointer.
-    if (!ownerByteOffset.add(InlineTypedObject::offsetOfDataStart())) {
-      return abort(AbortReason::Disable,
-                   "Overflow after adding the data start.");
-    }
-    *ownerElements = owner;
-  } else {
-    bool definitelyOutline = clasp && IsOutlineTypedObjectClass(clasp);
-    *ownerElements =
-        MTypedObjectElements::New(alloc(), owner, definitelyOutline);
-    current->add((*ownerElements)->toInstruction());
-  }
-
-  // Extract the constant adjustment from the byte offset.
-  *ownerByteAdjustment = ownerByteOffset.constant();
-  int32_t negativeAdjustment;
-  if (!SafeSub(0, *ownerByteAdjustment, &negativeAdjustment)) {
-    return abort(AbortReason::Disable);
-  }
-  if (!ownerByteOffset.add(negativeAdjustment)) {
-    return abort(AbortReason::Disable);
-  }
-
-  // Scale the byte offset if required by the MIR node which will access the
-  // typed object. In principle we should always be able to cleanly divide
-  // the terms in this lienar sum due to alignment restrictions, but due to
-  // limitations of ExtractLinearSum when applied to the terms in derived
-  // typed objects this isn't always be possible. In these cases, fall back
-  // on an explicit division operation.
-  if (ownerByteOffset.divide(scale)) {
-    *ownerScaledOffset = ConvertLinearSum(alloc(), current, ownerByteOffset);
-  } else {
-    MDefinition* unscaledOffset =
-        ConvertLinearSum(alloc(), current, ownerByteOffset);
-    *ownerScaledOffset = MDiv::New(alloc(), unscaledOffset, constantInt(scale),
-                                   MIRType::Int32, /* unsigned = */ false);
-    current->add((*ownerScaledOffset)->toInstruction());
-  }
-  return Ok();
-}
-
-// Looks up the offset/type-repr-set of the field `id`, given the type
-// set `objTypes` of the field owner. If a field is found, returns true
-// and sets *fieldOffset, *fieldPrediction, and *fieldIndex. Returns false
-// otherwise. Infallible.
-bool IonBuilder::typedObjectHasField(MDefinition* typedObj, PropertyName* name,
-                                     size_t* fieldOffset,
-                                     TypedObjectPrediction* fieldPrediction,
-                                     size_t* fieldIndex, bool* fieldMutable) {
-  TypedObjectPrediction objPrediction = typedObjectPrediction(typedObj);
-  if (objPrediction.isUseless()) {
-    return false;
-  }
-
-  // Must be accessing a struct.
-  if (objPrediction.kind() != type::Struct) {
-    return false;
-  }
-
-  // Determine the type/offset of the field `name`, if any.
-  if (!objPrediction.hasFieldNamed(NameToId(name), fieldOffset, fieldPrediction,
-                                   fieldIndex, fieldMutable)) {
-    return false;
-  }
-
-  return true;
-}
-
-MDefinition* IonBuilder::typeObjectForElementFromArrayStructType(
-    MDefinition* typeObj) {
-  MInstruction* elemType =
-      MLoadFixedSlot::New(alloc(), typeObj, JS_DESCR_SLOT_ARRAY_ELEM_TYPE);
-  current->add(elemType);
-
-  MInstruction* unboxElemType =
-      MUnbox::New(alloc(), elemType, MIRType::Object, MUnbox::Infallible);
-  current->add(unboxElemType);
-
-  return unboxElemType;
-}
-
-MDefinition* IonBuilder::typeObjectForFieldFromStructType(MDefinition* typeObj,
-                                                          size_t fieldIndex) {
-  // Load list of field type objects.
-
-  MInstruction* fieldTypes =
-      MLoadFixedSlot::New(alloc(), typeObj, JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
-  current->add(fieldTypes);
-
-  MInstruction* unboxFieldTypes =
-      MUnbox::New(alloc(), fieldTypes, MIRType::Object, MUnbox::Infallible);
-  current->add(unboxFieldTypes);
-
-  // Index into list with index of field.
-
-  MInstruction* fieldTypesElements = MElements::New(alloc(), unboxFieldTypes);
-  current->add(fieldTypesElements);
-
-  MConstant* fieldIndexDef = constantInt(fieldIndex);
-
-  MInstruction* fieldType = MLoadElement::New(alloc(), fieldTypesElements,
-                                              fieldIndexDef, false, false);
-  current->add(fieldType);
-
-  MInstruction* unboxFieldType =
-      MUnbox::New(alloc(), fieldType, MIRType::Object, MUnbox::Infallible);
-  current->add(unboxFieldType);
-
-  return unboxFieldType;
-}
-
-AbortReasonOr<Ok> IonBuilder::setPropTryScalarTypedObjectValue(
-    bool* emitted, MDefinition* typedObj, const LinearSum& byteOffset,
-    ScalarTypeDescr::Type type, MDefinition* value) {
-  MOZ_ASSERT(!*emitted);
-
-  // Find location within the owner object.
-  MDefinition* elements;
-  MDefinition* scaledOffset;
-  int32_t adjustment;
-  uint32_t alignment = ScalarTypeDescr::alignment(type);
-  MOZ_TRY(loadTypedObjectElements(typedObj, byteOffset, alignment, &elements,
-                                  &scaledOffset, &adjustment));
-
-  // Clamp value to [0, 255] when type is Uint8Clamped
-  MDefinition* toWrite = value;
-  if (type == Scalar::Uint8Clamped) {
-    toWrite = MClampToUint8::New(alloc(), value);
-    current->add(toWrite->toInstruction());
-  }
-
-  MStoreUnboxedScalar* store =
-      MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, toWrite, type,
-                               MStoreUnboxedScalar::TruncateInput,
-                               DoesNotRequireMemoryBarrier, adjustment);
-  current->add(store);
-  current->push(value);
-
-  *emitted = true;
-  return resumeAfter(store);
-}
-
-AbortReasonOr<Ok> IonBuilder::setPropTryReferenceTypedObjectValue(
-    bool* emitted, MDefinition* typedObj, const LinearSum& byteOffset,
-    ReferenceType type, MDefinition* value, PropertyName* name) {
-  MOZ_ASSERT(!*emitted);
-
-  // Make sure we aren't adding new type information for writes of object and
-  // value references.
-  if (type != ReferenceType::TYPE_STRING) {
-    MOZ_ASSERT(type == ReferenceType::TYPE_ANY ||
-               type == ReferenceType::TYPE_OBJECT);
-    MIRType implicitType =
-        (type == ReferenceType::TYPE_ANY) ? MIRType::Undefined : MIRType::Null;
-
-    if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
-                                      &typedObj, name, &value,
-                                      /* canModify = */ true, implicitType)) {
-      return Ok();
-    }
-  }
-
-  // Find location within the owner object.
-  MDefinition* elements;
-  MDefinition* scaledOffset;
-  int32_t adjustment;
-  uint32_t alignment = ReferenceTypeDescr::alignment(type);
-  MOZ_TRY(loadTypedObjectElements(typedObj, byteOffset, alignment, &elements,
-                                  &scaledOffset, &adjustment));
-
-  MInstruction* store = nullptr;  // initialize to silence GCC warning
-  switch (type) {
-    case ReferenceType::TYPE_ANY:
-      if (needsPostBarrier(value)) {
-        current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
-      }
-      store = MStoreElement::New(alloc(), elements, scaledOffset, value, false,
-                                 adjustment);
-      store->toStoreElement()->setNeedsBarrier();
-      break;
-    case ReferenceType::TYPE_OBJECT:
-      // Note: We cannot necessarily tell at this point whether a post
-      // barrier is needed, because the type policy may insert ToObjectOrNull
-      // instructions later, and those may require a post barrier. Therefore,
-      // defer the insertion of post barriers to the type policy.
-      store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset,
-                                             value, typedObj, adjustment);
-      break;
-    case ReferenceType::TYPE_STRING:
-      // See previous comment. The StoreUnboxedString type policy may insert
-      // ToString instructions that require a post barrier.
-      store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value,
-                                       typedObj, adjustment);
-      break;
-    case ReferenceType::TYPE_WASM_ANYREF:
-      MOZ_CRASH();
-  }
-
-  current->add(store);
-  current->push(value);
-
-  *emitted = true;
-  return resumeAfter(store);
-}
-
 void IonBuilder::checkNurseryCell(gc::Cell* cell) {
   // If we try to use any nursery pointers during compilation, make sure that
   // the main thread will cancel this compilation before performing a minor
   // GC. All constants used during compilation should either go through this
   // function or should come from a type set (which has a similar barrier).
   if (cell && IsInsideNursery(cell)) {
     realm->zone()->setMinorGCShouldCancelIonCompilations();
     mirGen().setNotSafeForMinorGC();
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -415,27 +415,16 @@ class MOZ_STACK_CLASS IonBuilder {
                                            bool innerized = false);
   AbortReasonOr<Ok> getPropTryInlineAccess(bool* emitted, MDefinition* obj,
                                            PropertyName* name,
                                            BarrierKind barrier,
                                            TemporaryTypeSet* types);
   AbortReasonOr<Ok> getPropTryInlineProtoAccess(bool* emitted, MDefinition* obj,
                                                 PropertyName* name,
                                                 TemporaryTypeSet* types);
-  AbortReasonOr<Ok> getPropTryTypedObject(bool* emitted, MDefinition* obj,
-                                          PropertyName* name);
-  AbortReasonOr<Ok> getPropTryScalarPropOfTypedObject(
-      bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-      TypedObjectPrediction fieldTypeReprs);
-  AbortReasonOr<Ok> getPropTryReferencePropOfTypedObject(
-      bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-      TypedObjectPrediction fieldPrediction, PropertyName* name);
-  AbortReasonOr<Ok> getPropTryComplexPropOfTypedObject(
-      bool* emitted, MDefinition* typedObj, int32_t fieldOffset,
-      TypedObjectPrediction fieldTypeReprs, size_t fieldIndex);
   AbortReasonOr<Ok> getPropTryInnerize(bool* emitted, MDefinition* obj,
                                        PropertyName* name,
                                        TemporaryTypeSet* types);
   AbortReasonOr<Ok> getPropAddCache(MDefinition* obj, PropertyName* name,
                                     BarrierKind barrier,
                                     TemporaryTypeSet* types);
 
   // jsop_setprop() helpers.
@@ -448,31 +437,16 @@ class MOZ_STACK_CLASS IonBuilder {
                                               TemporaryTypeSet* objTypes);
   AbortReasonOr<Ok> setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
                                            PropertyName* name,
                                            MDefinition* value, bool barrier);
   AbortReasonOr<Ok> setPropTryInlineAccess(bool* emitted, MDefinition* obj,
                                            PropertyName* name,
                                            MDefinition* value, bool barrier,
                                            TemporaryTypeSet* objTypes);
-  AbortReasonOr<Ok> setPropTryTypedObject(bool* emitted, MDefinition* obj,
-                                          PropertyName* name,
-                                          MDefinition* value);
-  AbortReasonOr<Ok> setPropTryReferencePropOfTypedObject(
-      bool* emitted, MDefinition* obj, int32_t fieldOffset, MDefinition* value,
-      TypedObjectPrediction fieldPrediction, PropertyName* name);
-  AbortReasonOr<Ok> setPropTryReferenceTypedObjectValue(
-      bool* emitted, MDefinition* typedObj, const LinearSum& byteOffset,
-      ReferenceType type, MDefinition* value, PropertyName* name);
-  AbortReasonOr<Ok> setPropTryScalarPropOfTypedObject(
-      bool* emitted, MDefinition* obj, int32_t fieldOffset, MDefinition* value,
-      TypedObjectPrediction fieldTypeReprs);
-  AbortReasonOr<Ok> setPropTryScalarTypedObjectValue(
-      bool* emitted, MDefinition* typedObj, const LinearSum& byteOffset,
-      ScalarTypeDescr::Type type, MDefinition* value);
   AbortReasonOr<Ok> setPropTryCache(bool* emitted, MDefinition* obj,
                                     PropertyName* name, MDefinition* value,
                                     bool barrier);
 
   // jsop_binary_arith helpers.
   MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left,
                                                   MDefinition* right);
   MIRType binaryArithNumberSpecialization(MDefinition* left,
@@ -539,71 +513,27 @@ class MOZ_STACK_CLASS IonBuilder {
   // jsop_in/jsop_hasown helpers.
   AbortReasonOr<Ok> inTryDense(bool* emitted, MDefinition* obj,
                                MDefinition* id);
   AbortReasonOr<Ok> hasTryNotDefined(bool* emitted, MDefinition* obj,
                                      MDefinition* id, bool ownProperty);
   AbortReasonOr<Ok> hasTryDefiniteSlotOrUnboxed(bool* emitted, MDefinition* obj,
                                                 MDefinition* id);
 
-  // binary data lookup helpers.
-  TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
-  TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
-  bool typedObjectHasField(MDefinition* typedObj, PropertyName* name,
-                           size_t* fieldOffset,
-                           TypedObjectPrediction* fieldTypeReprs,
-                           size_t* fieldIndex, bool* fieldMutable);
-  MDefinition* loadTypedObjectType(MDefinition* value);
-  AbortReasonOr<Ok> loadTypedObjectData(MDefinition* typedObj,
-                                        MDefinition** owner,
-                                        LinearSum* ownerOffset);
-  AbortReasonOr<Ok> loadTypedObjectElements(MDefinition* typedObj,
-                                            const LinearSum& byteOffset,
-                                            uint32_t scale,
-                                            MDefinition** ownerElements,
-                                            MDefinition** ownerScaledOffset,
-                                            int32_t* ownerByteAdjustment);
-  MDefinition* typeObjectForElementFromArrayStructType(MDefinition* typedObj);
-  MDefinition* typeObjectForFieldFromStructType(MDefinition* type,
-                                                size_t fieldIndex);
-  bool checkTypedObjectIndexInBounds(uint32_t elemSize, MDefinition* index,
-                                     TypedObjectPrediction objTypeDescrs,
-                                     LinearSum* indexAsByteOffset);
-  AbortReasonOr<Ok> pushDerivedTypedObject(
-      bool* emitted, MDefinition* obj, const LinearSum& byteOffset,
-      TypedObjectPrediction derivedTypeDescrs, MDefinition* derivedTypeObj);
-  AbortReasonOr<Ok> pushScalarLoadFromTypedObject(MDefinition* obj,
-                                                  const LinearSum& byteoffset,
-                                                  ScalarTypeDescr::Type type);
-  AbortReasonOr<Ok> pushReferenceLoadFromTypedObject(
-      MDefinition* typedObj, const LinearSum& byteOffset, ReferenceType type,
-      PropertyName* name);
-
   // jsop_setelem() helpers.
   AbortReasonOr<Ok> setElemTryTypedArray(bool* emitted, MDefinition* object,
                                          MDefinition* index,
                                          MDefinition* value);
-  AbortReasonOr<Ok> setElemTryTypedObject(bool* emitted, MDefinition* obj,
-                                          MDefinition* index,
-                                          MDefinition* value);
   AbortReasonOr<Ok> initOrSetElemTryDense(bool* emitted, MDefinition* object,
                                           MDefinition* index,
                                           MDefinition* value, bool writeHole);
   AbortReasonOr<Ok> setElemTryArguments(bool* emitted, MDefinition* object);
   AbortReasonOr<Ok> initOrSetElemTryCache(bool* emitted, MDefinition* object,
                                           MDefinition* index,
                                           MDefinition* value);
-  AbortReasonOr<Ok> setElemTryReferenceElemOfTypedObject(
-      bool* emitted, MDefinition* obj, MDefinition* index,
-      TypedObjectPrediction objPrediction, MDefinition* value,
-      TypedObjectPrediction elemPrediction);
-  AbortReasonOr<Ok> setElemTryScalarElemOfTypedObject(
-      bool* emitted, MDefinition* obj, MDefinition* index,
-      TypedObjectPrediction objTypeReprs, MDefinition* value,
-      TypedObjectPrediction elemTypeReprs, uint32_t elemSize);
 
   AbortReasonOr<Ok> initArrayElemTryFastPath(bool* emitted, MDefinition* obj,
                                              MDefinition* id,
                                              MDefinition* value);
 
   AbortReasonOr<Ok> initArrayElementFastPath(
       MNewArray* obj, MDefinition* id, MDefinition* value,
       bool addResumePointAndIncrementInitializedLength);
@@ -615,41 +545,28 @@ class MOZ_STACK_CLASS IonBuilder {
   AbortReasonOr<Ok> getElemTryDense(bool* emitted, MDefinition* obj,
                                     MDefinition* index);
   AbortReasonOr<Ok> getElemTryGetProp(bool* emitted, MDefinition* obj,
                                       MDefinition* index);
   AbortReasonOr<Ok> getElemTryTypedArray(bool* emitted, MDefinition* obj,
                                          MDefinition* index);
   AbortReasonOr<Ok> getElemTryCallSiteObject(bool* emitted, MDefinition* obj,
                                              MDefinition* index);
-  AbortReasonOr<Ok> getElemTryTypedObject(bool* emitted, MDefinition* obj,
-                                          MDefinition* index);
   AbortReasonOr<Ok> getElemTryString(bool* emitted, MDefinition* obj,
                                      MDefinition* index);
   AbortReasonOr<Ok> getElemTryArguments(bool* emitted, MDefinition* obj,
                                         MDefinition* index);
   AbortReasonOr<Ok> getElemTryArgumentsInlinedConstant(bool* emitted,
                                                        MDefinition* obj,
                                                        MDefinition* index);
   AbortReasonOr<Ok> getElemTryArgumentsInlinedIndex(bool* emitted,
                                                     MDefinition* obj,
                                                     MDefinition* index);
   AbortReasonOr<Ok> getElemAddCache(MDefinition* obj, MDefinition* index);
-  AbortReasonOr<Ok> getElemTryScalarElemOfTypedObject(
-      bool* emitted, MDefinition* obj, MDefinition* index,
-      TypedObjectPrediction objTypeReprs, TypedObjectPrediction elemTypeReprs,
-      uint32_t elemSize);
-  AbortReasonOr<Ok> getElemTryReferenceElemOfTypedObject(
-      bool* emitted, MDefinition* obj, MDefinition* index,
-      TypedObjectPrediction objPrediction,
-      TypedObjectPrediction elemPrediction);
-  AbortReasonOr<Ok> getElemTryComplexElemOfTypedObject(
-      bool* emitted, MDefinition* obj, MDefinition* index,
-      TypedObjectPrediction objTypeReprs, TypedObjectPrediction elemTypeReprs,
-      uint32_t elemSize);
+
   TemporaryTypeSet* computeHeapType(const TemporaryTypeSet* objTypes,
                                     const jsid id);
 
   enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
 
   MInstruction* addArrayBufferByteLength(MDefinition* obj);
 
   TypedArrayObject* tryTypedArrayEmbedConstantElements(MDefinition* obj);
@@ -955,21 +872,16 @@ class MOZ_STACK_CLASS IonBuilder {
                                           WrappingBehavior wrappingBehavior);
   InliningResult inlineIsTypedArray(CallInfo& callInfo);
   InliningResult inlineIsPossiblyWrappedTypedArray(CallInfo& callInfo);
   InliningResult inlineTypedArrayLength(CallInfo& callInfo);
   InliningResult inlinePossiblyWrappedTypedArrayLength(CallInfo& callInfo);
   InliningResult inlineTypedArrayByteOffset(CallInfo& callInfo);
   InliningResult inlineTypedArrayElementShift(CallInfo& callInfo);
 
-  // TypedObject intrinsics and natives.
-  InliningResult inlineObjectIsTypeDescr(CallInfo& callInfo);
-  InliningResult inlineConstructTypedObject(CallInfo& callInfo,
-                                            TypeDescr* target);
-
   // Utility intrinsics.
   InliningResult inlineIsCallable(CallInfo& callInfo);
   InliningResult inlineIsConstructor(CallInfo& callInfo);
   InliningResult inlineIsObject(CallInfo& callInfo);
   InliningResult inlineToObject(CallInfo& callInfo);
   InliningResult inlineIsCrossRealmArrayConstructor(CallInfo& callInfo);
   InliningResult inlineToIntegerPositiveZero(CallInfo& callInfo);
   InliningResult inlineToString(CallInfo& callInfo);
@@ -992,17 +904,16 @@ class MOZ_STACK_CLASS IonBuilder {
   InliningResult inlineAssertRecoveredOnBailout(CallInfo& callInfo);
 
   // Bind function.
   InliningResult inlineBoundFunction(CallInfo& callInfo, JSFunction* target);
 
   // Main inlining functions
   InliningResult inlineNativeCall(CallInfo& callInfo, JSFunction* target);
   InliningResult inlineNativeGetter(CallInfo& callInfo, JSFunction* target);
-  InliningResult inlineNonFunctionCall(CallInfo& callInfo, JSObject* target);
   InliningResult inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
   InliningResult inlineSingleCall(CallInfo& callInfo, JSObject* target);
 
   // Call functions
   InliningResult inlineCallsite(const InliningTargets& targets,
                                 CallInfo& callInfo);
   AbortReasonOr<Ok> inlineCalls(CallInfo& callInfo,
                                 const InliningTargets& targets,
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -229,42 +229,28 @@ void LIRGenerator::visitNewTypedArrayFro
 }
 
 void LIRGenerator::visitNewObject(MNewObject* ins) {
   LNewObject* lir = new (alloc()) LNewObject(temp());
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
 
-void LIRGenerator::visitNewTypedObject(MNewTypedObject* ins) {
-  LNewTypedObject* lir = new (alloc()) LNewTypedObject(temp());
-  define(lir, ins);
-  assignSafepoint(lir, ins);
-}
-
 void LIRGenerator::visitNewNamedLambdaObject(MNewNamedLambdaObject* ins) {
   LNewNamedLambdaObject* lir = new (alloc()) LNewNamedLambdaObject(temp());
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
 
 void LIRGenerator::visitNewCallObject(MNewCallObject* ins) {
   LNewCallObject* lir = new (alloc()) LNewCallObject(temp());
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
 
-void LIRGenerator::visitNewDerivedTypedObject(MNewDerivedTypedObject* ins) {
-  LNewDerivedTypedObject* lir = new (alloc()) LNewDerivedTypedObject(
-      useRegisterAtStart(ins->type()), useRegisterAtStart(ins->owner()),
-      useRegisterAtStart(ins->offset()));
-  defineReturn(lir, ins);
-  assignSafepoint(lir, ins);
-}
-
 void LIRGenerator::visitNewStringObject(MNewStringObject* ins) {
   MOZ_ASSERT(ins->input()->type() == MIRType::String);
 
   LNewStringObject* lir =
       new (alloc()) LNewStringObject(useRegister(ins->input()), temp());
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
@@ -2310,24 +2296,19 @@ void LIRGenerator::visitToObjectOrNull(M
 
   LValueToObjectOrNull* lir =
       new (alloc()) LValueToObjectOrNull(useBox(ins->input()));
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
 
 void LIRGenerator::visitRegExp(MRegExp* ins) {
-  if (ins->mustClone()) {
-    LRegExp* lir = new (alloc()) LRegExp(temp());
-    define(lir, ins);
-    assignSafepoint(lir, ins);
-  } else {
-    RegExpObject* source = ins->source();
-    define(new (alloc()) LPointer(source), ins);
-  }
+  LRegExp* lir = new (alloc()) LRegExp(temp());
+  define(lir, ins);
+  assignSafepoint(lir, ins);
 }
 
 void LIRGenerator::visitRegExpMatcher(MRegExpMatcher* ins) {
   MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   MOZ_ASSERT(ins->string()->type() == MIRType::String);
   MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
 
   LRegExpMatcher* lir = new (alloc()) LRegExpMatcher(
@@ -2934,27 +2915,16 @@ void LIRGenerator::visitTypedArrayIndexT
   if (input->type() == MIRType::Int32) {
     redefine(ins, input);
   } else {
     MOZ_ASSERT(input->type() == MIRType::Double);
     define(new (alloc()) LTypedArrayIndexToInt32(useRegister(input)), ins);
   }
 }
 
-void LIRGenerator::visitTypedObjectDescr(MTypedObjectDescr* ins) {
-  MOZ_ASSERT(ins->type() == MIRType::Object);
-  define(new (alloc()) LTypedObjectDescr(useRegisterAtStart(ins->object())),
-         ins);
-}
-
-void LIRGenerator::visitTypedObjectElements(MTypedObjectElements* ins) {
-  MOZ_ASSERT(ins->type() == MIRType::Elements);
-  define(new (alloc()) LTypedObjectElements(useRegister(ins->object())), ins);
-}
-
 void LIRGenerator::visitInitializedLength(MInitializedLength* ins) {
   MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   define(new (alloc()) LInitializedLength(useRegisterAtStart(ins->elements())),
          ins);
 }
 
 void LIRGenerator::visitSetInitializedLength(MSetInitializedLength* ins) {
   MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
@@ -3138,47 +3108,16 @@ void LIRGenerator::visitLoadElementHole(
       LLoadElementHole(useRegister(ins->elements()), useRegister(ins->index()),
                        useRegister(ins->initLength()));
   if (ins->needsNegativeIntCheck()) {
     assignSnapshot(lir, Bailout_NegativeIndex);
   }
   defineBox(lir, ins);
 }
 
-void LIRGenerator::visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins) {
-  MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
-  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
-
-  if (ins->type() == MIRType::Object || ins->type() == MIRType::ObjectOrNull) {
-    LLoadUnboxedPointerT* lir = new (alloc()) LLoadUnboxedPointerT(
-        useRegister(ins->elements()), useRegisterOrConstant(ins->index()));
-    if (ins->nullBehavior() == MLoadUnboxedObjectOrNull::BailOnNull) {
-      assignSnapshot(lir, Bailout_TypeBarrierO);
-    }
-    define(lir, ins);
-  } else {
-    MOZ_ASSERT(ins->type() == MIRType::Value);
-    MOZ_ASSERT(ins->nullBehavior() != MLoadUnboxedObjectOrNull::BailOnNull);
-
-    LLoadUnboxedPointerV* lir = new (alloc()) LLoadUnboxedPointerV(
-        useRegister(ins->elements()), useRegisterOrConstant(ins->index()));
-    defineBox(lir, ins);
-  }
-}
-
-void LIRGenerator::visitLoadUnboxedString(MLoadUnboxedString* ins) {
-  MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
-  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
-  MOZ_ASSERT(ins->type() == MIRType::String);
-
-  LLoadUnboxedPointerT* lir = new (alloc()) LLoadUnboxedPointerT(
-      useRegister(ins->elements()), useRegisterOrConstant(ins->index()));
-  define(lir, ins);
-}
-
 void LIRGenerator::visitLoadElementFromState(MLoadElementFromState* ins) {
   MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
 
   LDefinition temp1 = LDefinition::BogusTemp();
 #ifdef JS_NUNBOX32
   temp1 = temp();
 #endif
   MOZ_ASSERT(
@@ -3340,47 +3279,16 @@ void LIRGenerator::visitFallibleStoreEle
           LFallibleStoreElementT(object, elements, index, value, spectreTemp);
       break;
   }
 
   add(lir, ins);
   assignSafepoint(lir, ins);
 }
 
-void LIRGenerator::visitStoreUnboxedObjectOrNull(
-    MStoreUnboxedObjectOrNull* ins) {
-  MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
-  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
-  MOZ_ASSERT(ins->value()->type() == MIRType::Object ||
-             ins->value()->type() == MIRType::Null ||
-             ins->value()->type() == MIRType::ObjectOrNull);
-
-  const LUse elements = useRegister(ins->elements());
-  const LAllocation index = useRegisterOrNonDoubleConstant(ins->index());
-  const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
-
-  LInstruction* lir =
-      new (alloc()) LStoreUnboxedPointer(elements, index, value);
-  add(lir, ins);
-}
-
-void LIRGenerator::visitStoreUnboxedString(MStoreUnboxedString* ins) {
-  MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
-  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
-  MOZ_ASSERT(ins->value()->type() == MIRType::String);
-
-  const LUse elements = useRegister(ins->elements());
-  const LAllocation index = useRegisterOrConstant(ins->index());
-  const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
-
-  LInstruction* lir =
-      new (alloc()) LStoreUnboxedPointer(elements, index, value);
-  add(lir, ins);
-}
-
 void LIRGenerator::visitEffectiveAddress(MEffectiveAddress* ins) {
   define(new (alloc()) LEffectiveAddress(useRegister(ins->base()),
                                          useRegister(ins->index())),
          ins);
 }
 
 void LIRGenerator::visitArrayPopShift(MArrayPopShift* ins) {
   LUse object = useRegister(ins->object());
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -161,20 +161,16 @@ static bool CanInlineCrossRealm(Inlinabl
     case InlinableNative::IntrinsicGuardToSharedArrayBuffer:
     case InlinableNative::IntrinsicIsTypedArrayConstructor:
     case InlinableNative::IntrinsicIsTypedArray:
     case InlinableNative::IntrinsicIsPossiblyWrappedTypedArray:
     case InlinableNative::IntrinsicPossiblyWrappedTypedArrayLength:
     case InlinableNative::IntrinsicTypedArrayLength:
     case InlinableNative::IntrinsicTypedArrayByteOffset:
     case InlinableNative::IntrinsicTypedArrayElementShift:
-    case InlinableNative::IntrinsicObjectIsTypedObject:
-    case InlinableNative::IntrinsicObjectIsTypeDescr:
-    case InlinableNative::IntrinsicTypeDescrIsSimpleType:
-    case InlinableNative::IntrinsicTypeDescrIsArrayType:
     case InlinableNative::IntrinsicArrayIteratorPrototypeOptimizable:
       MOZ_CRASH("Unexpected cross-realm intrinsic call");
 
     case InlinableNative::TestBailout:
     case InlinableNative::TestAssertFloat32:
     case InlinableNative::TestAssertRecoveredOnBailout:
       // Testing functions, not worth inlining cross-realm.
       return false;
@@ -555,29 +551,16 @@ IonBuilder::InliningResult IonBuilder::i
       return inlinePossiblyWrappedTypedArrayLength(callInfo);
     case InlinableNative::IntrinsicTypedArrayLength:
       return inlineTypedArrayLength(callInfo);
     case InlinableNative::IntrinsicTypedArrayByteOffset:
       return inlineTypedArrayByteOffset(callInfo);
     case InlinableNative::IntrinsicTypedArrayElementShift:
       return inlineTypedArrayElementShift(callInfo);
 
-    // TypedObject intrinsics.
-    case InlinableNative::IntrinsicObjectIsTypedObject:
-      return inlineHasClass(callInfo, &OutlineTransparentTypedObject::class_,
-                            &OutlineOpaqueTypedObject::class_,
-                            &InlineTransparentTypedObject::class_,
-                            &InlineOpaqueTypedObject::class_);
-    case InlinableNative::IntrinsicObjectIsTypeDescr:
-      return inlineObjectIsTypeDescr(callInfo);
-    case InlinableNative::IntrinsicTypeDescrIsSimpleType:
-      return inlineHasClass(callInfo, &ScalarTypeDescr::class_,
-                            &ReferenceTypeDescr::class_);
-    case InlinableNative::IntrinsicTypeDescrIsArrayType:
-      return inlineHasClass(callInfo, &ArrayTypeDescr::class_);
     case InlinableNative::Limit:
       break;
   }
 
   MOZ_CRASH("Shouldn't get here");
 }
 
 IonBuilder::InliningResult IonBuilder::inlineNativeGetter(CallInfo& callInfo,
@@ -644,40 +627,16 @@ IonBuilder::InliningResult IonBuilder::i
     MDefinition* result = convertToBoolean(maskedFlag);
     current->push(result);
     return InliningStatus_Inlined;
   }
 
   return InliningStatus_NotInlined;
 }
 
-IonBuilder::InliningResult IonBuilder::inlineNonFunctionCall(CallInfo& callInfo,
-                                                             JSObject* target) {
-  // Inline a call to a non-function object, invoking the object's call or
-  // construct hook.
-
-  // Don't inline if we're constructing and new.target != callee. This can
-  // happen with Reflect.construct or derived class constructors.
-  if (callInfo.constructing() && callInfo.getNewTarget() != callInfo.fun()) {
-    return InliningStatus_NotInlined;
-  }
-
-  Realm* targetRealm = JS::GetObjectRealmOrNull(target);
-  if (!targetRealm || targetRealm != script()->realm()) {
-    return InliningStatus_NotInlined;
-  }
-
-  if (callInfo.constructing() &&
-      target->constructHook() == TypedObject::construct) {
-    return inlineConstructTypedObject(callInfo, &target->as<TypeDescr>());
-  }
-
-  return InliningStatus_NotInlined;
-}
-
 TemporaryTypeSet* IonBuilder::getInlineReturnTypeSet() {
   return bytecodeTypes(pc);
 }
 
 MIRType IonBuilder::getInlineReturnType() {
   TemporaryTypeSet* returnTypes = getInlineReturnTypeSet();
   return returnTypes->getKnownMIRType();
 }
@@ -3313,55 +3272,16 @@ IonBuilder::InliningResult IonBuilder::i
   auto* ins = MTypedArrayElementShift::New(alloc(), callInfo.getArg(0));
   current->add(ins);
   current->push(ins);
 
   callInfo.setImplicitlyUsedUnchecked();
   return InliningStatus_Inlined;
 }
 
-IonBuilder::InliningResult IonBuilder::inlineObjectIsTypeDescr(
-    CallInfo& callInfo) {
-  MOZ_ASSERT(!callInfo.constructing());
-  MOZ_ASSERT(callInfo.argc() == 1);
-
-  if (callInfo.getArg(0)->type() != MIRType::Object) {
-    return InliningStatus_NotInlined;
-  }
-  if (getInlineReturnType() != MIRType::Boolean) {
-    return InliningStatus_NotInlined;
-  }
-
-  // The test is elaborate: in-line only if there is exact
-  // information.
-
-  TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
-  if (!types) {
-    return InliningStatus_NotInlined;
-  }
-
-  bool result = false;
-  switch (types->forAllClasses(constraints(), IsTypeDescrClass)) {
-    case TemporaryTypeSet::ForAllResult::ALL_FALSE:
-    case TemporaryTypeSet::ForAllResult::EMPTY:
-      result = false;
-      break;
-    case TemporaryTypeSet::ForAllResult::ALL_TRUE:
-      result = true;
-      break;
-    case TemporaryTypeSet::ForAllResult::MIXED:
-      return InliningStatus_NotInlined;
-  }
-
-  pushConstant(BooleanValue(result));
-
-  callInfo.setImplicitlyUsedUnchecked();
-  return InliningStatus_Inlined;
-}
-
 IonBuilder::InliningResult IonBuilder::inlineUnsafeSetReservedSlot(
     CallInfo& callInfo) {
   MOZ_ASSERT(!callInfo.constructing());
   MOZ_ASSERT(callInfo.argc() == 3);
 
   if (getInlineReturnType() != MIRType::Undefined) {
     return InliningStatus_NotInlined;
   }
@@ -4073,49 +3993,16 @@ IonBuilder::InliningResult IonBuilder::i
     return InliningStatus_Inlined;
   }
 
   bool constructing = inlineCallInfo_->constructing();
   pushConstant(BooleanValue(constructing));
   return InliningStatus_Inlined;
 }
 
-IonBuilder::InliningResult IonBuilder::inlineConstructTypedObject(
-    CallInfo& callInfo, TypeDescr* descr) {
-  // Only inline default constructors for now.
-  if (callInfo.argc() != 0) {
-    return InliningStatus_NotInlined;
-  }
-
-  if (!InlineTypedObject::canAccommodateType(descr)) {
-    return InliningStatus_NotInlined;
-  }
-
-  JSObject* obj =
-      inspector->getTemplateObjectForClassHook(pc, descr->getClass());
-  if (!obj || !obj->is<InlineTypedObject>()) {
-    return InliningStatus_NotInlined;
-  }
-
-  InlineTypedObject* templateObject = &obj->as<InlineTypedObject>();
-  if (&templateObject->typeDescr() != descr) {
-    return InliningStatus_NotInlined;
-  }
-
-  callInfo.setImplicitlyUsedUnchecked();
-
-  MNewTypedObject* ins =
-      MNewTypedObject::New(alloc(), constraints(), templateObject,
-                           templateObject->group()->initialHeap(constraints()));
-  current->add(ins);
-  current->push(ins);
-
-  return InliningStatus_Inlined;
-}
-
 IonBuilder::InliningResult IonBuilder::inlineWasmCall(CallInfo& callInfo,
                                                       JSFunction* target) {
   MOZ_ASSERT(target->isWasmWithJitEntry());
 
   // Don't inline wasm constructors.
   if (callInfo.constructing()) {
     return InliningStatus_NotInlined;
   }
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -365,19 +365,16 @@ MDefinition* MInstruction::foldsToStore(
       value = store->toStoreFixedSlot()->value();
       break;
     case Opcode::StoreSlot:
       value = store->toStoreSlot()->value();
       break;
     case Opcode::StoreElement:
       value = store->toStoreElement()->value();
       break;
-    case Opcode::StoreUnboxedObjectOrNull:
-      value = store->toStoreUnboxedObjectOrNull()->value();
-      break;
     default:
       MOZ_CRASH("unknown store");
   }
 
   // If the type are matching then we return the value which is used as
   // argument of the store.
   if (value->type() != type()) {
     // If we expect to read a type which is more generic than the type seen
@@ -5153,48 +5150,16 @@ MDefinition::AliasType MLoadElement::mig
 MDefinition* MLoadElement::foldsTo(TempAllocator& alloc) {
   if (MDefinition* def = foldsToStore(alloc)) {
     return def;
   }
 
   return this;
 }
 
-MDefinition::AliasType MLoadUnboxedObjectOrNull::mightAlias(
-    const MDefinition* def) const {
-  if (def->isStoreUnboxedObjectOrNull()) {
-    const MStoreUnboxedObjectOrNull* store = def->toStoreUnboxedObjectOrNull();
-    if (store->index() != index()) {
-      if (DefinitelyDifferentValue(store->index(), index())) {
-        return AliasType::NoAlias;
-      }
-      return AliasType::MayAlias;
-    }
-
-    if (store->elements() != elements()) {
-      return AliasType::MayAlias;
-    }
-
-    if (store->offsetAdjustment() != offsetAdjustment()) {
-      return AliasType::MayAlias;
-    }
-
-    return AliasType::MustAlias;
-  }
-  return AliasType::MayAlias;
-}
-
-MDefinition* MLoadUnboxedObjectOrNull::foldsTo(TempAllocator& alloc) {
-  if (MDefinition* def = foldsToStore(alloc)) {
-    return def;
-  }
-
-  return this;
-}
-
 bool MGuardReceiverPolymorphic::congruentTo(const MDefinition* ins) const {
   if (!ins->isGuardReceiverPolymorphic()) {
     return false;
   }
 
   const MGuardReceiverPolymorphic* other = ins->toGuardReceiverPolymorphic();
 
   if (numReceivers() != other->numReceivers()) {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -22,17 +22,16 @@
 #include "jit/AtomicOp.h"
 #include "jit/BaselineIC.h"
 #include "jit/FixedList.h"
 #include "jit/InlineList.h"
 #include "jit/JitAllocPolicy.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MOpcodes.h"
 #include "jit/TIOracle.h"
-#include "jit/TypedObjectPrediction.h"
 #include "jit/TypePolicy.h"
 #include "js/HeapAPI.h"
 #include "vm/ArrayObject.h"
 #include "vm/EnvironmentObject.h"
 #include "vm/RegExpObject.h"
 #include "vm/SharedMem.h"
 #include "vm/TypedArrayObject.h"
 
@@ -2370,108 +2369,16 @@ class MNewIterator : public MUnaryInstru
 
   AliasSet getAliasSet() const override { return AliasSet::None(); }
 
   MOZ_MUST_USE bool writeRecoverData(
       CompactBufferWriter& writer) const override;
   bool canRecoverOnBailout() const override { return true; }
 };
 
-class MNewTypedObject : public MNullaryInstruction {
-  CompilerGCPointer<InlineTypedObject*> templateObject_;
-  gc::InitialHeap initialHeap_;
-
-  MNewTypedObject(TempAllocator& alloc, CompilerConstraintList* constraints,
-                  InlineTypedObject* templateObject,
-                  gc::InitialHeap initialHeap)
-      : MNullaryInstruction(classOpcode),
-        templateObject_(templateObject),
-        initialHeap_(initialHeap) {
-    setResultType(MIRType::Object);
-    setResultTypeSet(MakeSingletonTypeSet(alloc, constraints, templateObject));
-  }
-
- public:
-  INSTRUCTION_HEADER(NewTypedObject)
-  TRIVIAL_NEW_WRAPPERS_WITH_ALLOC
-
-  InlineTypedObject* templateObject() const { return templateObject_; }
-
-  gc::InitialHeap initialHeap() const { return initialHeap_; }
-
-  virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
-
-  bool appendRoots(MRootList& roots) const override {
-    return roots.append(templateObject_);
-  }
-};
-
-class MTypedObjectDescr : public MUnaryInstruction,
-                          public SingleObjectPolicy::Data {
- private:
-  explicit MTypedObjectDescr(MDefinition* object)
-      : MUnaryInstruction(classOpcode, object) {
-    setResultType(MIRType::Object);
-    setMovable();
-  }
-
- public:
-  INSTRUCTION_HEADER(TypedObjectDescr)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, object))
-
-  bool congruentTo(const MDefinition* ins) const override {
-    return congruentIfOperandsEqual(ins);
-  }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Load(AliasSet::ObjectFields);
-  }
-};
-
-// Creates a new derived type object. At runtime, this is just a call
-// to `BinaryBlock::createDerived()`. That is, the MIR itself does not
-// compile to particularly optimized code. However, using a distinct
-// MIR for creating derived type objects allows the compiler to
-// optimize ephemeral typed objects as would be created for a
-// reference like `a.b.c` -- here, the `a.b` will create an ephemeral
-// derived type object that aliases the memory of `a` itself. The
-// specific nature of `a.b` is revealed by using
-// `MNewDerivedTypedObject` rather than `MGetProperty` or what have
-// you. Moreover, the compiler knows that there are no side-effects,
-// so `MNewDerivedTypedObject` instructions can be reordered or pruned
-// as dead code.
-class MNewDerivedTypedObject
-    : public MTernaryInstruction,
-      public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>,
-                       UnboxedInt32Policy<2>>::Data {
- private:
-  TypedObjectPrediction prediction_;
-
-  MNewDerivedTypedObject(TypedObjectPrediction prediction, MDefinition* type,
-                         MDefinition* owner, MDefinition* offset)
-      : MTernaryInstruction(classOpcode, type, owner, offset),
-        prediction_(prediction) {
-    setMovable();
-    setResultType(MIRType::Object);
-  }
-
- public:
-  INSTRUCTION_HEADER(NewDerivedTypedObject)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, type), (1, owner), (2, offset))
-
-  TypedObjectPrediction prediction() const { return prediction_; }
-
-  virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
-
-  MOZ_MUST_USE bool writeRecoverData(
-      CompactBufferWriter& writer) const override;
-  bool canRecoverOnBailout() const override { return true; }
-};
-
 // Represent the content of all slots of an object.  This instruction is not
 // lowered and is not used to generate code.
 class MObjectState : public MVariadicInstruction,
                      public NoFloatPolicyAfter<1>::Data {
  private:
   uint32_t numSlots_;
   uint32_t numFixedSlots_;
 
@@ -6537,35 +6444,31 @@ class MDefFun : public MBinaryInstructio
   TRIVIAL_NEW_WRAPPERS
   NAMED_OPERANDS((0, fun), (1, environmentChain))
 
   bool possiblyCalls() const override { return true; }
 };
 
 class MRegExp : public MNullaryInstruction {
   CompilerGCPointer<RegExpObject*> source_;
-  bool mustClone_;
   bool hasShared_;
 
   MRegExp(TempAllocator& alloc, CompilerConstraintList* constraints,
           RegExpObject* source, bool hasShared)
       : MNullaryInstruction(classOpcode),
         source_(source),
-        mustClone_(true),
         hasShared_(hasShared) {
     setResultType(MIRType::Object);
     setResultTypeSet(MakeSingletonTypeSet(alloc, constraints, source));
   }
 
  public:
   INSTRUCTION_HEADER(RegExp)
   TRIVIAL_NEW_WRAPPERS_WITH_ALLOC
 
-  void setDoNotClone() { mustClone_ = false; }
-  bool mustClone() const { return mustClone_; }
   bool hasShared() const { return hasShared_; }
   RegExpObject* source() const { return source_; }
   AliasSet getAliasSet() const override { return AliasSet::None(); }
   bool possiblyCalls() const override { return true; }
   bool appendRoots(MRootList& roots) const override {
     return roots.append(source_);
   }
 };
@@ -7341,52 +7244,16 @@ class MTypedArrayIndexToInt32 : public M
     return congruentIfOperandsEqual(ins);
   }
 
   AliasSet getAliasSet() const override { return AliasSet::None(); }
 
   ALLOW_CLONE(MTypedArrayIndexToInt32)
 };
 
-// Load a binary data object's "elements", which is just its opaque
-// binary data space. Eventually this should probably be
-// unified with `MTypedArrayElements`.
-class MTypedObjectElements : public MUnaryInstruction,
-                             public SingleObjectPolicy::Data {
-  bool definitelyOutline_;
-
- private:
-  explicit MTypedObjectElements(MDefinition* object, bool definitelyOutline)
-      : MUnaryInstruction(classOpcode, object),
-        definitelyOutline_(definitelyOutline) {
-    setResultType(MIRType::Elements);
-    setMovable();
-  }
-
- public:
-  INSTRUCTION_HEADER(TypedObjectElements)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, object))
-
-  bool definitelyOutline() const { return definitelyOutline_; }
-  bool congruentTo(const MDefinition* ins) const override {
-    if (!ins->isTypedObjectElements()) {
-      return false;
-    }
-    const MTypedObjectElements* other = ins->toTypedObjectElements();
-    if (other->definitelyOutline() != definitelyOutline()) {
-      return false;
-    }
-    return congruentIfOperandsEqual(other);
-  }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Load(AliasSet::ObjectFields);
-  }
-};
-
 class MKeepAliveObject : public MUnaryInstruction,
                          public SingleObjectPolicy::Data {
   explicit MKeepAliveObject(MDefinition* object)
       : MUnaryInstruction(classOpcode, object) {
     setResultType(MIRType::None);
     setGuard();
   }
 
@@ -7687,109 +7554,16 @@ class MLoadElementHole : public MTernary
   AliasSet getAliasSet() const override {
     return AliasSet::Load(AliasSet::Element);
   }
   void collectRangeInfoPreTrunc() override;
 
   ALLOW_CLONE(MLoadElementHole)
 };
 
-class MLoadUnboxedObjectOrNull : public MBinaryInstruction,
-                                 public SingleObjectPolicy::Data {
- public:
-  enum NullBehavior { HandleNull, BailOnNull, NullNotPossible };
-
- private:
-  NullBehavior nullBehavior_;
-  int32_t offsetAdjustment_;
-
-  MLoadUnboxedObjectOrNull(MDefinition* elements, MDefinition* index,
-                           NullBehavior nullBehavior, int32_t offsetAdjustment)
-      : MBinaryInstruction(classOpcode, elements, index),
-        nullBehavior_(nullBehavior),
-        offsetAdjustment_(offsetAdjustment) {
-    if (nullBehavior == BailOnNull) {
-      // Don't eliminate loads which bail out on a null pointer, for the
-      // same reason as MLoadElement.
-      setGuard();
-    }
-    setResultType(nullBehavior == HandleNull ? MIRType::Value
-                                             : MIRType::Object);
-    setMovable();
-    MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
-    MOZ_ASSERT(index->type() == MIRType::Int32);
-  }
-
- public:
-  INSTRUCTION_HEADER(LoadUnboxedObjectOrNull)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, elements), (1, index))
-
-  NullBehavior nullBehavior() const { return nullBehavior_; }
-  int32_t offsetAdjustment() const { return offsetAdjustment_; }
-  bool fallible() const { return nullBehavior() == BailOnNull; }
-  bool congruentTo(const MDefinition* ins) const override {
-    if (!ins->isLoadUnboxedObjectOrNull()) {
-      return false;
-    }
-    const MLoadUnboxedObjectOrNull* other = ins->toLoadUnboxedObjectOrNull();
-    if (nullBehavior() != other->nullBehavior()) {
-      return false;
-    }
-    if (offsetAdjustment() != other->offsetAdjustment()) {
-      return false;
-    }
-    return congruentIfOperandsEqual(other);
-  }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Load(AliasSet::UnboxedElement);
-  }
-  AliasType mightAlias(const MDefinition* store) const override;
-  MDefinition* foldsTo(TempAllocator& alloc) override;
-
-  ALLOW_CLONE(MLoadUnboxedObjectOrNull)
-};
-
-class MLoadUnboxedString : public MBinaryInstruction,
-                           public SingleObjectPolicy::Data {
-  int32_t offsetAdjustment_;
-
-  MLoadUnboxedString(MDefinition* elements, MDefinition* index,
-                     int32_t offsetAdjustment = 0)
-      : MBinaryInstruction(classOpcode, elements, index),
-        offsetAdjustment_(offsetAdjustment) {
-    setResultType(MIRType::String);
-    setMovable();
-    MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
-    MOZ_ASSERT(index->type() == MIRType::Int32);
-  }
-
- public:
-  INSTRUCTION_HEADER(LoadUnboxedString)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, elements), (1, index))
-
-  int32_t offsetAdjustment() const { return offsetAdjustment_; }
-  bool congruentTo(const MDefinition* ins) const override {
-    if (!ins->isLoadUnboxedString()) {
-      return false;
-    }
-    const MLoadUnboxedString* other = ins->toLoadUnboxedString();
-    if (offsetAdjustment() != other->offsetAdjustment()) {
-      return false;
-    }
-    return congruentIfOperandsEqual(ins);
-  }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Load(AliasSet::UnboxedElement);
-  }
-
-  ALLOW_CLONE(MLoadUnboxedString)
-};
-
 class MStoreElementCommon {
   MIRType elementType_;
   bool needsBarrier_;
 
  protected:
   MStoreElementCommon() : elementType_(MIRType::Value), needsBarrier_(false) {}
 
  public:
@@ -7899,86 +7673,16 @@ class MFallibleStoreElement
   TRIVIAL_NEW_WRAPPERS
   NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
 
   bool needsHoleCheck() const { return needsHoleCheck_; }
 
   ALLOW_CLONE(MFallibleStoreElement)
 };
 
-// Store an unboxed object or null pointer to an elements vector.
-class MStoreUnboxedObjectOrNull : public MQuaternaryInstruction,
-                                  public StoreUnboxedObjectOrNullPolicy::Data {
-  int32_t offsetAdjustment_;
-  bool preBarrier_;
-
-  MStoreUnboxedObjectOrNull(MDefinition* elements, MDefinition* index,
-                            MDefinition* value, MDefinition* typedObj,
-                            int32_t offsetAdjustment = 0,
-                            bool preBarrier = true)
-      : MQuaternaryInstruction(classOpcode, elements, index, value, typedObj),
-        offsetAdjustment_(offsetAdjustment),
-        preBarrier_(preBarrier) {
-    MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
-    MOZ_ASSERT(index->type() == MIRType::Int32);
-    MOZ_ASSERT(typedObj->type() == MIRType::Object);
-  }
-
- public:
-  INSTRUCTION_HEADER(StoreUnboxedObjectOrNull)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, elements), (1, index), (2, value), (3, typedObj))
-
-  int32_t offsetAdjustment() const { return offsetAdjustment_; }
-  bool preBarrier() const { return preBarrier_; }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Store(AliasSet::UnboxedElement);
-  }
-
-  // For StoreUnboxedObjectOrNullPolicy.
-  void setValue(MDefinition* def) { replaceOperand(2, def); }
-
-  ALLOW_CLONE(MStoreUnboxedObjectOrNull)
-};
-
-// Store an unboxed string to an elements vector.
-class MStoreUnboxedString : public MQuaternaryInstruction,
-                            public StoreUnboxedStringPolicy::Data {
-  int32_t offsetAdjustment_;
-  bool preBarrier_;
-
-  MStoreUnboxedString(MDefinition* elements, MDefinition* index,
-                      MDefinition* value, MDefinition* typedObj,
-                      int32_t offsetAdjustment = 0, bool preBarrier = true)
-      : MQuaternaryInstruction(classOpcode, elements, index, value, typedObj),
-        offsetAdjustment_(offsetAdjustment),
-        preBarrier_(preBarrier) {
-    MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
-    MOZ_ASSERT(index->type() == MIRType::Int32);
-    MOZ_ASSERT(typedObj->type() == MIRType::Object);
-  }
-
- public:
-  INSTRUCTION_HEADER(StoreUnboxedString)
-  TRIVIAL_NEW_WRAPPERS
-  NAMED_OPERANDS((0, elements), (1, index), (2, value), (3, typedObj));
-
-  int32_t offsetAdjustment() const { return offsetAdjustment_; }
-  bool preBarrier() const { return preBarrier_; }
-  AliasSet getAliasSet() const override {
-    return AliasSet::Store(AliasSet::UnboxedElement);
-  }
-
-  // For StoreUnboxedStringPolicy, to replace the original output with the
-  // output of a post barrier (if one is needed.)
-  void setValue(MDefinition* def) { replaceOperand(2, def); }
-
-  ALLOW_CLONE(MStoreUnboxedString)
-};
-
 // Array.prototype.pop or Array.prototype.shift on a dense array.
 class MArrayPopShift : public MUnaryInstruction,
                        public SingleObjectPolicy::Data {
  public:
   enum Mode { Pop, Shift };
 
  private:
   Mode mode_;
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1190,30 +1190,16 @@ void MacroAssembler::initGCThing(Registe
           // RegExpObject stores a GC thing (RegExpShared*) in its
           // private slot, so we have to use ImmGCPtr.
           storePtr(ImmGCPtr(ntemplate.regExpShared()), privateSlot);
         } else {
           storePtr(ImmPtr(ntemplate.getPrivate()), privateSlot);
         }
       }
     }
-  } else if (templateObj.isInlineTypedObject()) {
-    JS::AutoAssertNoGC nogc;  // off-thread, so cannot GC
-    size_t nbytes = templateObj.getInlineTypedObjectSize();
-    const uint8_t* memory = templateObj.getInlineTypedObjectMem(nogc);
-
-    // Memcpy the contents of the template object to the new object.
-    size_t offset = 0;
-    while (nbytes) {
-      uintptr_t value = *(uintptr_t*)(memory + offset);
-      storePtr(ImmWord(value),
-               Address(obj, InlineTypedObject::offsetOfDataStart() + offset));
-      nbytes = (nbytes < sizeof(uintptr_t)) ? 0 : nbytes - sizeof(uintptr_t);
-      offset += sizeof(uintptr_t);
-    }
   } else {
     MOZ_CRASH("Unknown object");
   }
 
 #ifdef JS_GC_TRACE
   AllocatableRegisterSet regs(RegisterSet::Volatile());
   LiveRegisterSet save(regs.asLiveSet());
   PushRegsInMask(save);
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1309,41 +1309,16 @@ bool RNewIterator::recover(JSContext* cx
     return false;
   }
 
   result.setObject(*resultObject);
   iter.storeInstructionResult(result);
   return true;
 }
 
-bool MNewDerivedTypedObject::writeRecoverData(
-    CompactBufferWriter& writer) const {
-  MOZ_ASSERT(canRecoverOnBailout());
-  writer.writeUnsigned(uint32_t(RInstruction::Recover_NewDerivedTypedObject));
-  return true;
-}
-
-RNewDerivedTypedObject::RNewDerivedTypedObject(CompactBufferReader& reader) {}
-
-bool RNewDerivedTypedObject::recover(JSContext* cx,
-                                     SnapshotIterator& iter) const {
-  Rooted<TypeDescr*> descr(cx, &iter.read().toObject().as<TypeDescr>());
-  Rooted<TypedObject*> owner(cx, &iter.read().toObject().as<TypedObject>());
-  int32_t offset = iter.read().toInt32();
-
-  JSObject* obj = OutlineTypedObject::createDerived(cx, descr, owner, offset);
-  if (!obj) {
-    return false;
-  }
-
-  RootedValue result(cx, ObjectValue(*obj));
-  iter.storeInstructionResult(result);
-  return true;
-}
-
 bool MCreateThisWithTemplate::writeRecoverData(
     CompactBufferWriter& writer) const {
   MOZ_ASSERT(canRecoverOnBailout());
   writer.writeUnsigned(uint32_t(RInstruction::Recover_CreateThisWithTemplate));
   return true;
 }
 
 RCreateThisWithTemplate::RCreateThisWithTemplate(CompactBufferReader& reader) {}
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -102,17 +102,16 @@ namespace jit {
   _(ToDouble)                  \
   _(ToFloat32)                 \
   _(TruncateToInt32)           \
   _(NewObject)                 \
   _(NewTypedArray)             \
   _(NewArray)                  \
   _(NewArrayCopyOnWrite)       \
   _(NewIterator)               \
-  _(NewDerivedTypedObject)     \
   _(NewCallObject)             \
   _(CreateThisWithTemplate)    \
   _(Lambda)                    \
   _(LambdaArrow)               \
   _(ObjectState)               \
   _(ArrayState)                \
   _(SetArrayLength)            \
   _(AtomicIsLockFree)          \
@@ -631,24 +630,16 @@ class RNewIterator final : public RInstr
 
  public:
   RINSTRUCTION_HEADER_NUM_OP_(NewIterator, 1)
 
   MOZ_MUST_USE bool recover(JSContext* cx,
                             SnapshotIterator& iter) const override;
 };
 
-class RNewDerivedTypedObject final : public RInstruction {
- public:
-  RINSTRUCTION_HEADER_NUM_OP_(NewDerivedTypedObject, 3)
-
-  MOZ_MUST_USE bool recover(JSContext* cx,
-                            SnapshotIterator& iter) const override;
-};
-
 class RCreateThisWithTemplate final : public RInstruction {
  public:
   RINSTRUCTION_HEADER_NUM_OP_(CreateThisWithTemplate, 1)
 
   MOZ_MUST_USE bool recover(JSContext* cx,
                             SnapshotIterator& iter) const override;
 };
 
--- a/js/src/jit/TemplateObject-inl.h
+++ b/js/src/jit/TemplateObject-inl.h
@@ -31,20 +31,16 @@ inline bool TemplateObject::isArgumentsO
 inline bool TemplateObject::isTypedArrayObject() const {
   return obj_->is<TypedArrayObject>();
 }
 
 inline bool TemplateObject::isRegExpObject() const {
   return obj_->is<RegExpObject>();
 }
 
-inline bool TemplateObject::isInlineTypedObject() const {
-  return obj_->is<InlineTypedObject>();
-}
-
 inline bool TemplateObject::isCallObject() const {
   return obj_->is<CallObject>();
 }
 
 inline bool TemplateObject::isPlainObject() const {
   return obj_->is<PlainObject>();
 }
 
--- a/js/src/jit/TemplateObject.h
+++ b/js/src/jit/TemplateObject.h
@@ -36,17 +36,16 @@ class TemplateObject {
   // The following methods rely on the object's group->clasp. This is safe
   // to read off-thread for template objects.
   inline bool isNative() const;
   inline const NativeTemplateObject& asNativeTemplateObject() const;
   inline bool isArrayObject() const;
   inline bool isArgumentsObject() const;
   inline bool isTypedArrayObject() const;
   inline bool isRegExpObject() const;
-  inline bool isInlineTypedObject() const;
   inline bool isCallObject() const;
   inline bool isPlainObject() const;
 
   // The group and shape should not change. This is true for template objects
   // because they're never exposed to arbitrary script.
   inline gc::Cell* group() const;
   inline gc::Cell* shape() const;
 
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -1042,89 +1042,16 @@ bool StoreTypedArrayHolePolicy::adjustIn
   MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
   MOZ_ASSERT(store->index()->type() == MIRType::Int32);
   MOZ_ASSERT(store->length()->type() == MIRType::Int32);
 
   return StoreUnboxedScalarPolicy::adjustValueInput(
       alloc, ins, store->arrayType(), store->value(), 3);
 }
 
-bool StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator& alloc,
-                                                  MInstruction* ins) const {
-  if (!ObjectPolicy<0>::staticAdjustInputs(alloc, ins)) {
-    return false;
-  }
-
-  if (!ObjectPolicy<3>::staticAdjustInputs(alloc, ins)) {
-    return false;
-  }
-
-  // Change the value input to a ToObjectOrNull instruction if it might be
-  // a non-null primitive. Insert a post barrier for the instruction's object
-  // and whatever its new value is, unless the value is definitely null.
-  MStoreUnboxedObjectOrNull* store = ins->toStoreUnboxedObjectOrNull();
-
-  MOZ_ASSERT(store->typedObj()->type() == MIRType::Object);
-
-  MDefinition* value = store->value();
-  if (value->type() == MIRType::Object || value->type() == MIRType::Null ||
-      value->type() == MIRType::ObjectOrNull) {
-    if (value->type() != MIRType::Null) {
-      MInstruction* barrier =
-          MPostWriteBarrier::New(alloc, store->typedObj(), value);
-      store->block()->insertBefore(store, barrier);
-    }
-    return true;
-  }
-
-  MToObjectOrNull* replace = MToObjectOrNull::New(alloc, value);
-  store->block()->insertBefore(store, replace);
-  store->setValue(replace);
-
-  if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace)) {
-    return false;
-  }
-
-  MInstruction* barrier =
-      MPostWriteBarrier::New(alloc, store->typedObj(), replace);
-  store->block()->insertBefore(store, barrier);
-
-  return true;
-}
-
-bool StoreUnboxedStringPolicy::adjustInputs(TempAllocator& alloc,
-                                            MInstruction* ins) const {
-  if (!ObjectPolicy<0>::staticAdjustInputs(alloc, ins)) {
-    return false;
-  }
-
-  // Change the value input to a ToString instruction if it might be
-  // a non-null primitive.
-  if (!ConvertToStringPolicy<2>::staticAdjustInputs(alloc, ins)) {
-    return false;
-  }
-
-  if (!ObjectPolicy<3>::staticAdjustInputs(alloc, ins)) {
-    return false;
-  }
-
-  // Insert a post barrier for the instruction's object and whatever its new
-  // value is.
-  MStoreUnboxedString* store = ins->toStoreUnboxedString();
-
-  MOZ_ASSERT(store->typedObj()->type() == MIRType::Object);
-
-  MDefinition* value = store->value();
-  MOZ_ASSERT(value->type() == MIRType::String);
-  MInstruction* barrier =
-      MPostWriteBarrier::New(alloc, store->typedObj(), value);
-  store->block()->insertBefore(store, barrier);
-  return true;
-}
-
 bool ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
   MDefinition* in = ins->toClampToUint8()->input();
 
   switch (in->type()) {
     case MIRType::Int32:
     case MIRType::Double:
     case MIRType::Value:
       break;
@@ -1229,39 +1156,37 @@ bool TypedArrayIndexPolicy::adjustInputs
   }
 
   // Otherwise convert input to double.
   MOZ_ASSERT(specialization == MIRType::Double);
   return DoublePolicy<0>::staticAdjustInputs(alloc, ins);
 }
 
 // Lists of all TypePolicy specializations which are used by MIR Instructions.
-#define TYPE_POLICY_LIST(_)         \
-  _(AllDoublePolicy)                \
-  _(ArithPolicy)                    \
-  _(BitwisePolicy)                  \
-  _(BoxInputsPolicy)                \
-  _(CallPolicy)                     \
-  _(CallSetElementPolicy)           \
-  _(ClampPolicy)                    \
-  _(ComparePolicy)                  \
-  _(FilterTypeSetPolicy)            \
-  _(InstanceOfPolicy)               \
-  _(PowPolicy)                      \
-  _(SameValuePolicy)                \
-  _(SignPolicy)                     \
-  _(StoreTypedArrayHolePolicy)      \
-  _(StoreUnboxedScalarPolicy)       \
-  _(StoreUnboxedObjectOrNullPolicy) \
-  _(StoreUnboxedStringPolicy)       \
-  _(TestPolicy)                     \
-  _(ToDoublePolicy)                 \
-  _(ToInt32Policy)                  \
-  _(ToStringPolicy)                 \
-  _(TypeBarrierPolicy)              \
+#define TYPE_POLICY_LIST(_)    \
+  _(AllDoublePolicy)           \
+  _(ArithPolicy)               \
+  _(BitwisePolicy)             \
+  _(BoxInputsPolicy)           \
+  _(CallPolicy)                \
+  _(CallSetElementPolicy)      \
+  _(ClampPolicy)               \
+  _(ComparePolicy)             \
+  _(FilterTypeSetPolicy)       \
+  _(InstanceOfPolicy)          \
+  _(PowPolicy)                 \
+  _(SameValuePolicy)           \
+  _(SignPolicy)                \
+  _(StoreTypedArrayHolePolicy) \
+  _(StoreUnboxedScalarPolicy)  \
+  _(TestPolicy)                \
+  _(ToDoublePolicy)            \
+  _(ToInt32Policy)             \
+  _(ToStringPolicy)            \
+  _(TypeBarrierPolicy)         \
   _(TypedArrayIndexPolicy)
 
 #define TEMPLATE_TYPE_POLICY_LIST(_)                                          \
   _(BoxExceptPolicy<0, MIRType::Object>)                                      \
   _(BoxPolicy<0>)                                                             \
   _(ConvertToInt32Policy<0>)                                                  \
   _(ConvertToStringPolicy<0>)                                                 \
   _(ConvertToStringPolicy<2>)                                                 \
--- a/js/src/jit/TypePolicy.h
+++ b/js/src/jit/TypePolicy.h
@@ -478,32 +478,16 @@ class StoreUnboxedScalarPolicy : public 
 class StoreTypedArrayHolePolicy final : public StoreUnboxedScalarPolicy {
  public:
   constexpr StoreTypedArrayHolePolicy() {}
   EMPTY_DATA_;
   MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
                                  MInstruction* ins) const override;
 };
 
-class StoreUnboxedObjectOrNullPolicy final : public TypePolicy {
- public:
-  constexpr StoreUnboxedObjectOrNullPolicy() {}
-  EMPTY_DATA_;
-  MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
-                                 MInstruction* def) const override;
-};
-
-class StoreUnboxedStringPolicy final : public TypePolicy {
- public:
-  constexpr StoreUnboxedStringPolicy() {}
-  EMPTY_DATA_;
-  MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
-                                 MInstruction* def) const override;
-};
-
 // Accepts integers and doubles. Everything else is boxed.
 class ClampPolicy final : public TypePolicy {
  public:
   constexpr ClampPolicy() {}
   EMPTY_DATA_;
   MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
                                  MInstruction* ins) const override;
 };
deleted file mode 100644
--- a/js/src/jit/TypedObjectPrediction.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/* -*- 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 "jit/TypedObjectPrediction.h"
-
-using namespace js;
-using namespace jit;
-
-static const size_t ALL_FIELDS = SIZE_MAX;
-
-// Sets the prediction to be the common prefix of descrA and descrB,
-// considering at most the first max fields.
-//
-// In the case where the current prediction is a specific struct,
-// and we are now seeing a second struct, then descrA and descrB will be
-// the current and new struct and max will be ALL_FIELDS.
-//
-// In the case where the current prediction is already a prefix, and
-// we are now seeing an additional struct, then descrA will be the
-// current struct and max will be the current prefix length, and
-// descrB will be the new struct.
-//
-// (Note that in general it is not important which struct is passed as
-// descrA and which struct is passed as descrB, as the operation is
-// symmetric.)
-void TypedObjectPrediction::markAsCommonPrefix(const StructTypeDescr& descrA,
-                                               const StructTypeDescr& descrB,
-                                               size_t max) {
-  // count is the number of fields in common. It begins as the min
-  // of the number of fields from descrA, descrB, and max, and then
-  // is decremented as we find uncommon fields.
-  if (max > descrA.fieldCount()) {
-    max = descrA.fieldCount();
-  }
-  if (max > descrB.fieldCount()) {
-    max = descrB.fieldCount();
-  }
-
-  size_t i = 0;
-  for (; i < max; i++) {
-    if (&descrA.fieldName(i) != &descrB.fieldName(i)) {
-      break;
-    }
-    if (&descrA.fieldDescr(i) != &descrB.fieldDescr(i)) {
-      break;
-    }
-    MOZ_ASSERT(descrA.fieldOffset(i) == descrB.fieldOffset(i));
-  }
-
-  if (i == 0) {
-    // empty prefix is not particularly useful.
-    markInconsistent();
-  } else {
-    setPrefix(descrA, i);
-  }
-}
-
-void TypedObjectPrediction::addDescr(const TypeDescr& descr) {
-  switch (predictionKind()) {
-    case Empty:
-      return setDescr(descr);
-
-    case Inconsistent:
-      return;  // keep same state
-
-    case Descr: {
-      if (&descr == data_.descr) {
-        return;  // keep same state
-      }
-
-      if (descr.kind() != data_.descr->kind()) {
-        return markInconsistent();
-      }
-
-      if (descr.kind() != type::Struct) {
-        return markInconsistent();
-      }
-
-      const StructTypeDescr& structDescr = descr.as<StructTypeDescr>();
-      const StructTypeDescr& currentDescr = data_.descr->as<StructTypeDescr>();
-      markAsCommonPrefix(structDescr, currentDescr, ALL_FIELDS);
-      return;
-    }
-
-    case Prefix:
-      if (descr.kind() != type::Struct) {
-        return markInconsistent();
-      }
-
-      markAsCommonPrefix(*data_.prefix.descr, descr.as<StructTypeDescr>(),
-                         data_.prefix.fields);
-      return;
-  }
-
-  MOZ_CRASH("Bad predictionKind");
-}
-
-type::Kind TypedObjectPrediction::kind() const {
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      break;
-
-    case TypedObjectPrediction::Descr:
-      return descr().kind();
-
-    case TypedObjectPrediction::Prefix:
-      return prefix().descr->kind();
-  }
-
-  MOZ_CRASH("Bad prediction kind");
-}
-
-bool TypedObjectPrediction::ofArrayKind() const {
-  switch (kind()) {
-    case type::Scalar:
-    case type::Reference:
-    case type::Struct:
-      return false;
-
-    case type::Array:
-      return true;
-  }
-
-  MOZ_CRASH("Bad kind");
-}
-
-bool TypedObjectPrediction::hasKnownSize(uint32_t* out) const {
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      return false;
-
-    case TypedObjectPrediction::Descr:
-      *out = descr().size();
-      return true;
-
-    case TypedObjectPrediction::Prefix:
-      // We only know a prefix of the struct fields, hence we do not
-      // know its complete size.
-      return false;
-
-    default:
-      MOZ_CRASH("Bad prediction kind");
-  }
-}
-
-const TypedProto* TypedObjectPrediction::getKnownPrototype() const {
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      return nullptr;
-
-    case TypedObjectPrediction::Descr:
-      if (descr().is<ComplexTypeDescr>()) {
-        return &descr().as<ComplexTypeDescr>().instancePrototype();
-      }
-      return nullptr;
-
-    case TypedObjectPrediction::Prefix:
-      // We only know a prefix of the struct fields, hence we cannot
-      // say for certain what its prototype will be.
-      return nullptr;
-
-    default:
-      MOZ_CRASH("Bad prediction kind");
-  }
-}
-
-template <typename T>
-typename T::Type TypedObjectPrediction::extractType() const {
-  MOZ_ASSERT(kind() == T::Kind);
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      break;
-
-    case TypedObjectPrediction::Descr:
-      return descr().as<T>().type();
-
-    case TypedObjectPrediction::Prefix:
-      break;  // Prefixes are always structs, never scalars etc
-  }
-
-  MOZ_CRASH("Bad prediction kind");
-}
-
-ScalarTypeDescr::Type TypedObjectPrediction::scalarType() const {
-  return extractType<ScalarTypeDescr>();
-}
-
-ReferenceType TypedObjectPrediction::referenceType() const {
-  return extractType<ReferenceTypeDescr>();
-}
-
-bool TypedObjectPrediction::hasKnownArrayLength(int32_t* length) const {
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      return false;
-
-    case TypedObjectPrediction::Descr:
-      // In later patches, this condition will always be true
-      // so long as this represents an array
-      if (descr().is<ArrayTypeDescr>()) {
-        *length = descr().as<ArrayTypeDescr>().length();
-        return true;
-      }
-      return false;
-
-    case TypedObjectPrediction::Prefix:
-      // Prefixes are always structs, never arrays
-      return false;
-
-    default:
-      MOZ_CRASH("Bad prediction kind");
-  }
-}
-
-TypedObjectPrediction TypedObjectPrediction::arrayElementType() const {
-  MOZ_ASSERT(ofArrayKind());
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      break;
-
-    case TypedObjectPrediction::Descr:
-      return TypedObjectPrediction(descr().as<ArrayTypeDescr>().elementType());
-
-    case TypedObjectPrediction::Prefix:
-      break;  // Prefixes are always structs, never arrays
-  }
-  MOZ_CRASH("Bad prediction kind");
-}
-
-bool TypedObjectPrediction::hasFieldNamedPrefix(const StructTypeDescr& descr,
-                                                size_t fieldCount, jsid id,
-                                                size_t* fieldOffset,
-                                                TypedObjectPrediction* out,
-                                                size_t* index,
-                                                bool* isMutable) const {
-  // Find the index of the field |id| if any.
-  if (!descr.fieldIndex(id, index)) {
-    return false;
-  }
-
-  // Check whether the index falls within our known safe prefix.
-  if (*index >= fieldCount) {
-    return false;
-  }
-
-  // Load the offset and type.
-  *fieldOffset = descr.fieldOffset(*index);
-  *out = TypedObjectPrediction(descr.fieldDescr(*index));
-  *isMutable = descr.fieldIsMutable(*index);
-  return true;
-}
-
-bool TypedObjectPrediction::hasFieldNamed(jsid id, size_t* fieldOffset,
-                                          TypedObjectPrediction* fieldType,
-                                          size_t* fieldIndex,
-                                          bool* fieldMutable) const {
-  MOZ_ASSERT(kind() == type::Struct);
-
-  switch (predictionKind()) {
-    case TypedObjectPrediction::Empty:
-    case TypedObjectPrediction::Inconsistent:
-      return false;
-
-    case TypedObjectPrediction::Descr:
-      return hasFieldNamedPrefix(descr().as<StructTypeDescr>(), ALL_FIELDS, id,
-                                 fieldOffset, fieldType, fieldIndex,
-                                 fieldMutable);
-
-    case TypedObjectPrediction::Prefix:
-      return hasFieldNamedPrefix(*prefix().descr, prefix().fields, id,
-                                 fieldOffset, fieldType, fieldIndex,
-                                 fieldMutable);
-
-    default:
-      MOZ_CRASH("Bad prediction kind");
-  }
-}
deleted file mode 100644
--- a/js/src/jit/TypedObjectPrediction.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- 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/. */
-
-#ifndef jit_TypedObjectPrediction_h
-#define jit_TypedObjectPrediction_h
-
-#include "builtin/TypedObject.h"
-#include "jit/JitAllocPolicy.h"
-
-namespace js {
-namespace jit {
-
-// A TypedObjectPrediction summarizes what we know about the type of a
-// typed object at a given point (if anything). The prediction will
-// begin as precise as possible and degrade to less precise as more
-// typed object types are merged using |addDescr()|.
-//
-// To create a TypedObjectPrediction from TI, one initially creates an
-// empty prediction using the |TypedObjectPrediction()| constructor,
-// and then invokes |addDescr()| with the prototype of each typed
-// object. The prediction will automatically downgrade to less and
-// less specific settings as needed. Note that creating a prediction
-// in this way can never yield precise array dimensions, since TI only
-// tracks the prototype.
-//
-// TypedObjectPredictions can also result from other predictions using
-// the query methods (e.g., |arrayElementType()|). In those cases, the
-// precise array dimensions may be known.
-//
-// To query a prediction, you must first check whether it is "useless"
-// using |isUseless()|. If this is true, there is no usable
-// information to be extracted. Otherwise, you can inquire after the
-// |kind()| of the data (struct, array, etc) and from there make more
-// specific queries.
-class TypedObjectPrediction {
- public:
-  enum PredictionKind {
-    // No data.
-    Empty,
-
-    // Inconsistent data.
-    Inconsistent,
-
-    // Multiple different struct types flow into the same location,
-    // but they share fields in common. Prefix indicates that the first
-    // N fields of some struct type are known to be valid. This occurs
-    // in a subtyping scenario.
-    Prefix,
-
-    // The TypeDescr of the value is known. This is the most specific
-    // possible value and includes precise array bounds.
-    Descr
-  };
-
-  struct PrefixData {
-    const StructTypeDescr* descr;
-    size_t fields;
-  };
-
-  union Data {
-    const TypeDescr* descr;
-    PrefixData prefix;
-  };
-
- private:
-  PredictionKind kind_;
-  Data data_;
-
-  PredictionKind predictionKind() const { return kind_; }
-
-  void markInconsistent() { kind_ = Inconsistent; }
-
-  const TypeDescr& descr() const {
-    MOZ_ASSERT(predictionKind() == Descr);
-    return *data_.descr;
-  }
-
-  const PrefixData& prefix() const {
-    MOZ_ASSERT(predictionKind() == Prefix);
-    return data_.prefix;
-  }
-
-  void setDescr(const TypeDescr& descr) {
-    kind_ = Descr;
-    data_.descr = &descr;
-  }
-
-  void setPrefix(const StructTypeDescr& descr, size_t fields) {
-    kind_ = Prefix;
-    data_.prefix.descr = &descr;
-    data_.prefix.fields = fields;
-  }
-
-  void markAsCommonPrefix(const StructTypeDescr& descrA,
-                          const StructTypeDescr& descrB, size_t max);
-
-  template <typename T>
-  typename T::Type extractType() const;
-
-  bool hasFieldNamedPrefix(const StructTypeDescr& descr, size_t fieldCount,
-                           jsid id, size_t* fieldOffset,
-                           TypedObjectPrediction* out, size_t* index,
-                           bool* isMutable) const;
-
- public:
-  ///////////////////////////////////////////////////////////////////////////
-  // Constructing a prediction. Generally, you start with an empty
-  // prediction and invoke addDescr() repeatedly.
-
-  TypedObjectPrediction() : data_() { kind_ = Empty; }
-
-  explicit TypedObjectPrediction(const TypeDescr& descr) { setDescr(descr); }
-
-  TypedObjectPrediction(const StructTypeDescr& descr, size_t fields) {
-    setPrefix(descr, fields);
-  }
-
-  void addDescr(const TypeDescr& descr);
-
-  ///////////////////////////////////////////////////////////////////////////
-  // Queries that are always valid.
-
-  bool isUseless() const {
-    return predictionKind() == Empty || predictionKind() == Inconsistent;
-  }
-
-  // Determines whether we can predict the prototype for the typed
-  // object instance. Returns null if we cannot or if the typed
-  // object is of scalar/reference kind, in which case instances are
-  // not objects and hence do not have a (publicly available)
-  // prototype.
-  const TypedProto* getKnownPrototype() const;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // Queries that are valid if not useless.
-
-  type::Kind kind() const;
-
-  bool ofArrayKind() const;
-
-  // Returns true if the size of this typed object is statically
-  // known and sets |*out| to that size. Otherwise returns false.
-  //
-  // The size may not be statically known if (1) the object is
-  // an array whose dimensions are unknown or (2) only a prefix
-  // of its type is known.
-  bool hasKnownSize(uint32_t* out) const;
-
-  //////////////////////////////////////////////////////////////////////
-  // Simple operations
-  //
-  // Only valid when |kind()| is Scalar or Reference.
-
-  Scalar::Type scalarType() const;
-  ReferenceType referenceType() const;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // Queries valid only for arrays.
-
-  // Returns true if the length of the array is statically known,
-  // and sets |*length| appropriately. Otherwise returns false.
-  bool hasKnownArrayLength(int32_t* length) const;
-
-  // Returns a prediction for the array element type, if any.
-  TypedObjectPrediction arrayElementType() const;
-
-  //////////////////////////////////////////////////////////////////////
-  // Struct operations
-  //
-  // Only valid when |kind() == TypeDescr::Struct|
-
-  // Returns true if the predicted type includes a field named |id|
-  // and sets |*fieldOffset|, |*fieldType|, and |*fieldIndex| with
-  // the offset (in bytes), type, and index of the field
-  // respectively.  Otherwise returns false.
-  bool hasFieldNamed(jsid id, size_t* fieldOffset,
-                     TypedObjectPrediction* fieldType, size_t* fieldIndex,
-                     bool* fieldMutable) const;
-};
-
-}  // namespace jit
-}  // namespace js
-
-#endif
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -92,17 +92,16 @@ namespace jit {
   _(CheckOverRecursed, js::jit::CheckOverRecursed)                             \
   _(CheckOverRecursedBaseline, js::jit::CheckOverRecursedBaseline)             \
   _(CloneRegExpObject, js::CloneRegExpObject)                                  \
   _(ConcatStrings, js::ConcatStrings<CanGC>)                                   \
   _(ConvertElementsToDoubles, js::ObjectElements::ConvertElementsToDoubles)    \
   _(CopyElementsForWrite, js::NativeObject::CopyElementsForWrite)              \
   _(CopyLexicalEnvironmentObject, js::jit::CopyLexicalEnvironmentObject)       \
   _(CreateAsyncFromSyncIterator, js::CreateAsyncFromSyncIterator)              \
-  _(CreateDerivedTypedObj, js::jit::CreateDerivedTypedObj)                     \
   _(CreateGenerator, js::jit::CreateGenerator)                                 \
   _(CreateThisForFunctionWithProto, js::CreateThisForFunctionWithProto)        \
   _(CreateThisFromIC, js::jit::CreateThisFromIC)                               \
   _(CreateThisFromIon, js::jit::CreateThisFromIon)                             \
   _(CreateThisWithTemplate, js::CreateThisWithTemplate)                        \
   _(DebugAfterYield, js::jit::DebugAfterYield)                                 \
   _(DebugEpilogueOnBaselineReturn, js::jit::DebugEpilogueOnBaselineReturn)     \
   _(DebugLeaveLexicalEnv, js::jit::DebugLeaveLexicalEnv)                       \
@@ -151,17 +150,16 @@ namespace jit {
   _(ImplicitThisOperation, js::ImplicitThisOperation)                          \
   _(ImportMetaOperation, js::ImportMetaOperation)                              \
   _(InitElemGetterSetterOperation, js::InitElemGetterSetterOperation)          \
   _(InitElemOperation, js::InitElemOperation)                                  \
   _(InitElementArray, js::InitElementArray)                                    \
   _(InitFunctionEnvironmentObjects, js::jit::InitFunctionEnvironmentObjects)   \
   _(InitPropGetterSetterOperation, js::InitPropGetterSetterOperation)          \
   _(InitRestParameter, js::jit::InitRestParameter)                             \
-  _(InlineTypedObjectCreateCopy, js::InlineTypedObject::createCopy)            \
   _(InstrumentationActiveOperation, js::InstrumentationActiveOperation)        \
   _(InstrumentationCallbackOperation, js::InstrumentationCallbackOperation)    \
   _(InstrumentationScriptIdOperation, js::InstrumentationScriptIdOperation)    \
   _(Int32ToString, js::Int32ToString<CanGC>)                                   \
   _(InterpretResume, js::jit::InterpretResume)                                 \
   _(InterruptCheck, js::jit::InterruptCheck)                                   \
   _(InvokeFunction, js::jit::InvokeFunction)                                   \
   _(IonBinaryArithICUpdate, js::jit::IonBinaryArithIC::update)                 \
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1216,25 +1216,16 @@ bool LeaveWith(JSContext* cx, BaselineFr
 }
 
 bool InitBaselineFrameForOsr(BaselineFrame* frame,
                              InterpreterFrame* interpFrame,
                              uint32_t numStackValues) {
   return frame->initForOsr(interpFrame, numStackValues);
 }
 
-JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
-                                HandleObject owner, int32_t offset) {
-  MOZ_ASSERT(descr->is<TypeDescr>());
-  MOZ_ASSERT(owner->is<TypedObject>());
-  Rooted<TypeDescr*> descr1(cx, &descr->as<TypeDescr>());
-  Rooted<TypedObject*> owner1(cx, &owner->as<TypedObject>());
-  return OutlineTypedObject::createDerived(cx, descr1, owner1, offset);
-}
-
 JSString* StringReplace(JSContext* cx, HandleString string,
                         HandleString pattern, HandleString repl) {
   MOZ_ASSERT(string);
   MOZ_ASSERT(pattern);
   MOZ_ASSERT(repl);
 
   return str_replace_string_raw(cx, string, pattern, repl);
 }
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -1016,19 +1016,16 @@ MOZ_MUST_USE bool DebugLeaveLexicalEnv(J
 MOZ_MUST_USE bool PushVarEnv(JSContext* cx, BaselineFrame* frame,
                              HandleScope scope);
 MOZ_MUST_USE bool PopVarEnv(JSContext* cx, BaselineFrame* frame);
 
 MOZ_MUST_USE bool InitBaselineFrameForOsr(BaselineFrame* frame,
                                           InterpreterFrame* interpFrame,
                                           uint32_t numStackValues);
 
-JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
-                                HandleObject owner, int32_t offset);
-
 MOZ_MUST_USE bool IonRecompile(JSContext* cx);
 MOZ_MUST_USE bool IonForcedRecompile(JSContext* cx);
 MOZ_MUST_USE bool IonForcedInvalidation(JSContext* cx);
 
 JSString* StringReplace(JSContext* cx, HandleString string,
                         HandleString pattern, HandleString repl);
 
 MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj,
--- a/js/src/jit/moz.build
+++ b/js/src/jit/moz.build
@@ -82,17 +82,16 @@ UNIFIED_SOURCES += [
     'ScalarReplacement.cpp',
     'shared/CodeGenerator-shared.cpp',
     'shared/Disassembler-shared.cpp',
     'shared/Lowering-shared.cpp',
     'Sink.cpp',
     'Snapshots.cpp',
     'StupidAllocator.cpp',
     'TIOracle.cpp',
-    'TypedObjectPrediction.cpp',
     'TypePolicy.cpp',
     'ValueNumbering.cpp',
     'VMFunctions.cpp',
     'WasmBCE.cpp',
 ]
 
 if not CONFIG['ENABLE_ION']:
     lir_inputs += ['none/LIR-none.h']
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -438,30 +438,16 @@ class LNewObject : public LInstructionHe
     return mir()->isVMCall() ? "VMCall" : nullptr;
   }
 
   const LDefinition* temp() { return getTemp(0); }
 
   MNewObject* mir() const { return mir_->toNewObject(); }
 };
 
-class LNewTypedObject : public LInstructionHelper<1, 0, 1> {
- public:
-  LIR_HEADER(NewTypedObject)
-
-  explicit LNewTypedObject(const LDefinition& temp)
-      : LInstructionHelper(classOpcode) {
-    setTemp(0, temp);
-  }
-
-  const LDefinition* temp() { return getTemp(0); }
-
-  MNewTypedObject* mir() const { return mir_->toNewTypedObject(); }
-};
-
 // Allocates a new NamedLambdaObject.
 //
 // This instruction generates two possible instruction sets:
 //   (1) An inline allocation of the call object is attempted.
 //   (2) Otherwise, a callVM create a new object.
 //
 class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {
  public:
@@ -493,35 +479,16 @@ class LNewCallObject : public LInstructi
     setTemp(0, temp);
   }
 
   const LDefinition* temp() { return getTemp(0); }
 
   MNewCallObject* mir() const { return mir_->toNewCallObject(); }
 };
 
-class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0> {
- public:
-  LIR_HEADER(NewDerivedTypedObject);
-
-  LNewDerivedTypedObject(const LAllocation& type, const LAllocation& owner,
-                         const LAllocation& offset)
-      : LCallInstructionHelper(classOpcode) {
-    setOperand(0, type);
-    setOperand(1, owner);
-    setOperand(2, offset);
-  }
-
-  const LAllocation* type() { return getOperand(0); }
-
-  const LAllocation* owner() { return getOperand(1); }
-
-  const LAllocation* offset() { return getOperand(2); }
-};
-
 class LNewStringObject : public LInstructionHelper<1, 1, 1> {
  public:
   LIR_HEADER(NewStringObject)
 
   LNewStringObject(const LAllocation& input, const LDefinition& temp)
       : LInstructionHelper(classOpcode) {
     setOperand(0, input);
     setTemp(0, temp);
@@ -3861,43 +3828,16 @@ class LTypedArrayIndexToInt32 : public L
   }
 
   const LAllocation* index() { return getOperand(0); }
   const MTypedArrayIndexToInt32* mir() const {
     return mir_->toTypedArrayIndexToInt32();
   }
 };
 
-// Load a typed object's descriptor.
-class LTypedObjectDescr : public LInstructionHelper<1, 1, 0> {
- public:
-  LIR_HEADER(TypedObjectDescr)
-
-  explicit LTypedObjectDescr(const LAllocation& object)
-      : LInstructionHelper(classOpcode) {
-    setOperand(0, object);
-  }
-  const LAllocation* object() { return getOperand(0); }
-};
-
-// Load a typed object's elements vector.
-class LTypedObjectElements : public LInstructionHelper<1, 1, 0> {
- public:
-  LIR_HEADER(TypedObjectElements)
-
-  explicit LTypedObjectElements(const LAllocation& object)
-      : LInstructionHelper(classOpcode) {
-    setOperand(0, object);
-  }
-  const LAllocation* object() { return getOperand(0); }
-  const MTypedObjectElements* mir() const {
-    return mir_->toTypedObjectElements();
-  }
-};
-
 // Bailout if index >= length.
 class LBoundsCheck : public LInstructionHelper<0, 2, 0> {
  public:
   LIR_HEADER(BoundsCheck)
 
   LBoundsCheck(const LAllocation& index, const LAllocation& length)
       : LInstructionHelper(classOpcode) {
     setOperand(0, index);
@@ -4035,52 +3975,16 @@ class LLoadElementT : public LInstructio
                : (mir()->loadDoubles() ? "Doubles" : nullptr);
   }
 
   const MLoadElement* mir() const { return mir_->toLoadElement(); }
   const LAllocation* elements() { return getOperand(0); }
   const LAllocation* index() { return getOperand(1); }
 };
 
-class LLoadUnboxedPointerV : public LInstructionHelper<BOX_PIECES, 2, 0> {
- public:
-  LIR_HEADER(LoadUnboxedPointerV)
-
-  LLoadUnboxedPointerV(const LAllocation& elements, const LAllocation& index)
-      : LInstructionHelper(classOpcode) {
-    setOperand(0, elements);
-    setOperand(1, index);
-  }
-
-  const MLoadUnboxedObjectOrNull* mir() const {
-    return mir_->toLoadUnboxedObjectOrNull();
-  }
-  const LAllocation* elements() { return getOperand(0); }
-  const LAllocation* index() { return getOperand(1); }
-};
-
-class LLoadUnboxedPointerT : public LInstructionHelper<1, 2, 0> {
- public:
-  LIR_HEADER(LoadUnboxedPointerT)
-
-  LLoadUnboxedPointerT(const LAllocation& elements, const LAllocation& index)
-      : LInstructionHelper(classOpcode) {
-    setOperand(0, elements);
-    setOperand(1, index);
-  }
-
-  MDefinition* mir() {
-    MOZ_ASSERT(mir_->isLoadUnboxedObjectOrNull() ||
-               mir_->isLoadUnboxedString());
-    return mir_;
-  }
-  const LAllocation* elements() { return getOperand(0); }
-  const LAllocation* index() { return getOperand(1); }
-};
-
 class LUnboxObjectOrNull : public LInstructionHelper<1, 1, 0> {
  public:
   LIR_HEADER(UnboxObjectOrNull);
 
   explicit LUnboxObjectOrNull(const LAllocation& input)
       : LInstructionHelper(classOpcode) {
     setOperand(0, input);
   }
@@ -4266,39 +4170,16 @@ class LFallibleStoreElementT : public LI
   }
   const LAllocation* object() { return getOperand(0); }
   const LAllocation* elements() { return getOperand(1); }
   const LAllocation* index() { return getOperand(2); }
   const LAllocation* value() { return getOperand(3); }
   const LDefinition* spectreTemp() { return getTemp(0); }
 };
 
-class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0> {
- public:
-  LIR_HEADER(StoreUnboxedPointer)
-
-  LStoreUnboxedPointer(LAllocation elements, LAllocation index,
-                       LAllocation value)
-      : LInstructionHelper(classOpcode) {
-    setOperand(0, elements);
-    setOperand(1, index);
-    setOperand(2, value);
-  }
-
-  MDefinition* mir() {
-    MOZ_ASSERT(mir_->isStoreUnboxedObjectOrNull() ||
-               mir_->isStoreUnboxedString());
-    return mir_;
-  }
-
-  const LAllocation* elements() { return getOperand(0); }
-  const LAllocation* index() { return getOperand(1); }
-  const LAllocation* value() { return getOperand(2); }
-};
-
 class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2> {
  public:
   LIR_HEADER(ArrayPopShiftV)
 
   LArrayPopShiftV(const LAllocation& object, const LDefinition& temp0,
                   const LDefinition& temp1)
       : LInstructionHelper(classOpcode) {
     setOperand(0, object);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -727,15 +727,15 @@ MSG_DEF(JSMSG_BIGINT_NOT_SERIALIZABLE, 0
 MSG_DEF(JSMSG_SC_BIGINT_DISABLED, 0, JSEXN_ERR, "BigInt not cloned - feature disabled in receiver")
 
 // BinAST
 MSG_DEF(JSMSG_BINAST,                                    1, JSEXN_SYNTAXERR, "BinAST Parsing Error: {0}")
 
 // FinalizationGroup
 MSG_DEF(JSMSG_NOT_A_FINALIZATION_GROUP,                  1, JSEXN_TYPEERR, "{0} is not a FinalizationGroup")
 MSG_DEF(JSMSG_NOT_A_FINALIZATION_ITERATOR,               1, JSEXN_TYPEERR, "{0} is not a FinalizationGroupCleanupIterator")
-MSG_DEF(JSMSG_BAD_HOLDINGS,                              0, JSEXN_TYPEERR, "The holdings passed to FinalizationGroup.register must not be the same as its target object")
+MSG_DEF(JSMSG_BAD_HELD_VALUE,                            0, JSEXN_TYPEERR, "The heldValue parameter passed to FinalizationGroup.register must not be the same as the target parameter")
 MSG_DEF(JSMSG_BAD_UNREGISTER_TOKEN,                      1, JSEXN_TYPEERR, "Invalid unregister token passed to {0}")
 MSG_DEF(JSMSG_STALE_FINALIZATION_GROUP_ITERATOR,         0, JSEXN_TYPEERR, "Can't use stale finalization group iterator")
 MSG_DEF(JSMSG_BAD_CLEANUP_STATE,                         0, JSEXN_TYPEERR, "Can't call FinalizeGroup.cleanupSome while cleanup is in progress")
 
 // WeakRef
 MSG_DEF(JSMSG_NOT_A_WEAK_REF,                            1, JSEXN_TYPEERR, "{0} is not a WeakRef")
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -62,18 +62,16 @@
   MACRO(bytes, bytes, "bytes")                                                 \
   MACRO(BYTES_PER_ELEMENT, BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT")             \
   MACRO(calendar, calendar, "calendar")                                        \
   MACRO(call, call, "call")                                                    \
   MACRO(callContentFunction, callContentFunction, "callContentFunction")       \
   MACRO(callee, callee, "callee")                                              \
   MACRO(caller, caller, "caller")                                              \
   MACRO(callFunction, callFunction, "callFunction")                            \
-  MACRO(CallRegExpMethodIfWrapped, CallRegExpMethodIfWrapped,                  \
-        "CallRegExpMethodIfWrapped")                                           \
   MACRO(cancel, cancel, "cancel")                                              \
   MACRO(case, case_, "case")                                                   \
   MACRO(caseFirst, caseFirst, "caseFirst")                                     \
   MACRO(catch, catch_, "catch")                                                \
   MACRO(class, class_, "class")                                                \
   MACRO(cleanupSome, cleanupSome, "cleanupSome")                               \
   MACRO(close, close, "close")                                                 \
   MACRO(collation, collation, "collation")                                     \
@@ -355,24 +353,19 @@
   MACRO(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable")    \
   MACRO(protected, protected_, "protected")                                    \
   MACRO(proto, proto, "__proto__")                                             \
   MACRO(prototype, prototype, "prototype")                                     \
   MACRO(proxy, proxy, "proxy")                                                 \
   MACRO(quarter, quarter, "quarter")                                           \
   MACRO(raw, raw, "raw")                                                       \
   MACRO(reason, reason, "reason")                                              \
-  MACRO(RegExpBuiltinExec, RegExpBuiltinExec, "RegExpBuiltinExec")             \
   MACRO(RegExpFlagsGetter, RegExpFlagsGetter, "$RegExpFlagsGetter")            \
-  MACRO(RegExpMatcher, RegExpMatcher, "RegExpMatcher")                         \
-  MACRO(RegExpSearcher, RegExpSearcher, "RegExpSearcher")                      \
   MACRO(RegExpStringIterator, RegExpStringIterator, "RegExp String Iterator")  \
-  MACRO(RegExpTester, RegExpTester, "RegExpTester")                            \
   MACRO(RegExpToString, RegExpToString, "$RegExpToString")                     \
-  MACRO(RegExp_prototype_Exec, RegExp_prototype_Exec, "RegExp_prototype_Exec") \
   MACRO(region, region, "region")                                              \
   MACRO(register, register_, "register")                                       \
   MACRO(Reify, Reify, "Reify")                                                 \
   MACRO(reject, reject, "reject")                                              \
   MACRO(rejected, rejected, "rejected")                                        \
   MACRO(relatedYear, relatedYear, "relatedYear")                               \
   MACRO(RelativeTimeFormatFormat, RelativeTimeFormatFormat,                    \
         "Intl_RelativeTimeFormat_Format")                                      \
@@ -454,18 +447,16 @@
   MACRO(unicode, unicode, "unicode")                                           \
   MACRO(unit, unit, "unit")                                                    \
   MACRO(unitDisplay, unitDisplay, "unitDisplay")                               \
   MACRO(uninitialized, uninitialized, "uninitialized")                         \
   MACRO(unknown, unknown, "unknown")                                           \
   MACRO(unregister, unregister, "unregister")                                  \
   MACRO(unsized, unsized, "unsized")                                           \
   MACRO(unwatch, unwatch, "unwatch")                                           \
-  MACRO(UnwrapAndCallRegExpBuiltinExec, UnwrapAndCallRegExpBuiltinExec,        \
-        "UnwrapAndCallRegExpBuiltinExec")                                      \
   MACRO(url, url, "url")                                                       \
   MACRO(usage, usage, "usage")                                                 \
   MACRO(useAsm, useAsm, "use asm")                                             \
   MACRO(useGrouping, useGrouping, "useGrouping")                               \
   MACRO(useStrict, useStrict, "use strict")                                    \
   MACRO(void, void_, "void")                                                   \
   MACRO(value, value, "value")                                                 \
   MACRO(valueOf, valueOf, "valueOf")                                           \
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2376,24 +2376,21 @@ static const JSFunctionSpec intrinsic_fu
 
     // See builtin/TypedObject.h for descriptors of the typedobj functions.
     JS_FN("NewOpaqueTypedObject", js::NewOpaqueTypedObject, 3, 0),
     JS_FN("NewDerivedTypedObject", js::NewDerivedTypedObject, 3, 0),
     JS_FN("TypedObjectTypeDescr", js::TypedObjectTypeDescr, 1, 0),
     JS_FN("ClampToUint8", js::ClampToUint8, 1, 0),
     JS_FN("GetTypedObjectModule", js::GetTypedObjectModule, 0, 0),
 
-    JS_INLINABLE_FN("ObjectIsTypeDescr", js::ObjectIsTypeDescr, 1, 0,
-                    IntrinsicObjectIsTypeDescr),
-    JS_INLINABLE_FN("ObjectIsTypedObject", js::ObjectIsTypedObject, 1, 0,
-                    IntrinsicObjectIsTypedObject),
-    JS_INLINABLE_FN("TypeDescrIsArrayType", js::TypeDescrIsArrayType, 1, 0,
-                    IntrinsicTypeDescrIsArrayType),
-    JS_INLINABLE_FN("TypeDescrIsSimpleType", js::TypeDescrIsSimpleType, 1, 0,
-                    IntrinsicTypeDescrIsSimpleType),
+    JS_FN("ObjectIsTypeDescr", js::ObjectIsTypeDescr, 1, 0),
+    JS_FN("ObjectIsTypedObject", js::ObjectIsTypedObject, 1, 0),
+    JS_FN("TypeDescrIsArrayType", js::TypeDescrIsArrayType, 1, 0),
+    JS_FN("TypeDescrIsSimpleType", js::TypeDescrIsSimpleType, 1, 0),
+
     JS_FN("IsBoxedWasmAnyRef", js::IsBoxedWasmAnyRef, 1, 0),
     JS_FN("IsBoxableWasmAnyRef", js::IsBoxableWasmAnyRef, 1, 0),
     JS_FN("BoxWasmAnyRef", js::BoxWasmAnyRef, 1, 0),
     JS_FN("UnboxBoxedWasmAnyRef", js::UnboxBoxedWasmAnyRef, 1, 0),
 
 // clang-format off
 #define LOAD_AND_STORE_SCALAR_FN_DECLS(_constant, _type, _name)         \
     JS_FN("Store_" #_name, js::StoreScalar##_type::Func, 3, 0),         \
--- a/layout/base/tests/chrome/printpreview_helper.xhtml
+++ b/layout/base/tests/chrome/printpreview_helper.xhtml
@@ -414,16 +414,30 @@ async function compareFiles(src1, src2) 
   exitprintpreview();
 
   ok(compareCanvases(), `Printing ${src1} and ${src2} should produce the same results`);
 }
 
 // bug 1567105
 async function runTest11() {
   await compareFiles("printpreview_quirks.html", "printpreview_quirks_ref.html");
+  requestAnimationFrame(function() { setTimeout(runTest12); } );
+}
+
+// Crash test for bug 1615261
+async function runTest12() {
+  frameElts[0].contentDocument.body.innerHTML =
+    '<style> div { width: 100px; height: 100px; background-image: url("animated.gif"); } </style>' +
+    '<div>Firefox will crash if you try and print this page</div>';
+
+  // XXX Is there a more reliable way to wait for the background-image to load?
+  await new Promise(resolve => setTimeout(resolve, 500));
+
+  printpreview();
+  exitprintpreview();
   finish();
 }
 
 ]]></script>
 <table style="border: 1px solid black;" xmlns="http://www.w3.org/1999/xhtml">
 <tr><th>Print preview canvas 1</th><th>Print preview canvas 2</th></tr>
 <tr>
 <td><canvas height="400" width="400"></canvas></td>
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4645,17 +4645,16 @@ nsFrame::HandlePress(nsPresContext* aPre
   bool control = mouseEvent->IsControl();
 #endif
 
   RefPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
   if (mouseEvent->mClickCount > 1) {
     // These methods aren't const but can't actually delete anything,
     // so no need for AutoWeakFrame.
     fc->SetDragState(true);
-    fc->SetMouseDoubleDown(true);
     return HandleMultiplePress(aPresContext, mouseEvent, aEventStatus, control);
   }
 
   nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mouseEvent, this);
   ContentOffsets offsets = GetContentOffsetsFromPoint(pt, SKIP_HIDDEN);
 
   if (!offsets.content) return NS_ERROR_FAILURE;
 
--- a/layout/generic/nsFrameSelection.cpp
+++ b/layout/generic/nsFrameSelection.cpp
@@ -2737,49 +2737,16 @@ void nsFrameSelection::SetAncestorLimite
         nsCOMPtr<nsIContent> limiter(mAncestorLimiter);
         TakeFocus(limiter, 0, 0, CARET_ASSOCIATE_BEFORE,
                   FocusMode::kCollapseToNewPoint);
       }
     }
   }
 }
 
-nsresult nsFrameSelection::DeleteFromDocument() {
-  // If we're already collapsed, then we do nothing (bug 719503).
-  int8_t index = GetIndexFromSelectionType(SelectionType::eNormal);
-  if (!mDomSelections[index]) return NS_ERROR_NULL_POINTER;
-
-  if (mDomSelections[index]->IsCollapsed()) {
-    return NS_OK;
-  }
-
-  RefPtr<Selection> selection = mDomSelections[index];
-  for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
-    RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
-    ErrorResult res;
-    range->DeleteContents(res);
-    if (res.Failed()) {
-      return res.StealNSResult();
-    }
-  }
-
-  // Collapse to the new location.
-  // If we deleted one character, then we move back one element.
-  // FIXME  We don't know how to do this past frame boundaries yet.
-  if (mDomSelections[index]->AnchorOffset() > 0)
-    mDomSelections[index]->Collapse(mDomSelections[index]->GetAnchorNode(),
-                                    mDomSelections[index]->AnchorOffset());
-#ifdef DEBUG
-  else
-    printf("Don't know how to set selection back past frame boundary\n");
-#endif
-
-  return NS_OK;
-}
-
 void nsFrameSelection::SetDelayedCaretData(WidgetMouseEvent* aMouseEvent) {
   if (aMouseEvent) {
     mDelayedMouseEventValid = true;
     mDelayedMouseEventIsShift = aMouseEvent->IsShift();
     mDelayedMouseEventClickCount = aMouseEvent->mClickCount;
   } else {
     mDelayedMouseEventValid = false;
   }
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -309,29 +309,31 @@ class nsFrameSelection final {
 
   /**
    * Add cell to the selection.
    *
    * @param  aCell  [in] HTML td element.
    */
   nsresult SelectCellElement(nsIContent* aCell);
 
+ private:
   /**
    * Add cells to the selection inside of the given cells range.
    *
    * @param  aTable             [in] HTML table element
    * @param  aStartRowIndex     [in] row index where the cells range starts
    * @param  aStartColumnIndex  [in] column index where the cells range starts
    * @param  aEndRowIndex       [in] row index where the cells range ends
    * @param  aEndColumnIndex    [in] column index where the cells range ends
    */
   nsresult AddCellsToSelection(nsIContent* aTable, int32_t aStartRowIndex,
                                int32_t aStartColumnIndex, int32_t aEndRowIndex,
                                int32_t aEndColumnIndex);
 
+ public:
   /**
    * Remove cells from selection inside of the given cell range.
    *
    * @param  aTable             [in] HTML table element
    * @param  aStartRowIndex     [in] row index where the cells range starts
    * @param  aStartColumnIndex  [in] column index where the cells range starts
    * @param  aEndRowIndex       [in] row index where the cells range ends
    * @param  aEndColumnIndex    [in] column index where the cells range ends
@@ -640,31 +642,16 @@ class nsFrameSelection final {
    * parent page, which is very bad!
    */
   nsIContent* GetLimiter() const { return mLimiter; }
 
   nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; }
   MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetAncestorLimiter(nsIContent* aLimiter);
 
   /**
-   * This will tell the frame selection that a double click has been pressed
-   * so it can track abort future drags if inside the same selection
-   * @param aDoubleDown has the double click down happened
-   */
-  void SetMouseDoubleDown(bool aDoubleDown) {
-    mMouseDoubleDownState = aDoubleDown;
-  }
-
-  /**
-   * This will return whether the double down flag was set.
-   * @return whether the double down flag was set
-   */
-  bool GetMouseDoubleDown() const { return mMouseDoubleDownState; }
-
-  /**
    * GetPrevNextBidiLevels will return the frames and associated Bidi levels of
    * the characters logically before and after a (collapsed) selection.
    *
    * @param aNode is the node containing the selection
    * @param aContentOffset is the offset of the selection in the node
    * @param aJumpLines
    *   If true, look across line boundaries.
    *   If false, behave as if there were base-level frames at line edges.
@@ -715,19 +702,16 @@ class nsFrameSelection final {
 
   nsFrameSelection();
 
   void StartBatchChanges();
 
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
 
-  /*unsafe*/
-  nsresult DeleteFromDocument();
-
   mozilla::PresShell* GetPresShell() const { return mPresShell; }
 
   void DisconnectFromPresShell();
   nsresult ClearNormalSelection();
 
  private:
   ~nsFrameSelection();
 
@@ -783,17 +767,16 @@ class nsFrameSelection final {
   nsresult FetchDesiredPos(
       nsPoint& aDesiredPos);  // the position requested by the Key Handling for
                               // up down
   void
   InvalidateDesiredPos();  // do not listen to mDesiredPos you must get another.
   void SetDesiredPos(nsPoint aPos);  // set the mDesiredPos
 
   uint32_t GetBatching() const { return mBatching; }
-  bool GetNotifyFrames() const { return mNotifyFrames; }
   void SetDirty(bool aDirty = true) {
     if (mBatching) mChangesDuringBatching = aDirty;
   }
 
   // nsFrameSelection may get deleted when calling this,
   // so remember to use nsCOMPtr when needed.
   MOZ_CAN_RUN_SCRIPT
   nsresult NotifySelectionListeners(mozilla::SelectionType aSelectionType);
@@ -875,20 +858,18 @@ class nsFrameSelection final {
   bool mDelayedMouseEventValid = false;
   // These values are not used since they are only valid when
   // mDelayedMouseEventValid is true, and setting mDelayedMouseEventValid
   // always overrides these values.
   uint32_t mDelayedMouseEventClickCount = 0;
   bool mDelayedMouseEventIsShift = false;
 
   bool mChangesDuringBatching = false;
-  bool mNotifyFrames = true;
   bool mDragSelectingCells = false;
   bool mDragState = false;             // for drag purposes
-  bool mMouseDoubleDownState = false;  // has the doubleclick down happened
   bool mDesiredPosSet = false;
   bool mAccessibleCaretEnabled = false;
 
   int8_t mCaretMovementStyle = 0;
 
   static bool sSelectionEventsOnTextControlsEnabled;
 };
 
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -394,39 +394,70 @@ static CORSMode EffectiveCorsMode(nsIURI
   if (aURI->SchemeIs("resource")) {
     return CORSMode::CORS_NONE;
   }
   return CORSMode::CORS_ANONYMOUS;
 }
 
 /* static */
 already_AddRefed<imgRequestProxy> ImageLoader::LoadImage(
-    const StyleComputedImageUrl& aImage, Document& aLoadingDoc) {
+    const StyleComputedImageUrl& aImage, Document& aDocument) {
   MOZ_ASSERT(NS_IsMainThread());
   nsIURI* uri = aImage.GetURI();
   if (!uri) {
     return nullptr;
   }
 
   int32_t loadFlags =
       nsIRequest::LOAD_NORMAL |
       nsContentUtils::CORSModeToLoadImageFlags(EffectiveCorsMode(uri, aImage));
 
   const URLExtraData& data = aImage.ExtraData();
 
+  // NB: If aDocument is not the original document, we may not be able to load
+  // images from aDocument.  Instead we do the image load from the original
+  // doc and clone it to aDocument.
+  Document* loadingDoc = aDocument.GetOriginalDocument();
+  const bool isPrint = !!loadingDoc;
+  if (!loadingDoc) {
+    loadingDoc = &aDocument;
+  }
+
   RefPtr<imgRequestProxy> request;
   nsresult rv = nsContentUtils::LoadImage(
-      uri, &aLoadingDoc, &aLoadingDoc, data.Principal(), 0, data.ReferrerInfo(),
+      uri, loadingDoc, loadingDoc, data.Principal(), 0, data.ReferrerInfo(),
       sImageObserver, loadFlags, NS_LITERAL_STRING("css"),
       getter_AddRefs(request));
 
   if (NS_FAILED(rv) || !request) {
     return nullptr;
   }
 
+  if (isPrint) {
+    RefPtr<imgRequestProxy> ret;
+    request->GetStaticRequest(&aDocument, getter_AddRefs(ret));
+    // Now we have a static image. If it is different from the one from the
+    // loading doc (that is, `request` is an animated image, and `ret` is a
+    // frozen version of it), we can forget about notifications from the
+    // animated image (assuming nothing else cares about it already).
+    //
+    // This is not technically needed for correctness, but helps keep the
+    // invariant that we only receive notifications for images that are in
+    // `sImages`.
+    if (ret != request) {
+      if (!sImages->Contains(request)) {
+        request->CancelAndForgetObserver(NS_BINDING_ABORTED);
+      }
+      if (!ret) {
+        return nullptr;
+      }
+      request = std::move(ret);
+    }
+  }
+
   sImages->LookupForAdd(request).OrInsert([] { return new ImageTableEntry(); });
   return request.forget();
 }
 
 void ImageLoader::UnloadImage(imgRequestProxy* aImage) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aImage);
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -147,33 +147,17 @@ void StyleComputedUrl::ResolveImage(Docu
 
   RefPtr<imgRequestProxy> request;
   if (reuseProxy) {
     request = aOldImage->LoadData().resolved_image;
     if (request) {
       css::ImageLoader::NoteSharedLoad(request);
     }
   } else {
-    // NB: If aDocument is not the original document, we may not be able to load
-    // images from aDocument.  Instead we do the image load from the original
-    // doc and clone it to aDocument.
-    Document* loadingDoc = aDocument.GetOriginalDocument();
-    const bool isPrint = !!loadingDoc;
-    if (!loadingDoc) {
-      loadingDoc = &aDocument;
-    }
-
-    // Kick off the load in the loading document.
-    request = css::ImageLoader::LoadImage(*this, *loadingDoc);
-
-    if (isPrint && request) {
-      RefPtr<imgRequestProxy> ret;
-      request->GetStaticRequest(&aDocument, getter_AddRefs(ret));
-      request = std::move(ret);
-    }
+    request = css::ImageLoader::LoadImage(*this, aDocument);
   }
 
   if (!request) {
     return;
   }
 
   data.resolved_image = request.forget().take();
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -922,20 +922,16 @@ pref("print.print_headercenter", "");
 pref("print.print_headerright", "&U");
 pref("print.print_footerleft", "&PT");
 pref("print.print_footercenter", "");
 pref("print.print_footerright", "&D");
 pref("print.show_print_progress", true);
 
 // xxxbsmedberg: more toolkit prefs
 
-// When this is set to false each window has its own PrintSettings
-// and a change in one window does not affect the others
-pref("print.use_global_printsettings", true);
-
 // Save the Printings after each print job
 pref("print.save_print_settings", true);
 
 // Enables you to specify the amount of the paper that is to be treated
 // as unwriteable.  The print_edge_XXX and print_margin_XXX preferences
 // are treated as offsets that are added to this pref.
 // Default is "-1", which means "use the system default".  (If there is
 // no system default, then the -1 is treated as if it were 0.)
--- a/netwerk/dns/GetAddrInfo.cpp
+++ b/netwerk/dns/GetAddrInfo.cpp
@@ -4,20 +4,16 @@
  * 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 "GetAddrInfo.h"
 #include "mozilla/net/DNS.h"
 #include "prnetdb.h"
 #include "nsHostResolver.h"
 #include "nsError.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/StaticPtr.h"
-#include "MainThreadUtils.h"
-#include "mozilla/DebugOnly.h"
 #include "mozilla/net/DNS.h"
 #include <algorithm>
 #include "prerror.h"
 
 #include "mozilla/Logging.h"
 
 #ifdef DNSQUERY_AVAILABLE
 // There is a bug in windns.h where the type of parameter ppQueryResultsSet for
@@ -45,119 +41,27 @@ static LazyLogModule gGetAddrInfoLog("Ge
 ////////////////////////////
 
 // Ensure consistency of PR_* and AF_* constants to allow for legacy usage of
 // PR_* constants with this API.
 static_assert(PR_AF_INET == AF_INET && PR_AF_INET6 == AF_INET6 &&
                   PR_AF_UNSPEC == AF_UNSPEC,
               "PR_AF_* must match AF_*");
 
-// We intentionally leak this mutex. This is because we can run into a
-// situation where the worker threads are still running until the process
-// is actually fully shut down, and at any time one of those worker
-// threads can access gDnsapiInfoLock.
-static OffTheBooksMutex* gDnsapiInfoLock = nullptr;
-
-struct DnsapiInfo {
- public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DnsapiInfo);
-
-  HMODULE mLibrary;
-  decltype(&DnsQuery_A) mDnsQueryFunc;
-  decltype(&DnsFree) mDnsFreeFunc;
-
- private:
-  // This will either be called during shutdown of the GetAddrInfo module, or
-  // when a worker thread is done doing a lookup (ie: within
-  // _GetAddrInfo_Windows). Note that the lock must be held when this is
-  // called.
-  ~DnsapiInfo() {
-    if (gDnsapiInfoLock) {
-      gDnsapiInfoLock->AssertCurrentThreadOwns();
-    } else {
-      MOZ_ASSERT_UNREACHABLE(
-          "No mutex available during GetAddrInfo "
-          "shutdown.");
-      return;
-    }
-
-    LOG("Freeing Dnsapi.dll");
-    MOZ_ASSERT(mLibrary);
-    DebugOnly<BOOL> rv = FreeLibrary(mLibrary);
-    NS_WARNING_ASSERTION(rv, "Failed to free Dnsapi.dll.");
-  }
-};
-
-static StaticRefPtr<DnsapiInfo> gDnsapiInfo;
-
-static MOZ_ALWAYS_INLINE nsresult _GetAddrInfoInit_Windows() {
-  // This is necessary to ensure strict thread safety because if two threads
-  // run this function at the same time they can potentially create two
-  // mutexes.
-  MOZ_ASSERT(NS_IsMainThread(),
-             "Do not initialize GetAddrInfo off main thread!");
-
-  if (!gDnsapiInfoLock) {
-    gDnsapiInfoLock = new OffTheBooksMutex("GetAddrInfo.cpp::gDnsapiInfoLock");
-  }
-  OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
-
-  if (gDnsapiInfo) {
-    MOZ_ASSERT_UNREACHABLE("GetAddrInfo is being initialized multiple times!");
-    return NS_ERROR_ALREADY_INITIALIZED;
-  }
-
-  HMODULE library = LoadLibraryA("Dnsapi.dll");
-  if (NS_WARN_IF(!library)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  FARPROC dnsQueryFunc = GetProcAddress(library, "DnsQuery_A");
-  FARPROC dnsFreeFunc = GetProcAddress(library, "DnsFree");
-  if (NS_WARN_IF(!dnsQueryFunc) || NS_WARN_IF(!dnsFreeFunc)) {
-    DebugOnly<BOOL> rv = FreeLibrary(library);
-    NS_WARNING_ASSERTION(rv, "Failed to free Dnsapi.dll.");
-    return NS_ERROR_FAILURE;
-  }
-
-  DnsapiInfo* info = new DnsapiInfo;
-  info->mLibrary = library;
-  info->mDnsQueryFunc = (decltype(info->mDnsQueryFunc))dnsQueryFunc;
-  info->mDnsFreeFunc = (decltype(info->mDnsFreeFunc))dnsFreeFunc;
-  gDnsapiInfo = info;
-
-  return NS_OK;
-}
-
-static MOZ_ALWAYS_INLINE nsresult _GetAddrInfoShutdown_Windows() {
-  OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
-
-  if (NS_WARN_IF(!gDnsapiInfo) || NS_WARN_IF(!gDnsapiInfoLock)) {
-    MOZ_ASSERT_UNREACHABLE("GetAddrInfo not initialized!");
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  gDnsapiInfo = nullptr;
-
-  return NS_OK;
-}
-
 // If successful, returns in aResult a TTL value that is smaller or
 // equal with the one already there. Gets the TTL value by calling
-// to dnsapi->mDnsQueryFunc and iterating through the returned
+// to DnsQuery_A and iterating through the returned
 // records to find the one with the smallest TTL value.
-static MOZ_ALWAYS_INLINE nsresult
-_GetMinTTLForRequestType_Windows(DnsapiInfo* dnsapi, const char* aHost,
-                                 uint16_t aRequestType, unsigned int* aResult) {
-  MOZ_ASSERT(dnsapi);
+static MOZ_ALWAYS_INLINE nsresult _GetMinTTLForRequestType_Windows(
+    const char* aHost, uint16_t aRequestType, unsigned int* aResult) {
   MOZ_ASSERT(aHost);
   MOZ_ASSERT(aResult);
 
   PDNS_RECORDA dnsData = nullptr;
-  DNS_STATUS status = dnsapi->mDnsQueryFunc(
+  DNS_STATUS status = DnsQuery_A(
       aHost, aRequestType,
       (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE |
        DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE |
        DNS_QUERY_DONT_RESET_TTL_VALUES),
       nullptr, &dnsData, nullptr);
   if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR ||
       !dnsData) {
     LOG("No DNS records found for %s. status=%X. aRequestType = %X\n", aHost,
@@ -178,58 +82,39 @@ static MOZ_ALWAYS_INLINE nsresult
     if (curRecord->wType == aRequestType) {
       *aResult = std::min<unsigned int>(*aResult, curRecord->dwTtl);
     } else {
       LOG("Received unexpected record type %u in response for %s.\n",
           curRecord->wType, aHost);
     }
   }
 
-  dnsapi->mDnsFreeFunc(dnsData, DNS_FREE_TYPE::DnsFreeRecordList);
+  DnsFree(dnsData, DNS_FREE_TYPE::DnsFreeRecordList);
   return NS_OK;
 }
 
 static MOZ_ALWAYS_INLINE nsresult _GetTTLData_Windows(const nsACString& aHost,
                                                       uint32_t* aResult,
                                                       uint16_t aAddressFamily) {
   MOZ_ASSERT(!aHost.IsEmpty());
   MOZ_ASSERT(aResult);
   if (aAddressFamily != PR_AF_UNSPEC && aAddressFamily != PR_AF_INET &&
       aAddressFamily != PR_AF_INET6) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  RefPtr<DnsapiInfo> dnsapi = nullptr;
-  {
-    OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
-    dnsapi = gDnsapiInfo;
-  }
-
-  if (!dnsapi) {
-    LOG_WARNING("GetAddrInfo has been shutdown or has not been initialized.");
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
   // In order to avoid using ANY records which are not always implemented as a
   // "Gimme what you have" request in hostname resolvers, we should send A
   // and/or AAAA requests, based on the address family requested.
   unsigned int ttl = (unsigned int)-1;
   if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) {
-    _GetMinTTLForRequestType_Windows(dnsapi, aHost.BeginReading(), DNS_TYPE_A,
-                                     &ttl);
+    _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_A, &ttl);
   }
   if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) {
-    _GetMinTTLForRequestType_Windows(dnsapi, aHost.BeginReading(),
-                                     DNS_TYPE_AAAA, &ttl);
-  }
-
-  {
-    // dnsapi's destructor is not thread-safe, so we release explicitly here
-    OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
-    dnsapi = nullptr;
+    _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_AAAA, &ttl);
   }
 
   if (ttl == (unsigned int)-1) {
     LOG("No useable TTL found.");
     return NS_ERROR_FAILURE;
   }
 
   *aResult = ttl;
@@ -288,32 +173,22 @@ static MOZ_ALWAYS_INLINE nsresult
   return NS_OK;
 }
 
 //////////////////////////////////////
 // COMMON/PLATFORM INDEPENDENT CODE //
 //////////////////////////////////////
 nsresult GetAddrInfoInit() {
   LOG("Initializing GetAddrInfo.\n");
-
-#ifdef DNSQUERY_AVAILABLE
-  return _GetAddrInfoInit_Windows();
-#else
   return NS_OK;
-#endif
 }
 
 nsresult GetAddrInfoShutdown() {
   LOG("Shutting down GetAddrInfo.\n");
-
-#ifdef DNSQUERY_AVAILABLE
-  return _GetAddrInfoShutdown_Windows();
-#else
   return NS_OK;
-#endif
 }
 
 nsresult GetAddrInfo(const nsACString& aHost, uint16_t aAddressFamily,
                      uint16_t aFlags, AddrInfo** aAddrInfo, bool aGetTtl) {
   if (NS_WARN_IF(aHost.IsEmpty()) || NS_WARN_IF(!aAddrInfo)) {
     return NS_ERROR_NULL_POINTER;
   }
 
--- a/testing/condprofile/condprof/android.py
+++ b/testing/condprofile/condprof/android.py
@@ -244,17 +244,18 @@ class AndroidEnv(BaseEnv):
         except Exception:
             ERROR("Could not extract the logcat")
 
     @contextlib.contextmanager
     def get_browser(self):
         yield
 
     def get_browser_args(self, headless, prefs=None):
-        options = []
+        # XXX merge with DesktopEnv.get_browser_args
+        options = ["--allow-downgrade"]
         if headless:
             options.append("-headless")
         if prefs is None:
             prefs = {}
         return {"moz:firefoxOptions": {"args": options, "prefs": prefs}}
 
     def prepare(self, logfile):
         self.device.prepare(self.profile, logfile)
--- a/testing/condprofile/condprof/desktop.py
+++ b/testing/condprofile/condprof/desktop.py
@@ -58,17 +58,17 @@ class DesktopEnv(BaseEnv):
             if not os.path.exists(self.firefox):
                 raise IOError(self.firefox)
             yield
 
     def get_browser_args(self, headless, prefs=None):
         final_prefs = dict(DEFAULT_PREFS)
         if prefs is not None:
             final_prefs.update(prefs)
-        options = ["-profile", self.profile]
+        options = ["--allow-downgrade", "-profile", self.profile]
         if headless:
             options.append("-headless")
         args = {"moz:firefoxOptions": {"args": options}}
         if self.firefox is not None:
             args["moz:firefoxOptions"]["binary"] = self.firefox
         args["moz:firefoxOptions"]["prefs"] = final_prefs
         args["moz:firefoxOptions"]["log"] = {"level": "trace"}
         return args
--- a/testing/raptor/raptor/manifest.py
+++ b/testing/raptor/raptor/manifest.py
@@ -494,14 +494,15 @@ def get_raptor_test_list(args, oskey):
                 tests_to_run.remove(test)
     else:
         LOG.critical("abort: specified test name doesn't exist")
 
     return tests_to_run
 
 
 def bool_from_str(boolean_string):
-    if boolean_string == 'true':
+    lower_boolean_str = boolean_string.lower()
+    if lower_boolean_str == 'true':
         return True
-    elif boolean_string == 'false':
+    elif lower_boolean_str == 'false':
         return False
     else:
         raise ValueError("Expected either 'true' or 'false'")
--- a/testing/raptor/test/test_manifest.py
+++ b/testing/raptor/test/test_manifest.py
@@ -11,22 +11,22 @@ from six.moves.urllib.parse import parse
 # need this so raptor imports work both from /raptor and via mach
 here = os.path.abspath(os.path.dirname(__file__))
 
 raptor_dir = os.path.join(os.path.dirname(here), 'raptor')
 sys.path.insert(0, raptor_dir)
 
 from manifest import (
     add_test_url_params,
+    bool_from_str,
     get_browser_test_list,
     get_raptor_test_list,
     validate_test_ini,
 )
 
-
 # some test details (test INIs)
 VALID_MANIFESTS = [{
     # page load test with local playback
     'alert_on': 'fcp',
     'alert_threshold': 2.0,
     'apps': 'firefox',
     'lower_is_better': True,
     'manifest': 'valid_details_0',
@@ -138,16 +138,34 @@ INVALID_MANIFESTS = [{
     'playback_pageset_manifest': 'pageset.manifest',
     'playback_recordings': 'recorded_site.mp',
     'test_url': 'http://www.test-url/goes/here',
     'type': 'pageload',
     'unit': 'ms',
 }]
 
 
+@pytest.mark.parametrize('value, expected_result', [
+    ('true', True),
+    ('TRUE', True),
+    ('True', True),
+    ('false', False),
+    ('FALSE', False),
+    ('False', False)
+])
+def test_bool_from_str(value, expected_result):
+    assert expected_result == bool_from_str(value)
+
+
+@pytest.mark.parametrize('invalid_value', ['yes', 'no', '1', '0', 'invalid_str', ''])
+def test_bool_from_str_with_invalid_values(invalid_value):
+    with pytest.raises(ValueError):
+        bool_from_str(invalid_value)
+
+
 @pytest.mark.parametrize('app', ['firefox', 'chrome', 'chromium', 'geckoview', 'refbrow', 'fenix'])
 def test_get_browser_test_list(app):
     test_list = get_browser_test_list(app, run_local=True)
     assert len(test_list) > 0
 
 
 @pytest.mark.parametrize('test_details', VALID_MANIFESTS)
 def test_validate_test_ini_valid(test_details):
--- a/testing/web-platform/meta/web-share/__dir__.ini
+++ b/testing/web-platform/meta/web-share/__dir__.ini
@@ -1,1 +1,1 @@
-prefs: [dom.webshare.enabled:true]
\ No newline at end of file
+prefs: [dom.webshare.enabled:true]
--- a/testing/web-platform/meta/web-share/idlharness.https.window.js.ini
+++ b/testing/web-platform/meta/web-share/idlharness.https.window.js.ini
@@ -0,0 +1,12 @@
+[idlharness.https.window.html]
+  [Navigator interface: operation share(ShareData)]
+    expected:
+      if os == "win": FAIL
+
+  [Navigator interface: navigator must inherit property "share(ShareData)" with the proper type]
+    expected:
+      if os == "win": FAIL
+
+  [Navigator interface: calling share(ShareData) on navigator with too few arguments must throw TypeError]
+    expected:
+      if os == "win": FAIL
--- a/testing/web-platform/meta/web-share/share-empty.https.html.ini
+++ b/testing/web-platform/meta/web-share/share-empty.https.html.ini
@@ -0,0 +1,20 @@
+[share-empty.https.html]
+  [share with no arguments (same as empty dictionary)]
+    expected:
+      if os == "win": FAIL
+
+  [share with an empty dictionary]
+    expected:
+      if os == "win": FAIL
+
+  [share with a undefined argument (same as empty dictionary)]
+    expected:
+      if os == "win": FAIL
+
+  [share with a null argument (same as empty dictionary)]
+    expected:
+      if os == "win": FAIL
+
+  [share with a dictionary containing only surplus fields]
+    expected:
+      if os == "win": FAIL
--- a/testing/web-platform/meta/web-share/share-sharePromise-internal-slot.https.html.ini
+++ b/testing/web-platform/meta/web-share/share-sharePromise-internal-slot.https.html.ini
@@ -0,0 +1,6 @@
+[share-sharePromise-internal-slot.https.html]
+  expected:
+    if os == "win": TIMEOUT
+  [Only allow one share call at a time, which is controlled by the \[\[sharePromise\]\] internal slot.]
+    expected:
+      if os == "win": TIMEOUT
--- a/testing/web-platform/meta/web-share/share-url-invalid.https.html.ini
+++ b/testing/web-platform/meta/web-share/share-url-invalid.https.html.ini
@@ -0,0 +1,4 @@
+[share-url-invalid.https.html]
+  [share with an invalid URL]
+    expected:
+      if os == "win": FAIL
--- a/testing/web-platform/meta/web-share/share-without-user-gesture.https.html.ini
+++ b/testing/web-platform/meta/web-share/share-without-user-gesture.https.html.ini
@@ -0,0 +1,4 @@
+[share-without-user-gesture.https.html]
+  [share without a user gesture]
+    expected:
+      if os == "win": FAIL
--- a/toolkit/actors/PrintingChild.jsm
+++ b/toolkit/actors/PrintingChild.jsm
@@ -27,20 +27,17 @@ class PrintingChild extends ActorChild {
   // Bug 1088061: nsPrintJob's DoCommonPrint currently expects the
   // progress listener passed to it to QI to an nsIPrintingPromptService
   // in order to know that a printing progress dialog has been shown. That's
   // really all the interface is used for, hence the fact that I don't actually
   // implement the interface here. Bug 1088061 has been filed to remove
   // this hackery.
 
   get shouldSavePrintSettings() {
-    return (
-      Services.prefs.getBoolPref("print.use_global_printsettings") &&
-      Services.prefs.getBoolPref("print.save_print_settings")
-    );
+    return Services.prefs.getBoolPref("print.save_print_settings");
   }
 
   handleEvent(event) {
     switch (event.type) {
       case "PrintingError": {
         let win = event.target.defaultView;
         let wbp = win.getInterface(Ci.nsIWebBrowserPrint);
         let nsresult = event.detail;
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -57,17 +57,16 @@
  *     Due to a timing issue resulting in a main-process crash, we have to
  *     manually open the progress dialog for print preview. The progress
  *     dialog is opened here in PrintUtils, and then we listen for update
  *     messages from the child. Bug 1088061 has been filed to investigate
  *     other solutions.
  *
  */
 
-var gPrintSettingsAreGlobal = false;
 var gSavePrintSettings = false;
 var gFocusedElement = null;
 
 var PrintUtils = {
   init() {
     window.messageManager.addMessageListener("Printing:Error", this);
   },
 
@@ -412,34 +411,27 @@ var PrintUtils = {
     aPSSVC.initPrintSettingsFromPrefs(
       aPrintSettings,
       true,
       aPrintSettings.kInitSaveAll
     );
   },
 
   getPrintSettings() {
-    gPrintSettingsAreGlobal = Services.prefs.getBoolPref(
-      "print.use_global_printsettings"
-    );
     gSavePrintSettings = Services.prefs.getBoolPref(
       "print.save_print_settings"
     );
 
     var printSettings;
     try {
       var PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService(
         Ci.nsIPrintSettingsService
       );
-      if (gPrintSettingsAreGlobal) {
-        printSettings = PSSVC.globalPrintSettings;
-        this._setPrinterDefaultsForSelectedPrinter(PSSVC, printSettings);
-      } else {
-        printSettings = PSSVC.newPrintSettings;
-      }
+      printSettings = PSSVC.globalPrintSettings;
+      this._setPrinterDefaultsForSelectedPrinter(PSSVC, printSettings);
     } catch (e) {
       dump("getPrintSettings: " + e + "\n");
     }
     return printSettings;
   },
 
   // This observer is called once the progress dialog has been "opened"
   _obsPP: {
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -316,16 +316,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
         'version',
         'winspool',
         'comdlg32',
         'imm32',
         'msimg32',
         'netapi32',
         'shlwapi',
         'ws2_32',
+        'dnsapi',
         'dwmapi',
         'iphlpapi',
         'uxtheme',
         'setupapi',
         'secur32',
         'sensorsapi',
         'portabledeviceguids',
         'wininet',
--- a/widget/gtk/IMContextWrapper.cpp
+++ b/widget/gtk/IMContextWrapper.cpp
@@ -1110,16 +1110,23 @@ void IMContextWrapper::OnFocusChangeInGe
       gGtkIMLog, LogLevel::Info,
       ("0x%p OnFocusChangeInGecko(aFocus=%s), "
        "mCompositionState=%s, mIsIMFocused=%s",
        this, ToChar(aFocus), GetCompositionStateName(), ToChar(mIsIMFocused)));
 
   // We shouldn't carry over the removed string to another editor.
   mSelectedStringRemovedByComposition.Truncate();
   mSelection.Clear();
+
+  // When the focus changes, we need to inform IM about the new cursor
+  // position. Chinese input methods generally rely on this because they
+  // usually don't start composition until a character is picked.
+  if (aFocus && EnsureToCacheSelection()) {
+    SetCursorPosition(GetActiveContext());
+  }
 }
 
 void IMContextWrapper::ResetIME() {
   MOZ_LOG(gGtkIMLog, LogLevel::Info,
           ("0x%p ResetIME(), mCompositionState=%s, mIsIMFocused=%s", this,
            GetCompositionStateName(), ToChar(mIsIMFocused)));
 
   GtkIMContext* activeContext = GetActiveContext();
--- a/widget/windows/WindowsUIUtils.cpp
+++ b/widget/windows/WindowsUIUtils.cpp
@@ -20,25 +20,26 @@
 #include "mozilla/media/MediaUtils.h"
 #include "nsString.h"
 #include "nsIWidget.h"
 #include "nsIWindowMediator.h"
 #include "nsPIDOMWindow.h"
 #include "nsWindowGfx.h"
 #include "Units.h"
 
+using namespace mozilla;
+
 /* mingw currently doesn't support windows.ui.viewmanagement.h, so we disable it
  * until it's fixed. */
 #ifndef __MINGW32__
 
 #  include <windows.ui.viewmanagement.h>
 
 #  pragma comment(lib, "runtimeobject.lib")
 
-using namespace mozilla;
 using namespace ABI::Windows::UI;
 using namespace ABI::Windows::UI::ViewManagement;
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
 using namespace ABI::Windows::Foundation;
 using namespace ABI::Windows::ApplicationModel::DataTransfer;
 
 /* All of this is win10 stuff and we're compiling against win81 headers
@@ -274,75 +275,75 @@ WindowsUIUtils::UpdateTabletModeState() 
 }
 
 #ifndef __MINGW32__
 struct HStringDeleter {
   typedef HSTRING pointer;
   void operator()(pointer aString) { WindowsDeleteString(aString); }
 };
 
-typedef mozilla::UniquePtr<HSTRING, HStringDeleter> HStringUniquePtr;
+typedef UniquePtr<HSTRING, HStringDeleter> HStringUniquePtr;
 
-mozilla::Result<HStringUniquePtr, HRESULT> ConvertToWindowsString(
+Result<HStringUniquePtr, HRESULT> ConvertToWindowsString(
     const nsAString& aStr) {
   HSTRING rawStr;
   HRESULT hr = WindowsCreateString(PromiseFlatString(aStr).get(), aStr.Length(),
                                    &rawStr);
   if (FAILED(hr)) {
-    return mozilla::Err(hr);
+    return Err(hr);
   }
   return HStringUniquePtr(rawStr);
 }
 
-mozilla::Result<Ok, nsresult> RequestShare(
+Result<Ok, nsresult> RequestShare(
     const std::function<HRESULT(IDataRequestedEventArgs* pArgs)>& aCallback) {
   if (!IsWin10OrLater()) {
-    return mozilla::Err(NS_ERROR_FAILURE);
+    return Err(NS_ERROR_FAILURE);
   }
 
   HWND hwnd = GetForegroundWindow();
   if (!hwnd) {
-    return mozilla::Err(NS_ERROR_FAILURE);
+    return Err(NS_ERROR_FAILURE);
   }
 
   ComPtr<IDataTransferManagerInterop> dtmInterop;
   ComPtr<IDataTransferManager> dtm;
 
   HRESULT hr = RoGetActivationFactory(
       HStringReference(
           RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager)
           .Get(),
       IID_PPV_ARGS(&dtmInterop));
   if (FAILED(hr) ||
       FAILED(dtmInterop->GetForWindow(hwnd, IID_PPV_ARGS(&dtm)))) {
-    return mozilla::Err(NS_ERROR_FAILURE);
+    return Err(NS_ERROR_FAILURE);
   }
 
   auto callback = Callback<
       ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs*>>(
       [aCallback](IDataTransferManager*,
                   IDataRequestedEventArgs* pArgs) -> HRESULT {
         return aCallback(pArgs);
       });
 
   EventRegistrationToken dataRequestedToken;
   if (FAILED(dtm->add_DataRequested(callback.Get(), &dataRequestedToken)) ||
       FAILED(dtmInterop->ShowShareUIForWindow(hwnd))) {
-    return mozilla::Err(NS_ERROR_FAILURE);
+    return Err(NS_ERROR_FAILURE);
   }
 
   return Ok();
 }
 #endif
 
 RefPtr<SharePromise> WindowsUIUtils::Share(nsAutoString aTitle,
                                            nsAutoString aText,
                                            nsAutoString aUrl) {
-  auto promiseHolder = mozilla::MakeRefPtr<
-      mozilla::media::Refcountable<mozilla::MozPromiseHolder<SharePromise>>>();
+  auto promiseHolder = MakeRefPtr<
+      mozilla::media::Refcountable<MozPromiseHolder<SharePromise>>>();
   RefPtr<SharePromise> promise = promiseHolder->Ensure(__func__);
 
 #ifndef __MINGW32__
   auto result = RequestShare([promiseHolder, title = std::move(aTitle),
                               text = std::move(aText), url = std::move(aUrl)](
                                  IDataRequestedEventArgs* pArgs) {
     ComPtr<IDataRequest> spDataRequest;
     ComPtr<IDataPackage> spDataPackage;
--- a/widget/windows/components.conf
+++ b/widget/windows/components.conf
@@ -136,16 +136,23 @@ Classes = [
     {
         'cid': '{0f872c8c-3ee6-46bd-92a2-69652c6b474e}',
         'contract_ids': ['@mozilla.org/colorpicker;1'],
         'type': 'nsColorPicker',
         'headers': ['/widget/windows/nsColorPicker.h'],
         'processes': ProcessSelector.MAIN_PROCESS_ONLY,
     },
     {
+        'cid': '{1201d357-8417-4926-a694-e6408fbedcf8}',
+        'contract_ids': ['@mozilla.org/sharepicker;1'],
+        'type': 'nsSharePicker',
+        'headers': ['/widget/windows/nsSharePicker.h'],
+        'processes': ProcessSelector.MAIN_PROCESS_ONLY,
+    },
+    {
         'cid': '{8b5314ba-db01-11d2-96ce-0060b0fb9956}',
         'contract_ids': ['@mozilla.org/widget/clipboard;1'],
         'type': 'nsIClipboard',
         'processes': ProcessSelector.MAIN_PROCESS_ONLY,
     },
 ]
 
 if buildconfig.substs['CC_TYPE'] in ('msvc', 'clang-cl'):
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -88,16 +88,17 @@ UNIFIED_SOURCES += [
 # The following files cannot be built in unified mode because of name clashes.
 SOURCES += [
     'CompositorWidgetParent.cpp',
     'InProcessWinCompositorWidget.cpp',
     'JumpListBuilder.cpp',
     'MediaKeysEventSourceFactory.cpp',
     'nsBidiKeyboard.cpp',
     'nsFilePicker.cpp',
+    'nsSharePicker.cpp',
     'nsWidgetFactory.cpp',
     'WinCompositorWidget.cpp',
     'WindowsUIUtils.cpp',
     'WinMouseScrollHandler.cpp',
 ]
 
 # Needs INITGUID and we don't allow INITGUID in unified sources since bug 970429.
 SOURCES += [
new file mode 100644
--- /dev/null
+++ b/widget/windows/nsSharePicker.cpp
@@ -0,0 +1,81 @@
+/* -*- 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 "nsSharePicker.h"
+
+#include "nsString.h"
+#include "nsThreadUtils.h"
+#include "WindowsUIUtils.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/Unused.h"
+
+using mozilla::dom::Promise;
+
+///////////////////////////////////////////////////////////////////////////////
+// nsISharePicker
+
+NS_IMPL_ISUPPORTS(nsSharePicker, nsISharePicker)
+
+namespace {
+inline NS_ConvertUTF8toUTF16 NS_ConvertUTF8toUTF16_MaybeVoid(
+    const nsACString& aStr) {
+  auto str = NS_ConvertUTF8toUTF16(aStr);
+  str.SetIsVoid(aStr.IsVoid());
+  return str;
+}
+inline nsIGlobalObject* GetGlobalObject() {
+  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
+}
+}  // namespace
+
+NS_IMETHODIMP
+nsSharePicker::Init(mozIDOMWindowProxy* aOpenerWindow) {
+  if (mInited) {
+    return NS_ERROR_FAILURE;
+  }
+  mOpenerWindow = aOpenerWindow;
+  mInited = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSharePicker::GetOpenerWindow(mozIDOMWindowProxy **aOpenerWindow) {
+  *aOpenerWindow = mOpenerWindow;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSharePicker::Share(const nsACString& aTitle, const nsACString& aText,
+                     nsIURI* aUrl, Promise** aPromise) {
+  mozilla::ErrorResult result;
+  RefPtr<Promise> promise = Promise::Create(GetGlobalObject(), result);
+  if (NS_WARN_IF(result.Failed())) {
+    return result.StealNSResult();
+  }
+  nsAutoCString urlString;
+  if (aUrl) {
+    nsresult rv = aUrl->GetSpec(urlString);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    mozilla::Unused << rv;
+  } else {
+    urlString.SetIsVoid(true);
+  }
+
+  auto mozPromise =
+      WindowsUIUtils::Share(NS_ConvertUTF8toUTF16_MaybeVoid(aTitle),
+                            NS_ConvertUTF8toUTF16_MaybeVoid(aText),
+                            NS_ConvertUTF8toUTF16_MaybeVoid(urlString));
+  mozPromise->Then(
+      mozilla::GetCurrentThreadSerialEventTarget(), __func__,
+      [promise]() { promise->MaybeResolveWithUndefined(); },
+      [promise]() { promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); });
+
+  promise.forget(aPromise);
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/widget/windows/nsSharePicker.h
@@ -0,0 +1,29 @@
+/* -*- 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/. */
+
+#ifndef nsSharePicker_h__
+#define nsSharePicker_h__
+
+#include "nsCOMPtr.h"
+#include "nsISharePicker.h"
+#include "nsPIDOMWindow.h"
+#include "nsThreadUtils.h"
+
+class nsSharePicker : public nsISharePicker {
+  virtual ~nsSharePicker() = default;
+
+ public:
+  nsSharePicker() = default;
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISHAREPICKER
+
+ private:
+  bool mInited = false;
+  mozIDOMWindowProxy* mOpenerWindow;
+};
+
+#endif  // nsSharePicker_h__