Merge autoland to mozilla-central a=merge
authorAndreea Pavel <apavel@mozilla.com>
Thu, 07 Nov 2019 11:47:48 +0200
changeset 501035 d271c572a9bcd008ed14bf104b2eb81949952e4c
parent 500872 e8b7c48d4e7ed1b63aeedff379b51e566ea499d9 (current diff)
parent 501034 85aa4fa5722bdcb6e0d13f29951772d3c7806e42 (diff)
child 501044 8c32b5d7296d84dedb3a9678ffda886aba35f203
push id36778
push userapavel@mozilla.com
push dateThu, 07 Nov 2019 09:49:05 +0000
treeherdermozilla-central@d271c572a9bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone72.0a1
first release with
nightly linux32
d271c572a9bc / 72.0a1 / 20191107094905 / files
nightly linux64
d271c572a9bc / 72.0a1 / 20191107094905 / files
nightly mac
d271c572a9bc / 72.0a1 / 20191107094905 / files
nightly win32
d271c572a9bc / 72.0a1 / 20191107094905 / files
nightly win64
d271c572a9bc / 72.0a1 / 20191107094905 / 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
browser/components/urlbar/tests/browser/browser_moz_action_link.js
dom/xbl/XBLChildrenElement.cpp
dom/xbl/XBLChildrenElement.h
dom/xbl/moz.build
dom/xbl/nsBindingManager.cpp
dom/xbl/nsBindingManager.h
dom/xbl/nsXBLBinding.cpp
dom/xbl/nsXBLBinding.h
dom/xbl/nsXBLContentSink.cpp
dom/xbl/nsXBLContentSink.h
dom/xbl/nsXBLDocumentInfo.cpp
dom/xbl/nsXBLDocumentInfo.h
dom/xbl/nsXBLEventHandler.cpp
dom/xbl/nsXBLEventHandler.h
dom/xbl/nsXBLMaybeCompiled.h
dom/xbl/nsXBLProtoImpl.cpp
dom/xbl/nsXBLProtoImpl.h
dom/xbl/nsXBLProtoImplField.cpp
dom/xbl/nsXBLProtoImplField.h
dom/xbl/nsXBLProtoImplMember.h
dom/xbl/nsXBLProtoImplMethod.cpp
dom/xbl/nsXBLProtoImplMethod.h
dom/xbl/nsXBLProtoImplProperty.cpp
dom/xbl/nsXBLProtoImplProperty.h
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
dom/xbl/nsXBLPrototypeHandler.cpp
dom/xbl/nsXBLPrototypeHandler.h
dom/xbl/nsXBLSerialize.cpp
dom/xbl/nsXBLSerialize.h
dom/xbl/nsXBLService.cpp
dom/xbl/nsXBLService.h
dom/xbl/stub/nsXBLBinding.h
dom/xbl/test/.eslintrc.js
dom/xbl/test/bug310107-resource.xhtml
dom/xbl/test/chrome.ini
dom/xbl/test/file_bug310107.html
dom/xbl/test/file_bug366770.xml
dom/xbl/test/file_bug372769.xhtml
dom/xbl/test/file_bug379959_cross.html
dom/xbl/test/file_bug379959_data.html
dom/xbl/test/file_bug379959_xbl.xml
dom/xbl/test/file_bug397934.xhtml
dom/xbl/test/file_bug481558.xbl
dom/xbl/test/file_bug481558css.sjs
dom/xbl/test/file_bug591198_inner.html
dom/xbl/test/file_bug591198_xbl.xml
dom/xbl/test/file_bug844783.xhtml
dom/xbl/test/file_fieldScopeChain.xml
dom/xbl/test/mochitest.ini
dom/xbl/test/test_bug1086996.xhtml
dom/xbl/test/test_bug1098628_throw_from_construct.xhtml
dom/xbl/test/test_bug1359859.xhtml
dom/xbl/test/test_bug310107.html
dom/xbl/test/test_bug366770.html
dom/xbl/test/test_bug371724.xhtml
dom/xbl/test/test_bug372769.html
dom/xbl/test/test_bug378518.xul
dom/xbl/test/test_bug378866.xhtml
dom/xbl/test/test_bug379959.html
dom/xbl/test/test_bug389322.xhtml
dom/xbl/test/test_bug397934.html
dom/xbl/test/test_bug398135.xul
dom/xbl/test/test_bug398492.xul
dom/xbl/test/test_bug400705.xhtml
dom/xbl/test/test_bug401907.xhtml
dom/xbl/test/test_bug403162.xhtml
dom/xbl/test/test_bug468210.xhtml
dom/xbl/test/test_bug481558.html
dom/xbl/test/test_bug526178.xhtml
dom/xbl/test/test_bug542406.xhtml
dom/xbl/test/test_bug591198.html
dom/xbl/test/test_bug639338.xhtml
dom/xbl/test/test_bug721452.xul
dom/xbl/test/test_bug723676.xul
dom/xbl/test/test_bug772966.xul
dom/xbl/test/test_bug790265.xhtml
dom/xbl/test/test_bug844783.html
dom/xbl/test/test_bug872273.xhtml
dom/xbl/test/test_fieldScopeChain.html
js/src/gdb/mozilla/ExecutableAllocator.py
js/src/gdb/tests/test-ExecutableAllocator.cpp
js/src/gdb/tests/test-ExecutableAllocator.py
testing/web-platform/meta/service-workers/service-worker/clients-get.https.html.ini.orig
toolkit/content/tests/browser/browser_autoplay_policy_iframe_hierarchy.js
toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html
toolkit/content/tests/browser/file_autoplay_three_layers_frame2.html
toolkit/content/tests/browser/file_autoplay_two_layers_frame1.html
toolkit/content/tests/browser/file_autoplay_two_layers_frame2.html
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -231,17 +231,16 @@ module.exports = {
       "dom/tests/mochitest/**",
       "dom/u2f/**",
       "dom/vr/**",
       "dom/webauthn/**",
       "dom/webgpu/**",
       "dom/websocket/**",
       "dom/workers/**",
       "dom/worklet/**",
-      "dom/xbl/**",
       "dom/xml/**",
       "dom/xslt/**",
       "dom/xul/**",
     ],
     "rules": {
       "consistent-return": "off",
       "mozilla/avoid-removeChild": "off",
       "mozilla/consistent-if-bracing": "off",
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -134,27 +134,28 @@ uint32_t DocAccessibleParent::AddSubtree
     if (pending.mParentID == newChild.ID()) {
       if (!pending.mChildDoc->IsShutdown()) {
         AddChildDoc(pending.mChildDoc, pending.mParentID, false);
       }
       mPendingChildDocs.RemoveElementAt(index);
       break;
     }
   }
+  DebugOnly<bool> isOuterDoc = newProxy->ChildrenCount() == 1;
 
   uint32_t accessibles = 1;
   uint32_t kids = newChild.ChildrenCount();
   for (uint32_t i = 0; i < kids; i++) {
     uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
     if (!consumed) return 0;
 
     accessibles += consumed;
   }
 
-  MOZ_ASSERT(newProxy->ChildrenCount() == kids);
+  MOZ_ASSERT((isOuterDoc && kids == 0) || newProxy->ChildrenCount() == kids);
 
   return accessibles;
 }
 
 mozilla::ipc::IPCResult DocAccessibleParent::RecvHideEvent(
     const uint64_t& aRootID, const bool& aFromUser) {
   if (mShutdown) return IPC_OK();
 
--- a/accessible/mac/Platform.mm
+++ b/accessible/mac/Platform.mm
@@ -53,18 +53,21 @@ void ProxyCreated(ProxyAccessible* aProx
     // will be a non-remote accessible.
     Accessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
     if (outerDoc) {
       nativeParent = GetNativeFromGeckoAccessible(outerDoc);
     }
   } else {
     // Non-top level proxies need proxy parents' children invalidated.
     ProxyAccessible* parent = aProxy->Parent();
-    nativeParent = GetNativeFromProxy(parent);
-    NS_ASSERTION(parent, "a non-top-level proxy is missing a parent?");
+    MOZ_ASSERT(parent ||
+                   // It's expected that an OOP iframe might not have a parent yet.
+                   (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevelInContentProcess()),
+               "a non-top-level proxy is missing a parent?");
+    nativeParent = parent ? GetNativeFromProxy(parent) : nullptr;
   }
 
   if (nativeParent) {
     [nativeParent invalidateChildren];
   }
 }
 
 void ProxyDestroyed(ProxyAccessible* aProxy) {
@@ -93,16 +96,31 @@ void ProxyDestroyed(ProxyAccessible* aPr
   aProxy->SetWrapper(0);
 
   if (nativeParent) {
     [nativeParent invalidateChildren];
   }
 }
 
 void ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType) {
+  if (aEventType == nsIAccessibleEvent::EVENT_REORDER && aProxy->ChildrenCount() == 1 &&
+      aProxy->ChildAt(0)->IsDoc()) {
+    // This is a remote OuterDocAccessible. The reorder event indicates that Its
+    // embedded document has been added or changed. If the document itself is
+    // an existing Accessible, ProxyCreated won't have been called, so we won't
+    // have invalidated native children. This can happen for in-process iframes
+    // if the OuterDocAccessible is re-created (e.g. due to layout reflow).
+    // It always happens for out-of-process iframes, as we must always call
+    // ProxyCreated before DocAccessibleParent::AddChildDoc for those.
+    mozAccessible* wrapper = GetNativeFromProxy(aProxy);
+    if (wrapper) {
+      [wrapper invalidateChildren];
+    }
+  }
+
   // ignore everything but focus-changed, value-changed, caret and selection
   // events for now.
   if (aEventType != nsIAccessibleEvent::EVENT_FOCUS &&
       aEventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
       aEventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
       aEventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
       aEventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
     return;
--- a/browser/base/content/browser-siteProtections.js
+++ b/browser/base/content/browser-siteProtections.js
@@ -1231,28 +1231,40 @@ var gProtectionsHandler = {
     ));
   },
   get _protectionsPopupSiteNotWorkingTPSwitch() {
     delete this._protectionsPopupSiteNotWorkingTPSwitch;
     return (this._protectionsPopupSiteNotWorkingTPSwitch = document.getElementById(
       "protections-popup-siteNotWorking-tp-switch"
     ));
   },
+  get _protectionsPopupSiteNotWorkingReportError() {
+    delete this._protectionsPopupSiteNotWorkingReportError;
+    return (this._protectionsPopupSiteNotWorkingReportError = document.getElementById(
+      "protections-popup-sendReportView-report-error"
+    ));
+  },
   get _protectionsPopupSendReportLearnMore() {
     delete this._protectionsPopupSendReportLearnMore;
     return (this._protectionsPopupSendReportLearnMore = document.getElementById(
       "protections-popup-sendReportView-learn-more"
     ));
   },
   get _protectionsPopupSendReportURL() {
     delete this._protectionsPopupSendReportURL;
     return (this._protectionsPopupSendReportURL = document.getElementById(
       "protections-popup-sendReportView-collection-url"
     ));
   },
+  get _protectionsPopupSendReportButton() {
+    delete this._protectionsPopupSendReportButton;
+    return (this._protectionsPopupSendReportButton = document.getElementById(
+      "protections-popup-sendReportView-submit"
+    ));
+  },
   get _trackingProtectionIconTooltipLabel() {
     delete this._trackingProtectionIconTooltipLabel;
     return (this._trackingProtectionIconTooltipLabel = document.getElementById(
       "tracking-protection-icon-tooltip-label"
     ));
   },
 
   get noTrackersDetectedDescription() {
@@ -2169,17 +2181,22 @@ var gProtectionsHandler = {
   showSendReportView() {
     // Save this URI to make sure that the user really only submits the location
     // they see in the report breakage dialog.
     this.reportURI = gBrowser.currentURI;
     let urlWithoutQuery = this.reportURI.asciiSpec.replace(
       "?" + this.reportURI.query,
       ""
     );
+    let commentsTextarea = document.getElementById(
+      "protections-popup-sendReportView-collection-comments"
+    );
+    commentsTextarea.value = "";
     this._protectionsPopupSendReportURL.value = urlWithoutQuery;
+    this._protectionsPopupSiteNotWorkingReportError.hidden = true;
     this._protectionsPopupMultiView.showSubView(
       "protections-popup-sendReportView"
     );
   },
 
   toggleBreakageLink() {
     // The breakage link will only be shown if tracking protection is enabled
     // for the site and the TP toggle state is on. And we won't show the
@@ -2187,16 +2204,17 @@ var gProtectionsHandler = {
     // know the previous TP state. We check the ContentBlockingAllowList instead
     // of 'hasException' attribute of the protection popup for the previous
     // since the 'hasException' will also be toggled as well as toggling the TP
     // switch. We won't be able to know the previous TP state through the
     // 'hasException' attribute. So we fallback to check the
     // ContentBlockingAllowList here.
     this._protectionsPopupTPSwitchBreakageLink.hidden =
       ContentBlockingAllowList.includes(gBrowser.selectedBrowser) ||
+      !this._protectionsPopup.hasAttribute("blocking") ||
       !this._protectionsPopupTPSwitch.hasAttribute("enabled");
   },
 
   submitBreakageReport(uri) {
     let reportEndpoint = Services.prefs.getStringPref(
       this.PREF_REPORT_BREAKAGE_URL
     );
     if (!reportEndpoint) {
@@ -2264,38 +2282,41 @@ var gProtectionsHandler = {
         activatedBlockers.push(blocker.reportBreakageLabel);
       }
     }
 
     if (activatedBlockers.length) {
       formData.set("labels", activatedBlockers.join(","));
     }
 
+    this._protectionsPopupSendReportButton.disabled = true;
+
     fetch(reportEndpoint, {
       method: "POST",
       credentials: "omit",
       body: formData,
     })
-      .then(function(response) {
+      .then(response => {
+        this._protectionsPopupSendReportButton.disabled = false;
         if (!response.ok) {
           Cu.reportError(
             `Content Blocking report to ${reportEndpoint} failed with status ${
               response.status
             }`
           );
+          this._protectionsPopupSiteNotWorkingReportError.hidden = false;
         } else {
-          // Clear the textarea value when the report is submitted
-          commentsTextarea.value = "";
+          this._protectionsPopup.hidePopup();
+          ConfirmationHint.show(this.iconBox, "breakageReport");
         }
       })
       .catch(Cu.reportError);
   },
 
   onSendReportClicked() {
-    this._protectionsPopup.hidePopup();
     this.submitBreakageReport(this.reportURI);
   },
 
   async maybeUpdateEarliestRecordedDateTooltip() {
     if (this._hasEarliestRecord) {
       return;
     }
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3315,20 +3315,16 @@ function URLBarSetURI(aURI, updatePopupN
     gURLBar.selectionStart = gURLBar.selectionEnd = 0;
   }
 
   SetPageProxyState(valid ? "valid" : "invalid", updatePopupNotifications);
 }
 
 function losslessDecodeURI(aURI) {
   let scheme = aURI.scheme;
-  if (scheme == "moz-action") {
-    throw new Error("losslessDecodeURI should never get a moz-action URI");
-  }
-
   var value = aURI.displaySpec;
 
   let decodeASCIIOnly = !["https", "http", "file", "ftp"].includes(scheme);
   // Try to decode as UTF-8 if there's no encoding sequence that we would break.
   if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value)) {
     if (decodeASCIIOnly) {
       // This only decodes ascii characters (hex) 20-7e, except 25 (%).
       // This avoids both cases stipulated below (%-related issues, and \r, \n
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -72,16 +72,17 @@
         persist="screenX screenY width height sizemode"
         data-l10n-sync="true">
 
 <linkset>
   <html:link rel="localization" href="branding/brand.ftl"/>
   <html:link rel="localization" href="browser/branding/sync-brand.ftl"/>
   <html:link rel="localization" href="browser/browser.ftl"/>
   <html:link rel="localization" href="browser/menubar.ftl"/>
+  <html:link rel="localization" href="browser/protectionsPanel.ftl"/>
   <html:link rel="localization" href="browser/appmenu.ftl"/>
   <html:link rel="localization" href="browser/readerView.ftl"/>
 </linkset>
 
 # All JS files which are needed by browser.xhtml and other top level windows to
 # support MacOS specific features *must* go into the global-scripts.inc file so
 # that they can be shared with macWindow.inc.xul.
 #include global-scripts.inc
--- a/browser/base/content/test/siteProtections/browser.ini
+++ b/browser/base/content/test/siteProtections/browser.ini
@@ -1,6 +1,7 @@
 [DEFAULT]
 support-files =
   head.js
 
 [browser_protections_UI.js]
+skip-if = fission # Bug 1590696
 [browser_protections_UI_milestones.js]
--- a/browser/base/content/test/siteProtections/browser_protections_UI.js
+++ b/browser/base/content/test/siteProtections/browser_protections_UI.js
@@ -1,46 +1,57 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /* Basic UI tests for the protections panel */
 
+"use strict";
+
+const TRACKING_PAGE =
+  "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
+
 ChromeUtils.defineModuleGetter(
   this,
   "ContentBlockingAllowList",
   "resource://gre/modules/ContentBlockingAllowList.jsm"
 );
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({
     set: [
       // Set the auto hide timing to 100ms for blocking the test less.
       ["browser.protections_panel.toast.timeout", 100],
       // Hide protections cards so as not to trigger more async messaging
       // when landing on the page.
       ["browser.contentblocking.report.monitor.enabled", false],
       ["browser.contentblocking.report.lockwise.enabled", false],
       ["browser.contentblocking.report.proxy.enabled", false],
+      ["privacy.trackingprotection.enabled", true],
     ],
   });
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
   Services.telemetry.clearEvents();
 
   registerCleanupFunction(() => {
     Services.telemetry.canRecordExtended = oldCanRecord;
     Services.telemetry.clearEvents();
   });
 });
 
 add_task(async function testToggleSwitch() {
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
-    "https://example.com"
+    TRACKING_PAGE
   );
+
+  await TestUtils.waitForCondition(() => {
+    return gProtectionsHandler._protectionsPopup.hasAttribute("blocking");
+  });
+
   await openProtectionsPanel();
   let events = Services.telemetry.snapshotEvents(
     Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
   ).parent;
   let buttonEvents = events.filter(
     e =>
       e[1] == "security.ui.protectionspopup" &&
       e[2] == "open" &&
--- a/browser/base/content/test/siteProtections/browser_protections_UI_milestones.js
+++ b/browser/base/content/test/siteProtections/browser_protections_UI_milestones.js
@@ -4,16 +4,17 @@
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({
     set: [
       // Hide protections cards so as not to trigger more async messaging
       // when landing on the page.
       ["browser.contentblocking.report.monitor.enabled", false],
       ["browser.contentblocking.report.lockwise.enabled", false],
       ["browser.contentblocking.report.proxy.enabled", false],
+      ["browser.contentblocking.cfr-milestone.update-interval", 0],
     ],
   });
 });
 
 add_task(async function doTest() {
   // This also ensures that the DB tables have been initialized.
   await TrackingDBService.clearAll();
 
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -64,18 +64,18 @@ skip-if = !e10s # Test only relevant for
 [browser_new_tab_insert_position.js]
 skip-if = (debug && os == 'linux' && bits == 32) #Bug 1455882, disabled on Linux32 for almost permafailing
 support-files = file_new_tab_page.html
 [browser_new_tab_in_privilegedabout_process_pref.js]
 skip-if = !e10s # Pref and test only relevant for e10s.
 [browser_privilegedmozilla_process_pref.js]
 skip-if = !e10s # Pref and test only relevant for e10s.
 [browser_new_web_tab_in_file_process_pref.js]
-fail-if = fission # Expects http tab opened from file to be loaded in file content process
 skip-if = !e10s # Pref and test only relevant for e10s.
+        || fission # Expects http tab opened from file to be loaded in file content process. See bug 1594221
 [browser_newwindow_tabstrip_overflow.js]
 [browser_open_newtab_start_observer_notification.js]
 [browser_opened_file_tab_navigated_to_web.js]
 [browser_overflowScroll.js]
 [browser_paste_event_at_middle_click_on_link.js]
 tags = clipboard
 support-files = file_anchor_elements.html
 [browser_pinnedTabs_clickOpen.js]
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -59,16 +59,19 @@ add_task(async function setup() {
     ],
   });
 });
 
 add_task(async function testReportBreakageCancel() {
   Services.prefs.setBoolPref(TP_PREF, true);
 
   await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
+    await TestUtils.waitForCondition(() =>
+      gProtectionsHandler._protectionsPopup.hasAttribute("blocking")
+    );
     await openProtectionsPopup();
 
     let siteNotWorkingButton = document.getElementById(
       "protections-popup-tp-switch-breakage-link"
     );
     ok(
       BrowserTestUtils.is_visible(siteNotWorkingButton),
       "site not working button is visible"
@@ -103,16 +106,41 @@ add_task(async function testReportBreaka
     await viewShown;
 
     ok(true, "Main view was shown");
   });
 
   Services.prefs.clearUserPref(TP_PREF);
 });
 
+add_task(async function testNoTracking() {
+  await BrowserTestUtils.withNewTab(BENIGN_PAGE, async function() {
+    await openProtectionsPopup();
+
+    let siteNotWorkingButton = document.getElementById(
+      "protections-popup-tp-switch-breakage-link"
+    );
+    ok(
+      BrowserTestUtils.is_hidden(siteNotWorkingButton),
+      "site not working button is not visible"
+    );
+  });
+});
+
+add_task(async function testReportBreakageError() {
+  Services.prefs.setBoolPref(TP_PREF, true);
+  // Make sure that we correctly strip the query.
+  let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
+  await BrowserTestUtils.withNewTab(url, async function() {
+    await testReportBreakage(TRACKING_PAGE, "trackingprotection", true);
+  });
+
+  Services.prefs.clearUserPref(TP_PREF);
+});
+
 add_task(async function testTP() {
   Services.prefs.setBoolPref(TP_PREF, true);
   // Make sure that we correctly strip the query.
   let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
   await BrowserTestUtils.withNewTab(url, async function() {
     await testReportBreakage(TRACKING_PAGE, "trackingprotection");
   });
 
@@ -134,61 +162,68 @@ add_task(async function testCR() {
 });
 
 add_task(async function testFP() {
   Services.prefs.setIntPref(CB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
   Services.prefs.setBoolPref(FP_PREF, true);
   // Make sure that we correctly strip the query.
   let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
   await BrowserTestUtils.withNewTab(url, async function(browser) {
+    let promise = waitForContentBlockingEvent();
     await SpecialPowers.spawn(browser, [], function() {
       content.postMessage("fingerprinting", "*");
     });
+    await promise;
 
     await testReportBreakage(TRACKING_PAGE, "fingerprinting");
   });
 
   Services.prefs.clearUserPref(FP_PREF);
   Services.prefs.clearUserPref(CB_PREF);
 });
 
 add_task(async function testCM() {
   Services.prefs.setIntPref(CB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
   Services.prefs.setBoolPref(CM_PREF, true);
   // Make sure that we correctly strip the query.
   let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
   await BrowserTestUtils.withNewTab(url, async function(browser) {
+    let promise = waitForContentBlockingEvent();
     await SpecialPowers.spawn(browser, [], function() {
       content.postMessage("cryptomining", "*");
     });
+    await promise;
 
     await testReportBreakage(TRACKING_PAGE, "cryptomining");
   });
 
   Services.prefs.clearUserPref(CM_PREF);
   Services.prefs.clearUserPref(CB_PREF);
 });
 
-async function testReportBreakage(url, tags) {
+async function testReportBreakage(url, tags, error = false) {
   // Setup a mock server for receiving breakage reports.
   let server = new HttpServer();
   server.start(-1);
   let i = server.identity;
   let path =
     i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort + "/";
 
   Services.prefs.setStringPref(PREF_REPORT_BREAKAGE_URL, path);
 
+  await TestUtils.waitForCondition(() =>
+    gProtectionsHandler._protectionsPopup.hasAttribute("blocking")
+  );
   await openProtectionsPopup();
 
   let siteNotWorkingButton = document.getElementById(
     "protections-popup-tp-switch-breakage-link"
   );
-  await TestUtils.waitForCondition(
-    () => BrowserTestUtils.is_visible(siteNotWorkingButton),
+  ok(
+    BrowserTestUtils.is_visible(siteNotWorkingButton),
     "site not working button is visible"
   );
   let siteNotWorkingView = document.getElementById(
     "protections-popup-siteNotWorkingView"
   );
   let viewShown = BrowserTestUtils.waitForEvent(
     siteNotWorkingView,
     "ViewShown"
@@ -276,22 +311,45 @@ async function testReportBreakage(url, t
             "This is a comment\r\n",
           'Content-Disposition: form-data; name="labels"\r\n\r\n' +
             `${tags}\r\n`,
           "",
         ],
         "Should send the correct form data"
       );
 
+      if (error) {
+        response.setStatusLine(request.httpVersion, 500, "Request failed");
+      } else {
+        response.setStatusLine(request.httpVersion, 201, "Entry created");
+      }
+
       resolve();
     });
 
     comments.value = "This is a comment";
     submitButton.click();
   });
 
+  let errorMessage = document.getElementById(
+    "protections-popup-sendReportView-report-error"
+  );
+  if (error) {
+    await BrowserTestUtils.waitForCondition(() =>
+      BrowserTestUtils.is_visible(errorMessage)
+    );
+    is(
+      comments.value,
+      "This is a comment",
+      "Comment not cleared in case of an error"
+    );
+    gProtectionsHandler._protectionsPopup.hidePopup();
+  } else {
+    ok(BrowserTestUtils.is_hidden(errorMessage), "Error message not shown");
+  }
+
   await popuphidden;
 
   // Stop the server.
   await new Promise(r => server.stop(r));
 
   Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
 }
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -2108,17 +2108,25 @@ BrowserGlue.prototype = {
         "permissions.eventTelemetry.enabled",
         this._togglePermissionPromptTelemetry
       );
       this._togglePermissionPromptTelemetry();
     });
 
     // Begin listening for incoming push messages.
     Services.tm.idleDispatchToMainThread(() => {
-      PushService.wrappedJSObject.ensureReady();
+      try {
+        PushService.wrappedJSObject.ensureReady();
+      } catch (ex) {
+        // NS_ERROR_NOT_AVAILABLE will get thrown for the PushService getter
+        // if the PushService is disabled.
+        if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+          throw ex;
+        }
+      }
     });
 
     Services.tm.idleDispatchToMainThread(() => {
       this._recordContentBlockingTelemetry();
     });
 
     Services.tm.idleDispatchToMainThread(() => {
       this._recordContentBlockerTelemetry();
--- a/browser/components/controlcenter/content/protectionsPanel.inc.xul
+++ b/browser/components/controlcenter/content/protectionsPanel.inc.xul
@@ -305,16 +305,19 @@
           <vbox class="protections-popup-sendReportView-collection-section">
             <label control="protections-popup-sendReportView-collection-url">&contentBlocking.breakageReportView.collection.url.label;</label>
             <html:input readonly="readonly" id="protections-popup-sendReportView-collection-url" aria-label="&contentBlocking.breakageReportView.collection.url.label;"/>
           </vbox>
           <vbox class="protections-popup-sendReportView-collection-section">
             <label control="protections-popup-sendReportView-collection-comments">&contentBlocking.breakageReportView2.collection.comments.label;</label>
             <html:textarea id="protections-popup-sendReportView-collection-comments" aria-label="&contentBlocking.breakageReportView2.collection.comments.label;"/>
           </vbox>
+          <label id="protections-popup-sendReportView-report-error"
+            data-l10n-id="protections-panel-sendreportview-error"
+            hidden="true" role="alert"></label>
         </vbox>
         <vbox id="protections-popup-sendReportView-footer"
               class="panel-footer">
           <button id="protections-popup-sendReportView-cancel"
                   label="&contentBlocking.breakageReportView.cancel.label;"
                   oncommand="gProtectionsHandler._protectionsPopupMultiView.goBack();"/>
           <button id="protections-popup-sendReportView-submit"
                   default="true"
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -1,14 +1,18 @@
 [DEFAULT]
 tags = webextensions
 prefs =
     # We don't want to reset this at the end of the test, so that we don't have
     # to spawn a new extension child process for each test unit.
     dom.ipc.keepProcessesAlive.extension=1
+    # With Fission enabled, this directory spawns many child processes, which
+    # somehow results in frequent leaks and shutdown hangs. Reuse the content
+    # processes to avoid this.
+    dom.ipc.keepProcessesAlive.webIsolated.perOrigin=1
     dom.animations-api.core.enabled=true
     dom.animations-api.timelines.enabled=true
     plugin.load_flash_only=false
 support-files =
   head.js
   head_devtools.js
   file_inspectedwindow_reload_target.sjs
   silence.ogg
--- a/browser/components/newtab/content-src/asrouter/templates/FirstRun/FirstRun.jsx
+++ b/browser/components/newtab/content-src/asrouter/templates/FirstRun/FirstRun.jsx
@@ -17,22 +17,28 @@ export const FLUENT_FILES = [
   "browser/newtab/onboarding.ftl",
 ];
 
 export const helpers = {
   selectInterruptAndTriplets(message = {}, interruptCleared) {
     const hasInterrupt =
       interruptCleared === true ? false : Boolean(message.content);
     const hasTriplets = Boolean(message.bundle && message.bundle.length);
+    // Allow 1) falsy to not render a header 2) default welcome 3) custom header
+    const tripletsHeaderId =
+      message.tripletsHeaderId === undefined
+        ? "onboarding-welcome-header"
+        : message.tripletsHeaderId;
     const UTMTerm = message.utm_term || "";
     return {
       hasTriplets,
       hasInterrupt,
       interrupt: hasInterrupt ? message : null,
       triplets: hasTriplets ? message.bundle : null,
+      tripletsHeaderId,
       UTMTerm,
     };
   },
 
   addFluent(document) {
     FLUENT_FILES.forEach(file => {
       const link = document.head.appendChild(document.createElement("link"));
       link.href = file;
@@ -50,16 +56,17 @@ export class FirstRun extends React.Pure
     this.state = {
       prevMessage: undefined,
 
       hasInterrupt: false,
       hasTriplets: false,
 
       interrupt: undefined,
       triplets: undefined,
+      tripletsHeaderId: "",
 
       isInterruptVisible: false,
       isTripletsContainerVisible: false,
       isTripletsContentVisible: false,
 
       UTMTerm: "",
 
       flowParams: undefined,
@@ -82,28 +89,30 @@ export class FirstRun extends React.Pure
       interruptCleared !== state.prevInterruptCleared ||
       (message && message.id !== state.prevMessageId)
     ) {
       const {
         hasTriplets,
         hasInterrupt,
         interrupt,
         triplets,
+        tripletsHeaderId,
         UTMTerm,
       } = helpers.selectInterruptAndTriplets(message, interruptCleared);
 
       return {
         prevMessageId: message.id,
         prevInterruptCleared: interruptCleared,
 
         hasInterrupt,
         hasTriplets,
 
         interrupt,
         triplets,
+        tripletsHeaderId,
 
         isInterruptVisible: hasInterrupt,
         isTripletsContainerVisible: hasTriplets,
         isTripletsContentVisible: !(hasInterrupt || !hasTriplets),
 
         UTMTerm,
       };
     }
@@ -167,16 +176,17 @@ export class FirstRun extends React.Pure
       fxaEndpoint,
       dispatch,
       executeAction,
     } = props;
 
     const {
       interrupt,
       triplets,
+      tripletsHeaderId,
       isInterruptVisible,
       isTripletsContainerVisible,
       isTripletsContentVisible,
       hasTriplets,
       UTMTerm,
       flowParams,
     } = this.state;
 
@@ -196,16 +206,17 @@ export class FirstRun extends React.Pure
             onDismiss={this.closeInterrupt}
             fxaEndpoint={fxaEndpoint}
           />
         ) : null}
         {hasTriplets ? (
           <Triplets
             document={props.document}
             cards={triplets}
+            headerId={tripletsHeaderId}
             showCardPanel={isTripletsContainerVisible}
             showContent={isTripletsContentVisible}
             hideContainer={this.closeTriplets}
             sendUserActionTelemetry={sendUserActionTelemetry}
             UTMTerm={`${UTMTerm}-card`}
             flowParams={flowParams}
             onAction={executeAction}
           />
--- a/browser/components/newtab/content-src/asrouter/templates/FirstRun/Triplets.jsx
+++ b/browser/components/newtab/content-src/asrouter/templates/FirstRun/Triplets.jsx
@@ -50,26 +50,27 @@ export class Triplets extends React.Pure
       message_id: cards.map(m => m.id).join(","),
       action: "onboarding_user_event",
     });
   }
 
   render() {
     const {
       cards,
+      headerId,
       showCardPanel,
       showContent,
       sendUserActionTelemetry,
     } = this.props;
     return (
       <div
         className={`trailheadCards ${showCardPanel ? "expanded" : "collapsed"}`}
       >
         <div className="trailheadCardsInner" aria-hidden={!showContent}>
-          <h1 data-l10n-id="onboarding-welcome-header" />
+          {headerId && <h1 data-l10n-id={headerId} />}
           <div className={`trailheadCardGrid${showContent ? " show" : ""}`}>
             {cards.map(card => (
               <OnboardingCard
                 key={card.id}
                 className="trailheadCard"
                 sendUserActionTelemetry={sendUserActionTelemetry}
                 onAction={this.onCardAction}
                 UISurface="TRAILHEAD"
--- a/browser/components/newtab/data/content/activity-stream.bundle.js
+++ b/browser/components/newtab/data/content/activity-stream.bundle.js
@@ -3614,27 +3614,28 @@ class Triplets extends react__WEBPACK_IM
       message_id: cards.map(m => m.id).join(","),
       action: "onboarding_user_event"
     });
   }
 
   render() {
     const {
       cards,
+      headerId,
       showCardPanel,
       showContent,
       sendUserActionTelemetry
     } = this.props;
     return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
       className: `trailheadCards ${showCardPanel ? "expanded" : "collapsed"}`
     }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
       className: "trailheadCardsInner",
       "aria-hidden": !showContent
-    }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
-      "data-l10n-id": "onboarding-welcome-header"
+    }, headerId && react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
+      "data-l10n-id": headerId
     }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
       className: `trailheadCardGrid${showContent ? " show" : ""}`
     }, cards.map(card => react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_templates_OnboardingMessage_OnboardingMessage__WEBPACK_IMPORTED_MODULE_1__["OnboardingCard"], _extends({
       key: card.id,
       className: "trailheadCard",
       sendUserActionTelemetry: sendUserActionTelemetry,
       onAction: this.onCardAction,
       UISurface: "TRAILHEAD"
@@ -14692,22 +14693,24 @@ var addUtmParams = __webpack_require__(2
  // Note: should match the transition time on .trailheadCards in _Trailhead.scss
 
 const TRANSITION_LENGTH = 500;
 const FLUENT_FILES = ["branding/brand.ftl", "browser/branding/brandings.ftl", "browser/branding/sync-brand.ftl", "browser/newtab/onboarding.ftl"];
 const helpers = {
   selectInterruptAndTriplets(message = {}, interruptCleared) {
     const hasInterrupt = interruptCleared === true ? false : Boolean(message.content);
     const hasTriplets = Boolean(message.bundle && message.bundle.length);
+    const tripletsHeaderId = message.tripletsHeaderId === undefined ? "onboarding-welcome-header" : message.tripletsHeaderId;
     const UTMTerm = message.utm_term || "";
     return {
       hasTriplets,
       hasInterrupt,
       interrupt: hasInterrupt ? message : null,
       triplets: hasTriplets ? message.bundle : null,
+      tripletsHeaderId,
       UTMTerm
     };
   },
 
   addFluent(document) {
     FLUENT_FILES.forEach(file => {
       const link = document.head.appendChild(document.createElement("link"));
       link.href = file;
@@ -14721,16 +14724,17 @@ class FirstRun_FirstRun extends external
     super(props);
     this.didLoadFlowParams = false;
     this.state = {
       prevMessage: undefined,
       hasInterrupt: false,
       hasTriplets: false,
       interrupt: undefined,
       triplets: undefined,
+      tripletsHeaderId: "",
       isInterruptVisible: false,
       isTripletsContainerVisible: false,
       isTripletsContentVisible: false,
       UTMTerm: "",
       flowParams: undefined
     };
     this.closeInterrupt = this.closeInterrupt.bind(this);
     this.closeTriplets = this.closeTriplets.bind(this);
@@ -14749,25 +14753,27 @@ class FirstRun_FirstRun extends external
     } = props;
 
     if (interruptCleared !== state.prevInterruptCleared || message && message.id !== state.prevMessageId) {
       const {
         hasTriplets,
         hasInterrupt,
         interrupt,
         triplets,
+        tripletsHeaderId,
         UTMTerm
       } = helpers.selectInterruptAndTriplets(message, interruptCleared);
       return {
         prevMessageId: message.id,
         prevInterruptCleared: interruptCleared,
         hasInterrupt,
         hasTriplets,
         interrupt,
         triplets,
+        tripletsHeaderId,
         isInterruptVisible: hasInterrupt,
         isTripletsContainerVisible: hasTriplets,
         isTripletsContentVisible: !(hasInterrupt || !hasTriplets),
         UTMTerm
       };
     }
 
     return null;
@@ -14839,16 +14845,17 @@ class FirstRun_FirstRun extends external
       sendUserActionTelemetry,
       fxaEndpoint,
       dispatch,
       executeAction
     } = props;
     const {
       interrupt,
       triplets,
+      tripletsHeaderId,
       isInterruptVisible,
       isTripletsContainerVisible,
       isTripletsContentVisible,
       hasTriplets,
       UTMTerm,
       flowParams
     } = this.state;
     return external_React_default.a.createElement(external_React_default.a.Fragment, null, isInterruptVisible ? external_React_default.a.createElement(Interrupt_Interrupt, {
@@ -14861,16 +14868,17 @@ class FirstRun_FirstRun extends external
       executeAction: executeAction,
       dispatch: dispatch,
       flowParams: flowParams,
       onDismiss: this.closeInterrupt,
       fxaEndpoint: fxaEndpoint
     }) : null, hasTriplets ? external_React_default.a.createElement(Triplets["Triplets"], {
       document: props.document,
       cards: triplets,
+      headerId: tripletsHeaderId,
       showCardPanel: isTripletsContainerVisible,
       showContent: isTripletsContentVisible,
       hideContainer: this.closeTriplets,
       sendUserActionTelemetry: sendUserActionTelemetry,
       UTMTerm: `${UTMTerm}-card`,
       flowParams: flowParams,
       onAction: executeAction
     }) : null);
--- a/browser/components/newtab/lib/ASRouter.jsm
+++ b/browser/components/newtab/lib/ASRouter.jsm
@@ -1976,17 +1976,16 @@ class _ASRouter {
         lastMessageId: message ? message.id : null,
         messages: message
           ? state.messages.filter(m => m.id !== message.id)
           : state.messages,
       }));
     } else {
       // On new tab, send cards if they match; othwerise send a snippet
       message = await this.handleMessageRequest({
-        provider: "onboarding",
         template: "extended_triplets",
       });
 
       // Set up the experiment for extended triplets. It's done here because we
       // only want to enroll users (for both control and holdback) if they meet
       // the targeting criteria.
       if (message) {
         await this.setupExtendedTriplets();
--- a/browser/components/newtab/test/unit/asrouter/ASRouter.test.js
+++ b/browser/components/newtab/test/unit/asrouter/ASRouter.test.js
@@ -1383,17 +1383,16 @@ describe("ASRouter", () => {
       });
       it("should handle onboarding message provider", async () => {
         const handleMessageRequestStub = sandbox.stub(
           Router,
           "handleMessageRequest"
         );
         handleMessageRequestStub
           .withArgs({
-            provider: "onboarding",
             template: "extended_triplets",
           })
           .resolves({ id: "foo" });
         const spy = sandbox.spy(Router, "setupExtendedTriplets");
         const msg = fakeAsyncMessage({
           type: "NEWTAB_MESSAGE_REQUEST",
           data: {},
         });
@@ -1404,57 +1403,53 @@ describe("ASRouter", () => {
       it("should fallback to snippets if one was assigned to the holdback experiment", async () => {
         sandbox.stub(global.Sampling, "ratioSample").resolves(1); // 1 = holdback branch
         const handleMessageRequestStub = sandbox.stub(
           Router,
           "handleMessageRequest"
         );
         handleMessageRequestStub
           .withArgs({
-            provider: "onboarding",
             template: "extended_triplets",
           })
           .resolves({ id: "foo" });
         const msg = fakeAsyncMessage({
           type: "NEWTAB_MESSAGE_REQUEST",
           data: {},
         });
         await Router.onMessage(msg);
 
         assert.calledTwice(handleMessageRequestStub);
         assert.calledWithExactly(handleMessageRequestStub, {
-          provider: "onboarding",
           template: "extended_triplets",
         });
         assert.calledWithExactly(handleMessageRequestStub, {
           provider: "snippets",
         });
       });
       it("should fallback to snippets if onboarding message provider returned none", async () => {
         const handleMessageRequestStub = sandbox.stub(
           Router,
           "handleMessageRequest"
         );
         handleMessageRequestStub
           .withArgs({
-            provider: "onboarding",
             template: "extended_triplets",
           })
           .resolves(null);
         const spy = sandbox.spy(Router, "setupExtendedTriplets");
         const msg = fakeAsyncMessage({
           type: "NEWTAB_MESSAGE_REQUEST",
           data: {},
         });
         await Router.onMessage(msg);
 
         assert.notCalled(spy);
         assert.calledTwice(handleMessageRequestStub);
         assert.calledWithExactly(handleMessageRequestStub, {
-          provider: "onboarding",
           template: "extended_triplets",
         });
         assert.calledWithExactly(handleMessageRequestStub, {
           provider: "snippets",
         });
       });
     });
 
--- a/browser/components/privatebrowsing/test/browser/browser.ini
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -24,17 +24,16 @@ support-files =
 skip-if = fission || verify
 tags = trackingprotection
 [browser_privatebrowsing_about_search_banner.js]
 [browser_privatebrowsing_aboutSessionRestore.js]
 [browser_privatebrowsing_cache.js]
 [browser_privatebrowsing_certexceptionsui.js]
 [browser_privatebrowsing_concurrent.js]
 [browser_privatebrowsing_context_and_chromeFlags.js]
-skip-if = fission
 [browser_privatebrowsing_crh.js]
 [browser_privatebrowsing_downloadLastDir.js]
 skip-if = verify
 [browser_privatebrowsing_downloadLastDir_c.js]
 [browser_privatebrowsing_downloadLastDir_toggle.js]
 [browser_privatebrowsing_favicon.js]
 [browser_privatebrowsing_geoprompt.js]
 tags = geolocation
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
@@ -49,17 +49,19 @@ function assertWindowIsPrivate(win) {
  * window.
  */
 add_task(async function test_context_and_chromeFlags() {
   let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
   await assertWindowIsPrivate(win);
 
   let browser = win.gBrowser.selectedBrowser;
 
-  let newWinPromise = BrowserTestUtils.waitForNewWindow();
+  let newWinPromise = BrowserTestUtils.waitForNewWindow({
+    url: "http://example.com/",
+  });
   await ContentTask.spawn(browser, null, async function() {
     content.open("http://example.com", "_blank", "width=100,height=100");
   });
 
   let win2 = await newWinPromise;
   await assertWindowIsPrivate(win2);
 
   await BrowserTestUtils.closeWindow(win2);
--- a/browser/components/urlbar/tests/browser/browser.ini
+++ b/browser/components/urlbar/tests/browser/browser.ini
@@ -44,17 +44,16 @@ skip-if = verify && os == 'linux' # Bug 
 [browser_doubleClickSelectsAll.js]
 [browser_downArrowKeySearch.js]
 [browser_dragdropURL.js]
 [browser_dropmarker.js]
 [browser_ime_composition.js]
 [browser_inputHistory.js]
 [browser_inputHistory_emptystring.js]
 [browser_keepStateAcrossTabSwitches.js]
-skip-if = fission
 [browser_keywordBookmarklets.js]
 [browser_keyword_override.js]
 [browser_keywordSearch.js]
 support-files =
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
 [browser_keywordSearch_postData.js]
 support-files =
@@ -64,18 +63,16 @@ support-files =
 [browser_keyword.js]
 support-files =
   print_postdata.sjs
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
 [browser_locationBarCommand.js]
 skip-if = (os == 'mac' && os_version == '10.14') # bug 1554807
 [browser_locationBarExternalLoad.js]
-[browser_moz_action_link.js]
-skip-if = fission # Timeouts
 [browser_new_tab_urlbar_reset.js]
 [browser_openViewOnFocus.js]
 [browser_pasteAndGo.js]
 tags = clipboard
 [browser_percent_encoded.js]
 [browser_populateAfterPushState.js]
 [browser_primary_selection_safe_on_new_tab.js]
 [browser_privateBrowsingWindowChange.js]
--- a/browser/components/urlbar/tests/browser/browser_keepStateAcrossTabSwitches.js
+++ b/browser/components/urlbar/tests/browser/browser_keepStateAcrossTabSwitches.js
@@ -2,48 +2,47 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /**
  * Verify user typed text remains in the URL bar when tab switching, even when
  * loads fail.
  */
-add_task(async function() {
+add_task(async function validURL() {
   let input = "i-definitely-dont-exist.example.com";
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
-    "about:blank",
-    false
+    "http://example.com/"
   );
   let browser = tab.linkedBrowser;
   // Note: Waiting on content document not being hidden because new tab pages can be preloaded,
   // in which case no load events fire.
   await ContentTask.spawn(browser, null, async () => {
     await ContentTaskUtils.waitForCondition(() => {
       return content.document && !content.document.hidden;
     });
   });
-  let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
+  let errorPageLoaded = BrowserTestUtils.waitForErrorPage(browser);
   gURLBar.value = input;
   gURLBar.select();
   EventUtils.sendKey("return");
   await errorPageLoaded;
   is(gURLBar.value, input, "Text is still in URL bar");
   await BrowserTestUtils.switchTab(gBrowser, tab.previousElementSibling);
   await BrowserTestUtils.switchTab(gBrowser, tab);
   is(gURLBar.value, input, "Text is still in URL bar after tab switch");
   BrowserTestUtils.removeTab(tab);
 });
 
 /**
  * Invalid URIs fail differently (that is, immediately, in the loadURI call)
  * if keyword searches are turned off. Test that this works, too.
  */
-add_task(async function() {
+add_task(async function invalidURL() {
   let input = "To be or not to be-that is the question";
   await SpecialPowers.pushPrefEnv({ set: [["keyword.enabled", false]] });
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
     "about:blank",
     false
   );
   let browser = tab.linkedBrowser;
deleted file mode 100644
--- a/browser/components/urlbar/tests/browser/browser_moz_action_link.js
+++ /dev/null
@@ -1,40 +0,0 @@
-"use strict";
-
-const kURIs = ["moz-action:foo,", "moz-action:foo"];
-
-add_task(async function() {
-  for (let uri of kURIs) {
-    let dataURI = `data:text/html,<a id=a href="${uri}" target=_blank rel="opener">Link</a>`;
-    let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dataURI);
-
-    let tabSwitchPromise = BrowserTestUtils.switchTab(gBrowser, function() {});
-    await ContentTask.spawn(tab.linkedBrowser, null, async function() {
-      content.document.getElementById("a").click();
-    });
-    await tabSwitchPromise;
-    isnot(gBrowser.selectedTab, tab, "Switched to new tab!");
-    is(
-      gURLBar.value,
-      "about:blank",
-      "URL bar should be displaying about:blank"
-    );
-    let newTab = gBrowser.selectedTab;
-    await BrowserTestUtils.switchTab(gBrowser, tab);
-    await BrowserTestUtils.switchTab(gBrowser, newTab);
-    is(gBrowser.selectedTab, newTab, "Switched to new tab again!");
-    is(
-      gURLBar.value,
-      "about:blank",
-      "URL bar should be displaying about:blank after tab switch"
-    );
-    // Finally, check that directly setting it produces the right results, too:
-    URLBarSetURI(makeURI(uri));
-    is(
-      gURLBar.value,
-      "about:blank",
-      "URL bar should still be displaying about:blank"
-    );
-    BrowserTestUtils.removeTab(newTab);
-    BrowserTestUtils.removeTab(tab);
-  }
-});
--- a/browser/components/urlbar/tests/browser/browser_urlbarDecode.js
+++ b/browser/components/urlbar/tests/browser/browser_urlbarDecode.js
@@ -49,18 +49,17 @@ add_task(function losslessDecode() {
 
 add_task(async function actionURILosslessDecode() {
   let urlNoScheme = "example.com/\u30a2\u30a4\u30a6\u30a8\u30aa";
   let url = "http://" + urlNoScheme;
   await promiseAutocompleteResultPopup(url);
 
   // At this point the heuristic result is selected but the urlbar's value is
   // simply `url`.  Key down and back around until the heuristic result is
-  // selected again, and at that point the urlbar's value should be a visiturl
-  // moz-action.
+  // selected again.
   do {
     EventUtils.synthesizeKey("KEY_ArrowDown");
   } while (UrlbarTestUtils.getSelectedRowIndex(window) != 0);
 
   let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
 
   Assert.equal(
     result.type,
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -863,32 +863,36 @@ sync-device-name-save =
     .accesskey = v
 
 sync-connect-another-device = Connect another device
 
 ## Privacy Section
 
 privacy-header = Browser Privacy
 
-## Privacy Section - Forms
+## Privacy Section - Logins and Passwords
 
 logins-header = Logins and Passwords
+
+# Checkbox to control whether UI is shown to users to save or fill logins/passwords.
 forms-ask-to-save-logins =
     .label = Ask to save logins and passwords for websites
     .accesskey = r
 forms-exceptions =
     .label = Exceptions…
     .accesskey = x
 forms-generate-passwords =
     .label = Suggest and generate strong passwords
     .accesskey = u
 forms-breach-alerts =
     .label = Show alerts about passwords for breached websites
     .accesskey = b
 forms-breach-alerts-learn-more-link = Learn more
+
+# Checkbox which controls filling saved logins into fields automatically when they appear, in some cases without user interaction.
 forms-fill-logins-and-passwords =
     .label = Autofill logins and passwords
     .accesskey = i
 forms-saved-logins =
     .label = Saved Logins…
     .accesskey = L
 forms-master-pw-use =
     .label = Use a master password
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/browser/protectionsPanel.ftl
@@ -0,0 +1,5 @@
+# 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/.
+
+protections-panel-sendreportview-error = There was an error sending the report. Please try again later.
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -1015,13 +1015,14 @@ storageAccess.description.learnmore = th
 
 confirmationHint.sendToDevice.label = Sent!
 confirmationHint.copyURL.label = Copied to clipboard!
 confirmationHint.pageBookmarked.label = Saved to Library!
 confirmationHint.addSearchEngine.label = Search engine added!
 confirmationHint.pinTab.label = Pinned!
 confirmationHint.pinTab.description = Right-click the tab to unpin it.
 confirmationHint.passwordSaved.label = Password saved!
+confirmationHint.breakageReport.label = Report sent. Thank you!
 
 # LOCALIZATION NOTE (livebookmarkMigration.title):
 # Used by the export of user's live bookmarks to an OPML file as a title for the file.
 # %S will be replaced with brandShortName
 livebookmarkMigration.title                      = %S Live Bookmarks
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -474,16 +474,21 @@ description#identity-popup-content-verif
 #protections-popup-sendReportView-collection-comments {
   height: 120px;
 }
 
 #protections-popup-sendReportView label {
   margin-inline-start: 0;
 }
 
+#protections-popup-sendReportView-report-error {
+  margin-bottom: 24px;
+  color: #d74345;
+}
+
 .protections-popup-category {
   /* Overwrite toolbarbutton styles */
   -moz-appearance: none;
   margin: 0;
   padding-inline-start: 0;
 }
 
 .protections-popup-category:-moz-focusring,
--- a/browser/themes/shared/urlbar-autocomplete.inc.css
+++ b/browser/themes/shared/urlbar-autocomplete.inc.css
@@ -124,19 +124,24 @@
   white-space: nowrap;
 }
 
 .urlbarView:not(.megabar) .urlbarView-results {
   padding-inline: @urlbarViewPadding@;
 }
 
 .urlbarView-row {
-  border-radius: 2px;
   fill: currentColor;
   fill-opacity: .6;
+  padding-block: 3px;
+}
+
+.urlbarView:not(.megabar) .urlbarView-row,
+.urlbarView.megabar .urlbarView-row-inner {
+  border-radius: 2px;
   padding-block: 6px;
   padding-inline-start: calc(@urlbarViewItemPaddingStart@);
 }
 
 .urlbarView:not(.megabar) .urlbarView-row {
   padding-inline-start: calc(var(--item-padding-start, calc(5px + @urlbarViewFaviconOffset@)) - @urlbarViewFaviconOffset@);
   padding-inline-end: var(--item-padding-end, 5px);
 }
@@ -161,21 +166,23 @@
   mask-image: linear-gradient(to right, transparent, black 2em);
 }
 
 .urlbarView-title[isurl]:-moz-locale-dir(rtl),
 .urlbarView-url:-moz-locale-dir(rtl) {
   direction: ltr !important;
 }
 
-.urlbarView-row:not([type=tip]):hover {
+.urlbarView:not(.megabar) .urlbarView-row:not([type=tip]):hover,
+.urlbarView.megabar .urlbarView-row:not([type=tip]):hover > .urlbarView-row-inner {
   background: var(--arrowpanel-dimmed);
 }
 
-.urlbarView-row:not([type=tip])[selected] {
+.urlbarView:not(.megabar) .urlbarView-row:not([type=tip])[selected],
+.urlbarView.megabar .urlbarView-row:not([type=tip])[selected] > .urlbarView-row-inner {
   background: var(--autocomplete-popup-highlight-background);
   color: var(--autocomplete-popup-highlight-color);
   fill-opacity: 1;
 }
 
 .urlbarView-type-icon,
 .urlbarView-favicon {
   min-width: 16px;
--- a/build/unix/mozconfig.unix
+++ b/build/unix/mozconfig.unix
@@ -8,17 +8,22 @@ if [ -n "$FORCE_GCC" ]; then
 
     # We want to make sure we use binutils and other binaries in the tooltool
     # package.
     mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$PATH"
     ac_add_options --with-clang-path=$MOZ_FETCHES_DIR/clang/bin/clang
 else
     CC="$MOZ_FETCHES_DIR/clang/bin/clang"
     CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
-    export ENABLE_CLANG_PLUGIN=1
+
+    # For some builds we don't want to have Clang based static-analysis activated
+    if [ -z "$DISABLE_CLANG_PLUGIN" ]; then
+        export ENABLE_CLANG_PLUGIN=1
+    fi
+
     case "$PERFHERDER_EXTRA_OPTIONS" in
     base-toolchains*)
       # Clang versions < 7.0 don't support the -fcrash-diagnostics-dir flag.
       ;;
     *)
       export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
       export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
       ;;
--- a/devtools/client/debugger/src/actions/navigation.js
+++ b/devtools/client/debugger/src/actions/navigation.js
@@ -73,12 +73,13 @@ export function connect(
   };
 }
 
 /**
  * @memberof actions/navigation
  * @static
  */
 export function navigated() {
-  return async function({ panel }: ThunkArgs) {
+  return async function({ dispatch, panel }: ThunkArgs) {
+    await dispatch(updateThreads());
     panel.emit("reloaded");
   };
 }
--- a/devtools/client/debugger/src/actions/threads.js
+++ b/devtools/client/debugger/src/actions/threads.js
@@ -3,18 +3,24 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import { differenceBy } from "lodash";
 import type { Action, ThunkArgs } from "./types";
 import type { ThreadType } from "../types";
 import { removeSourceActors } from "./source-actors";
+import { newGeneratedSources } from "./sources";
 
-import { getContext, getThreads, getSourceActorsForThread } from "../selectors";
+import {
+  getContext,
+  getAllThreads,
+  getThreads,
+  getSourceActorsForThread,
+} from "../selectors";
 
 export function updateThreads(type: ?ThreadType) {
   return async function({ dispatch, getState, client }: ThunkArgs) {
     const cx = getContext(getState());
     const threads = await client.fetchThreads(type);
 
     const currentThreads = getThreads(getState());
 
@@ -31,11 +37,32 @@ export function updateThreads(type: ?Thr
           type: "REMOVE_THREADS",
           cx,
           threads: removedThreads.map(t => t.actor),
         }: Action)
       );
     }
     if (addedThreads.length > 0) {
       dispatch(({ type: "INSERT_THREADS", cx, threads: addedThreads }: Action));
+
+      // Fetch the sources and install breakpoints on any new workers.
+      // NOTE: This runs in the background and fails quietly because it is
+      // pretty easy for sources to throw during the fetch if their thread
+      // shuts down, which would cause test failures.
+      for (const thread of addedThreads) {
+        client
+          .fetchThreadSources(thread.actor)
+          .then(sources => dispatch(newGeneratedSources(sources)))
+          .catch(e => console.error(e));
+      }
     }
   };
 }
+
+export function ensureHasThread(thread: string) {
+  return async function({ dispatch, getState, client }: ThunkArgs) {
+    const currentThreads = getAllThreads(getState());
+    if (!currentThreads.some(t => t.actor == thread)) {
+      await dispatch(updateThreads("worker"));
+      await dispatch(updateThreads("contentProcess"));
+    }
+  };
+}
--- a/devtools/client/debugger/src/client/firefox/commands.js
+++ b/devtools/client/debugger/src/client/firefox/commands.js
@@ -310,20 +310,22 @@ function autocomplete(
       cursor,
       result => resolve(result),
       frameId
     );
   });
 }
 
 function navigate(url: string): Promise<*> {
+  targets = { worker: {}, contentProcess: {} };
   return currentTarget.navigateTo({ url });
 }
 
 function reload(): Promise<*> {
+  targets = { worker: {}, contentProcess: {} };
   return currentTarget.reload();
 }
 
 function getProperties(thread: string, grip: Grip): Promise<*> {
   const objClient = lookupThreadFront(thread).pauseGrip(grip);
 
   return objClient.getPrototypeAndProperties().then(resp => {
     const { ownProperties, safeGetterValues } = resp;
@@ -442,16 +444,22 @@ function getAllThreadFronts() {
 async function fetchSources(): Promise<Array<GeneratedSourceData>> {
   let sources = [];
   for (const threadFront of getAllThreadFronts()) {
     sources = sources.concat(await getSources(threadFront));
   }
   return sources;
 }
 
+async function fetchThreadSources(
+  thread: string
+): Promise<Array<GeneratedSourceData>> {
+  return getSources(lookupThreadFront(thread));
+}
+
 // Check if any of the targets were paused before we opened
 // the debugger. If one is paused. Fake a `pause` RDP event
 // by directly calling the client event listener.
 async function checkIfAlreadyPaused() {
   for (const threadFront of getAllThreadFronts()) {
     const pausedPacket = threadFront.getLastPausePacket();
     if (pausedPacket) {
       clientEvents.paused(threadFront, pausedPacket);
@@ -478,36 +486,23 @@ async function fetchThreads(type: ?Threa
 
 async function updateThreads(type: ThreadType) {
   const options = {
     breakpoints,
     eventBreakpoints,
     observeAsmJS: true,
   };
 
-  const oldActors = Object.keys(targets[type]);
-
   await updateTargets(type, {
     currentTarget,
     debuggerClient,
     targets,
     options,
   });
 
-  // Fetch the sources and install breakpoints on any new workers.
-  // NOTE: This runs in the background and fails quitely because it is
-  // pretty easy for sources to throw during the fetch if their thread
-  // shuts down, which would cause test failures.
-  for (const entry of Object.entries(targets[type])) {
-    const [actor, { threadFront }] = (entry: any);
-    if (!oldActors.includes(actor)) {
-      getSources(threadFront).catch(e => console.error(e));
-    }
-  }
-
   return Object.entries(targets[type]).map(([actor, target]) =>
     createThread((actor: any), (target: any))
   );
 }
 
 function getMainThread() {
   return currentThreadFront.actor;
 }
@@ -591,16 +586,17 @@ const clientCommands = {
   evaluateExpressions,
   navigate,
   reload,
   getProperties,
   getFrameScopes,
   pauseOnExceptions,
   toggleEventLogging,
   fetchSources,
+  fetchThreadSources,
   checkIfAlreadyPaused,
   registerSourceActor,
   fetchThreads,
   getMainThread,
   sendPacket,
   setSkipPausing,
   setEventListenerBreakpoints,
   getEventListenerBreakpointTypes,
--- a/devtools/client/debugger/src/client/firefox/events.js
+++ b/devtools/client/debugger/src/client/firefox/events.js
@@ -11,16 +11,22 @@ import type {
   Actions,
   Target,
   DebuggerClient,
 } from "./types";
 
 import { createPause, prepareSourcePayload } from "./create";
 import sourceQueue from "../../utils/source-queue";
 import { recordEvent } from "../../utils/telemetry";
+import { features } from "../../utils/prefs";
+
+const {
+  WorkersListener,
+  // $FlowIgnore
+} = require("devtools/client/shared/workers-listener.js");
 
 const CALL_STACK_PAGE_SIZE = 1000;
 
 type Dependencies = {
   threadFront: ThreadFront,
   tabTarget: Target,
   actions: Actions,
   debuggerClient: DebuggerClient,
@@ -40,19 +46,31 @@ function setupEvents(dependencies: Depen
   actions = dependencies.actions;
   sourceQueue.initialize(actions);
 
   addThreadEventListeners(threadFront);
   tabTarget.on("workerListChanged", () => threadListChanged("worker"));
   debuggerClient.mainRoot.on("processListChanged", () =>
     threadListChanged("contentProcess")
   );
+
+  // If we are attaching to service workers we need to listen to worker changes
+  // everywhere in the browser.
+  if (features.windowlessServiceWorkers) {
+    const workersListener = new WorkersListener(debuggerClient.mainRoot);
+    workersListener.addListener(() => threadListChanged("worker"));
+  }
 }
 
 async function paused(threadFront: ThreadFront, packet: PausedPacket) {
+  // When reloading we might get pauses from threads before they have been
+  // added to the store. Ensure the pause won't be processed until we've
+  // finished adding the thread.
+  await actions.ensureHasThread(threadFront.actor);
+
   // If paused by an explicit interrupt, which are generated by the
   // slow script dialog and internal events such as setting
   // breakpoints, ignore the event.
   const { why } = packet;
   if (why.type === "interrupted" && !packet.why.onNext) {
     isInterrupted = true;
     return;
   }
--- a/devtools/client/debugger/src/client/firefox/targets.js
+++ b/devtools/client/debugger/src/client/firefox/targets.js
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import { addThreadEventListeners } from "./events";
-import { prefs } from "../../utils/prefs";
+import { prefs, features } from "../../utils/prefs";
+import { sameOrigin } from "../../utils/url";
 import type { DebuggerClient, Target } from "./types";
 import type { ThreadType } from "../../types";
 
 // $FlowIgnore
 const { defaultThreadOptions } = require("devtools/client/shared/thread-utils");
 
 type Args = {
   currentTarget: Target,
@@ -59,22 +60,35 @@ async function attachTargets(type, targe
     } catch (e) {
       // If any of the workers have terminated since the list command initiated
       // then we will get errors. Ignore these.
     }
   }
 }
 
 export async function updateWorkerTargets(type: ThreadType, args: Args) {
-  const { currentTarget } = args;
+  const { currentTarget, debuggerClient } = args;
   if (!currentTarget.isBrowsingContext || currentTarget.isContentProcess) {
     return;
   }
 
   const { workers } = await currentTarget.listWorkers();
+
+  if (features.windowlessServiceWorkers && currentTarget.url) {
+    const { service } = await debuggerClient.mainRoot.listAllWorkers();
+    for (const { active, id, url } of service) {
+      // Attach to any service workers that are same-origin with our target.
+      // For now, ignore service workers associated with cross-origin iframes.
+      if (active && sameOrigin(url, currentTarget.url)) {
+        const workerTarget = await debuggerClient.mainRoot.getWorker(id);
+        workers.push(workerTarget);
+      }
+    }
+  }
+
   await attachTargets(type, workers, args);
 }
 
 export async function updateProcessTargets(type: ThreadType, args: Args) {
   const { currentTarget, debuggerClient } = args;
   if (!prefs.fission || !currentTarget.chrome || currentTarget.isAddon) {
     return;
   }
--- a/devtools/client/debugger/src/client/firefox/types.js
+++ b/devtools/client/debugger/src/client/firefox/types.js
@@ -181,16 +181,17 @@ export type TabPayload = {
  * @static
  */
 export type Actions = {
   paused: Pause => void,
   resumed: ActorId => void,
   newQueuedSources: (QueuedSourceData[]) => void,
   fetchEventListeners: () => void,
   updateThreads: typeof actions.updateThreads,
+  ensureHasThread: typeof actions.ensureHasThread,
   setFramePositions: typeof actions.setFramePositions,
 };
 
 type ConsoleClient = {
   evaluateJS: (
     script: Script,
     func: Function,
     params?: { frameActor: ?FrameId }
@@ -251,16 +252,18 @@ export type DebuggerClient = {
   _activeRequests: {
     get: any => any,
     delete: any => void,
   },
   mainRoot: {
     traits: any,
     getFront: string => Promise<*>,
     listProcesses: () => Promise<{ processes: ProcessDescriptor }>,
+    listAllWorkers: () => Promise<*>,
+    getWorker: any => Promise<*>,
     on: (string, Function) => void,
   },
   connect: () => Promise<*>,
   request: (packet: Object) => Promise<*>,
   attachConsole: (actor: String, listeners: Array<*>) => Promise<*>,
   createObjectFront: (grip: Grip) => ObjectFront,
   release: (actor: String) => {},
   getFrontByID: (actor: String) => { release: () => Promise<*> },
--- a/devtools/client/debugger/src/utils/prefs.js
+++ b/devtools/client/debugger/src/utils/prefs.js
@@ -138,16 +138,17 @@ export const features = new PrefsHelper(
   xhrBreakpoints: ["Bool", "xhr-breakpoints"],
   originalBlackbox: ["Bool", "original-blackbox"],
   eventListenersBreakpoints: ["Bool", "event-listeners-breakpoints"],
   domMutationBreakpoints: ["Bool", "dom-mutation-breakpoints"],
   logPoints: ["Bool", "log-points"],
   showOverlay: ["Bool", "overlay"],
   inlinePreview: ["Bool", "inline-preview"],
   watchpoints: ["Bool", "watchpoints"],
+  windowlessServiceWorkers: ["Bool", "windowless-service-workers"],
 });
 
 export const asyncStore = asyncStoreHelper("debugger", {
   pendingBreakpoints: ["pending-breakpoints", {}],
   tabs: ["tabs", []],
   xhrBreakpoints: ["xhr-breakpoints", []],
   eventListenerBreakpoints: ["event-listener-breakpoints", undefined],
 });
--- a/devtools/client/debugger/src/utils/url.js
+++ b/devtools/client/debugger/src/utils/url.js
@@ -32,8 +32,12 @@ export const parse = memoize(function pa
     // If we're given simply a filename...
     if (url) {
       return { ...defaultUrl, path: url, pathname: url };
     }
 
     return defaultUrl;
   }
 });
+
+export function sameOrigin(firstUrl: string, secondUrl: string) {
+  return parse(firstUrl).origin == parse(secondUrl).origin;
+}
--- a/devtools/client/debugger/test/mochitest/browser.ini
+++ b/devtools/client/debugger/test/mochitest/browser.ini
@@ -154,16 +154,17 @@ skip-if = os == "win"
 [browser_dbg-tabs-without-urls.js]
 [browser_dbg-toggling-tools.js]
 [browser_dbg-react-app.js]
 skip-if = os == "win"
 [browser_dbg-wasm-sourcemaps.js]
 [browser_dbg-windowless-workers.js]
 [browser_dbg-windowless-workers-early-breakpoint.js]
 [browser_dbg-worker-exception.js]
+[browser_dbg-windowless-service-workers.js]
 [browser_dbg-worker-scopes.js]
 skip-if = (os == 'linux' && debug) || (os == 'linux' && asan) || ccov  #Bug 1456013, Bug 1559547
 [browser_dbg-event-handler.js]
 [browser_dbg-event-breakpoints.js]
 [browser_dbg-eval-throw.js]
 [browser_dbg-sourceURL-breakpoint.js]
 [browser_dbg-old-breakpoint.js]
 [browser_dbg-idb-run-to-completion.js]
--- a/devtools/client/debugger/test/mochitest/browser_dbg-bfcache.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg-bfcache.js
@@ -1,12 +1,14 @@
 /* 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/>. */
 
+PromiseTestUtils.whitelistRejectionsGlobally(/Connection closed/);
+
 // Test that sources appear in the debugger when navigating using the BFCache.
 add_task(async function() {
   const dbg = await initDebugger("doc-bfcache1.html");
   await navigate(dbg, "doc-bfcache2.html", "doc-bfcache2.html");
   invokeInTab("goBack");
   await waitForSources(dbg, "doc-bfcache1.html");
   invokeInTab("goForward");
   await waitForSources(dbg, "doc-bfcache2.html");
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers.js
@@ -0,0 +1,68 @@
+/* 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/>. */
+
+// Test that we can detect a new service worker and hit breakpoints that we've
+// set in it.
+add_task(async function() {
+  await pushPref("devtools.debugger.features.windowless-service-workers", true);
+  await pushPref("devtools.debugger.workers-visible", true);
+  await pushPref("dom.serviceWorkers.enabled", true);
+  await pushPref("dom.serviceWorkers.testing.enabled", true);
+
+  let dbg = await initDebugger("doc-service-workers.html");
+
+  invokeInTab("registerWorker");
+
+  await waitForSource(dbg, "service-worker.js");
+  const workerSource = findSource(dbg, "service-worker.js");
+
+  await addBreakpoint(dbg, "service-worker.js", 14);
+
+  invokeInTab("fetchFromWorker");
+
+  await waitForPaused(dbg);
+  assertPausedAtSourceAndLine(dbg, workerSource.id, 14);
+
+  await dbg.actions.removeAllBreakpoints(getContext(dbg));
+
+  await resume(dbg);
+
+  // Leave the worker registration in place for the next task.
+
+  // Set startup breakpoint for the next test.
+  //await addBreakpoint(dbg, "service-worker.js", 6);
+});
+
+async function checkWorkerThreads(dbg, count) {
+  await waitUntil(() => dbg.selectors.getThreads().length == count);
+  ok(true, `Have ${count} threads`);
+}
+
+// Test that service workers remain after reloading.
+add_task(async function() {
+  const toolbox = await openNewTabAndToolbox(EXAMPLE_URL + "doc-service-workers.html", "jsdebugger");
+  const dbg = createDebuggerContext(toolbox);
+
+  await checkWorkerThreads(dbg, 1);
+
+  await reload(dbg);
+
+  await waitForSource(dbg, "service-worker.js");
+  const workerSource = findSource(dbg, "service-worker.js");
+
+  await addBreakpoint(dbg, "service-worker.js", 14);
+
+  invokeInTab("fetchFromWorker");
+
+  await waitForPaused(dbg);
+  assertPausedAtSourceAndLine(dbg, workerSource.id, 14);
+  await checkWorkerThreads(dbg, 1);
+
+  await resume(dbg);
+
+  invokeInTab("unregisterWorker");
+
+  await dbg.actions.removeAllBreakpoints(getContext(dbg));
+  await checkWorkerThreads(dbg, 0);
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/examples/doc-service-workers.html
@@ -0,0 +1,32 @@
+<script>
+async function registerWorker() {
+  const sw = navigator.serviceWorker;
+  const swr = await sw.register("service-worker.js", { scope: "" });
+  dump(`Registered, scope is: ${swr.scope}\n`);
+
+  await new Promise(resolve => {
+    const worker = swr.installing || swr.waiting || swr.active;
+    if (worker.state === 'activated') {
+      return resolve();
+    }
+
+    worker.addEventListener('statechange', () => {
+      if (worker.state === 'activated') {
+        return resolve();
+      }
+    });
+  });
+}
+
+async function unregisterWorker() {
+  const sw = navigator.serviceWorker;
+  const swr = await sw.register("service-worker.js", { scope: "" });
+  return swr.unregister();
+}
+
+async function fetchFromWorker() {
+  const response = await fetch("whatever");
+  const text = await response.text();
+  console.log(`Response ${text}`);
+}
+</script>
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/test/mochitest/examples/service-worker.js
@@ -0,0 +1,20 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+dump("Starting\n");
+
+self.addEventListener("activate", event => {
+  dump("Activate\n");
+  event.waitUntil(self.clients.claim());
+});
+
+self.addEventListener("fetch", event => {
+  const url = event.request.url;
+  dump(`Fetch: ${url}\n`);
+  if (url.includes("whatever")) {
+    const response = new Response("Service worker response", { statusText: "OK" });
+    event.respondWith(response);
+  }
+});
--- a/devtools/client/preferences/debugger.js
+++ b/devtools/client/preferences/debugger.js
@@ -80,8 +80,9 @@ pref("devtools.debugger.features.autocom
 pref("devtools.debugger.features.map-expression-bindings", true);
 pref("devtools.debugger.features.xhr-breakpoints", true);
 pref("devtools.debugger.features.original-blackbox", true);
 pref("devtools.debugger.features.event-listeners-breakpoints", true);
 pref("devtools.debugger.features.dom-mutation-breakpoints", true);
 pref("devtools.debugger.features.log-points", true);
 pref("devtools.debugger.features.overlay", true);
 pref("devtools.debugger.features.inline-preview", true);
+pref("devtools.debugger.features.windowless-service-workers", false);
--- a/devtools/client/responsive/browser/tunnel.js
+++ b/devtools/client/responsive/browser/tunnel.js
@@ -133,17 +133,16 @@ function tunnelToInnerBrowser(outer, inn
       }
       if (!inner.isRemoteBrowser) {
         throw new Error("The inner browser must be remote.");
       }
 
       // Various browser methods access the `frameLoader` property, including:
       //   * `saveBrowser` from contentAreaUtils.js
       //   * `docShellIsActive` from browser.js
-      //   * `hasContentOpener` from browser.js
       //   * `preserveLayers` from browser.js
       //   * `receiveMessage` from SessionStore.jsm
       // In general, these methods are interested in the `frameLoader` for the content,
       // so we redirect them to the inner browser's `frameLoader`.
       outer[FRAME_LOADER] = outer.frameLoader;
       Object.defineProperty(outer, "frameLoader", {
         get() {
           const stack = getStack();
--- a/devtools/client/webconsole/test/browser/browser.ini
+++ b/devtools/client/webconsole/test/browser/browser.ini
@@ -387,17 +387,16 @@ skip-if = fission
 [browser_webconsole_input_focus.js]
 [browser_webconsole_insecure_passwords_about_blank_web_console_warning.js]
 [browser_webconsole_insecure_passwords_web_console_warning.js]
 [browser_webconsole_inspect_cross_domain_object.js]
 skip-if = fission
 [browser_webconsole_keyboard_accessibility.js]
 [browser_webconsole_location_debugger_link.js]
 [browser_webconsole_location_logpoint_debugger_link.js]
-skip-if = (os == 'linux' && bits == 64) || (os == 'win') # Bug 1583706
 [browser_webconsole_location_styleeditor_link.js]
 [browser_webconsole_logErrorInPage.js]
 [browser_webconsole_loglimit.js]
 [browser_webconsole_logWarningInPage.js]
 [browser_webconsole_longstring_getter.js]
 [browser_webconsole_longstring.js]
 [browser_webconsole_message_categories.js]
 skip-if = fission
--- a/devtools/server/actors/replay/control.js
+++ b/devtools/server/actors/replay/control.js
@@ -334,23 +334,25 @@ function closestChild(point) {
 
 // The singleton ReplayDebugger, or undefined if it doesn't exist.
 let gDebugger;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Asynchronous Manifests
 ////////////////////////////////////////////////////////////////////////////////
 
-// Asynchronous manifest worklists.
-const gAsyncManifests = new Set();
-const gAsyncManifestsLowPriority = new Set();
+// Priority levels for asynchronous manifests.
+const Priority = {
+  HIGH: 0,
+  MEDIUM: 1,
+  LOW: 2,
+};
 
-function asyncManifestWorklist(lowPriority) {
-  return lowPriority ? gAsyncManifestsLowPriority : gAsyncManifests;
-}
+// Asynchronous manifest worklists.
+const gAsyncManifests = [new Set(), new Set(), new Set()];
 
 // Send a manifest asynchronously, returning a promise that resolves when the
 // manifest has been finished. Async manifests have the following properties:
 //
 // shouldSkip: Callback invoked before sending the manifest. Returns true if the
 //   manifest should not be sent, and the promise resolved immediately.
 //
 // contents: Callback invoked with the executing child when it is being sent.
@@ -364,36 +366,36 @@ function asyncManifestWorklist(lowPriori
 //
 // snapshot: Optional point at which the associated child should take a snapshot
 //   while heading to the point.
 //
 // scanCheckpoint: If the manifest relies on scan data, the saved checkpoint
 //   whose range the child must have scanned. Such manifests do not have side
 //   effects in the child, and can be sent to the active child.
 //
-// lowPriority: True if this manifest should be processed only after all other
-//   manifests have been processed.
+// priority: Optional priority for this manifest. Default is HIGH.
 //
 // destination: An optional destination where the child will end up.
 //
 // expectedDuration: Optional estimate of the time needed to run the manifest.
 //
 // mightRewind: Flag that must be set if the child might restore a snapshot
 //   while processing the manifest.
 function sendAsyncManifest(manifest) {
   pokeChildrenSoon();
   return new Promise(resolve => {
     manifest.resolve = resolve;
-    asyncManifestWorklist(manifest.lowPriority).add(manifest);
+    const priority = manifest.priority || Priority.HIGH;
+    gAsyncManifests[priority].add(manifest);
   });
 }
 
 // Pick the best async manifest for a child to process.
-function pickAsyncManifest(child, lowPriority) {
-  const worklist = asyncManifestWorklist(lowPriority);
+function pickAsyncManifest(child, priority) {
+  const worklist = gAsyncManifests[priority];
 
   let best = null,
     bestTime = Infinity;
   for (const manifest of worklist) {
     // Prune any manifests that can be skipped.
     if (manifest.shouldSkip()) {
       manifest.resolve();
       worklist.delete(manifest);
@@ -442,22 +444,24 @@ function processAsyncManifest(child) {
   if (manifest && child == gActiveChild) {
     // After a child becomes the active child, it gives up on any in progress
     // async manifest it was processing.
     sendAsyncManifest(manifest);
     manifest = null;
   }
 
   if (!manifest) {
-    manifest = pickAsyncManifest(child, /* lowPriority */ false);
+    for (const priority of Object.values(Priority)) {
+      manifest = pickAsyncManifest(child, priority);
+      if (manifest) {
+        break;
+      }
+    }
     if (!manifest) {
-      manifest = pickAsyncManifest(child, /* lowPriority */ true);
-      if (!manifest) {
-        return false;
-      }
+      return false;
     }
   }
 
   child.asyncManifest = manifest;
 
   if (
     manifest.point &&
     maybeReachPoint(child, manifest.point, manifest.snapshot)
@@ -1034,17 +1038,17 @@ async function queuePauseData({
       if (!data.restoredSnapshot) {
         addPauseData(point, data, trackCached);
         child.divergedFromRecording = true;
       }
     },
     point,
     snapshot,
     expectedDuration: 250,
-    lowPriority: true,
+    priority: Priority.LOW,
     mightRewind: true,
   });
 }
 
 function addPauseData(point, data, trackCached) {
   if (data.paintData) {
     // Atomize paint data strings to ensure that we don't store redundant
     // strings for execution points with the same paint data.
@@ -1571,17 +1575,17 @@ async function evaluateLogpoint({
         if (!fast) {
           child.divergedFromRecording = true;
         }
       }
     },
     point,
     snapshot,
     expectedDuration: 250,
-    lowPriority: true,
+    priority: Priority.MEDIUM,
     mightRewind: true,
   });
 }
 
 // Asynchronously invoke a logpoint's callback with all results from hitting
 // the logpoint in the range of the recording covered by checkpoint.
 async function findLogpointHits(
   checkpoint,
--- a/dom/animation/test/chrome/test_running_on_compositor.html
+++ b/dom/animation/test/chrome/test_running_on_compositor.html
@@ -1112,64 +1112,107 @@ promise_test(async t => {
   properties.forEach(property => {
     assert_true(property.runningOnCompositor,
                 property.property + ' is running on the compositor');
   });
 }, 'Multiple transform-like properties animation runs on the compositor');
 
 promise_test(async t => {
   const div = addDiv(t);
+  const animation = div.animate({ offsetPath: ['none', 'none'] },
+                                100 * MS_PER_SEC);
+
+  await waitForAnimationReadyToRestyle(animation);
+  await waitForPaints();
+
+  assert_animation_is_running_on_compositor(animation,
+    'offset-path animation should be running on the compositor even if ' +
+    'it is always none');
+}, 'offset-path none animation runs on the compositor');
+
+promise_test(async t => {
+  const div = addDiv(t);
   const animation = div.animate({ offsetPath: ['path("M0 0l100 100")',
                                                'path("M0 0l200 200")'] },
                                 100 * MS_PER_SEC);
 
   await waitForAnimationReadyToRestyle(animation);
   await waitForPaints();
 
   assert_animation_is_running_on_compositor(animation,
     'offset-path animation should be running on the compositor');
 }, 'offset-path animation runs on the compositor');
 
-// FIXME:  Bug 1592787: We should stop sending offset-* properties to the
-// compositor and skip restyling entirely if offset-path is none and we don't
-// have any animation of it.
 promise_test(async t => {
   const div = addDiv(t);
   const animation = div.animate({ offsetDistance: ['0%', '100%'] },
                                 100 * MS_PER_SEC);
 
   await waitForAnimationReadyToRestyle(animation);
   await waitForPaints();
 
+  assert_animation_is_not_running_on_compositor(animation,
+    'offset-distance animation is not running on the compositor because ' +
+    'offset-path is none');
+
+  const newAnim = div.animate({ offsetPath: ['None', 'None'] },
+                              100 * MS_PER_SEC);
+  await waitForAnimationReadyToRestyle(newAnim);
+  await waitForPaints();
+
   assert_animation_is_running_on_compositor(animation,
     'offset-distance animation should be running on the compositor');
+  assert_animation_is_running_on_compositor(newAnim,
+    'new added offset-path animation should be running on the compositor');
 }, 'offset-distance animation runs on the compositor');
 
 promise_test(async t => {
   const div = addDiv(t);
   const animation = div.animate({ offsetRotate: ['0deg', '45deg'] },
                                 100 * MS_PER_SEC);
 
   await waitForAnimationReadyToRestyle(animation);
   await waitForPaints();
 
+  assert_animation_is_not_running_on_compositor(animation,
+    'offset-rotate animation is not running on the compositor because ' +
+    'offset-path is none');
+
+  const newAnim = div.animate({ offsetPath: ['None', 'None'] },
+                              100 * MS_PER_SEC);
+  await waitForAnimationReadyToRestyle(newAnim);
+  await waitForPaints();
+
   assert_animation_is_running_on_compositor(animation,
     'offset-rotate animation should be running on the compositor');
+  assert_animation_is_running_on_compositor(newAnim,
+    'new added offset-path animation should be running on the compositor');
 }, 'offset-rotate animation runs on the compositor');
 
 promise_test(async t => {
   const div = addDiv(t);
   const animation = div.animate({ offsetAnchor: ['0% 0%', '100% 100%'] },
                                 100 * MS_PER_SEC);
 
   await waitForAnimationReadyToRestyle(animation);
   await waitForPaints();
 
+  assert_animation_is_not_running_on_compositor(animation,
+    'offset-anchor animation is not running on the compositor because ' +
+    'offset-path is none');
+
+  const newAnim = div.animate({ offsetPath: ['None', 'None'] },
+                              100 * MS_PER_SEC);
+  await waitForAnimationReadyToRestyle(newAnim);
+  await waitForPaints();
+
   assert_animation_is_running_on_compositor(animation,
     'offset-anchor animation should be running on the compositor');
+  assert_animation_is_running_on_compositor(newAnim,
+    'new added offset-path animation should be running on the compositor');
 }, 'offset-anchor animation runs on the compositor');
 
 promise_test(async t => {
   const div = addDiv(t);
   const animation = div.animate({ translate: ['0px', '100px'],
                                   rotate: ['0deg', '45deg'],
                                   transform: ['translate(0px)',
                                               'translate(100px)'],
--- a/dom/base/BindContext.h
+++ b/dom/base/BindContext.h
@@ -4,19 +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/. */
 
 /* State that is passed down to BindToTree. */
 
 #ifndef mozilla_dom_BindContext_h__
 #define mozilla_dom_BindContext_h__
 
-#ifdef MOZ_XBL
-#  include "nsXBLBinding.h"
-#endif
 #include "mozilla/Attributes.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ShadowRoot.h"
 
 namespace mozilla {
 namespace dom {
@@ -94,29 +91,16 @@ struct MOZ_STACK_CLASS BindContext final
         mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
         mSubtreeRootChanges(true),
         mCollectingDisplayedNodeDataDuringLoad(
             ShouldCollectDisplayedNodeDataDuringLoad(mInComposedDoc, mDoc,
                                                      aParentElement)) {
     MOZ_ASSERT(mInComposedDoc, "Binding NAC in a disconnected subtree?");
   }
 
-#ifdef MOZ_XBL
-  // This is meant to be used to bind XBL anonymous content.
-  BindContext(nsXBLBinding& aBinding, Element& aParentElement)
-      : mDoc(*aParentElement.OwnerDoc()),
-        mBindingParent(aBinding.GetBoundElement()),
-        mInComposedDoc(aParentElement.IsInComposedDoc()),
-        mInUncomposedDoc(aParentElement.IsInUncomposedDoc()),
-        mSubtreeRootChanges(true),
-        mCollectingDisplayedNodeDataDuringLoad(
-            ShouldCollectDisplayedNodeDataDuringLoad(mInComposedDoc, mDoc,
-                                                     aParentElement)) {}
-#endif
-
   bool CollectingDisplayedNodeDataDuringLoad() const {
     return mCollectingDisplayedNodeDataDuringLoad;
   }
 
  private:
   static bool IsLikelyUndisplayed(const nsINode& aParent) {
     return aParent.IsAnyOfHTMLElements(nsGkAtoms::style, nsGkAtoms::script);
   }
--- a/dom/base/CharacterData.cpp
+++ b/dom/base/CharacterData.cpp
@@ -24,19 +24,16 @@
 #include "nsReadableUtils.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsDOMString.h"
 #include "nsChangeHint.h"
 #include "nsCOMArray.h"
 #include "mozilla/dom/DirectionalityUtils.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsCCUncollectableMarker.h"
 #include "mozAutoDocUpdate.h"
 #include "nsTextNode.h"
 #include "nsBidiUtils.h"
 #include "PLDHashTable.h"
 #include "mozilla/Sprintf.h"
 #include "nsWindowSizes.h"
 #include "nsWrapperCacheInlines.h"
@@ -510,20 +507,16 @@ nsresult CharacterData::BindToTree(BindC
 }
 
 void CharacterData::UnbindFromTree(bool aNullParent) {
   // Unset frame flags; if we need them again later, they'll get set again.
   UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE);
 
   HandleShadowDOMRelatedRemovalSteps(aNullParent);
 
-#ifdef MOZ_XBL
-  Document* document = GetComposedDoc();
-#endif
-
   if (aNullParent) {
     if (IsRootOfNativeAnonymousSubtree()) {
       MutationObservers::NotifyNativeAnonymousChildListChange(this, true);
     }
     if (GetParent()) {
       NS_RELEASE(mParent);
     } else {
       mParent = nullptr;
@@ -535,29 +528,16 @@ void CharacterData::UnbindFromTree(bool 
 
   if (aNullParent || !mParent->IsInShadowTree()) {
     UnsetFlags(NODE_IS_IN_SHADOW_TREE);
 
     // Begin keeping track of our subtree root.
     SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
   }
 
-#ifdef MOZ_XBL
-  if (document && !GetContainingShadow()) {
-    // Notify XBL- & nsIAnonymousContentCreator-generated
-    // anonymous content that the document is changing.
-    // Unlike XBL, bindings for web components shadow DOM
-    // do not get uninstalled.
-    if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-      nsContentUtils::AddScriptRunner(new RemoveFromBindingManagerRunnable(
-          document->BindingManager(), this, document));
-    }
-  }
-#endif
-
   nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
   if (slots) {
     slots->mBindingParent = nullptr;
     if (aNullParent || !mParent->IsInShadowTree()) {
       slots->mContainingShadow = nullptr;
     }
   }
 
--- a/dom/base/CharacterData.h
+++ b/dom/base/CharacterData.h
@@ -164,20 +164,16 @@ class CharacterData : public nsIContent 
   void SaveSubtreeState() final {}
 
 #ifdef DEBUG
   void List(FILE* out, int32_t aIndent) const override {}
 
   void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override {}
 #endif
 
-#ifdef MOZ_XBL
-  nsXBLBinding* DoGetXBLBinding() const final { return nullptr; }
-#endif
-
   bool IsNodeOfType(uint32_t aFlags) const override { return false; }
 
   bool IsLink(nsIURI** aURI) const final {
     *aURI = nullptr;
     return false;
   }
 
   nsresult Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const override {
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -3,19 +3,16 @@
 /* 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 "ChildIterator.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/HTMLSlotElement.h"
-#ifdef MOZ_XBL
-#  include "mozilla/dom/XBLChildrenElement.h"
-#endif
 #include "mozilla/dom/ShadowRoot.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsIFrame.h"
 #include "nsCSSAnonBoxes.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -43,27 +40,17 @@ nsIContent* ExplicitChildIterator::GetNe
                    ? assignedNodes[mIndexInInserted++]->AsContent()
                    : nullptr;
       if (!mChild) {
         mIndexInInserted = 0;
       }
       return mChild;
     }
 
-#ifdef MOZ_XBL
-    MOZ_ASSERT(mChild->IsActiveChildrenElement());
-    auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
-    if (mIndexInInserted < childrenElement->InsertedChildrenLength()) {
-      return childrenElement->InsertedChild(mIndexInInserted++);
-    }
-    mIndexInInserted = 0;
-    mChild = mChild->GetNextSibling();
-#else
     MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
-#endif
   } else if (mDefaultChild) {
     // If we're already in default content, check if there are more nodes there
     MOZ_ASSERT(mChild);
     MOZ_ASSERT(mChild->IsActiveChildrenElement());
 
     mDefaultChild = mDefaultChild->GetNextSibling();
     if (mDefaultChild) {
       return mDefaultChild;
@@ -89,40 +76,17 @@ nsIContent* ExplicitChildIterator::GetNe
   } else if (mChild) {  // in the middle of the child list
     mChild = mChild->GetNextSibling();
   }
 
   // Iterate until we find a non-insertion point, or an insertion point with
   // content.
   while (mChild) {
     if (mChild->IsActiveChildrenElement()) {
-#ifdef MOZ_XBL
-      // If the current child being iterated is a content insertion point
-      // then the iterator needs to return the nodes distributed into
-      // the content insertion point.
-      auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
-      if (childrenElement->HasInsertedChildren()) {
-        // Iterate through elements projected on insertion point.
-        mIndexInInserted = 1;
-        return childrenElement->InsertedChild(0);
-      }
-
-      // Insertion points inside fallback/default content
-      // are considered inactive and do not get assigned nodes.
-      mDefaultChild = mChild->GetFirstChild();
-      if (mDefaultChild) {
-        return mDefaultChild;
-      }
-
-      // If we have an insertion point with no assigned nodes and
-      // no default content, move on to the next node.
-      mChild = mChild->GetNextSibling();
-#else
       MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
-#endif
     } else {
       // mChild is not an insertion point, thus it is the next node to
       // return from this iterator.
       break;
     }
   }
 
   return mChild;
@@ -138,27 +102,16 @@ void FlattenedChildIterator::Init(bool a
   // FlattenedChildIterators with Element.
   if (mParent->IsElement()) {
     if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) {
       mParent = shadow;
       mXBLInvolved = Some(true);
       return;
     }
   }
-
-#ifdef MOZ_XBL
-  nsXBLBinding* binding =
-      mParent->OwnerDoc()->BindingManager()->GetBindingWithContent(mParent);
-
-  if (binding) {
-    MOZ_ASSERT(binding->GetAnonymousContent());
-    mParent = binding->GetAnonymousContent();
-    mXBLInvolved = Some(true);
-  }
-#endif
 }
 
 bool FlattenedChildIterator::ComputeWhetherXBLIsInvolved() const {
   MOZ_ASSERT(mXBLInvolved.isNothing());
   // We set mXBLInvolved to true if either the node we're iterating has a
   // binding with content attached to it (in which case it is handled in Init),
   // the node is generated XBL content and has an <xbl:children> child, or the
   // node is a <slot> element.
@@ -206,23 +159,17 @@ nsIContent* ExplicitChildIterator::Get()
 
   // When mParentAsSlot is set, mChild is always set to the current child. It
   // does not matter whether mChild is an assigned node or a fallback content.
   if (mParentAsSlot) {
     return mChild;
   }
 
   if (mIndexInInserted) {
-#ifdef MOZ_XBL
-    MOZ_ASSERT(mChild->IsActiveChildrenElement());
-    auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
-    return childrenElement->InsertedChild(mIndexInInserted - 1);
-#else
     MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
-#endif
   }
 
   return mDefaultChild ? mDefaultChild : mChild;
 }
 
 nsIContent* ExplicitChildIterator::GetPreviousChild() {
   // If we're already in the inserted-children array, look there first
   if (mIndexInInserted) {
@@ -235,28 +182,17 @@ nsIContent* ExplicitChildIterator::GetPr
                    : nullptr;
 
       if (!mChild) {
         mIsFirst = true;
       }
       return mChild;
     }
 
-#ifdef MOZ_XBL
-    // NB: mIndexInInserted points one past the last returned child so we need
-    // to look *two* indices back in order to return the previous child.
-    MOZ_ASSERT(mChild->IsActiveChildrenElement());
-    auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
-    if (--mIndexInInserted) {
-      return childrenElement->InsertedChild(mIndexInInserted - 1);
-    }
-    mChild = mChild->GetPreviousSibling();
-#else
     MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
-#endif
   } else if (mDefaultChild) {
     // If we're already in default content, check if there are more nodes there
     mDefaultChild = mDefaultChild->GetPreviousSibling();
     if (mDefaultChild) {
       return mDefaultChild;
     }
 
     mChild = mChild->GetPreviousSibling();
@@ -279,35 +215,17 @@ nsIContent* ExplicitChildIterator::GetPr
 
     mChild = mParent->GetLastChild();
   }
 
   // Iterate until we find a non-insertion point, or an insertion point with
   // content.
   while (mChild) {
     if (mChild->IsActiveChildrenElement()) {
-#ifdef MOZ_XBL
-      // If the current child being iterated is a content insertion point
-      // then the iterator needs to return the nodes distributed into
-      // the content insertion point.
-      auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
-      if (childrenElement->HasInsertedChildren()) {
-        mIndexInInserted = childrenElement->InsertedChildrenLength();
-        return childrenElement->InsertedChild(mIndexInInserted - 1);
-      }
-
-      mDefaultChild = mChild->GetLastChild();
-      if (mDefaultChild) {
-        return mDefaultChild;
-      }
-
-      mChild = mChild->GetPreviousSibling();
-#else
       MOZ_ASSERT_UNREACHABLE("This needs to be revisited");
-#endif
     } else {
       // mChild is not an insertion point, thus it is the next node to
       // return from this iterator.
       break;
     }
   }
 
   if (!mChild) {
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -174,19 +174,16 @@
 #include "nsICookiePermission.h"
 #include "nsICookieService.h"
 
 #include "nsBidiUtils.h"
 
 #include "nsContentCreatorFunctions.h"
 
 #include "nsIScriptContext.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsHTMLDocument.h"
 #include "nsIRequest.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 
 #include "nsCharsetSource.h"
 #include "nsIParser.h"
 #include "nsIContentSink.h"
 
@@ -1943,25 +1940,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(Document, tmp->mRefCnt.get())
   }
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
-#ifdef MOZ_XBL
-  if (tmp->mMaybeEndOutermostXBLUpdateRunner) {
-    // The cached runnable keeps a reference to the document object..
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
-        cb, "mMaybeEndOutermostXBLUpdateRunner.mObj");
-    cb.NoteXPCOMChild(ToSupports(tmp));
-  }
-#endif
-
   tmp->mExternalResourceMap.Traverse(&cb);
 
   // Traverse all Document pointer members.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSecurityInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReadyForIdle)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentL10n)
@@ -2080,19 +2068,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Do
     tmp->DisconnectChild(child);
     child->UnbindFromTree();
   }
 
   tmp->UnlinkOriginalDocumentIfStatic();
 
   tmp->mCachedRootElement = nullptr;  // Avoid a dangling pointer
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
-#ifdef MOZ_XBL
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMaybeEndOutermostXBLUpdateRunner)
-#endif
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImages);
@@ -5908,32 +5893,16 @@ void Document::TryChannelCharset(nsIChan
 static inline void AssertNoStaleServoDataIn(nsINode& aSubtreeRoot) {
 #ifdef DEBUG
   for (nsINode* node : ShadowIncludingTreeIterator(aSubtreeRoot)) {
     const Element* element = Element::FromNode(node);
     if (!element) {
       continue;
     }
     MOZ_ASSERT(!element->HasServoData());
-#  ifdef MOZ_XBL
-    if (nsXBLBinding* binding = element->GetXBLBinding()) {
-      if (nsXBLBinding* bindingWithContent = binding->GetBindingWithContent()) {
-        nsIContent* content = bindingWithContent->GetAnonymousContent();
-        // Need to do this instead of just AssertNoStaleServoDataIn(*content),
-        // because the parent of the children of the <content> element isn't the
-        // <content> element, but the bound element, and that confuses
-        // GetNextNode a lot.
-        MOZ_ASSERT(!content->AsElement()->HasServoData());
-        for (nsINode* child = content->GetFirstChild(); child;
-             child = child->GetNextSibling()) {
-          AssertNoStaleServoDataIn(*child);
-        }
-      }
-    }
-#  endif
   }
 #endif
 }
 
 already_AddRefed<PresShell> Document::CreatePresShell(
     nsPresContext* aContext, nsViewManager* aViewManager) {
   MOZ_ASSERT(!mPresShell, "We have a presshell already!");
 
@@ -6919,76 +6888,43 @@ bool Document::RemoveObserver(nsIDocumen
   if (!mInDestructor) {
     RemoveMutationObserver(aObserver);
     return mObservers.RemoveElement(aObserver);
   }
 
   return mObservers.Contains(aObserver);
 }
 
-#ifdef MOZ_XBL
-void Document::MaybeEndOutermostXBLUpdate() {
-  // Only call BindingManager()->EndOutermostUpdate() when
-  // we're not in an update and it is safe to run scripts.
-  if (mUpdateNestLevel == 0 && mInXBLUpdate) {
-    if (nsContentUtils::IsSafeToRunScript()) {
-      mInXBLUpdate = false;
-      BindingManager()->EndOutermostUpdate();
-    } else if (!mInDestructor) {
-      if (!mMaybeEndOutermostXBLUpdateRunner) {
-        mMaybeEndOutermostXBLUpdateRunner =
-            NewRunnableMethod("Document::MaybeEndOutermostXBLUpdate", this,
-                              &Document::MaybeEndOutermostXBLUpdate);
-      }
-      nsContentUtils::AddScriptRunner(mMaybeEndOutermostXBLUpdateRunner);
-    }
-  }
-}
-#endif
-
 void Document::BeginUpdate() {
   // If the document is going away, then it's probably okay to do things to it
   // in the wrong DocGroup. We're unlikely to run JS or do anything else
   // observable at this point. We reach this point when cycle collecting a
   // <link> element and the unlink code removes a style sheet.
   //
   // TODO(emilio): Style updates are gone, can this happen now?
   if (mDocGroup && !mIsGoingAway && !mInUnlinkOrDeletion &&
       !mIgnoreDocGroupMismatches) {
     mDocGroup->ValidateAccess();
   }
 
-#ifdef MOZ_XBL
-  if (mUpdateNestLevel == 0 && !mInXBLUpdate) {
-    mInXBLUpdate = true;
-    BindingManager()->BeginOutermostUpdate();
-  }
-#endif
-
   ++mUpdateNestLevel;
   nsContentUtils::AddScriptBlocker();
   NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this));
 }
 
 void Document::EndUpdate() {
   const bool reset = !mPendingMaybeEditingStateChanged;
   mPendingMaybeEditingStateChanged = true;
 
   NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this));
 
   nsContentUtils::RemoveScriptBlocker();
 
   --mUpdateNestLevel;
 
-#ifdef MOZ_XBL
-  // This set of updates may have created XBL bindings.  Let the
-  // binding manager know we're done.
-  MaybeEndOutermostXBLUpdate();
-#endif
-
   MaybeInitializeFinalizeFrameLoaders();
   if (mXULBroadcastManager) {
     mXULBroadcastManager->MaybeBroadcast();
   }
 
   if (reset) {
     mPendingMaybeEditingStateChanged = false;
   }
@@ -7869,88 +7805,29 @@ already_AddRefed<nsINode> Document::Impo
 Element* Document::GetBindingParent(nsINode& aNode) {
   nsCOMPtr<nsIContent> content(do_QueryInterface(&aNode));
   if (!content) return nullptr;
 
   nsIContent* bindingParent = content->GetBindingParent();
   return bindingParent ? bindingParent->AsElement() : nullptr;
 }
 
-#ifdef MOZ_XBL
-static Element* GetElementByAttribute(Element* aElement, nsAtom* aAttrName,
-                                      const nsAString& aAttrValue,
-                                      bool aUniversalMatch) {
-  if (aUniversalMatch ? aElement->HasAttr(kNameSpaceID_None, aAttrName)
-                      : aElement->AttrValueIs(kNameSpaceID_None, aAttrName,
-                                              aAttrValue, eCaseMatters)) {
-    return aElement;
-  }
-
-  for (nsIContent* child = aElement->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    if (!child->IsElement()) {
-      continue;
-    }
-
-    Element* matchedElement = GetElementByAttribute(
-        child->AsElement(), aAttrName, aAttrValue, aUniversalMatch);
-    if (matchedElement) return matchedElement;
-  }
-
-  return nullptr;
-}
-#endif
-
 Element* Document::GetAnonymousElementByAttribute(
     nsIContent* aElement, nsAtom* aAttrName,
     const nsAString& aAttrValue) const {
-#ifdef MOZ_XBL
-  nsINodeList* nodeList = BindingManager()->GetAnonymousNodesFor(aElement);
-  if (!nodeList) return nullptr;
-
-  uint32_t length = nodeList->Length();
-
-  bool universalMatch = aAttrValue.EqualsLiteral("*");
-
-  for (uint32_t i = 0; i < length; ++i) {
-    Element* current = Element::FromNode(nodeList->Item(i));
-    if (!current) {
-      continue;
-    }
-
-    Element* matchedElm =
-        GetElementByAttribute(current, aAttrName, aAttrValue, universalMatch);
-    if (matchedElm) return matchedElm;
-  }
-
   return nullptr;
-#else
-  return nullptr;
-#endif
 }
 
 Element* Document::GetAnonymousElementByAttribute(Element& aElement,
                                                   const nsAString& aAttrName,
                                                   const nsAString& aAttrValue) {
-#ifdef MOZ_XBL
-  RefPtr<nsAtom> attribute = NS_Atomize(aAttrName);
-
-  return GetAnonymousElementByAttribute(&aElement, attribute, aAttrValue);
-#else
   return nullptr;
-#endif
-}
-
-nsINodeList* Document::GetAnonymousNodes(Element& aElement) {
-#ifdef MOZ_XBL
-  return BindingManager()->GetAnonymousNodesFor(&aElement);
-#else
-  return nullptr;
-#endif
-}
+}
+
+nsINodeList* Document::GetAnonymousNodes(Element& aElement) { return nullptr; }
 
 already_AddRefed<nsRange> Document::CreateRange(ErrorResult& rv) {
   RefPtr<nsRange> range = new nsRange(this);
   nsresult res = range->CollapseTo(this, 0);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
@@ -9297,26 +9174,16 @@ nsINode* Document::AdoptNode(nsINode& aA
       } while ((doc = doc->GetInProcessParentDocument()));
 
       // Remove from parent.
       nsCOMPtr<nsINode> parent = adoptedNode->GetParentNode();
       if (parent) {
         parent->RemoveChildNode(adoptedNode->AsContent(), true);
       } else {
         MOZ_ASSERT(!adoptedNode->IsInUncomposedDoc());
-
-#ifdef MOZ_XBL
-        // If we're adopting a node that's not in a document, it might still
-        // have a binding applied. Remove the binding from the element now
-        // that it's getting adopted into a new document.
-        // TODO Fully tear down the binding.
-        if (Element* element = Element::FromNode(adoptedNode)) {
-          element->SetXBLBinding(nullptr);
-        }
-#endif
       }
 
       break;
     }
     case DOCUMENT_NODE: {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return nullptr;
     }
@@ -14193,25 +14060,16 @@ void Document::AddSizeOfNodeTree(nsINode
     for (nsIContent* anonKid : anonKids) {
       AddSizeOfNodeTree(*anonKid, aWindowSizes);
     }
 
     if (auto* element = Element::FromNode(aNode)) {
       if (ShadowRoot* shadow = element->GetShadowRoot()) {
         AddSizeOfNodeTree(*shadow, aWindowSizes);
       }
-
-#ifdef MOZ_XBL
-      for (nsXBLBinding* binding = element->GetXBLBinding(); binding;
-           binding = binding->GetBaseBinding()) {
-        if (nsIContent* anonContent = binding->GetAnonymousContent()) {
-          AddSizeOfNodeTree(*anonContent, aWindowSizes);
-        }
-      }
-#endif
     }
   }
 
   // NOTE(emilio): If you feel smart and want to change this function to use
   // GetNextNode(), think twice, since you'd need to handle <xbl:content> in a
   // sane way, and kids of <content> won't point to the parent, so we'd never
   // find the root node where we should stop at.
   for (nsIContent* kid = aNode.GetFirstChild(); kid;
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -80,19 +80,16 @@ namespace mozilla {
 namespace dom {
 class ElementCreationOptionsOrString;
 }  // namespace dom
 }  // namespace mozilla
 #endif  // MOZILLA_INTERNAL_API
 
 class gfxUserFontSet;
 class imgIRequest;
-#ifdef MOZ_XBL
-class nsBindingManager;
-#endif
 class nsCachableElementsByNameNodeList;
 class nsCommandManager;
 class nsContentList;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
 class nsGlobalWindowInner;
@@ -1808,20 +1805,16 @@ class Document : public nsINode,
   nsresult InitFeaturePolicy(nsIChannel* aChannel);
 
   nsresult InitReferrerInfo(nsIChannel* aChannel);
 
   void PostUnblockOnloadEvent();
 
   void DoUnblockOnload();
 
-#ifdef MOZ_XBL
-  void MaybeEndOutermostXBLUpdate();
-#endif
-
   void RetrieveRelevantHeaders(nsIChannel* aChannel);
 
   void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
                          NotNull<const Encoding*>& aEncoding,
                          nsHtml5TreeOpExecutor* aExecutor);
 
   void DispatchContentLoadedEvents();
 
@@ -2389,22 +2382,16 @@ class Document : public nsINode,
   // Triggers an update of <svg:use> element shadow trees.
   void UpdateSVGUseElementShadowTrees() {
     if (mSVGUseElementsNeedingShadowTreeUpdate.IsEmpty()) {
       return;
     }
     DoUpdateSVGUseElementShadowTrees();
   }
 
-#ifdef MOZ_XBL
-  nsBindingManager* BindingManager() const {
-    return mNodeInfoManager->GetBindingManager();
-  }
-#endif
-
   /**
    * Only to be used inside Gecko, you can't really do anything with the
    * pointer outside Gecko anyway.
    */
   nsNodeInfoManager* NodeInfoManager() const { return mNodeInfoManager; }
 
   /**
    * Reset the document using the given channel and loadgroup.  This works
@@ -5289,19 +5276,16 @@ class Document : public nsINode,
 
   CSSCoord mMinWidth;
   CSSCoord mMaxWidth;
   CSSCoord mMinHeight;
   CSSCoord mMaxHeight;
 
   RefPtr<EventListenerManager> mListenerManager;
 
-#ifdef MOZ_XBL
-  nsCOMPtr<nsIRunnable> mMaybeEndOutermostXBLUpdateRunner;
-#endif
   nsCOMPtr<nsIRequest> mOnloadBlocker;
 
   nsTArray<RefPtr<StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
 
   // Member to store out last-selected stylesheet set.
   nsString mLastStyleSheetSet;
   nsString mPreferredStyleSheetSet;
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -11,16 +11,17 @@
  */
 
 #include "mozilla/dom/ElementInlines.h"
 
 #include "AnimationCommon.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/StaticPrefs_layout.h"
+#include "mozilla/StaticPrefs_full_screen_api.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/Flex.h"
 #include "mozilla/dom/Grid.h"
 #include "mozilla/dom/Link.h"
 #include "mozilla/dom/MutationObservers.h"
 #include "mozilla/dom/ScriptLoader.h"
@@ -89,22 +90,16 @@
 #  include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "SVGElement.h"
 #include "nsFrameSelection.h"
 #ifdef DEBUG
 #  include "nsRange.h"
 #endif
 
-#ifdef MOZ_XBL
-#  include "nsXBLPrototypeBinding.h"
-#  include "nsBindingManager.h"
-#  include "nsXBLBinding.h"
-#  include "nsXBLService.h"
-#endif
 #include "nsPIDOMWindow.h"
 #include "mozilla/dom/DOMRect.h"
 #include "nsSVGUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "ChildIterator.h"
 
 #include "nsIDOMEventListener.h"
@@ -262,23 +257,17 @@ Element::QueryInterface(REFNSIID aIID, v
   }
 
   NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
   nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr);
   if (NS_SUCCEEDED(rv)) {
     return NS_OK;
   }
 
-#if MOZ_XBL
-  // Give the binding manager a chance to get an interface for this element.
-  return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
-                                                                aInstancePtr);
-#else
   return NS_NOINTERFACE;
-#endif
 }
 
 EventStates Element::IntrinsicState() const {
   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE
                       : NS_EVENT_STATE_MOZ_READONLY;
 }
 
 void Element::NotifyStateChange(EventStates aStates) {
@@ -377,58 +366,16 @@ void Element::Focus(const FocusOptions& 
 
 void Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError) {
   nsAutoString value;
   value.AppendInt(aTabIndex);
 
   SetAttr(nsGkAtoms::tabindex, value, aError);
 }
 
-#ifdef MOZ_XBL
-void Element::SetXBLBinding(nsXBLBinding* aBinding,
-                            nsBindingManager* aOldBindingManager) {
-  nsBindingManager* bindingManager;
-  if (aOldBindingManager) {
-    MOZ_ASSERT(!aBinding,
-               "aOldBindingManager should only be provided "
-               "when removing a binding.");
-    bindingManager = aOldBindingManager;
-  } else {
-    bindingManager = OwnerDoc()->BindingManager();
-  }
-
-  // After this point, aBinding will be the most-derived binding for aContent.
-  // If we already have a binding for aContent, make sure to
-  // remove it from the attached stack.  Otherwise we might end up firing its
-  // constructor twice (if aBinding inherits from it) or firing its constructor
-  // after aContent has been deleted (if aBinding is null and the content node
-  // dies before we process mAttachedStack).
-  RefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
-  if (oldBinding) {
-    bindingManager->RemoveFromAttachedQueue(oldBinding);
-  }
-
-  if (aBinding) {
-    SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
-    nsExtendedDOMSlots* slots = ExtendedDOMSlots();
-    slots->mXBLBinding = aBinding;
-    bindingManager->AddBoundContent(this);
-  } else {
-    nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
-    if (slots) {
-      slots->mXBLBinding = nullptr;
-    }
-    bindingManager->RemoveBoundContent(this);
-    if (oldBinding) {
-      oldBinding->SetBoundElement(nullptr);
-    }
-  }
-}
-#endif
-
 void Element::SetShadowRoot(ShadowRoot* aShadowRoot) {
   nsExtendedDOMSlots* slots = ExtendedDOMSlots();
   slots->mShadowRoot = aShadowRoot;
 }
 
 void Element::Blur(mozilla::ErrorResult& aError) {
   if (!ShouldBlur(this)) {
     return;
@@ -1060,21 +1007,17 @@ already_AddRefed<ShadowRoot> Element::At
     aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return nullptr;
   }
 
   /**
    * 3. If context object is a shadow host, then throw
    *    an "InvalidStateError" DOMException.
    */
-  if (GetShadowRoot()
-#ifdef MOZ_XBL
-      || GetXBLBinding()
-#endif
-  ) {
+  if (GetShadowRoot()) {
     aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   if (StaticPrefs::dom_webcomponents_shadowdom_report_usage()) {
     OwnerDoc()->ReportShadowDOMUsage();
   }
 
@@ -1591,29 +1534,16 @@ nsresult Element::BindToTree(BindContext
   //  because it has to happen after updating the parent pointer, but before
   //  recursively binding the kids.
   if (IsHTMLElement()) {
     SetDirOnBind(this, nsIContent::FromNode(aParent));
   }
 
   UpdateEditableState(false);
 
-#ifdef MOZ_XBL
-  // If we had a pre-existing XBL binding, we might have anonymous children that
-  // also need to be told that they are moving.
-  if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    nsXBLBinding* binding =
-        aContext.OwnerDoc().BindingManager()->GetBindingWithContent(this);
-
-    if (binding) {
-      binding->BindAnonymousContent(binding->GetAnonymousContent(), this);
-    }
-  }
-#endif
-
   // Call BindToTree on shadow root children.
   nsresult rv;
   if (ShadowRoot* shadowRoot = GetShadowRoot()) {
     rv = shadowRoot->Bind();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Now recurse into our kids. Ensure this happens after binding the shadow
@@ -1684,44 +1614,16 @@ nsresult Element::BindToTree(BindContext
              "Bound to wrong binding parent");
   MOZ_ASSERT(aParent.IsInUncomposedDoc() == IsInUncomposedDoc());
   MOZ_ASSERT(aParent.IsInComposedDoc() == IsInComposedDoc());
   MOZ_ASSERT(aParent.IsInShadowTree() == IsInShadowTree());
   MOZ_ASSERT(aParent.SubtreeRoot() == SubtreeRoot());
   return NS_OK;
 }
 
-#ifdef MOZ_XBL
-RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(
-    nsBindingManager* aManager, nsIContent* aContent, Document* aDoc)
-    : mozilla::Runnable("dom::RemoveFromBindingManagerRunnable"),
-      mManager(aManager),
-      mContent(aContent),
-      mDoc(aDoc) {}
-
-RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
-
-NS_IMETHODIMP
-RemoveFromBindingManagerRunnable::Run() {
-  // It may be the case that the element was removed from the
-  // DOM, causing this runnable to be created, then inserted back
-  // into the document before the this runnable had a chance to
-  // tear down the binding. Only tear down the binding if the element
-  // is still no longer in the DOM. nsXBLService::LoadBinding tears
-  // down the old binding if the element is inserted back into the
-  // DOM and loads a different binding.
-  if (!mContent->IsInComposedDoc()) {
-    mManager->RemovedFromDocumentInternal(mContent, mDoc,
-                                          nsBindingManager::eRunDtor);
-  }
-
-  return NS_OK;
-}
-#endif
-
 bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) {
   // If our parent still is in a shadow tree by now, and we're not removing
   // ourselves from it, then we're still going to be in a shadow tree after
   // this.
   return aElement.IsInShadowTree() &&
          (aNullParent || !aElement.GetParent()->IsInShadowTree());
 }
 
@@ -1859,32 +1761,16 @@ void Element::UnbindFromTree(bool aNullP
       slots->mBindingParent = nullptr;
     }
     if (aNullParent || !mParent->IsInShadowTree()) {
       slots->mContainingShadow = nullptr;
     }
   }
 
   if (document) {
-#ifdef MOZ_XBL
-    if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-      // Notify XBL- & nsIAnonymousContentCreator-generated anonymous content
-      // that the document is changing.
-      nsContentUtils::AddScriptRunner(new RemoveFromBindingManagerRunnable(
-          document->BindingManager(), this, document));
-      nsXBLBinding* binding =
-          document->BindingManager()->GetBindingWithContent(this);
-      if (binding) {
-        nsXBLBinding::UnbindAnonymousContent(document,
-                                             binding->GetAnonymousContent(),
-                                             /* aNullParent */ false);
-      }
-    }
-#endif
-
     // Disconnected must be enqueued whenever a connected custom element becomes
     // disconnected.
     CustomElementData* data = GetCustomElementData();
     if (data) {
       if (data->mState == CustomElementData::State::eCustom) {
         nsContentUtils::EnqueueLifecycleCallback(Document::eDisconnected, this);
       } else {
         // Remove an unresolved custom element that is a candidate for upgrade
@@ -2403,25 +2289,16 @@ nsresult Element::SetAttrAndNotify(
       oldValue = nullptr;
     }
   } else {
     // No need to conditionally assign null here. If there was no previously
     // set value for the attribute, aOldValue will already be null.
     oldValue = aOldValue;
   }
 
-#ifdef MOZ_XBL
-  if (aComposedDocument) {
-    RefPtr<nsXBLBinding> binding = GetXBLBinding();
-    if (binding) {
-      binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
-    }
-  }
-#endif
-
   if (HasElementCreatedFromPrototypeAndHasUnmodifiedL10n() &&
       aNamespaceID == kNameSpaceID_None &&
       (aName == nsGkAtoms::datal10nid || aName == nsGkAtoms::datal10nargs)) {
     ClearElementCreatedFromPrototypeAndHasUnmodifiedL10n();
     if (aComposedDocument) {
       aComposedDocument->mL10nProtoElements.Remove(this);
     }
   }
@@ -2512,16 +2389,22 @@ bool Element::ParseAttribute(int32_t aNa
   }
 
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::_class || aAttribute == nsGkAtoms::part) {
       aResult.ParseAtomArray(aValue);
       return true;
     }
 
+    if (aAttribute == nsGkAtoms::exportparts &&
+        StaticPrefs::layout_css_shadow_parts_enabled()) {
+      aResult.ParsePartMapping(aValue);
+      return true;
+    }
+
     if (aAttribute == nsGkAtoms::id) {
       // Store id as an atom.  id="" means that the element has no id,
       // not that it has an emptystring as the id.
       if (aValue.IsEmpty()) {
         return false;
       }
       aResult.ParseAtom(aValue);
       return true;
@@ -2715,25 +2598,16 @@ nsresult Element::UnsetAttr(int32_t aNam
   }
 
   nsAttrValue oldValue;
   rv = mAttrs.RemoveAttrAt(index, oldValue);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PostIdMaybeChange(aNameSpaceID, aName, nullptr);
 
-#ifdef MOZ_XBL
-  if (document) {
-    RefPtr<nsXBLBinding> binding = GetXBLBinding();
-    if (binding) {
-      binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
-    }
-  }
-#endif
-
   CustomElementDefinition* definition = GetCustomElementDefinition();
   // Only custom element which is in `custom` state could get the
   // CustomElementDefinition.
   if (definition && definition->IsInObservedAttributeList(aName)) {
     nsAutoString ns;
     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
 
     RefPtr<nsAtom> oldValueAtom = oldValue.GetAsAtom();
@@ -2843,63 +2717,16 @@ void Element::List(FILE* out, int32_t aI
     for (; child; child = child->GetNextSibling()) {
       child->List(out, aIndent + 1);
     }
 
     for (indent = aIndent; --indent >= 0;) fputs("  ", out);
   }
 
   fputs(">\n", out);
-
-#  ifdef MOZ_XBL
-  Element* nonConstThis = const_cast<Element*>(this);
-
-  // XXX sXBL/XBL2 issue! Owner or current document?
-  Document* document = OwnerDoc();
-
-  // Note: not listing nsIAnonymousContentCreator-created content...
-
-  nsBindingManager* bindingManager = document->BindingManager();
-  nsINodeList* anonymousChildren =
-      bindingManager->GetAnonymousNodesFor(nonConstThis);
-
-  if (anonymousChildren) {
-    uint32_t length = anonymousChildren->Length();
-
-    for (indent = aIndent; --indent >= 0;) fputs("  ", out);
-    fputs("anonymous-children<\n", out);
-
-    for (uint32_t i = 0; i < length; ++i) {
-      nsIContent* child = anonymousChildren->Item(i);
-      child->List(out, aIndent + 1);
-    }
-
-    for (indent = aIndent; --indent >= 0;) fputs("  ", out);
-    fputs(">\n", out);
-
-    bool outHeader = false;
-    ExplicitChildIterator iter(nonConstThis);
-    for (nsIContent* child = iter.GetNextChild(); child;
-         child = iter.GetNextChild()) {
-      if (!outHeader) {
-        outHeader = true;
-
-        for (indent = aIndent; --indent >= 0;) fputs("  ", out);
-        fputs("content-list<\n", out);
-      }
-
-      child->List(out, aIndent + 1);
-    }
-
-    if (outHeader) {
-      for (indent = aIndent; --indent >= 0;) fputs("  ", out);
-      fputs(">\n", out);
-    }
-  }
-#  endif
 }
 
 void Element::DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const {
   int32_t indent;
   for (indent = aIndent; --indent >= 0;) fputs("  ", out);
 
   const nsString& buf = mNodeInfo->QualifiedName();
   fputs("<", out);
@@ -3909,23 +3736,16 @@ template <class T>
 void Element::GetCustomInterface(nsGetterAddRefs<T> aResult) {
   nsCOMPtr<nsISupports> iface = CustomElementRegistry::CallGetCustomInterface(
       this, NS_GET_TEMPLATE_IID(T));
   if (iface) {
     if (NS_SUCCEEDED(CallQueryInterface(iface, static_cast<T**>(aResult)))) {
       return;
     }
   }
-
-#ifdef MOZ_XBL
-  // Otherwise, check the binding manager to see if it implements the interface
-  // for this element.
-  OwnerDoc()->BindingManager()->GetBindingImplementation(
-      this, NS_GET_TEMPLATE_IID(T), aResult);
-#endif
 }
 
 void Element::ClearServoData(Document* aDoc) {
   MOZ_ASSERT(aDoc);
   if (HasServoData()) {
     Servo_Element_ClearData(this);
   } else {
     UnsetFlags(kAllServoDescendantBits | NODE_NEEDS_FRAME);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -219,34 +219,16 @@ class Element : public FragmentOrElement
    */
   int32_t TabIndex();
 
   /**
    * Set tabIndex value to this element.
    */
   void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
 
-#ifdef MOZ_XBL
-  /**
-   * Sets or unsets an XBL binding for this element. Setting a
-   * binding on an element that already has a binding will remove the
-   * old binding.
-   *
-   * @param aBinding The binding to bind to this content. If nullptr is
-   *        provided as the argument, then existing binding will be
-   *        removed.
-   *
-   * @param aOldBindingManager The old binding manager that contains
-   *                           this content if this content was adopted
-   *                           to another document.
-   */
-  void SetXBLBinding(nsXBLBinding* aBinding,
-                     nsBindingManager* aOldBindingManager = nullptr);
-#endif
-
   /**
    * Sets the ShadowRoot binding for this element. The contents of the
    * binding is rendered in place of this node's children.
    *
    * @param aShadowRoot The ShadowRoot to be bound to this element.
    */
   void SetShadowRoot(ShadowRoot* aShadowRoot);
 
@@ -1970,32 +1952,16 @@ class Element : public FragmentOrElement
   // descendants of display: none elements.
   mozilla::RustCell<ServoNodeData*> mServoData;
 
  protected:
   // Array containing all attributes for this element
   AttrArray mAttrs;
 };
 
-#ifdef MOZ_XBL
-class RemoveFromBindingManagerRunnable : public mozilla::Runnable {
- public:
-  RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
-                                   nsIContent* aContent, Document* aDoc);
-
-  NS_IMETHOD Run() override;
-
- private:
-  virtual ~RemoveFromBindingManagerRunnable();
-  RefPtr<nsBindingManager> mManager;
-  RefPtr<nsIContent> mContent;
-  RefPtr<Document> mDoc;
-};
-#endif
-
 NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
 
 inline bool Element::HasAttr(int32_t aNameSpaceID, const nsAtom* aName) const {
   NS_ASSERTION(nullptr != aName, "must have attribute name");
   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
                "must have a real namespace ID!");
 
   return mAttrs.IndexOfAttr(aName, aNameSpaceID) >= 0;
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -64,21 +64,16 @@
 #  include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "nsFrameSelection.h"
 #ifdef DEBUG
 #  include "nsRange.h"
 #endif
 
 #include "nsFrameLoader.h"
-#ifdef MOZ_XBL
-#  include "nsXBLPrototypeBinding.h"
-#  include "nsBindingManager.h"
-#  include "nsXBLBinding.h"
-#endif
 #include "nsPIDOMWindow.h"
 #include "nsSVGUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsTextFragment.h"
 #include "nsContentCID.h"
 #include "nsWindowSizes.h"
@@ -679,22 +674,16 @@ void FragmentOrElement::nsExtendedDOMSlo
   aCb.NoteXPCOMChild(mControllers);
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mLabelsList");
   aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsINodeList*, mLabelsList));
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mShadowRoot");
   aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
 
-#ifdef MOZ_XBL
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mXBLBinding");
-  aCb.NoteNativeChild(mXBLBinding,
-                      NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
-#endif
-
   if (mCustomElementData) {
     mCustomElementData->Traverse(aCb);
   }
 }
 
 size_t FragmentOrElement::nsExtendedDOMSlots::SizeOfExcludingThis(
     MallocSizeOf aMallocSizeOf) const {
   size_t n =
@@ -718,24 +707,16 @@ size_t FragmentOrElement::nsExtendedDOMS
 
   if (mLabelsList) {
     n += mLabelsList->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   // mShadowRoot should be handled during normal DOM tree memory reporting, just
   // like kids, siblings, etc.
 
-#ifdef MOZ_XBL
-  // We don't seem to have memory reporting for nsXBLBinding.  At least
-  // report the memory it's using directly.
-  if (mXBLBinding) {
-    n += aMallocSizeOf(mXBLBinding);
-  }
-#endif
-
   if (mCustomElementData) {
     n += mCustomElementData->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   return n;
 }
 
 FragmentOrElement::FragmentOrElement(
@@ -1086,24 +1067,16 @@ bool nsIContent::IsFocusableInternal(int
   return false;
 }
 
 bool FragmentOrElement::IsLink(nsIURI** aURI) const {
   *aURI = nullptr;
   return false;
 }
 
-#ifdef MOZ_XBL
-nsXBLBinding* FragmentOrElement::DoGetXBLBinding() const {
-  MOZ_ASSERT(HasFlag(NODE_MAY_BE_IN_BINDING_MNGR));
-  const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
-  return slots ? slots->mXBLBinding.get() : nullptr;
-}
-#endif
-
 nsIContent* nsIContent::GetContainingShadowHost() const {
   if (mozilla::dom::ShadowRoot* shadow = GetContainingShadow()) {
     return shadow->GetHost();
   }
   return nullptr;
 }
 
 void nsIContent::SetAssignedSlot(HTMLSlotElement* aSlot) {
@@ -1164,22 +1137,16 @@ void FragmentOrElement::DestroyContent()
   // around the flattened tree.
   //
   // TODO(emilio): I suspect this can be asserted against instead, with a bit of
   // effort to avoid calling Document::Destroy with a shell...
   if (IsElement()) {
     AsElement()->ClearServoData();
   }
 
-#ifdef MOZ_XBL
-  Document* document = OwnerDoc();
-  document->BindingManager()->RemovedFromDocument(this, document,
-                                                  nsBindingManager::eRunDtor);
-#endif
-
 #ifdef DEBUG
   uint32_t oldChildCount = GetChildCount();
 #endif
 
   for (nsIContent* child = GetFirstChild(); child;
        child = child->GetNextSibling()) {
     child->DestroyContent();
     MOZ_ASSERT(child->GetParent() == this,
@@ -1375,22 +1342,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Fr
     unbind the child nodes.
   } */
 
   if (ShadowRoot* shadowRoot = tmp->GetShadowRoot()) {
     shadowRoot->Unbind();
     tmp->ExtendedDOMSlots()->mShadowRoot = nullptr;
   }
 
-#ifdef MOZ_XBL
-  Document* doc = tmp->OwnerDoc();
-  doc->BindingManager()->RemovedFromDocument(tmp, doc,
-                                             nsBindingManager::eDoNotRunDtor);
-#endif
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FragmentOrElement)
 
 void FragmentOrElement::MarkNodeChildren(nsINode* aNode) {
   JSObject* o = GetJSObjectChild(aNode);
   if (o) {
     JS::ExposeObjectToActiveJS(o);
@@ -1605,42 +1566,32 @@ static bool ShouldClearPurple(nsIContent
 // with a frame in a document which has currently active presshell,
 // we can act as if it was optimizable. When the primary frame dies, aNode
 // will end up to the purple buffer because of the refcount change.
 bool NodeHasActiveFrame(Document* aCurrentDoc, nsINode* aNode) {
   return aCurrentDoc->GetPresShell() && aNode->IsElement() &&
          aNode->AsElement()->GetPrimaryFrame();
 }
 
-#ifdef MOZ_XBL
-bool OwnedByBindingManager(Document* aCurrentDoc, nsINode* aNode) {
-  return aNode->IsElement() && aNode->AsElement()->GetXBLBinding();
-}
-#endif
-
 // CanSkip checks if aNode is known-live, and if it is, returns true. If aNode
 // is in a known-live DOM tree, CanSkip may also remove other objects from
 // purple buffer and unmark event listeners and user data.  If the root of the
 // DOM tree is a document, less optimizations are done since checking the
 // liveness of the current document is usually fast and we don't want slow down
 // such common cases.
 bool FragmentOrElement::CanSkip(nsINode* aNode, bool aRemovingAllowed) {
   // Don't try to optimize anything during shutdown.
   if (nsCCUncollectableMarker::sGeneration == 0) {
     return false;
   }
 
   bool unoptimizable = aNode->UnoptimizableCCNode();
   Document* currentDoc = aNode->GetComposedDoc();
   if (currentDoc && IsCertainlyAliveNode(aNode, currentDoc) &&
-      (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode)
-#ifdef MOZ_XBL
-       || OwnedByBindingManager(currentDoc, aNode)
-#endif
-           )) {
+      (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode))) {
     MarkNodeChildren(aNode);
     return true;
   }
 
   if (unoptimizable) {
     return false;
   }
 
@@ -1833,20 +1784,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(FragmentOrElement, tmp->mRefCnt.get())
   }
 
   if (!nsIContent::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
-#ifdef MOZ_XBL
-  tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
-#endif
-
   // Check that whenever we have effect properties, MayHaveAnimations is set.
 #ifdef DEBUG
   nsAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms();
   for (uint32_t i = 0; effectProps[i]; ++i) {
     MOZ_ASSERT_IF(tmp->GetProperty(effectProps[i]), tmp->MayHaveAnimations());
   }
 #endif
 
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -15,19 +15,16 @@
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCycleCollectionParticipant.h"  // NS_DECL_CYCLE_*
 #include "nsIContent.h"                    // base class
 #include "nsIHTMLCollection.h"
 #include "nsDataHashtable.h"
-#ifdef MOZ_XBL
-#  include "nsXBLBinding.h"
-#endif
 
 class ContentUnbinder;
 class nsContentList;
 class nsLabelsNodeList;
 class nsDOMAttributeMap;
 class nsDOMTokenList;
 class nsIControllers;
 class nsICSSDeclaration;
@@ -96,19 +93,16 @@ class FragmentOrElement : public nsICont
                                       mozilla::ErrorResult& aError) override;
 
   // nsIContent interface methods
   virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) override;
   virtual const nsTextFragment* GetText() override;
   virtual uint32_t TextLength() const override;
   virtual bool TextIsOnlyWhitespace() override;
   virtual bool ThreadSafeTextIsOnlyWhitespace() const override;
-#ifdef MOZ_XBL
-  virtual nsXBLBinding* DoGetXBLBinding() const override;
-#endif
   virtual bool IsLink(nsIURI** aURI) const override;
 
   virtual void DestroyContent() override;
   virtual void SaveSubtreeState() override;
 
   nsIHTMLCollection* Children();
   uint32_t ChildElementCount() { return Children()->Length(); }
 
@@ -191,23 +185,16 @@ class FragmentOrElement : public nsICont
      */
     RefPtr<nsLabelsNodeList> mLabelsList;
 
     /**
      * ShadowRoot bound to the element.
      */
     RefPtr<ShadowRoot> mShadowRoot;
 
-#ifdef MOZ_XBL
-    /**
-     * XBL binding installed on the element.
-     */
-    RefPtr<nsXBLBinding> mXBLBinding;
-#endif
-
     /**
      * Web components custom element data.
      */
     RefPtr<CustomElementData> mCustomElementData;
   };
 
   class nsDOMSlots : public nsIContent::nsContentSlots {
    public:
--- a/dom/base/IDTracker.cpp
+++ b/dom/base/IDTracker.cpp
@@ -5,20 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDTracker.h"
 
 #include "mozilla/Encoding.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
 #include "nsIReferrerInfo.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#  include "nsXBLPrototypeBinding.h"
-#endif
 #include "nsEscape.h"
 #include "nsCycleCollectionParticipant.h"
 
 namespace mozilla {
 namespace dom {
 
 static DocumentOrShadowRoot* DocOrShadowFromContent(nsIContent& aContent) {
   ShadowRoot* shadow = aContent.GetContainingShadow();
@@ -60,63 +56,28 @@ void IDTracker::ResetToURIFragmentID(nsI
   nsresult rv = encoding->DecodeWithoutBOMHandling(refPart, ref);
   if (NS_FAILED(rv) || ref.IsEmpty()) {
     return;
   }
   rv = NS_OK;
 
   nsIContent* bindingParent = aFromContent->GetBindingParent();
   if (bindingParent && !aFromContent->IsInShadowTree()) {
-#ifdef MOZ_XBL
-    nsXBLBinding* binding = bindingParent->GetXBLBinding();
-    if (!binding) {
-#endif
-      // This happens, for example, if aFromContent is part of the content
-      // inserted by a call to Document::InsertAnonymousContent, which we
-      // also want to handle.  (It also happens for <use>'s anonymous
-      // content etc.)
-      Element* anonRoot =
-          doc->GetAnonRootIfInAnonymousContentContainer(aFromContent);
-      if (anonRoot) {
-        mElement = nsContentUtils::MatchElementId(anonRoot, ref);
-        // We don't have watching working yet for anonymous content, so bail out
-        // here.
-        return;
-      }
-#ifdef MOZ_XBL
-    } else {
-      bool isEqualExceptRef;
-      rv = aURI->EqualsExceptRef(binding->PrototypeBinding()->DocURI(),
-                                 &isEqualExceptRef);
-      if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
-        // XXX sXBL/XBL2 issue
-        // Our content is an anonymous XBL element from a binding inside the
-        // same document that the referenced URI points to. In order to avoid
-        // the risk of ID collisions we restrict ourselves to anonymous
-        // elements from this binding; specifically, URIs that are relative to
-        // the binding document should resolve to the copy of the target
-        // element that has been inserted into the bound document.
-        // If the URI points to a different document we don't need this
-        // restriction.
-        nsINodeList* anonymousChildren =
-            doc->BindingManager()->GetAnonymousNodesFor(bindingParent);
-
-        if (anonymousChildren) {
-          uint32_t length = anonymousChildren->Length();
-          for (uint32_t i = 0; i < length && !mElement; ++i) {
-            mElement =
-                nsContentUtils::MatchElementId(anonymousChildren->Item(i), ref);
-          }
-        }
-
-        // We don't have watching working yet for XBL, so bail out here.
-        return;
-      }
+    // This happens, for example, if aFromContent is part of the content
+    // inserted by a call to Document::InsertAnonymousContent, which we
+    // also want to handle.  (It also happens for <use>'s anonymous
+    // content etc.)
+    Element* anonRoot =
+        doc->GetAnonRootIfInAnonymousContentContainer(aFromContent);
+    if (anonRoot) {
+      mElement = nsContentUtils::MatchElementId(anonRoot, ref);
+      // We don't have watching working yet for anonymous content, so bail out
+      // here.
+      return;
     }
-#endif
   }
 
   bool isEqualExceptRef;
   rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef);
   if (NS_FAILED(rv) || !isEqualExceptRef) {
     RefPtr<Document::ExternalResourceLoad> load;
     doc = doc->RequestExternalResource(aURI, aReferrerInfo, aFromContent,
                                        getter_AddRefs(load));
--- a/dom/base/MutationObservers.cpp
+++ b/dom/base/MutationObservers.cpp
@@ -18,19 +18,16 @@
 #include "mozilla/EventListenerManager.h"
 #include "nsIXPConnect.h"
 #include "PLDHashTable.h"
 #include "nsCOMArray.h"
 #include "nsPIDOMWindow.h"
 #ifdef MOZ_XUL
 #  include "nsXULElement.h"
 #endif
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsGenericHTMLElement.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/KeyframeEffect.h"
 #include "mozilla/PresShell.h"
 #include "nsWrapperCacheInlines.h"
@@ -51,24 +48,19 @@ enum class IsRemoveNotification {
 
 #ifdef DEBUG
 #  define COMPOSED_DOC_DECL \
     const bool wasInComposedDoc = !!node->GetComposedDoc();
 #else
 #  define COMPOSED_DOC_DECL
 #endif
 
-#ifdef MOZ_XBL
-#  define CALL_BINDING_MANAGER(func_, params_) \
-    doc->BindingManager()->func_ params_
-#else
-#  define CALL_BINDING_MANAGER(func_, params_) \
-    do {                                       \
-    } while (0)
-#endif
+#define CALL_BINDING_MANAGER(func_, params_) \
+  do {                                       \
+  } while (0)
 
 // This macro expects the ownerDocument of content_ to be in scope as
 // |Document* doc|
 #define IMPL_MUTATION_NOTIFICATION(func_, content_, params_, remove_)         \
   PR_BEGIN_MACRO                                                              \
   bool needsEnterLeave = doc->MayHaveDOMMutationObservers();                  \
   if (needsEnterLeave) {                                                      \
     nsDOMMutationObserver::EnterMutationHandling();                           \
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -7,19 +7,16 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsWindowSizes.h"
-#ifdef MOZ_XBL
-#  include "nsXBLPrototypeBinding.h"
-#endif
 #include "mozilla/dom/DirectionalityUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/dom/TreeOrderedArrayInlines.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IdentifierMapEntry.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/PresShellInlines.h"
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -520,19 +520,16 @@ LOCAL_INCLUDES += [
     '/layout/xul',
     '/netwerk/base',
     '/netwerk/url-classifier',
     '/security/manager/ssl',
     '/widget',
     '/xpcom/ds',
 ]
 
-if CONFIG['MOZ_XBL']:
-    LOCAL_INCLUDES += ['/dom/xbl']
-
 if CONFIG['MOZ_WEBRTC']:
     LOCAL_INCLUDES += [
         '/netwerk/sctp/datachannel',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -15,16 +15,17 @@
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/ServoUtils.h"
+#include "mozilla/ShadowParts.h"
 #include "mozilla/DeclarationBlock.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsHTMLCSSStyleSheet.h"
 #include "nsStyledElement.h"
 #include "nsIURI.h"
 #include "mozilla/dom/Document.h"
 #include "ReferrerInfo.h"
@@ -276,16 +277,17 @@ void nsAttrValue::SetTo(const nsAttrValu
     case ePercent: {
       cont->mDoubleValue = otherCont->mDoubleValue;
       break;
     }
     case eColor: {
       cont->mValue.mColor = otherCont->mValue.mColor;
       break;
     }
+    case eShadowParts:
     case eCSSDeclaration: {
       MOZ_CRASH("These should be refcounted!");
     }
     case eURL: {
       NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
       break;
     }
     case eAtomArray: {
@@ -296,19 +298,20 @@ void nsAttrValue::SetTo(const nsAttrValu
       }
       break;
     }
     case eDoubleValue: {
       cont->mDoubleValue = otherCont->mDoubleValue;
       break;
     }
     case eIntMarginValue: {
-      if (otherCont->mValue.mIntMargin)
+      if (otherCont->mValue.mIntMargin) {
         cont->mValue.mIntMargin =
             new nsIntMargin(*otherCont->mValue.mIntMargin);
+      }
       break;
     }
     default: {
       if (IsSVGType(otherCont->mType)) {
         // All SVG types are just pointers to classes and will therefore have
         // the same size so it doesn't really matter which one we assign
         cont->mValue.mSVGLength = otherCont->mValue.mSVGLength;
       } else {
@@ -1150,24 +1153,35 @@ void nsAttrValue::ParseAtomArray(const n
   }
 
   SetMiscAtomOrString(&aValue);
 }
 
 void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
   uint32_t len = aValue.Length();
   // Don't bother with atoms if it's an empty string since
-  // we can store those efficently anyway.
+  // we can store those efficiently anyway.
   if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
     ParseAtom(aValue);
   } else {
     SetTo(aValue);
   }
 }
 
+void nsAttrValue::ParsePartMapping(const nsAString& aValue) {
+  ResetIfSet();
+  MiscContainer* cont = EnsureEmptyMiscContainer();
+
+  cont->mType = eShadowParts;
+  cont->mValue.mShadowParts = new ShadowParts(ShadowParts::Parse(aValue));
+  NS_ADDREF(cont);
+  SetMiscAtomOrString(&aValue);
+  MOZ_ASSERT(cont->mValue.mRefCount == 1);
+}
+
 void nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType,
                                      const nsAString* aStringValue) {
   if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ||
       aValue < NS_ATTRVALUE_INTEGERTYPE_MINVALUE) {
     MiscContainer* cont = EnsureEmptyMiscContainer();
     switch (aType) {
       case eInteger: {
         cont->mValue.mInteger = aValue;
@@ -1735,16 +1749,22 @@ MiscContainer* nsAttrValue::ClearMiscCon
       switch (cont->mType) {
         case eCSSDeclaration: {
           MOZ_ASSERT(cont->mValue.mRefCount == 1);
           cont->Release();
           cont->Evict();
           NS_RELEASE(cont->mValue.mCSSDeclaration);
           break;
         }
+        case eShadowParts: {
+          MOZ_ASSERT(cont->mValue.mRefCount == 1);
+          cont->Release();
+          delete cont->mValue.mShadowParts;
+          break;
+        }
         case eURL: {
           NS_RELEASE(cont->mValue.mURL);
           break;
         }
         case eAtomArray: {
           delete cont->mValue.mAtomArray;
           break;
         }
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -96,16 +96,20 @@ class nsAttrValue {
     // Values below here won't matter, they'll be always stored in the 'misc'
     // struct.
     eCSSDeclaration = 0x10,
     eURL,
     eImage,
     eAtomArray,
     eDoubleValue,
     eIntMarginValue,
+    // eShadowParts is refcounted in the misc container, as we do copy attribute
+    // values quite a bit (for example to process style invalidation), and the
+    // underlying value could get expensive to copy.
+    eShadowParts,
     eSVGIntegerPair,
     eSVGTypesBegin = eSVGIntegerPair,
     eSVGOrient,
     eSVGLength,
     eSVGLengthList,
     eSVGNumberList,
     eSVGNumberPair,
     eSVGPathData,
@@ -252,16 +256,23 @@ class nsAttrValue {
    */
   bool Contains(const nsAString& aValue) const;
 
   void ParseAtom(const nsAString& aValue);
   void ParseAtomArray(const nsAString& aValue);
   void ParseStringOrAtom(const nsAString& aValue);
 
   /**
+   * Parses an exportparts attribute.
+   *
+   * https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
+   */
+  void ParsePartMapping(const nsAString&);
+
+  /**
    * Structure for a mapping from int (enum) values to strings.  When you use
    * it you generally create an array of them.
    * Instantiate like this:
    * EnumTable myTable[] = {
    *   { "string1", 1 },
    *   { "string2", 2 },
    *   { nullptr, 0 }
    * }
--- a/dom/base/nsAttrValueInlines.h
+++ b/dom/base/nsAttrValueInlines.h
@@ -9,16 +9,20 @@
 
 #include <stdint.h>
 
 #include "nsAttrValue.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ServoUtils.h"
 
+namespace mozilla {
+class ShadowParts;
+}
+
 struct MiscContainer final {
   typedef nsAttrValue::ValueType ValueType;
 
   ValueType mType;
   // mStringBits points to either nsAtom* or nsStringBuffer* and is used when
   // mType isn't eCSSDeclaration.
   // Note eStringBase and eAtomBase is used also to handle the type of
   // mStringBits.
@@ -36,16 +40,17 @@ struct MiscContainer final {
       union {
         int32_t mInteger;
         nscolor mColor;
         uint32_t mEnumValue;
         mozilla::DeclarationBlock* mCSSDeclaration;
         nsIURI* mURL;
         mozilla::AtomArray* mAtomArray;
         nsIntMargin* mIntMargin;
+        const mozilla::ShadowParts* mShadowParts;
         const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair;
         const mozilla::SVGAnimatedLength* mSVGLength;
         const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair;
         const mozilla::SVGAnimatedOrient* mSVGAnimatedOrient;
         const mozilla::SVGAnimatedPreserveAspectRatio*
             mSVGAnimatedPreserveAspectRatio;
         const mozilla::SVGAnimatedViewBox* mSVGAnimatedViewBox;
         const mozilla::SVGLengthList* mSVGLengthList;
@@ -90,17 +95,18 @@ struct MiscContainer final {
     MOZ_ASSERT(NS_IsMainThread());
     mStringBits = aBits;
   }
 
   inline bool IsRefCounted() const {
     // Nothing stops us from refcounting (and sharing) other types of
     // MiscContainer (except eDoubleValue types) but there's no compelling
     // reason to.
-    return mType == nsAttrValue::eCSSDeclaration;
+    return mType == nsAttrValue::eCSSDeclaration ||
+           mType == nsAttrValue::eShadowParts;
   }
 
   inline int32_t AddRef() {
     MOZ_ASSERT(IsRefCounted());
     return ++mValue.mRefCount;
   }
 
   inline int32_t Release() {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -111,19 +111,16 @@
 #include "mozilla/TextControlState.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/TextEvents.h"
 #include "nsArrayUtils.h"
 #include "nsAString.h"
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsCanvasFrame.h"
 #include "nsCaret.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsCOMPtr.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentDLF.h"
 #include "nsContentList.h"
@@ -2146,23 +2143,17 @@ bool nsContentUtils::ThreadsafeIsSystemC
 
   return ccjscx->IsSystemCaller();
 }
 
 // static
 bool nsContentUtils::LookupBindingMember(
     JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
     JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
-#ifdef MOZ_XBL
-  nsXBLBinding* binding = aContent->GetXBLBinding();
-  if (!binding) return true;
-  return binding->LookupMember(aCx, aId, aDesc);
-#else
   return true;
-#endif
 }
 
 // static
 nsINode* nsContentUtils::GetCrossDocParentNode(nsINode* aChild) {
   MOZ_ASSERT(aChild, "The child is null!");
 
   nsINode* parent = aChild->GetParentNode();
   if (parent && parent->IsContent() && aChild->IsContent()) {
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -30,19 +30,16 @@
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/Selection.h"
 #include "nsXULPopupManager.h"
 #include "nsMenuPopupFrame.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIPrincipal.h"
 #include "nsIObserverService.h"
 #include "nsIObjectFrame.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "BrowserChild.h"
 #include "nsFrameLoader.h"
 #include "nsHTMLDocument.h"
 #include "nsNumberControlFrame.h"
 #include "nsNetUtil.h"
 #include "nsRange.h"
 
 #include "mozilla/AccessibleCaretEventHub.h"
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -179,21 +179,16 @@
 #  include "nsIPrintSettingsService.h"
 #  include "nsIWebBrowserPrint.h"
 #endif
 
 #include "nsWindowRoot.h"
 #include "nsNetCID.h"
 #include "nsIArray.h"
 
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#  include "nsXBLService.h"
-#endif
-
 #include "nsIDragService.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Selection.h"
 #include "nsFrameLoader.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPCOMCID.h"
 #include "mozilla/Logging.h"
 #include "prenv.h"
@@ -2003,23 +1998,16 @@ nsresult nsGlobalWindowInner::PostHandle
 
         // XXX The WebVR 1.1 spec does not define which of multiple VR
         // presenting VR displays will be chosen during navigation.
         // As the underlying platform VR API's currently only allow a single
         // VR display, it is safe to choose the first VR display for now.
         break;
       }
     }
-#ifdef MOZ_XBL
-    // Execute bindingdetached handlers before we tear ourselves
-    // down.
-    if (mDoc) {
-      mDoc->BindingManager()->ExecuteDetachedHandlers();
-    }
-#endif
     mIsDocumentLoaded = false;
   } else if (aVisitor.mEvent->mMessage == eLoad &&
              aVisitor.mEvent->IsTrusted()) {
     // This is page load event since load events don't propagate to |window|.
     // @see Document::GetEventTargetParent.
     mIsDocumentLoaded = true;
 
     mTimeoutManager->OnDocumentLoaded();
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -173,20 +173,16 @@
 
 #include "nsWindowRoot.h"
 #include "nsNetCID.h"
 #include "nsIArray.h"
 
 #include "nsIDOMXULCommandDispatcher.h"
 
 #include "mozilla/GlobalKeyListener.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#  include "nsXBLService.h"
-#endif
 
 #include "nsIDragService.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Selection.h"
 #include "nsFrameLoader.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPCOMCID.h"
 #include "mozilla/Logging.h"
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -16,19 +16,16 @@
 
 // Forward declarations
 class nsAtom;
 class nsIURI;
 class nsAttrValue;
 class nsAttrName;
 class nsTextFragment;
 class nsIFrame;
-#ifdef MOZ_XBL
-class nsXBLBinding;
-#endif
 class nsITextControlElement;
 
 namespace mozilla {
 class EventChainPreVisitor;
 struct URLExtraData;
 namespace dom {
 struct BindContext;
 class ShadowRoot;
@@ -392,33 +389,16 @@ class nsIContent : public nsINode {
    *
    * @return the binding parent
    */
   virtual mozilla::dom::Element* GetBindingParent() const {
     const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
     return slots ? slots->mBindingParent.get() : nullptr;
   }
 
-#ifdef MOZ_XBL
-  /**
-   * Gets the current XBL binding that is bound to this element.
-   *
-   * @return the current binding.
-   */
-  nsXBLBinding* GetXBLBinding() const {
-    if (!HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-      return nullptr;
-    }
-
-    return DoGetXBLBinding();
-  }
-
-  virtual nsXBLBinding* DoGetXBLBinding() const = 0;
-#endif
-
   /**
    * Gets the ShadowRoot binding for this element.
    *
    * @return The ShadowRoot currently bound to this element.
    */
   inline mozilla::dom::ShadowRoot* GetShadowRoot() const;
 
   /**
--- a/dom/base/nsIContentInlines.h
+++ b/dom/base/nsIContentInlines.h
@@ -4,19 +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/. */
 
 #ifndef nsIContentInlines_h
 #define nsIContentInlines_h
 
 #include "nsIContent.h"
 #include "mozilla/dom/Document.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsContentUtils.h"
 #include "nsAtom.h"
 #include "nsIFrame.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 
 inline bool nsINode::IsUAWidget() const {
@@ -115,32 +112,16 @@ static inline nsINode* GetFlattenedTreeP
     }
 
     if (auto* shadowRoot =
             mozilla::dom::ShadowRoot::FromNode(parentAsContent)) {
       return shadowRoot->GetHost();
     }
   }
 
-#ifdef MOZ_XBL
-  if (content->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
-      parent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    if (nsIContent* xblInsertionPoint = content->GetXBLInsertionPoint()) {
-      return xblInsertionPoint->GetParent();
-    }
-
-    if (parent->OwnerDoc()->BindingManager()->GetBindingWithContent(
-            parentAsContent)) {
-      // This is an unassigned node child of the bound element, so it isn't part
-      // of the flat tree.
-      return nullptr;
-    }
-  }
-#endif
-
   MOZ_ASSERT(!parentAsContent->IsActiveChildrenElement(),
              "<xbl:children> isn't in the flattened tree");
 
   // Common case.
   return parent;
 }
 
 inline nsINode* nsINode::GetFlattenedTreeParentNode() const {
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -89,21 +89,16 @@
 #include "nsObjectLoadingContent.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "nsString.h"
 #include "nsStyleConsts.h"
 #include "nsSVGUtils.h"
 #include "nsTextNode.h"
 #include "nsUnicharUtils.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#  include "nsXBLBinding.h"
-#  include "nsXBLPrototypeBinding.h"
-#endif
 #include "nsWindowSizes.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "HTMLLegendElement.h"
 #include "nsWrapperCacheInlines.h"
 #include "WrapperFactory.h"
 #include <algorithm>
 #include "nsGlobalWindow.h"
@@ -531,21 +526,16 @@ void nsINode::LastRelease() {
       }
     }
 #endif
 
     nsContentUtils::RemoveListenerManager(this);
     UnsetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
-#ifdef MOZ_XBL
-  NS_ASSERTION(
-      !Element::FromNode(this) || !Element::FromNode(this)->GetXBLBinding(),
-      "Node has binding on destruction");
-#endif
 
   ReleaseWrapper(this);
 
   FragmentOrElement::RemoveBlackMarkedNode(this);
 }
 
 #ifdef DEBUG
 void nsINode::CheckNotNativeAnonymous() const {
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -25,19 +25,16 @@
 #include "nsCOMPtr.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.h"
 #include "nsJSPrincipals.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
-#ifdef MOZ_XBL
-#  include "nsXBLPrototypeBinding.h"
-#endif
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/StaticPrefs_browser.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Utf8.h"  // mozilla::Utf8Unit
 
@@ -615,41 +612,16 @@ bool nsJSUtils::GetScopeChainForElement(
     if (!AddScopeChainItem(aCx, cur, aScopeChain)) {
       return false;
     }
   }
 
   return true;
 }
 
-#ifdef MOZ_XBL
-/* static */
-bool nsJSUtils::GetScopeChainForXBL(
-    JSContext* aCx, Element* aElement,
-    const nsXBLPrototypeBinding& aProtoBinding,
-    JS::MutableHandleVector<JSObject*> aScopeChain) {
-  if (!aElement) {
-    return true;
-  }
-
-  if (!aProtoBinding.SimpleScopeChain()) {
-    return GetScopeChainForElement(aCx, aElement, aScopeChain);
-  }
-
-  if (!AddScopeChainItem(aCx, aElement, aScopeChain)) {
-    return false;
-  }
-
-  if (!AddScopeChainItem(aCx, aElement->OwnerDoc(), aScopeChain)) {
-    return false;
-  }
-  return true;
-}
-#endif
-
 /* static */
 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
 
 /* static */
 bool nsJSUtils::DumpEnabled() {
 #if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
   return true;
 #else
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -236,29 +236,16 @@ class nsJSUtils {
   static nsresult ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule);
 
   // Returns false if an exception got thrown on aCx.  Passing a null
   // aElement is allowed; that wil produce an empty aScopeChain.
   static bool GetScopeChainForElement(
       JSContext* aCx, mozilla::dom::Element* aElement,
       JS::MutableHandleVector<JSObject*> aScopeChain);
 
-#ifdef MOZ_XBL
-  // Returns a scope chain suitable for XBL execution.
-  //
-  // This is by default GetScopeChainForElemenet, but will be different if the
-  // <binding> element had the simpleScopeChain attribute.
-  //
-  // This is to prevent footguns like bug 1446342.
-  static bool GetScopeChainForXBL(
-      JSContext* aCx, mozilla::dom::Element* aBoundElement,
-      const nsXBLPrototypeBinding& aProtoBinding,
-      JS::MutableHandleVector<JSObject*> aScopeChain);
-#endif
-
   static void ResetTimeZone();
 
   static bool DumpEnabled();
 };
 
 inline void AssignFromStringBuffer(nsStringBuffer* buffer, size_t len,
                                    nsAString& dest) {
   buffer->ToString(len, dest);
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -16,19 +16,16 @@
 #include "nsAtom.h"
 #include "nsCOMArray.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsGkAtoms.h"
 #include "mozilla/dom/Document.h"
 #include "nsString.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/ClearOnShutdown.h"
-#ifdef MOZ_XBL
-#  include "mozilla/dom/XBLChildrenElement.h"
-#endif
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static const char* kPrefSVGDisabled = "svg.disabled";
 static const char* kPrefMathMLDisabled = "mathml.disabled";
@@ -200,22 +197,16 @@ nsresult NS_NewElement(Element** aResult
       return NS_NewSVGElement(aResult, ni.forget(), aFromParser);
     }
     RefPtr<mozilla::dom::NodeInfo> genericXMLNI =
         ni->NodeInfoManager()->GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(),
                                            kNameSpaceID_disabled_SVG,
                                            ni->NodeType(), ni->GetExtraName());
     return NS_NewXMLElement(aResult, genericXMLNI.forget());
   }
-#ifdef MOZ_XBL
-  if (ns == kNameSpaceID_XBL && ni->Equals(nsGkAtoms::children)) {
-    NS_ADDREF(*aResult = new XBLChildrenElement(ni.forget()));
-    return NS_OK;
-  }
-#endif
 
   return NS_NewXMLElement(aResult, ni.forget());
 }
 
 bool nsNameSpaceManager::HasElementCreator(int32_t aNameSpaceID) {
   return aNameSpaceID == kNameSpaceID_XHTML ||
 #ifdef MOZ_XUL
          aNameSpaceID == kNameSpaceID_XUL ||
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -20,19 +20,16 @@
 #include "nsAtom.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
-#ifdef MOZ_XBL
-#  include "nsBindingManager.h"
-#endif
 #include "nsHashKeys.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsNameSpaceManager.h"
 #include "nsWindowSizes.h"
 
 using namespace mozilla;
 using mozilla::dom::NodeInfo;
 
@@ -55,37 +52,30 @@ nsNodeInfoManager::nsNodeInfoManager()
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
             ("NODEINFOMANAGER %p created", this));
 }
 
 nsNodeInfoManager::~nsNodeInfoManager() {
   // Note: mPrincipal may be null here if we never got inited correctly
   mPrincipal = nullptr;
 
-#ifdef MOZ_XBL
-  mBindingManager = nullptr;
-#endif
-
   if (gNodeInfoManagerLeakPRLog)
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
             ("NODEINFOMANAGER %p destroyed", this));
 
   nsLayoutStatics::Release();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager)
   if (tmp->mNonDocumentNodeInfos) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
   }
-#ifdef MOZ_XBL
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBindingManager)
-#endif
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsNodeInfoManager)
   if (tmp->mDocument) {
     return NS_CYCLE_COLLECTION_PARTICIPANT(mozilla::dom::Document)
@@ -107,40 +97,28 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_B
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 nsresult nsNodeInfoManager::Init(mozilla::dom::Document* aDocument) {
   MOZ_ASSERT(!mPrincipal, "Being inited when we already have a principal?");
 
   mPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
 
-#ifdef MOZ_XBL
-  if (aDocument) {
-    mBindingManager = new nsBindingManager(aDocument);
-  }
-#endif
-
   mDefaultPrincipal = mPrincipal;
 
   mDocument = aDocument;
 
   if (gNodeInfoManagerLeakPRLog)
     MOZ_LOG(gNodeInfoManagerLeakPRLog, LogLevel::Debug,
             ("NODEINFOMANAGER %p Init document=%p", this, aDocument));
 
   return NS_OK;
 }
 
 void nsNodeInfoManager::DropDocumentReference() {
-#ifdef MOZ_XBL
-  if (mBindingManager) {
-    mBindingManager->DropDocumentReference();
-  }
-#endif
-
   // This is probably not needed anymore.
   for (auto iter = mNodeInfoHash.Iter(); !iter.Done(); iter.Next()) {
     iter.Data()->mDocument = nullptr;
   }
 
   NS_ASSERTION(!mNonDocumentNodeInfos,
                "Shouldn't have non-document nodeinfos!");
   mDocument = nullptr;
@@ -372,19 +350,12 @@ bool nsNodeInfoManager::InternalMathMLEn
                      nsContentUtils::IsSystemPrincipal(mPrincipal));
   mMathMLEnabled = Some(conclusion);
   return conclusion;
 }
 
 void nsNodeInfoManager::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
   aSizes.mDOMOtherSize += aSizes.mState.mMallocSizeOf(this);
 
-#ifdef MOZ_XBL
-  if (mBindingManager) {
-    aSizes.mBindingsSize +=
-        mBindingManager->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
-  }
-#endif
-
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - mNodeInfoHash
 }
--- a/dom/base/nsNodeInfoManager.h
+++ b/dom/base/nsNodeInfoManager.h
@@ -14,19 +14,16 @@
 #include "mozilla/Attributes.h"  // for final
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/MruCache.h"
 #include "nsCOMPtr.h"                      // for member
 #include "nsCycleCollectionParticipant.h"  // for NS_DECL_CYCLE_*
 #include "nsDataHashtable.h"
 #include "nsStringFwd.h"
 
-#ifdef MOZ_XBL
-class nsBindingManager;
-#endif
 class nsAtom;
 class nsIPrincipal;
 class nsWindowSizes;
 template <class T>
 struct already_AddRefed;
 
 namespace mozilla {
 namespace dom {
@@ -95,20 +92,16 @@ class nsNodeInfoManager final {
    */
   nsIPrincipal* DocumentPrincipal() const {
     NS_ASSERTION(mPrincipal, "How'd that happen?");
     return mPrincipal;
   }
 
   void RemoveNodeInfo(mozilla::dom::NodeInfo* aNodeInfo);
 
-#ifdef MOZ_XBL
-  nsBindingManager* GetBindingManager() const { return mBindingManager; }
-#endif
-
   /**
    * Returns true if SVG nodes in this document have real SVG semantics.
    */
   bool SVGEnabled() { return mSVGEnabled.valueOr(InternalSVGEnabled()); }
 
   /**
    * Returns true if MathML nodes in this document have real MathML semantics.
    */
@@ -160,17 +153,14 @@ class nsNodeInfoManager final {
   nsCOMPtr<nsIPrincipal> mPrincipal;  // Never null after Init() succeeds.
   nsCOMPtr<nsIPrincipal> mDefaultPrincipal;  // Never null after Init() succeeds
   mozilla::dom::NodeInfo* MOZ_NON_OWNING_REF
       mTextNodeInfo;  // WEAK to avoid circular ownership
   mozilla::dom::NodeInfo* MOZ_NON_OWNING_REF
       mCommentNodeInfo;  // WEAK to avoid circular ownership
   mozilla::dom::NodeInfo* MOZ_NON_OWNING_REF
       mDocumentNodeInfo;  // WEAK to avoid circular ownership
-#ifdef MOZ_XBL
-  RefPtr<nsBindingManager> mBindingManager;
-#endif
   NodeInfoCache mRecentlyUsedNodeInfos;
   mozilla::Maybe<bool> mSVGEnabled;     // Lazily initialized.
   mozilla::Maybe<bool> mMathMLEnabled;  // Lazily initialized.
 };
 
 #endif /* nsNodeInfoManager_h___ */
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -88,19 +88,16 @@ LOCAL_INCLUDES += [
     '/layout/xul/tree',
     '/media/mtransport',
     '/media/webrtc/',
     '/media/webrtc/signaling/src/common/time_profiling',
     '/media/webrtc/signaling/src/peerconnection',
     '/media/webrtc/trunk/',
 ]
 
-if CONFIG['MOZ_XBL']:
-    LOCAL_INCLUDES += ['/dom/xbl']
-
 LOCAL_INCLUDES += ['/third_party/msgpack/include']
 
 DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True
 DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True
 
 UNIFIED_SOURCES += [
     'BindingUtils.cpp',
     'CallbackInterface.cpp',
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -5507,30 +5507,32 @@ void EventStateManager::RemoveNodeFromCh
       !aContentRemoved->AsElement()->State().HasState(aState)) {
     return;
   }
 
   nsCOMPtr<nsIContent>& leaf =
       aState == NS_EVENT_STATE_HOVER ? mHoverContent : mActiveContent;
 
   MOZ_ASSERT(leaf);
-  // XBL Likes to unbind content without notifying, thus the
-  // NODE_IS_ANONYMOUS_ROOT check...
+  // These two NS_ASSERTIONS below can fail for Shadow DOM sometimes, and it's
+  // not clear how to best handle it, see
+  // https://github.com/whatwg/html/issues/4795 and bug 1551621.
   //
-  // This can also happen for Shadow DOM sometimes, and it's not clear how to
-  // best handle it, see https://github.com/whatwg/html/issues/4795 and
-  // bug 1551621.
+  // The NODE_IS_ANONYMOUS_ROOT is there because XBL used to remove content
+  // without notifying, but it shouldn't apply to NAC since
+  // NAC notifies (see NativeAnonymousContentRemoved).
   NS_ASSERTION(nsContentUtils::ContentIsFlattenedTreeDescendantOf(
                    leaf, aContentRemoved) ||
-                   leaf->SubtreeRoot()->HasFlag(NODE_IS_ANONYMOUS_ROOT),
+               leaf->SubtreeRoot()->HasFlag(NODE_IS_ANONYMOUS_ROOT),
                "Flat tree and active / hover chain got out of sync");
 
   nsIContent* newLeaf = aContentRemoved->GetFlattenedTreeParent();
-  MOZ_ASSERT_IF(newLeaf, newLeaf->IsElement() &&
-                             newLeaf->AsElement()->State().HasState(aState));
+  MOZ_ASSERT(!newLeaf || newLeaf->IsElement());
+  NS_ASSERTION(!newLeaf || newLeaf->AsElement()->State().HasState(aState),
+               "State got out of sync because of shadow DOM");
   if (aNotify) {
     SetContentState(newLeaf, aState);
   } else {
     // We don't update the removed content's state here, since removing NAC
     // happens from layout and we don't really want to notify at that point or
     // what not.
     //
     // Also, NAC is not observable and NAC being removed will go away soon.
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -248,18 +248,15 @@ LOCAL_INCLUDES += [
     '/layout/forms',
     '/layout/generic',
     '/layout/style',
     '/layout/tables',
     '/layout/xul',
     '/netwerk/base',
 ]
 
-if CONFIG['MOZ_XBL']:
-    LOCAL_INCLUDES += ['/dom/xbl']
-
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_ANDROID_HLS_SUPPORT']:
     DEFINES['MOZ_ANDROID_HLS_SUPPORT'] = True
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/dom/interfaces/base/nsIRemoteTab.idl
+++ b/dom/interfaces/base/nsIRemoteTab.idl
@@ -52,17 +52,16 @@ interface nsIRemoteTab : nsISupports
 
   readonly attribute uint64_t contentProcessId;
 
   /**
    * The OS level process Id of the related child process.
    */
   readonly attribute int32_t osPid;
 
-  readonly attribute boolean hasContentOpener;
   /**
    * True if we've previously received layers for this tab when switching to
    * it.
    */
   readonly attribute boolean hasPresented;
 
   /**
    * Ensures that the content process which has this remote tab has all of the
--- a/dom/ipc/BrowserBridgeParent.cpp
+++ b/dom/ipc/BrowserBridgeParent.cpp
@@ -227,16 +227,27 @@ IPCResult BrowserBridgeParent::RecvSetIs
   return IPC_OK();
 }
 
 IPCResult BrowserBridgeParent::RecvSetEmbedderAccessible(
     PDocAccessibleParent* aDoc, uint64_t aID) {
 #ifdef ACCESSIBILITY
   mEmbedderAccessibleDoc = static_cast<a11y::DocAccessibleParent*>(aDoc);
   mEmbedderAccessibleID = aID;
+  if (auto embeddedBrowser = GetBrowserParent()) {
+    a11y::DocAccessibleParent* childDocAcc =
+        embeddedBrowser->GetTopLevelDocAccessible();
+    if (childDocAcc && !childDocAcc->IsShutdown()) {
+      // The embedded DocAccessibleParent has already been created. This can
+      // happen if, for example, an iframe is hidden and then shown or
+      // an iframe is reflowed by layout.
+      mEmbedderAccessibleDoc->AddChildDoc(childDocAcc, aID,
+                                          /* aCreating */ false);
+    }
+  }
 #endif
   return IPC_OK();
 }
 
 void BrowserBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { Destroy(); }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/ipc/BrowserHost.cpp
+++ b/dom/ipc/BrowserHost.cpp
@@ -254,27 +254,16 @@ BrowserHost::GetOsPid(int32_t* aOsPid) {
   if (!mRoot) {
     *aOsPid = 0;
     return NS_OK;
   }
   *aOsPid = GetContentParent()->Pid();
   return NS_OK;
 }
 
-/* readonly attribute boolean hasContentOpener; */
-NS_IMETHODIMP
-BrowserHost::GetHasContentOpener(bool* aHasContentOpener) {
-  if (!mRoot) {
-    *aHasContentOpener = false;
-    return NS_OK;
-  }
-  *aHasContentOpener = mRoot->GetHasContentOpener();
-  return NS_OK;
-}
-
 /* readonly attribute boolean hasPresented; */
 NS_IMETHODIMP
 BrowserHost::GetHasPresented(bool* aHasPresented) {
   if (!mRoot) {
     *aHasPresented = false;
     return NS_OK;
   }
   *aHasPresented = mRoot->GetHasPresented();
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "BrowserParent.h"
 
 #ifdef ACCESSIBILITY
 #  include "mozilla/a11y/DocAccessibleParent.h"
+#  include "mozilla/a11y/Platform.h"
+#  include "mozilla/a11y/ProxyAccessibleBase.h"
 #  include "nsAccessibilityService.h"
 #endif
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/dom/CancelContentJSOptionsBinding.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DataTransferItemList.h"
@@ -206,17 +208,16 @@ BrowserParent::BrowserParent(ContentPare
       mCustomCursor{},
       mCustomCursorHotspotX(0),
       mCustomCursorHotspotY(0),
       mVerifyDropLinks{},
       mDocShellIsActive(false),
       mMarkedDestroying(false),
       mIsDestroyed(false),
       mTabSetsCursor(false),
-      mHasContentOpener(false),
       mPreserveLayers(false),
       mRenderLayers(true),
       mActiveInPriorityManager(false),
       mHasLayers(false),
       mHasPresented(false),
       mIsReadyToHandleInputEvents(false),
       mIsMouseEnterIntoWidgetEventSuppressed(false),
       mIsActiveRecordReplayTab(false) {
@@ -1168,45 +1169,54 @@ mozilla::ipc::IPCResult BrowserParent::R
     if (a11y::nsWinUtils::IsWindowEmulationStarted()) {
       doc->SetEmulatedWindowHandle(parentDoc->GetEmulatedWindowHandle());
     }
 #  endif
 
     return IPC_OK();
   }
 
-  a11y::DocAccessibleParent* embedderDoc;
-  uint64_t embedderID;
-  Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
-  if (embedderDoc) {
+  if (GetBrowserBridgeParent()) {
     // Iframe document rendered in a different process to its embedder.
     // In this case, we don't get aParentDoc and aParentID.
     MOZ_ASSERT(!aParentDoc && !aParentID);
-    MOZ_ASSERT(embedderID);
     doc->SetTopLevelInContentProcess();
 #  ifdef XP_WIN
     MOZ_ASSERT(!aDocCOMProxy.IsNull());
     RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
     doc->SetCOMInterface(proxy);
 #  endif
-    mozilla::ipc::IPCResult added = embedderDoc->AddChildDoc(doc, embedderID);
-    if (!added) {
-#  ifdef DEBUG
-      return added;
-#  else
-      return IPC_OK();
-#  endif
-    }
+    a11y::ProxyCreated(
+        doc, a11y::Interfaces::DOCUMENT | a11y::Interfaces::HYPERTEXT);
 #  ifdef XP_WIN
-    // This *must* be called after AddChildDoc because AddChildDoc
-    // calls ProxyCreated and WrapperFor will fail before that.
+    // This *must* be called after ProxyCreated because WrapperFor will fail
+    // before that.
     a11y::AccessibleWrap* wrapper = a11y::WrapperFor(doc);
     MOZ_ASSERT(wrapper);
     wrapper->SetID(aMsaaID);
 #  endif
+    a11y::DocAccessibleParent* embedderDoc;
+    uint64_t embedderID;
+    Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
+    // It's possible the embedder accessible hasn't been set yet; e.g.
+    // a hidden iframe. In that case, embedderDoc will be null and this will
+    // be handled when the embedder is set.
+    if (embedderDoc) {
+      MOZ_ASSERT(embedderID);
+      mozilla::ipc::IPCResult added =
+          embedderDoc->AddChildDoc(doc, embedderID,
+                                   /* aCreating */ false);
+      if (!added) {
+#  ifdef DEBUG
+        return added;
+#  else
+        return IPC_OK();
+#  endif
+      }
+    }
     return IPC_OK();
   } else {
     // null aParentDoc means this document is at the top level in the child
     // process.  That means it makes no sense to get an id for an accessible
     // that is its parent.
     MOZ_ASSERT(!aParentID);
     if (aParentID) {
       return IPC_FAIL_NO_REASON(this);
@@ -3347,22 +3357,16 @@ void BrowserParent::NotifyResolutionChan
 
 void BrowserParent::Deprioritize() {
   if (mActiveInPriorityManager) {
     ProcessPriorityManager::TabActivityChanged(this, false);
     mActiveInPriorityManager = false;
   }
 }
 
-bool BrowserParent::GetHasContentOpener() { return mHasContentOpener; }
-
-void BrowserParent::SetHasContentOpener(bool aHasContentOpener) {
-  mHasContentOpener = aHasContentOpener;
-}
-
 bool BrowserParent::StartApzAutoscroll(float aAnchorX, float aAnchorY,
                                        nsViewID aScrollId,
                                        uint32_t aPresShellId) {
   if (!AsyncPanZoomEnabled()) {
     return false;
   }
 
   bool success = false;
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -249,17 +249,16 @@ class BrowserParent final : public PBrow
   }
 
   void SetOwnerElement(Element* aElement);
 
   void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
     mBrowserDOMWindow = aBrowserDOMWindow;
   }
 
-  void SetHasContentOpener(bool aHasContentOpener);
 
   void SwapFrameScriptsFrom(nsTArray<FrameScriptInfo>& aFrameScripts) {
     aFrameScripts.SwapElements(mDelayedFrameScripts);
   }
 
   void CacheFrameLoader(nsFrameLoader* aFrameLoader);
 
   void Destroy();
@@ -736,18 +735,16 @@ class BrowserParent final : public PBrow
   bool GetHasLayers();
   bool GetRenderLayers();
   void SetRenderLayers(bool aRenderLayers);
   void PreserveLayers(bool aPreserveLayers);
   void NotifyResolutionChanged();
 
   void Deprioritize();
 
-  bool GetHasContentOpener();
-
   bool StartApzAutoscroll(float aAnchorX, float aAnchorY, nsViewID aScrollId,
                           uint32_t aPresShellId);
   void StopApzAutoscroll(nsViewID aScrollId, uint32_t aPresShellId);
 
  protected:
   friend BrowserBridgeParent;
   friend BrowserHost;
 
@@ -943,18 +940,16 @@ class BrowserParent final : public PBrow
   bool mMarkedDestroying;
   // When true, the BrowserParent is invalid and we should not send IPC messages
   // anymore.
   bool mIsDestroyed;
   // True if the cursor changes from the BrowserChild should change the widget
   // cursor.  This happens whenever the cursor is in the tab's region.
   bool mTabSetsCursor;
 
-  bool mHasContentOpener;
-
   // If this flag is set, then the tab's layers will be preserved even when
   // the tab's docshell is inactive.
   bool mPreserveLayers;
 
   // Holds the most recent value passed to the RenderLayers function. This
   // does not necessarily mean that the layers have finished rendering
   // and have uploaded - for that, use mHasLayers.
   bool mRenderLayers;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -227,16 +227,17 @@
 #include "mozilla/StyleSheetInlines.h"
 #include "nsICaptivePortalService.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIBidiKeyboard.h"
 #include "nsLayoutStylesheetCache.h"
 #include "MMPrinter.h"
 #include "nsStreamUtils.h"
 #include "nsIAsyncInputStream.h"
+#include "xpcpublic.h"
 
 #include "mozilla/Sprintf.h"
 
 #ifdef MOZ_WEBRTC
 #  include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
 #if defined(XP_MACOSX)
@@ -1804,17 +1805,25 @@ bool ContentParent::ShouldKeepProcessAli
   }
 
   // We might want to keep some content processes alive for performance reasons.
   // e.g. test runs and privileged content process for some about: pages.
   // We don't want to alter behavior if the pref is not set, so default to 0.
   int32_t processesToKeepAlive = 0;
 
   nsAutoCString keepAlivePref("dom.ipc.keepProcessesAlive.");
-  keepAlivePref.Append(NS_ConvertUTF16toUTF8(mRemoteType));
+
+  if (StringBeginsWith(mRemoteType,
+                       NS_LITERAL_STRING(FISSION_WEB_REMOTE_TYPE)) &&
+      xpc::IsInAutomation()) {
+    keepAlivePref.Append(FISSION_WEB_REMOTE_TYPE);
+    keepAlivePref.AppendLiteral(".perOrigin");
+  } else {
+    keepAlivePref.Append(NS_ConvertUTF16toUTF8(mRemoteType));
+  }
   if (NS_FAILED(
           Preferences::GetInt(keepAlivePref.get(), &processesToKeepAlive))) {
     return false;
   }
 
   int32_t numberOfAliveProcesses = contentParents->Length();
 
   return numberOfAliveProcesses <= processesToKeepAlive;
@@ -4943,20 +4952,16 @@ mozilla::ipc::IPCResult ContentParent::R
     // We always expect to open a new window here. If we don't, it's an error.
     if (!cwi.windowOpened() || NS_FAILED(rv)) {
       if (newTab) {
         newTab->Destroy();
       }
     }
   });
 
-  // Content has requested that we open this new content window, so
-  // we must have an opener.
-  newTab->SetHasContentOpener(true);
-
   BrowserParent::AutoUseNewTab aunt(newTab, &cwi.urlToLoad());
   const uint64_t nextRemoteTabId = ++sNextRemoteTabId;
   sNextBrowserParents.Put(nextRemoteTabId, newTab);
 
   const nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
 
   nsCOMPtr<nsIRemoteTab> newRemoteTab;
   int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -47,16 +47,17 @@
 #define CHILD_PROCESS_SHUTDOWN_MESSAGE \
   NS_LITERAL_STRING("child-process-shutdown")
 
 // These must match the similar ones in E10SUtils.jsm and ProcInfo.h.
 // Process names as reported by about:memory are defined in
 // ContentChild:RecvRemoteType.  Add your value there too or it will be called
 // "Web Content".
 #define DEFAULT_REMOTE_TYPE "web"
+#define FISSION_WEB_REMOTE_TYPE "webIsolated"
 #define FILE_REMOTE_TYPE "file"
 #define EXTENSION_REMOTE_TYPE "extension"
 #define PRIVILEGEDABOUT_REMOTE_TYPE "privilegedabout"
 #define PRIVILEGEDMOZILLA_REMOTE_TYPE "privilegedmozilla"
 #define WITH_COOP_COEP_REMOTE_TYPE_PREFIX "webCOOP+COEP="
 
 // This must start with the DEFAULT_REMOTE_TYPE above.
 #define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"
--- a/dom/l10n/tests/mochitest/chrome.ini
+++ b/dom/l10n/tests/mochitest/chrome.ini
@@ -6,16 +6,17 @@
 [l10n_overlays/test_same_id.html]
 [l10n_overlays/test_same_id_args.html]
 
 [l10n_mutations/test_append_content_post_dcl.html]
 [l10n_mutations/test_append_content_pre_dcl.html]
 [l10n_mutations/test_append_fragment_post_dcl.html]
 [l10n_mutations/test_set_attributes.html]
 [l10n_mutations/test_pause_observing.html]
+[l10n_mutations/test_template.html]
 
 [dom_localization/test_attr_sanitized.html]
 [dom_localization/test_getAttributes.html]
 [dom_localization/test_setAttributes.html]
 [dom_localization/test_translateElements.html]
 [dom_localization/test_translateFragment.html]
 [dom_localization/test_connectRoot.html]
 [dom_localization/test_connectRoot_webcomponent.html]
new file mode 100644
--- /dev/null
+++ b/dom/l10n/tests/mochitest/l10n_mutations/test_template.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test L10n Mutations in Template elements</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+  <link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
+  <script type="application/javascript">
+  "use strict";
+  SimpleTest.waitForExplicitFinish();
+
+  document.addEventListener("DOMContentLoaded", async () => {
+    await document.l10n.ready;
+    let template = document.getElementById("template");
+    let clone = document.importNode(template.content, true);
+    let span = clone.querySelector("span");
+    is(span.textContent.length, 0,
+      "Element has not been translated while in template");
+    document.body.appendChild(clone);
+
+    let verifyL10n = () => {
+      if (span.textContent.length > 0) {
+        window.removeEventListener("MozAfterPaint", verifyL10n);
+        SimpleTest.finish();
+      }
+    };
+    window.addEventListener("MozAfterPaint", verifyL10n);
+  });
+  </script>
+</head>
+<body>
+  <template id="template">
+    <span data-l10n-id="crash-reports-title"></span>
+  </template>
+</body>
+</html>
--- a/dom/media/test/file_autoplay_policy_activation_frame.html
+++ b/dom/media/test/file_autoplay_policy_activation_frame.html
@@ -13,16 +13,17 @@
     </style>
   </head>
   <body>
     <script>
       window.addEventListener("message",
         (event) => {
           if (event.data == "click") {
             SpecialPowers.wrap(document).notifyUserGestureActivation();
+            event.source.postMessage("activated", "*");
           } else if (event.data == "play-audible") {
             playAndPostResult(false, event.source);
           } else if (event.data == "play-muted") {
             playAndPostResult(true, event.source);
           }
         });
       let w = window.opener || window.parent;
       w.postMessage("ready", "*");
--- a/dom/media/test/file_autoplay_policy_activation_window.html
+++ b/dom/media/test/file_autoplay_policy_activation_window.html
@@ -12,55 +12,69 @@
     <script src="/tests/SimpleTest/EventUtils.js"></script>
     <script type="text/javascript" src="manifest.js"></script>
     <script type="text/javascript" src="AutoplayTestUtils.js"></script>
   </head>
   <body>
     <pre id="test">
       <script>
 
-        function testAutoplayInWindow(test_case, parent_window) {
-          log("testAutoplayInWindow: " + test_case.name);
-          playAndPostResult(test_case.muted, parent_window);
-        }
-
-        async function testAutoplayInChildFrame(test_case, parent_window) {
-          log("testAutoplayInChildFrame: " + test_case.name);
-          // Create a child iframe...
-          var frame = document.createElement("iframe");
-          var origin = test_case.same_origin_child
+        async function createChildFrame(testInfo) {
+          let frame = document.createElement("iframe");
+          let origin = testInfo.same_origin_child
             ? "http://mochi.test:8888" : "http://example.org";
           frame.src = origin + "/tests/dom/media/test/file_autoplay_policy_activation_frame.html";
           // Wait for it to load...
           document.body.appendChild(frame);
           is((await nextWindowMessage()).data, "ready", "Expected a 'ready' message");
-          // Click the iframe to activate if appropriate.
-          if (test_case.activated_child) {
-            frame.contentWindow.postMessage("click", "*");
+          return frame;
+        }
+
+        async function activateDocument(testInfo) {
+          // Click the window to activate if appropriate.
+          if (testInfo.activated_from == "parent") {
+            info(`activate parent's document`);
+            SpecialPowers.wrap(document).notifyUserGestureActivation();
+          } else if (testInfo.activated_from == "child") {
+            info(`activate child's document`);
+            testInfo.childFrame.contentWindow.postMessage("click", "*");
+            is((await nextWindowMessage()).data, "activated", "has activated child frame.");
           }
+        }
+
+        function testAutoplayInWindow(testInfo) {
+          info(`start autoplay from parent frame`);
+          playAndPostResult(testInfo.muted, testInfo.parentWindow);
+        }
+
+        async function testAutoplayInChildFrame(testInfo) {
+          info("start autoplay from " +  (testInfo.same_origin_child ? "same" : "cross")  + " origin child frame");
           // Ask the child iframe to try to play video.
-          let play_message = test_case.muted ? "play-muted" : "play-audible";
-          frame.contentWindow.postMessage(play_message, "*");
+          let play_message = testInfo.muted ? "play-muted" : "play-audible";
+          testInfo.childFrame.contentWindow.postMessage(play_message, "*");
           // Wait for the iframe to tell us whether it could play video.
           let result = await nextWindowMessage();
           // Report whether the iframe could play to the parent.
-          parent_window.postMessage(result.data, "*");
+          testInfo.parentWindow.postMessage(result.data, "*");
         }
 
         nextWindowMessage().then(
-          (event) => {
-            let test_case = event.data;
-            // Click the window to activate if appropriate.
-            if (test_case.activated_parent) {
-              SpecialPowers.wrap(document).notifyUserGestureActivation();
-            }
-            let parent_window = event.source;
-            if (test_case.same_origin_child === undefined) {
-              testAutoplayInWindow(test_case, parent_window);
-            } else {
-              testAutoplayInChildFrame(test_case, parent_window);
+          async (event) => {
+            let testInfo = event.data;
+            testInfo.parentWindow = event.source;
+            testInfo.childFrame = await createChildFrame(testInfo);
+
+            await activateDocument(testInfo);
+            switch (testInfo.play_from) {
+              case "parent":
+                testAutoplayInWindow(testInfo);
+                break;
+              case "child":
+                testAutoplayInChildFrame(testInfo);
+                break;
+              default:
+                ok(false, "Incorrect 'play_from' value!")
             }
           });
-
       </script>
     </pre>
   </body>
 </html>
--- a/dom/media/test/test_autoplay_policy_activation.html
+++ b/dom/media/test/test_autoplay_policy_activation.html
@@ -18,121 +18,143 @@
                         ["media.autoplay.enabled.user-gestures-needed", true]);
 
         SpecialPowers.pushPrefEnv({'set': gTestPrefs}, () => {
           runTest();
         });
 
         let test_cases = [
           {
-            name: "inaudible playback in unactivated same-origin iframe in activated parent allowed",
+            name: "inaudible playback in unactivated same-origin iframe in activated parent -> allowed",
             muted: true,
             same_origin_child: true,
-            activated_child: false,
-            activated_parent: true,
+            activated_from: "parent",
+            play_from: "child",
             should_play: true,
           },
 
           {
-            name: "inaudible playback in unactivated same-origin iframe in unactivated parent allowed",
+            name: "inaudible playback in unactivated same-origin iframe in unactivated parent -> allowed",
             muted: true,
             same_origin_child: true,
-            activated_child: false,
-            activated_parent: false,
+            activated_from: "none",
+            play_from: "child",
+            should_play: true,
+          },
+
+          {
+            name: "audible playback in unactivated same-origin iframe in activated parent -> allowed",
+            muted: false,
+            same_origin_child: true,
+            activated_from: "parent",
+            play_from: "child",
             should_play: true,
           },
 
           {
-            name: "audible playback in unactivated same-origin iframe in activated parent allowed",
+            name: "audible playback in unactivated same-origin iframe in unactivated parent -> blocked",
             muted: false,
             same_origin_child: true,
-            activated_child: false,
-            activated_parent: true,
+            activated_from: "none",
+            play_from: "child",
+            should_play: false,
+          },
+
+          {
+            name: "inaudible playback in unactivated cross-origin iframe in activated parent -> allowed",
+            muted: true,
+            same_origin_child: false,
+            activated_from: "parent",
+            play_from: "child",
             should_play: true,
           },
 
           {
-            name: "audible playback in unactivated same-origin iframe in unactivated parent blocked",
-            muted: false,
-            same_origin_child: true,
-            activated_child: false,
-            activated_parent: false,
-            should_play: false,
+            name: "inaudible playback in unactivated cross-origin iframe in unactivated parent -> allowed",
+            muted: true,
+            same_origin_child: false,
+            activated_from: "none",
+            play_from: "child",
+            should_play: true,
           },
 
           {
-            name: "inaudible playback in unactivated cross-origin iframe in activated parent allowed",
-            muted: true,
+            name: "audible playback in unactivated cross-origin iframe in activated parent -> allowed",
+            muted: false,
             same_origin_child: false,
-            activated_child: false,
-            activated_parent: true,
+            activated_from: "parent",
+            play_from: "child",
             should_play: true,
           },
 
           {
-            name: "inaudible playback in unactivated cross-origin iframe in unactivated parent allowed",
-            muted: true,
-            same_origin_child: false,
-            activated_child: false,
-            activated_parent: false,
-            should_play: true,
-          },
-
-          {
-            name: "audible playback in unactivated cross-origin iframe in activated parent allowed",
+            name: "audible playback in unactivated cross-origin iframe in unactivated parent -> blocked",
             muted: false,
             same_origin_child: false,
-            activated_child: false,
-            activated_parent: true,
-            should_play: true,
-          },
-
-          {
-            name: "audible playback in unactivated cross-origin iframe in unactivated parent blocked",
-            muted: false,
-            same_origin_child: false,
-            activated_child: false,
-            activated_parent: false,
+            activated_from: "none",
+            play_from: "child",
             should_play: false,
           },
 
           {
-            name: "audible playback in activated cross-origin iframe allowed",
+            name: "audible playback in activated cross-origin iframe -> allowed",
             muted: false,
             same_origin_child: false,
-            activated_child: true,
-            activated_parent: false,
+            activated_from: "child",
+            play_from: "child",
             should_play: true,
           },
 
           {
-            name: "audible playback in activated document allowed",
+            name: "audible playback in activated document -> allowed",
             muted: false,
-            activated_parent: true,
+            activated_from: "parent",
+            play_from: "parent",
             should_play: true,
           },
 
           {
-            name: "audible playback in unactivated document blocked",
+            name: "audible playback in unactivated document -> blocked",
             muted: false,
-            activated_parent: false,
+            activated_from: "none",
+            play_from: "parent",
             should_play: false,
           },
 
           {
-            name: "inaudible playback in activated document allowed",
-            muted: true,
-            activated_parent: true,
+            name: "audible playback in activated document (via cross-origin child) -> allowed",
+            muted: false,
+            same_origin_child: false,
+            activated_from: "child",
+            play_from: "parent",
             should_play: true,
           },
 
           {
-            name: "inaudible playback in unactivated document allowed",
+            name: "audible playback in activated document (via same-origin child) -> allowed",
+            muted: false,
+            same_origin_child: true,
+            activated_from: "child",
+            play_from: "parent",
+            should_play: true,
+          },
+
+          {
+            name: "inaudible playback in activated document -> allowed",
             muted: true,
-            activated_parent: false,
+            activated_from: "parent",
+            play_from: "parent",
+            should_play: true,
+          },
+
+          {
+            name: "inaudible playback in unactivated document -> allowed",
+            muted: true,
+            activated_from: "none",
+            play_from: "parent",
             should_play: true,
           },
 
         ];
 
         let child_url = "file_autoplay_policy_activation_window.html";
 
         async function runTest() {
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -103,21 +103,16 @@ DIRS += [
     'serviceworkers',
     'simpledb',
     'reporting',
     'localstorage',
     'prio',
     'l10n',
 ]
 
-if CONFIG['MOZ_XBL']:
-    DIRS += ['xbl']
-else:
-    EXPORTS += ['xbl/stub/nsXBLBinding.h']
-
 if CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['plugins/ipc/hangui']
 
 DIRS += ['presentation']
 
 TEST_DIRS += [
     'tests',
     'imptests',
--- a/dom/prototype/moz.build
+++ b/dom/prototype/moz.build
@@ -15,14 +15,11 @@ SOURCES += [
     'PrototypeDocumentContentSink.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/xul',
 ]
 
-if CONFIG['MOZ_XBL']:
-    LOCAL_INCLUDES += ['/dom/xbl']
-
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
 
 FINAL_LIBRARY = 'xul'
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -119,17 +119,17 @@ ServiceWorkerPrivate::~ServiceWorkerPriv
   MOZ_ASSERT(mSupportsArray.IsEmpty());
   MOZ_ASSERT(mIdlePromiseHolder.IsEmpty());
 
   mIdleWorkerTimer->Cancel();
 }
 
 namespace {
 
-class CheckScriptEvaluationWithCallback final : public WorkerRunnable {
+class CheckScriptEvaluationWithCallback final : public WorkerDebuggeeRunnable {
   nsMainThreadPtrHandle<ServiceWorkerPrivate> mServiceWorkerPrivate;
   nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
 
   // The script evaluation result must be reported even if the runnable
   // is cancelled.
   RefPtr<LifeCycleEventCallback> mScriptEvaluationCallback;
 
 #ifdef DEBUG
@@ -137,17 +137,17 @@ class CheckScriptEvaluationWithCallback 
 #endif
 
  public:
   CheckScriptEvaluationWithCallback(
       WorkerPrivate* aWorkerPrivate,
       ServiceWorkerPrivate* aServiceWorkerPrivate,
       KeepAliveToken* aKeepAliveToken,
       LifeCycleEventCallback* aScriptEvaluationCallback)
-      : WorkerRunnable(aWorkerPrivate),
+      : WorkerDebuggeeRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
         mServiceWorkerPrivate(new nsMainThreadPtrHolder<ServiceWorkerPrivate>(
             "CheckScriptEvaluationWithCallback::mServiceWorkerPrivate",
             aServiceWorkerPrivate)),
         mKeepAliveToken(new nsMainThreadPtrHolder<KeepAliveToken>(
             "CheckScriptEvaluationWithCallback::mKeepAliveToken",
             aKeepAliveToken)),
         mScriptEvaluationCallback(aScriptEvaluationCallback)
 #ifdef DEBUG
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -254,13 +254,10 @@ LOCAL_INCLUDES += [
     '/dom/xml',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
     '/layout/xul',
 ]
 
-if CONFIG['MOZ_XBL']:
-    LOCAL_INCLUDES += ['/dom/xbl']
-
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/dom/worklet/WorkletThread.cpp
+++ b/dom/worklet/WorkletThread.cpp
@@ -368,17 +368,17 @@ void WorkletThread::Terminate() {
 
   nsContentUtils::UnregisterShutdownObserver(this);
 
   RefPtr<TerminateRunnable> runnable = new TerminateRunnable(this);
   DispatchRunnable(runnable.forget());
 }
 
 void WorkletThread::TerminateInternal() {
-  AssertIsOnWorkletThread();
+  MOZ_ASSERT(!CycleCollectedJSContext::Get() || IsOnWorkletThread());
 
   mExitLoop = true;
 
   nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(
       "WorkletThread::Shutdown", this, &WorkletThread::Shutdown);
   NS_DispatchToMainThread(runnable);
 }
 
deleted file mode 100644
--- a/dom/xbl/XBLChildrenElement.cpp
+++ /dev/null
@@ -1,177 +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 "mozilla/dom/XBLChildrenElement.h"
-
-#include "mozilla/PresShell.h"
-#include "mozilla/dom/NodeListBinding.h"
-#include "nsAttrValueOrString.h"
-#include "nsCharSeparatedTokenizer.h"
-
-namespace mozilla {
-namespace dom {
-
-XBLChildrenElement::~XBLChildrenElement() {}
-
-NS_IMPL_ELEMENT_CLONE(XBLChildrenElement)
-
-nsresult XBLChildrenElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
-                                           const nsAttrValueOrString* aValue,
-                                           bool aNotify) {
-  if (aNamespaceID == kNameSpaceID_None) {
-    if (aName == nsGkAtoms::includes) {
-      mIncludes.Clear();
-      if (aValue) {
-        nsCharSeparatedTokenizer tok(
-            aValue->String(), '|',
-            nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
-        while (tok.hasMoreTokens()) {
-          mIncludes.AppendElement(NS_Atomize(tok.nextToken()));
-        }
-      }
-    }
-  }
-
-  return nsXMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify);
-}
-
-void XBLChildrenElement::DoRemoveDefaultContent(bool aNotify) {
-  // Default content is going away, need to tell layout about it first.
-  MOZ_ASSERT(HasChildren(), "Why bothering?");
-  MOZ_ASSERT(GetParentElement());
-
-  // We don't want to do this from frame construction while setting up the
-  // binding initially.
-  if (aNotify) {
-    Element* parent = GetParentElement();
-    if (Document* doc = parent->GetComposedDoc()) {
-      if (PresShell* presShell = doc->GetPresShell()) {
-        presShell->DestroyFramesForAndRestyle(parent);
-      }
-    }
-  }
-
-  for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    MOZ_ASSERT(!child->GetPrimaryFrame());
-    MOZ_ASSERT(!child->IsElement() || !child->AsElement()->HasServoData());
-    child->SetXBLInsertionPoint(nullptr);
-  }
-}
-
-}  // namespace dom
-}  // namespace mozilla
-
-using namespace mozilla::dom;
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsAnonymousContentList, mParent)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnonymousContentList)
-
-NS_INTERFACE_TABLE_HEAD(nsAnonymousContentList)
-  NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
-  NS_INTERFACE_TABLE(nsAnonymousContentList, nsINodeList)
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsAnonymousContentList)
-NS_INTERFACE_MAP_END
-
-uint32_t nsAnonymousContentList::Length() {
-  if (!mParent) {
-    return 0;
-  }
-
-  uint32_t count = 0;
-  for (nsIContent* child = mParent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-      XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (point->HasInsertedChildren()) {
-        count += point->InsertedChildrenLength();
-      } else {
-        count += point->GetChildCount();
-      }
-    } else {
-      ++count;
-    }
-  }
-
-  return count;
-}
-
-nsIContent* nsAnonymousContentList::Item(uint32_t aIndex) {
-  if (!mParent) {
-    return nullptr;
-  }
-
-  uint32_t remIndex = aIndex;
-  for (nsIContent* child = mParent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-      XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (point->HasInsertedChildren()) {
-        if (remIndex < point->InsertedChildrenLength()) {
-          return point->InsertedChild(remIndex);
-        }
-        remIndex -= point->InsertedChildrenLength();
-      } else {
-        if (remIndex < point->GetChildCount()) {
-          return point->GetChildAt_Deprecated(remIndex);
-        }
-        remIndex -= point->GetChildCount();
-      }
-    } else {
-      if (remIndex == 0) {
-        return child;
-      }
-      --remIndex;
-    }
-  }
-
-  return nullptr;
-}
-
-int32_t nsAnonymousContentList::IndexOf(nsIContent* aContent) {
-  NS_ASSERTION(
-      !aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL),
-      "Looking for insertion point");
-
-  if (!mParent) {
-    return -1;
-  }
-
-  int32_t index = 0;
-  for (nsIContent* child = mParent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-      XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (point->HasInsertedChildren()) {
-        int32_t insIndex = point->IndexOfInsertedChild(aContent);
-        if (insIndex != -1) {
-          return index + insIndex;
-        }
-        index += point->InsertedChildrenLength();
-      } else {
-        int32_t insIndex = point->ComputeIndexOf(aContent);
-        if (insIndex != -1) {
-          return index + insIndex;
-        }
-        index += point->GetChildCount();
-      }
-    } else {
-      if (child == aContent) {
-        return index;
-      }
-      ++index;
-    }
-  }
-
-  return -1;
-}
-
-JSObject* nsAnonymousContentList::WrapObject(
-    JSContext* cx, JS::Handle<JSObject*> aGivenProto) {
-  return mozilla::dom::NodeList_Binding::Wrap(cx, this, aGivenProto);
-}
deleted file mode 100644
--- a/dom/xbl/XBLChildrenElement.h
+++ /dev/null
@@ -1,155 +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 nsXBLChildrenElement_h___
-#define nsXBLChildrenElement_h___
-
-#include "nsINodeList.h"
-#include "nsBindingManager.h"
-#include "mozilla/dom/nsXMLElement.h"
-
-class nsAnonymousContentList;
-
-namespace mozilla {
-namespace dom {
-
-class XBLChildrenElement : public nsXMLElement {
- public:
-  explicit XBLChildrenElement(
-      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
-      : nsXMLElement(std::move(aNodeInfo)) {}
-
-  // nsISupports
-  NS_INLINE_DECL_REFCOUNTING_INHERITED(XBLChildrenElement, nsXMLElement)
-
-  // nsINode interface methods
-  virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
-
-  void AppendInsertedChild(nsIContent* aChild, bool aNotify) {
-    // Appending an inserted child causes the inserted
-    // children to be projected instead of default content.
-    MaybeRemoveDefaultContent(aNotify);
-
-    mInsertedChildren.AppendElement(aChild);
-    aChild->SetXBLInsertionPoint(this);
-  }
-
-  void InsertInsertedChildAt(nsIContent* aChild, uint32_t aIndex) {
-    // Inserting an inserted child causes the inserted
-    // children to be projected instead of default content.
-    MaybeRemoveDefaultContent(true);
-
-    mInsertedChildren.InsertElementAt(aIndex, aChild);
-    aChild->SetXBLInsertionPoint(this);
-  }
-
-  void RemoveInsertedChild(nsIContent* aChild) {
-    // Can't use this assertion as we cheat for dynamic insertions and
-    // only insert in the innermost insertion point.
-    // NS_ASSERTION(mInsertedChildren.Contains(aChild),
-    //             "Removing child that's not there");
-    mInsertedChildren.RemoveElement(aChild);
-
-    // After removing the inserted child, default content
-    // may be projected into this insertion point.
-    //
-    // FIXME: Layout should be told about this before clearing
-    // mInsertedChildren, this leaves stale styles and frames in the frame tree.
-    MaybeSetupDefaultContent();
-  }
-
-  void ClearInsertedChildren() {
-    for (auto* child : mInsertedChildren) {
-      if (child->GetXBLInsertionPoint() == this) {
-        child->SetXBLInsertionPoint(nullptr);
-      }
-    }
-    mInsertedChildren.Clear();
-
-    // After clearing inserted children, default content
-    // will be projected into this insertion point.
-    //
-    // FIXME: Layout should be told about this before clearing
-    // mInsertedChildren, this leaves stale styles and frames in the frame tree.
-    MaybeSetupDefaultContent();
-  }
-
-  void MaybeSetupDefaultContent() {
-    if (!HasInsertedChildren()) {
-      for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild();
-           child; child = child->GetNextSibling()) {
-        child->SetXBLInsertionPoint(this);
-      }
-    }
-  }
-
-  void MaybeRemoveDefaultContent(bool aNotify) {
-    if (!HasInsertedChildren() && HasChildren()) {
-      DoRemoveDefaultContent(aNotify);
-    }
-  }
-
-  uint32_t InsertedChildrenLength() { return mInsertedChildren.Length(); }
-
-  bool HasInsertedChildren() { return !mInsertedChildren.IsEmpty(); }
-
-  int32_t IndexOfInsertedChild(nsIContent* aChild) {
-    return mInsertedChildren.IndexOf(aChild);
-  }
-
-  bool Includes(nsIContent* aChild) {
-    NS_ASSERTION(!mIncludes.IsEmpty(),
-                 "Shouldn't check for includes on default insertion point");
-    return mIncludes.Contains(aChild->NodeInfo()->NameAtom());
-  }
-
-  bool IsDefaultInsertion() { return mIncludes.IsEmpty(); }
-
-  nsIContent* InsertedChild(uint32_t aIndex) {
-    return mInsertedChildren[aIndex];
-  }
-
- protected:
-  ~XBLChildrenElement();
-  virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
-                                 const nsAttrValueOrString* aValue,
-                                 bool aNotify) override;
-
-  void DoRemoveDefaultContent(bool aNotify);
-
- private:
-  nsTArray<nsIContent*> mInsertedChildren;  // WEAK
-  nsTArray<RefPtr<nsAtom> > mIncludes;
-};
-
-}  // namespace dom
-}  // namespace mozilla
-
-class nsAnonymousContentList final : public nsINodeList {
- public:
-  explicit nsAnonymousContentList(nsIContent* aParent) : mParent(aParent) {}
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsAnonymousContentList)
-
-  // nsINodeList interface
-  virtual int32_t IndexOf(nsIContent* aContent) override;
-  virtual nsINode* GetParentObject() override { return mParent; }
-  virtual nsIContent* Item(uint32_t aIndex) override;
-  uint32_t Length() override;
-
-  virtual JSObject* WrapObject(JSContext* cx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  bool IsListFor(nsIContent* aContent) { return mParent == aContent; }
-
- private:
-  virtual ~nsAnonymousContentList() {}
-
-  nsCOMPtr<nsIContent> mParent;
-};
-
-#endif  // nsXBLChildrenElement_h___
deleted file mode 100644
--- a/dom/xbl/moz.build
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-with Files("**"):
-    BUG_COMPONENT = ("Core", "XBL")
-
-EXPORTS += [
-    'nsBindingManager.h',
-    'nsXBLBinding.h',
-    'nsXBLPrototypeHandler.h',
-    'nsXBLService.h',
-]
-
-EXPORTS.mozilla.dom += [
-    'XBLChildrenElement.h',
-]
-
-UNIFIED_SOURCES += [
-    'nsBindingManager.cpp',
-    'nsXBLBinding.cpp',
-    'nsXBLContentSink.cpp',
-    'nsXBLDocumentInfo.cpp',
-    'nsXBLEventHandler.cpp',
-    'nsXBLProtoImpl.cpp',
-    'nsXBLProtoImplField.cpp',
-    'nsXBLProtoImplMethod.cpp',
-    'nsXBLProtoImplProperty.cpp',
-    'nsXBLPrototypeBinding.cpp',
-    'nsXBLPrototypeHandler.cpp',
-    'nsXBLSerialize.cpp',
-    'nsXBLService.cpp',
-    'XBLChildrenElement.cpp',
-]
-
-LOCAL_INCLUDES += [
-    '/dom/base',
-    '/dom/html',
-    '/dom/xml',
-    '/dom/xul',
-    '/layout/style',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
-
-MOCHITEST_MANIFESTS += ['test/mochitest.ini']
-MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
-
-if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-    CXXFLAGS += ['-Wno-error=shadow']
deleted file mode 100644
--- a/dom/xbl/nsBindingManager.cpp
+++ /dev/null
@@ -1,876 +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 "nsBindingManager.h"
-
-#include "nsAutoPtr.h"
-#include "nsCOMPtr.h"
-#include "nsXBLService.h"
-#include "nsIInputStream.h"
-#include "nsIURI.h"
-#include "nsIURL.h"
-#include "nsIChannel.h"
-#include "nsString.h"
-#include "plstr.h"
-#include "nsIContent.h"
-#include "nsIContentInlines.h"
-#include "mozilla/dom/Document.h"
-#include "nsContentUtils.h"
-#include "nsIXMLContentSink.h"
-#include "nsContentCID.h"
-#include "mozilla/dom/XMLDocument.h"
-#include "nsIStreamListener.h"
-#include "ChildIterator.h"
-#include "nsITimer.h"
-
-#include "nsXBLBinding.h"
-#include "nsXBLPrototypeBinding.h"
-#include "nsXBLDocumentInfo.h"
-#include "mozilla/dom/XBLChildrenElement.h"
-#ifdef MOZ_XUL
-#  include "nsXULPrototypeCache.h"
-#endif
-
-#include "nsIWeakReference.h"
-
-#include "nsWrapperCacheInlines.h"
-#include "nsIXPConnect.h"
-#include "nsDOMCID.h"
-#include "nsIScriptGlobalObject.h"
-#include "nsTHashtable.h"
-
-#include "nsIScriptContext.h"
-#include "xpcpublic.h"
-#include "js/Wrapper.h"
-
-#include "nsThreadUtils.h"
-#include "mozilla/dom/NodeListBinding.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/PresShell.h"
-#include "mozilla/PresShellInlines.h"
-#include "mozilla/Unused.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-// Implement our nsISupports methods
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsBindingManager)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBindingManager)
-  tmp->mDestroyed = true;
-
-  if (tmp->mBoundContentSet) tmp->mBoundContentSet->Clear();
-
-  if (tmp->mDocumentTable) tmp->mDocumentTable->Clear();
-
-  if (tmp->mLoadingDocTable) tmp->mLoadingDocTable->Clear();
-
-  if (tmp->mWrapperTable) {
-    tmp->mWrapperTable->Clear();
-    tmp->mWrapperTable = nullptr;
-  }
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttachedStack)
-
-  if (tmp->mProcessAttachedQueueEvent) {
-    tmp->mProcessAttachedQueueEvent->Revoke();
-  }
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBindingManager)
-  // The hashes keyed on nsIContent are traversed from the nsIContent itself.
-  if (tmp->mDocumentTable) {
-    for (auto iter = tmp->mDocumentTable->Iter(); !iter.Done(); iter.Next()) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocumentTable value");
-      cb.NoteXPCOMChild(iter.UserData());
-    }
-  }
-  if (tmp->mLoadingDocTable) {
-    for (auto iter = tmp->mLoadingDocTable->Iter(); !iter.Done(); iter.Next()) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mLoadingDocTable value");
-      cb.NoteXPCOMChild(iter.UserData());
-    }
-  }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttachedStack)
-  // No need to traverse mProcessAttachedQueueEvent, since it'll just
-  // fire at some point or become revoke and drop its ref to us.
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsBindingManager)
-  NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBindingManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBindingManager)
-
-// Constructors/Destructors
-nsBindingManager::nsBindingManager(Document* aDocument)
-    : mProcessingAttachedStack(false),
-      mDestroyed(false),
-      mAttachedStackSizeOnOutermost(0),
-      mDocument(aDocument) {}
-
-nsBindingManager::~nsBindingManager(void) { mDestroyed = true; }
-
-nsXBLBinding* nsBindingManager::GetBindingWithContent(
-    const nsIContent* aContent) {
-  nsXBLBinding* binding = aContent ? aContent->GetXBLBinding() : nullptr;
-  return binding ? binding->GetBindingWithContent() : nullptr;
-}
-
-void nsBindingManager::AddBoundContent(nsIContent* aContent) {
-  if (!mBoundContentSet) {
-    mBoundContentSet = new nsTHashtable<nsRefPtrHashKey<nsIContent>>;
-  }
-  mBoundContentSet->PutEntry(aContent);
-}
-
-void nsBindingManager::RemoveBoundContent(nsIContent* aContent) {
-  if (mBoundContentSet) {
-    mBoundContentSet->RemoveEntry(aContent);
-  }
-
-  // The death of the bindings means the death of the JS wrapper.
-  SetWrappedJS(aContent, nullptr);
-}
-
-nsIXPConnectWrappedJS* nsBindingManager::GetWrappedJS(nsIContent* aContent) {
-  if (!mWrapperTable) {
-    return nullptr;
-  }
-
-  if (!aContent || !aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    return nullptr;
-  }
-
-  return mWrapperTable->GetWeak(aContent);
-}
-
-nsresult nsBindingManager::SetWrappedJS(nsIContent* aContent,
-                                        nsIXPConnectWrappedJS* aWrappedJS) {
-  if (mDestroyed) {
-    return NS_OK;
-  }
-
-  if (aWrappedJS) {
-    // lazily create the table, but only when adding elements
-    if (!mWrapperTable) {
-      mWrapperTable = new WrapperHashtable();
-    }
-    aContent->SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
-
-    NS_ASSERTION(aContent, "key must be non-null");
-    if (!aContent) return NS_ERROR_INVALID_ARG;
-
-    mWrapperTable->Put(aContent, aWrappedJS);
-
-    return NS_OK;
-  }
-
-  // no value, so remove the key from the table
-  if (mWrapperTable) {
-    mWrapperTable->Remove(aContent);
-  }
-
-  return NS_OK;
-}
-
-void nsBindingManager::RemovedFromDocumentInternal(
-    nsIContent* aContent, Document* aOldDocument,
-    DestructorHandling aDestructorHandling) {
-  MOZ_ASSERT(aOldDocument != nullptr, "no old document");
-
-  RefPtr<nsXBLBinding> binding = aContent->GetXBLBinding();
-  if (binding) {
-    // The binding manager may have been destroyed before a runnable
-    // has had a chance to reach this point. If so, we bail out on calling
-    // BindingDetached (which may invoke a XBL destructor) and
-    // ChangeDocument, but we still want to clear out the binding
-    // and insertion parent that may hold references.
-    if (!mDestroyed && aDestructorHandling == eRunDtor) {
-      binding->PrototypeBinding()->BindingDetached(binding->GetBoundElement());
-      binding->ChangeDocument(aOldDocument, nullptr);
-    }
-
-    aContent->AsElement()->SetXBLBinding(nullptr, this);
-  }
-
-  // Clear out insertion point and content lists.
-  aContent->SetXBLInsertionPoint(nullptr);
-}
-
-nsINodeList* nsBindingManager::GetAnonymousNodesFor(nsIContent* aContent) {
-  nsXBLBinding* binding = GetBindingWithContent(aContent);
-  return binding ? binding->GetAnonymousNodeList() : nullptr;
-}
-
-nsresult nsBindingManager::ClearBinding(Element* aElement) {
-  // Hold a ref to the binding so it won't die when we remove it from our table
-  RefPtr<nsXBLBinding> binding = aElement ? aElement->GetXBLBinding() : nullptr;
-
-  if (!binding) {
-    return NS_OK;
-  }
-
-  // For now we can only handle removing a binding if it's the only one
-  NS_ENSURE_FALSE(binding->GetBaseBinding(), NS_ERROR_FAILURE);
-
-  // Hold strong ref in case removing the binding tries to close the
-  // window or something.
-  // XXXbz should that be ownerdoc?  Wouldn't we need a ref to the
-  // currentdoc too?  What's the one that should be passed to
-  // ChangeDocument?
-  nsCOMPtr<Document> doc = aElement->OwnerDoc();
-
-  // Destroy the frames here before the UnbindFromTree happens.
-  if (PresShell* presShell = doc->GetPresShell()) {
-    presShell->DestroyFramesForAndRestyle(aElement);
-  }
-
-  // Finally remove the binding...
-  // XXXbz this doesn't remove the implementation!  Should fix!  Until
-  // then we need the explicit UnhookEventHandlers here.
-  binding->UnhookEventHandlers();
-  binding->ChangeDocument(doc, nullptr);
-  aElement->SetXBLBinding(nullptr, this);
-  binding->MarkForDeath();
-
-  // ...and recreate its frames. We need to do this since the frames may have
-  // been removed and style may have changed due to the removal of the
-  // anonymous children.
-  // XXXbz this should be using the current doc (if any), not the owner doc.
-  // get the shell again, just in case it changed
-  PresShell* presShell = doc->GetPresShell();
-  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
-  presShell->PostRecreateFramesFor(aElement);
-  return NS_OK;
-}
-
-void nsBindingManager::RemoveFromAttachedQueue(nsXBLBinding* aBinding) {
-  // Don't remove items here as that could mess up an executing
-  // ProcessAttachedQueue. Instead, null the entry in the queue.
-  size_t index = mAttachedStack.IndexOf(aBinding);
-  if (index != nsBindingList::NoIndex) {
-    mAttachedStack[index] = nullptr;
-  }
-}
-
-nsresult nsBindingManager::AddToAttachedQueue(nsXBLBinding* aBinding) {
-  mAttachedStack.AppendElement(aBinding);
-
-  // If we're in the middle of processing our queue already, don't
-  // bother posting the event.
-  if (!mProcessingAttachedStack && !mProcessAttachedQueueEvent) {
-    PostProcessAttachedQueueEvent();
-  }
-
-  // Make sure that flushes will flush out the new items as needed.
-  if (PresShell* presShell = mDocument->GetPresShell()) {
-    presShell->SetNeedStyleFlush();
-  }
-
-  return NS_OK;
-}
-
-void nsBindingManager::PostProcessAttachedQueueEvent() {
-  MOZ_ASSERT(NS_IsMainThread());
-  if (!mDocument) {
-    return;
-  }
-  mProcessAttachedQueueEvent =
-      NewRunnableMethod("nsBindingManager::DoProcessAttachedQueue", this,
-                        &nsBindingManager::DoProcessAttachedQueue);
-  nsresult rv = mDocument->EventTargetFor(TaskCategory::Other)
-                    ->Dispatch(do_AddRef(mProcessAttachedQueueEvent));
-  if (NS_SUCCEEDED(rv)) {
-    mDocument->BlockOnload();
-  }
-}
-
-// static
-void nsBindingManager::PostPAQEventCallback(nsITimer* aTimer, void* aClosure) {
-  RefPtr<nsBindingManager> mgr = already_AddRefed<nsBindingManager>(
-      static_cast<nsBindingManager*>(aClosure));
-  mgr->PostProcessAttachedQueueEvent();
-  NS_RELEASE(aTimer);
-}
-
-void nsBindingManager::DoProcessAttachedQueue() {
-  if (!mProcessingAttachedStack) {
-    ProcessAttachedQueue();
-
-    NS_ASSERTION(mAttachedStack.Length() == 0,
-                 "Shouldn't have pending bindings!");
-
-    mProcessAttachedQueueEvent = nullptr;
-  } else {
-    // Someone's doing event processing from inside a constructor.
-    // They're evil, but we'll fight back!  Just poll on them being
-    // done and repost the attached queue event.
-    //
-    // But don't poll in a tight loop -- otherwise we keep the Gecko
-    // event loop non-empty and trigger bug 1021240 on OS X.
-    nsresult rv = NS_ERROR_FAILURE;
-    nsCOMPtr<nsITimer> timer;
-    rv = NS_NewTimerWithFuncCallback(
-        getter_AddRefs(timer), PostPAQEventCallback, this, 100,
-        nsITimer::TYPE_ONE_SHOT, "nsBindingManager::DoProcessAttachedQueue");
-    if (NS_SUCCEEDED(rv)) {
-      NS_ADDREF_THIS();
-      // We drop our reference to the timer here, since the timer callback is
-      // responsible for releasing the object.
-      Unused << timer.forget().take();
-    }
-  }
-
-  // No matter what, unblock onload for the event that's fired.
-  if (mDocument) {
-    // Hold a strong reference while calling UnblockOnload since that might
-    // run script.
-    nsCOMPtr<Document> doc = mDocument;
-    doc->UnblockOnload(true);
-  }
-}
-
-void nsBindingManager::ProcessAttachedQueueInternal(uint32_t aSkipSize) {
-  mProcessingAttachedStack = true;
-
-  // Excute constructors. Do this from high index to low
-  while (mAttachedStack.Length() > aSkipSize) {
-    uint32_t lastItem = mAttachedStack.Length() - 1;
-    RefPtr<nsXBLBinding> binding = mAttachedStack.ElementAt(lastItem);
-    mAttachedStack.RemoveElementAt(lastItem);
-    if (binding) {
-      binding->ExecuteAttachedHandler();
-    }
-  }
-
-  // If NodeWillBeDestroyed has run we don't want to clobber
-  // mProcessingAttachedStack set there.
-  if (mDocument) {
-    mProcessingAttachedStack = false;
-  }
-
-  NS_ASSERTION(mAttachedStack.Length() == aSkipSize, "How did we get here?");
-
-  mAttachedStack.Compact();
-}
-
-// Keep bindings and bound elements alive while executing detached handlers.
-void nsBindingManager::ExecuteDetachedHandlers() {
-  // Walk our hashtable of bindings.
-  if (!mBoundContentSet) {
-    return;
-  }
-
-  nsCOMArray<nsIContent> boundElements;
-  nsBindingList bindings;
-
-  for (auto iter = mBoundContentSet->Iter(); !iter.Done(); iter.Next()) {
-    nsXBLBinding* binding = iter.Get()->GetKey()->GetXBLBinding();
-    if (binding && bindings.AppendElement(binding)) {
-      if (!boundElements.AppendObject(binding->GetBoundElement())) {
-        bindings.RemoveLastElement();
-      }
-    }
-  }
-
-  uint32_t i, count = bindings.Length();
-  for (i = 0; i < count; ++i) {
-    bindings[i]->ExecuteDetachedHandler();
-  }
-}
-
-nsresult nsBindingManager::PutXBLDocumentInfo(
-    nsXBLDocumentInfo* aDocumentInfo) {
-  MOZ_ASSERT(aDocumentInfo, "Must have a non-null documentinfo!");
-
-  if (!mDocumentTable) {
-    mDocumentTable = new nsRefPtrHashtable<nsURIHashKey, nsXBLDocumentInfo>();
-  }
-
-  mDocumentTable->Put(aDocumentInfo->DocumentURI(), aDocumentInfo);
-
-  return NS_OK;
-}
-
-void nsBindingManager::RemoveXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo) {
-  if (mDocumentTable) {
-    mDocumentTable->Remove(aDocumentInfo->DocumentURI());
-  }
-}
-
-nsXBLDocumentInfo* nsBindingManager::GetXBLDocumentInfo(nsIURI* aURL) {
-  if (!mDocumentTable) return nullptr;
-
-  return mDocumentTable->GetWeak(aURL);
-}
-
-nsresult nsBindingManager::PutLoadingDocListener(nsIURI* aURL,
-                                                 nsIStreamListener* aListener) {
-  MOZ_ASSERT(aListener, "Must have a non-null listener!");
-
-  if (!mLoadingDocTable) {
-    mLoadingDocTable =
-        new nsInterfaceHashtable<nsURIHashKey, nsIStreamListener>();
-  }
-  mLoadingDocTable->Put(aURL, aListener);
-
-  return NS_OK;
-}
-
-nsIStreamListener* nsBindingManager::GetLoadingDocListener(nsIURI* aURL) {
-  if (!mLoadingDocTable) return nullptr;
-
-  return mLoadingDocTable->GetWeak(aURL);
-}
-
-void nsBindingManager::RemoveLoadingDocListener(nsIURI* aURL) {
-  if (mLoadingDocTable) {
-    mLoadingDocTable->Remove(aURL);
-  }
-}
-
-// Used below to protect from recurring in QI calls through XPConnect.
-struct AntiRecursionData {
-  nsIContent* element;
-  REFNSIID iid;
-  AntiRecursionData* next;
-
-  AntiRecursionData(nsIContent* aElement, REFNSIID aIID,
-                    AntiRecursionData* aNext)
-      : element(aElement), iid(aIID), next(aNext) {}
-};
-
-nsresult nsBindingManager::GetBindingImplementation(nsIContent* aContent,
-                                                    REFNSIID aIID,
-                                                    void** aResult) {
-  *aResult = nullptr;
-  nsXBLBinding* binding = aContent ? aContent->GetXBLBinding() : nullptr;
-  if (binding) {
-    // The binding should not be asked for nsISupports
-    NS_ASSERTION(!aIID.Equals(NS_GET_IID(nsISupports)),
-                 "Asking a binding for nsISupports");
-    if (binding->ImplementsInterface(aIID)) {
-      nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = GetWrappedJS(aContent);
-
-      if (wrappedJS) {
-        // Protect from recurring in QI calls through XPConnect.
-        // This can happen when a second binding is being resolved.
-        // At that point a wrappedJS exists, but it doesn't yet know about
-        // the iid we are asking for. So, without this protection,
-        // AggregatedQueryInterface would end up recurring back into itself
-        // through this code.
-        //
-        // With this protection, when we detect the recursion we return
-        // NS_NOINTERFACE in the inner call. The outer call will then fall
-        // through (see below) and build a new chained wrappedJS for the iid.
-        //
-        // We're careful to not assume that only one direct nesting can occur
-        // because there is a call into JS in the middle and we can't assume
-        // that this code won't be reached by some more complex nesting path.
-        //
-        // NOTE: We *assume* this is single threaded, so we can use a
-        // static linked list to do the check.
-
-        static AntiRecursionData* list = nullptr;
-
-        for (AntiRecursionData* p = list; p; p = p->next) {
-          if (p->element == aContent && p->iid.Equals(aIID)) {
-            *aResult = nullptr;
-            return NS_NOINTERFACE;
-          }
-        }
-
-        AntiRecursionData item(aContent, aIID, list);
-        list = &item;
-
-        nsresult rv = wrappedJS->AggregatedQueryInterface(aIID, aResult);
-
-        list = item.next;
-
-        if (*aResult) return rv;
-
-        // No result was found, so this must be another XBL interface.
-        // Fall through to create a new wrapper.
-      }
-
-      // We have never made a wrapper for this implementation.
-      // Create an XPC wrapper for the script object and hand it back.
-      AutoJSAPI jsapi;
-      jsapi.Init();
-      JSContext* cx = jsapi.cx();
-
-      nsIXPConnect* xpConnect = nsContentUtils::XPConnect();
-
-      JS::Rooted<JSObject*> jsobj(cx, aContent->GetWrapper());
-      NS_ENSURE_TRUE(jsobj, NS_NOINTERFACE);
-
-      // If we're using an XBL scope, we need to use the Xray view to the bound
-      // content in order to view the full array of methods defined in the
-      // binding, some of which may not be exposed on the prototype of
-      // untrusted content. We don't need to consider add-on scopes here
-      // because they're chrome-only and no Xrays are involved.
-      //
-      // If there's no separate XBL scope, or if the reflector itself lives in
-      // the XBL scope, we'll end up with the global of the reflector.
-      JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, jsobj));
-      NS_ENSURE_TRUE(xblScope, NS_ERROR_UNEXPECTED);
-      JSAutoRealm ar(cx, xblScope);
-      bool ok = JS_WrapObject(cx, &jsobj);
-      NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
-      MOZ_ASSERT_IF(js::IsWrapper(jsobj), xpc::IsXrayWrapper(jsobj));
-
-      nsresult rv = xpConnect->WrapJSAggregatedToNative(aContent, cx, jsobj,
-                                                        aIID, aResult);
-      if (NS_FAILED(rv)) return rv;
-
-      // We successfully created a wrapper.  We will own this wrapper for as
-      // long as the binding remains alive.  At the time the binding is cleared
-      // out of the bindingManager, we will remove the wrapper from the
-      // bindingManager as well.
-      nsISupports* supp = static_cast<nsISupports*>(*aResult);
-      wrappedJS = do_QueryInterface(supp);
-      SetWrappedJS(aContent, wrappedJS);
-
-      return rv;
-    }
-  }
-
-  *aResult = nullptr;
-  return NS_NOINTERFACE;
-}
-
-static void InsertAppendedContent(XBLChildrenElement* aPoint,
-                                  nsIContent* aFirstNewContent) {
-  int32_t insertionIndex;
-  if (nsIContent* prevSibling = aFirstNewContent->GetPreviousSibling()) {
-    // If we have a previous sibling, then it must already be in aPoint. Find
-    // it and insert after it.
-    insertionIndex = aPoint->IndexOfInsertedChild(prevSibling);
-    MOZ_ASSERT(insertionIndex != -1);
-
-    // Our insertion index is one after our previous sibling's index.
-    ++insertionIndex;
-  } else {
-    // Otherwise, we append.
-    // TODO This is wrong for nested insertion points. In that case, we need to
-    // keep track of the right index to insert into.
-    insertionIndex = aPoint->InsertedChildrenLength();
-  }
-
-  // Do the inserting.
-  for (nsIContent* currentChild = aFirstNewContent; currentChild;
-       currentChild = currentChild->GetNextSibling()) {
-    aPoint->InsertInsertedChildAt(currentChild, insertionIndex++);
-  }
-}
-
-void nsBindingManager::ContentAppended(nsIContent* aFirstNewContent) {
-  // Try to find insertion points for all the new kids.
-  XBLChildrenElement* point = nullptr;
-  nsIContent* container = aFirstNewContent->GetParent();
-  nsIContent* parent = container;
-
-  // Handle appending of default content.
-  if (parent && parent->IsActiveChildrenElement()) {
-    XBLChildrenElement* childrenEl = static_cast<XBLChildrenElement*>(parent);
-    if (childrenEl->HasInsertedChildren()) {
-      // Appending default content that isn't being used. Ignore.
-      return;
-    }
-
-    childrenEl->MaybeSetupDefaultContent();
-    parent = childrenEl->GetParent();
-  }
-
-  bool first = true;
-  do {
-    nsXBLBinding* binding = GetBindingWithContent(parent);
-    if (!binding) {
-      break;
-    }
-
-    if (binding->HasFilteredInsertionPoints()) {
-      // There are filtered insertion points involved, handle each child
-      // separately.
-      // We could optimize this in the case when we've nested a few levels
-      // deep already, without hitting bindings that have filtered insertion
-      // points.
-      for (nsIContent* currentChild = aFirstNewContent; currentChild;
-           currentChild = currentChild->GetNextSibling()) {
-        HandleChildInsertion(container, currentChild, true);
-      }
-
-      return;
-    }
-
-    point = binding->GetDefaultInsertionPoint();
-    if (!point) {
-      break;
-    }
-
-    // Even though we're in ContentAppended, nested insertion points force us
-    // to deal with this append as an insertion except in the outermost
-    // binding.
-    if (first) {
-      first = false;
-      for (nsIContent* child = aFirstNewContent; child;
-           child = child->GetNextSibling()) {
-        point->AppendInsertedChild(child, true);
-      }
-    } else {
-      InsertAppendedContent(point, aFirstNewContent);
-    }
-
-    nsIContent* newParent = point->GetParent();
-    if (newParent == parent) {
-      break;
-    }
-    parent = newParent;
-  } while (parent);
-}
-
-void nsBindingManager::ContentInserted(nsIContent* aChild) {
-  HandleChildInsertion(aChild->GetParent(), aChild, false);
-}
-
-void nsBindingManager::ContentRemoved(nsIContent* aChild,
-                                      nsIContent* aPreviousSibling) {
-  aChild->SetXBLInsertionPoint(nullptr);
-
-  XBLChildrenElement* point = nullptr;
-  nsIContent* parent = aChild->GetParent();
-
-  // Handle appending of default content.
-  if (parent && parent->IsActiveChildrenElement()) {
-    XBLChildrenElement* childrenEl = static_cast<XBLChildrenElement*>(parent);
-    if (childrenEl->HasInsertedChildren()) {
-      // Removing default content that isn't being used. Ignore.
-      return;
-    }
-
-    parent = childrenEl->GetParent();
-  }
-
-  do {
-    nsXBLBinding* binding = GetBindingWithContent(parent);
-    if (!binding) {
-      // If aChild is XBL content, it might have <xbl:children> elements
-      // somewhere under it. We need to inform those elements that they're no
-      // longer in the tree so they can tell their distributed children that
-      // they're no longer distributed under them.
-      // XXX This is wrong. We need to do far more work to update the parent
-      // binding's list of insertion points and to get the new insertion parent
-      // for the newly-distributed children correct.
-      if (aChild->GetBindingParent()) {
-        ClearInsertionPointsRecursively(aChild);
-      }
-      return;
-    }
-
-    point = binding->FindInsertionPointFor(aChild);
-    if (!point) {
-      break;
-    }
-
-    point->RemoveInsertedChild(aChild);
-
-    nsIContent* newParent = point->GetParent();
-    if (newParent == parent) {
-      break;
-    }
-    parent = newParent;
-  } while (parent);
-}
-
-void nsBindingManager::ClearInsertionPointsRecursively(nsIContent* aContent) {
-  if (aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-    static_cast<XBLChildrenElement*>(aContent)->ClearInsertedChildren();
-  }
-
-  for (nsIContent* child = aContent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    ClearInsertionPointsRecursively(child);
-  }
-}
-
-void nsBindingManager::DropDocumentReference() {
-  mDestroyed = true;
-
-  // Make sure to not run any more XBL constructors
-  mProcessingAttachedStack = true;
-  if (mProcessAttachedQueueEvent) {
-    mProcessAttachedQueueEvent->Revoke();
-  }
-
-  if (mBoundContentSet) {
-    mBoundContentSet->Clear();
-  }
-
-  mDocument = nullptr;
-}
-
-void nsBindingManager::Traverse(nsIContent* aContent,
-                                nsCycleCollectionTraversalCallback& cb) {
-  if (!aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
-      !aContent->IsElement()) {
-    // Don't traverse if content is not in this binding manager.
-    // We also don't traverse non-elements because there should not
-    // be bindings (checking the flag alone is not sufficient because
-    // the flag is also set on children of insertion points that may be
-    // non-elements).
-    return;
-  }
-
-  if (mBoundContentSet && mBoundContentSet->Contains(aContent)) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
-        cb, "[via binding manager] mBoundContentSet entry");
-    cb.NoteXPCOMChild(aContent);
-  }
-
-  nsIXPConnectWrappedJS* value = GetWrappedJS(aContent);
-  if (value) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
-        cb, "[via binding manager] mWrapperTable key");
-    cb.NoteXPCOMChild(aContent);
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
-        cb, "[via binding manager] mWrapperTable value");
-    cb.NoteXPCOMChild(value);
-  }
-}
-
-void nsBindingManager::HandleChildInsertion(nsIContent* aContainer,
-                                            nsIContent* aChild, bool aAppend) {
-  MOZ_ASSERT(aChild, "Must have child");
-
-  XBLChildrenElement* point = nullptr;
-  nsIContent* parent = aContainer;
-
-  // Handle insertion of default content.
-  if (parent && parent->IsActiveChildrenElement()) {
-    XBLChildrenElement* childrenEl = static_cast<XBLChildrenElement*>(parent);
-    if (childrenEl->HasInsertedChildren()) {
-      // Inserting default content that isn't being used. Ignore.
-      return;
-    }
-
-    childrenEl->MaybeSetupDefaultContent();
-    parent = childrenEl->GetParent();
-  }
-
-  while (parent) {
-    nsXBLBinding* binding = GetBindingWithContent(parent);
-    if (!binding) {
-      break;
-    }
-
-    point = binding->FindInsertionPointFor(aChild);
-    if (!point) {
-      break;
-    }
-
-    // Insert the child into the proper insertion point.
-    // TODO If there were multiple insertion points, this approximation can be
-    // wrong. We need to re-run the distribution algorithm. In the meantime,
-    // this should work well enough.
-    uint32_t index = aAppend ? point->InsertedChildrenLength() : 0;
-    for (nsIContent* currentSibling = aChild->GetPreviousSibling();
-         currentSibling;
-         currentSibling = currentSibling->GetPreviousSibling()) {
-      // If we find one of our previous siblings in the insertion point, the
-      // index following it is the correct insertion point. Otherwise, we guess
-      // based on whether we're appending or inserting.
-      int32_t pointIndex = point->IndexOfInsertedChild(currentSibling);
-      if (pointIndex != -1) {
-        index = pointIndex + 1;
-        break;
-      }
-    }
-
-    point->InsertInsertedChildAt(aChild, index);
-
-    nsIContent* newParent = point->GetParent();
-    if (newParent == parent) {
-      break;
-    }
-
-    parent = newParent;
-  }
-}
-
-nsIContent* nsBindingManager::FindNestedSingleInsertionPoint(
-    nsIContent* aContainer, bool* aMulti) {
-  *aMulti = false;
-
-  nsIContent* parent = aContainer;
-  if (aContainer->IsActiveChildrenElement()) {
-    if (static_cast<XBLChildrenElement*>(aContainer)->HasInsertedChildren()) {
-      return nullptr;
-    }
-    parent = aContainer->GetParent();
-  }
-
-  while (parent) {
-    nsXBLBinding* binding = GetBindingWithContent(parent);
-    if (!binding) {
-      break;
-    }
-
-    if (binding->HasFilteredInsertionPoints()) {
-      *aMulti = true;
-      return nullptr;
-    }
-
-    XBLChildrenElement* point = binding->GetDefaultInsertionPoint();
-    if (!point) {
-      return nullptr;
-    }
-
-    nsIContent* newParent = point->GetParent();
-    if (newParent == parent) {
-      break;
-    }
-    parent = newParent;
-  }
-
-  return parent;
-}
-
-size_t nsBindingManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
-  size_t n = aMallocSizeOf(this);
-
-#define SHALLOW_SIZE_INCLUDING(field_) \
-  n += field_ ? field_->ShallowSizeOfIncludingThis(aMallocSizeOf) : 0;
-  SHALLOW_SIZE_INCLUDING(mBoundContentSet);
-  SHALLOW_SIZE_INCLUDING(mWrapperTable);
-  SHALLOW_SIZE_INCLUDING(mLoadingDocTable);
-#undef SHALLOW_SIZE_INCLUDING
-  n += mAttachedStack.ShallowSizeOfExcludingThis(aMallocSizeOf);
-
-  if (mDocumentTable) {
-    n += mDocumentTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
-#ifdef MOZ_XUL
-    nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
-#endif
-    for (auto iter = mDocumentTable->Iter(); !iter.Done(); iter.Next()) {
-      nsXBLDocumentInfo* docInfo = iter.UserData();
-#ifdef MOZ_XUL
-      nsXBLDocumentInfo* cachedInfo = cache->GetXBLDocumentInfo(iter.Key());
-      if (cachedInfo == docInfo) {
-        // If this binding has been cached, skip it since it can be
-        // reused by other documents.
-        continue;
-      }
-#endif
-      n += docInfo->SizeOfIncludingThis(aMallocSizeOf);
-    }
-  }
-
-  return n;
-}
deleted file mode 100644
--- a/dom/xbl/nsBindingManager.h
+++ /dev/null
@@ -1,204 +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 nsBindingManager_h_
-#define nsBindingManager_h_
-
-#include "nsAutoPtr.h"
-#include "nsIContent.h"
-#include "nsStubMutationObserver.h"
-#include "nsHashKeys.h"
-#include "nsInterfaceHashtable.h"
-#include "nsRefPtrHashtable.h"
-#include "nsURIHashKey.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsXBLBinding.h"
-#include "nsTArray.h"
-#include "nsThreadUtils.h"
-#include "mozilla/MediaFeatureChange.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/EventStates.h"
-
-struct ElementDependentRuleProcessorData;
-class nsIXPConnectWrappedJS;
-class nsAtom;
-class nsIURI;
-class nsXBLDocumentInfo;
-class nsIStreamListener;
-class nsXBLBinding;
-typedef nsTArray<RefPtr<nsXBLBinding> > nsBindingList;
-class nsIPrincipal;
-class nsITimer;
-
-class nsBindingManager final : public nsStubMutationObserver {
-  ~nsBindingManager();
-
- public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
-
-  explicit nsBindingManager(mozilla::dom::Document* aDocument);
-
-  nsXBLBinding* GetBindingWithContent(const nsIContent* aContent);
-
-  void AddBoundContent(nsIContent* aContent);
-  void RemoveBoundContent(nsIContent* aContent);
-
-  /**
-   * Notify the binding manager that an element
-   * has been removed from its document,
-   * so that it can update any bindings or
-   * nsIAnonymousContentCreator-created anonymous
-   * content that may depend on the document.
-   * @param aContent the element that's being moved
-   * @param aOldDocument the old document in which the
-   *   content resided.
-   * @param aDestructorHandling whether or not to run the possible XBL
-   *        destructor.
-   */
-
-  enum DestructorHandling { eRunDtor, eDoNotRunDtor };
-  void RemovedFromDocument(nsIContent* aContent,
-                           mozilla::dom::Document* aOldDocument,
-                           DestructorHandling aDestructorHandling) {
-    if (aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-      RemovedFromDocumentInternal(aContent, aOldDocument, aDestructorHandling);
-    }
-  }
-  void RemovedFromDocumentInternal(nsIContent* aContent,
-                                   mozilla::dom::Document* aOldDocument,
-                                   DestructorHandling aDestructorHandling);
-
-  /**
-   * Return the nodelist of "anonymous" kids for this node.  This might
-   * actually include some of the nodes actual DOM kids, if there are
-   * <children> tags directly as kids of <content>.  This will only end up
-   * returning a non-null list for nodes which have a binding attached.
-   */
-  nsINodeList* GetAnonymousNodesFor(nsIContent* aContent);
-
-  nsresult ClearBinding(mozilla::dom::Element* aElement);
-
-  nsresult AddToAttachedQueue(nsXBLBinding* aBinding);
-  void RemoveFromAttachedQueue(nsXBLBinding* aBinding);
-  void ProcessAttachedQueue(uint32_t aSkipSize = 0) {
-    if (mProcessingAttachedStack || mAttachedStack.Length() <= aSkipSize) {
-      return;
-    }
-
-    ProcessAttachedQueueInternal(aSkipSize);
-  }
-
- private:
-  void ProcessAttachedQueueInternal(uint32_t aSkipSize);
-
- public:
-  void ExecuteDetachedHandlers();
-
-  nsresult PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo);
-  nsXBLDocumentInfo* GetXBLDocumentInfo(nsIURI* aURI);
-  void RemoveXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo);
-
-  nsresult PutLoadingDocListener(nsIURI* aURL, nsIStreamListener* aListener);
-  nsIStreamListener* GetLoadingDocListener(nsIURI* aURL);
-  void RemoveLoadingDocListener(nsIURI* aURL);
-
-  nsresult GetBindingImplementation(nsIContent* aContent, REFNSIID aIID,
-                                    void** aResult);
-
-  void Traverse(nsIContent* aContent, nsCycleCollectionTraversalCallback& cb);
-
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsBindingManager)
-
-  // Notify the binding manager when an outermost update begins and
-  // ends.  The end method can execute script.
-  void BeginOutermostUpdate() {
-    mAttachedStackSizeOnOutermost = mAttachedStack.Length();
-  }
-
-  void EndOutermostUpdate() {
-    if (!mProcessingAttachedStack) {
-      ProcessAttachedQueue(mAttachedStackSizeOnOutermost);
-      mAttachedStackSizeOnOutermost = 0;
-    }
-  }
-
-  // When removing an insertion point or a parent of one, clear the insertion
-  // points and their insertion parents.
-  void ClearInsertionPointsRecursively(nsIContent* aContent);
-
-  // Called when the document is going away
-  void DropDocumentReference();
-
-  nsIContent* FindNestedSingleInsertionPoint(nsIContent* aContainer,
-                                             bool* aMulti);
-
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
-
- protected:
-  nsIXPConnectWrappedJS* GetWrappedJS(nsIContent* aContent);
-  nsresult SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
-
-  // Called by ContentAppended and ContentInserted to handle a single child
-  // insertion.  aChild must not be null.  aContainer may be null.
-  // aAppend is true if this child is being appended, not inserted.
-  void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild,
-                            bool aAppend);
-
-  // Same as ProcessAttachedQueue, but also nulls out
-  // mProcessAttachedQueueEvent
-  void DoProcessAttachedQueue();
-
-  // Post an event to process the attached queue.
-  void PostProcessAttachedQueueEvent();
-
-  // Call PostProcessAttachedQueueEvent() on a timer.
-  static void PostPAQEventCallback(nsITimer* aTimer, void* aClosure);
-
-  // MEMBER VARIABLES
-  // A set of nsIContent that currently have a binding installed.
-  nsAutoPtr<nsTHashtable<nsRefPtrHashKey<nsIContent> > > mBoundContentSet;
-
-  // A mapping from nsIContent* to nsIXPWrappedJS* (an XPConnect
-  // wrapper for JS objects).  For XBL bindings that implement XPIDL
-  // interfaces, and that get referred to from C++, this table caches
-  // the XPConnect wrapper for the binding.  By caching it, I control
-  // its lifetime, and I prevent a re-wrap of the same script object
-  // (in the case where multiple bindings in an XBL inheritance chain
-  // both implement an XPIDL interface).
-  typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXPConnectWrappedJS>
-      WrapperHashtable;
-  nsAutoPtr<WrapperHashtable> mWrapperTable;
-
-  // A mapping from a URL (a string) to nsXBLDocumentInfo*.  This table
-  // is the cache of all binding documents that have been loaded by a
-  // given bound document.
-  nsAutoPtr<nsRefPtrHashtable<nsURIHashKey, nsXBLDocumentInfo> > mDocumentTable;
-
-  // A mapping from a URL (a string) to a nsIStreamListener. This
-  // table is the currently loading binding docs.  If they're in this
-  // table, they have not yet finished loading.
-  nsAutoPtr<nsInterfaceHashtable<nsURIHashKey, nsIStreamListener> >
-      mLoadingDocTable;
-
-  // A queue of binding attached event handlers that are awaiting execution.
-  nsBindingList mAttachedStack;
-  bool mProcessingAttachedStack;
-  bool mDestroyed;
-  uint32_t mAttachedStackSizeOnOutermost;
-
-  // Our posted event to process the attached queue, if any
-  friend class nsRunnableMethod<nsBindingManager>;
-  RefPtr<nsRunnableMethod<nsBindingManager> > mProcessAttachedQueueEvent;
-
-  // Our document.  This is a weak ref; the document owns us
-  mozilla::dom::Document* mDocument;
-};
-
-#endif
deleted file mode 100644
--- a/dom/xbl/nsXBLBinding.cpp
+++ /dev/null
@@ -1,1028 +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 "nsCOMPtr.h"
-#include "nsAtom.h"
-#include "nsXBLDocumentInfo.h"
-#include "nsIInputStream.h"
-#include "nsNameSpaceManager.h"
-#include "nsIURI.h"
-#include "nsIURL.h"
-#include "nsIChannel.h"
-#include "nsString.h"
-#include "nsReadableUtils.h"
-#include "plstr.h"
-#include "nsIContent.h"
-#include "mozilla/dom/BindContext.h"
-#include "mozilla/dom/Document.h"
-#include "nsContentUtils.h"
-#include "ChildIterator.h"
-#include "nsIXMLContentSink.h"
-#include "nsContentCID.h"
-#include "mozilla/dom/XMLDocument.h"
-#include "jsapi.h"
-#include "nsXBLService.h"
-#include "nsIXPConnect.h"
-#include "nsIScriptContext.h"
-#include "nsCRT.h"
-
-// Event listeners
-#include "mozilla/EventListenerManager.h"
-#include "nsIDOMEventListener.h"
-#include "nsAttrName.h"
-
-#include "nsGkAtoms.h"
-
-#include "nsXBLPrototypeHandler.h"
-
-#include "nsXBLPrototypeBinding.h"
-#include "nsXBLBinding.h"
-#include "nsIPrincipal.h"
-#include "nsIScriptSecurityManager.h"
-#include "mozilla/dom/XBLChildrenElement.h"
-
-#include "nsJSUtils.h"
-
-#include "mozilla/DeferredFinalize.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/ScriptSettings.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-// Helper classes
-
-/***********************************************************************/
-//
-// The JS class for XBLBinding
-//
-static void XBLFinalize(JSFreeOp* fop, JSObject* obj) {
-  nsXBLDocumentInfo* docInfo =
-      static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj));
-  DeferredFinalize(docInfo);
-}
-
-static bool XBLEnumerate(JSContext* cx, JS::Handle<JSObject*> obj) {
-  nsXBLPrototypeBinding* protoBinding = static_cast<nsXBLPrototypeBinding*>(
-      ::JS_GetReservedSlot(obj, 0).toPrivate());
-  MOZ_ASSERT(protoBinding);
-
-  return protoBinding->ResolveAllFields(cx, obj);
-}
-
-static const JSClassOps gPrototypeJSClassOps = {
-    nullptr,     nullptr, XBLEnumerate, nullptr, nullptr, nullptr,
-    XBLFinalize, nullptr, nullptr,      nullptr, nullptr};
-
-static const JSClass gPrototypeJSClass = {
-    "XBL prototype JSClass",
-    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
-        JSCLASS_FOREGROUND_FINALIZE |
-        // Our one reserved slot holds the relevant nsXBLPrototypeBinding
-        JSCLASS_HAS_RESERVED_SLOTS(1),
-    &gPrototypeJSClassOps};
-
-// Implementation //////////////////////////////////////////////////////////////
-
-// Constructors/Destructors
-nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
-    : mMarkedForDeath(false),
-      mPrototypeBinding(aBinding),
-      mBoundElement(nullptr) {
-  NS_ASSERTION(mPrototypeBinding, "Must have a prototype binding!");
-  // Grab a ref to the document info so the prototype binding won't die
-  NS_ADDREF(mPrototypeBinding->XBLDocumentInfo());
-}
-
-nsXBLBinding::~nsXBLBinding() {
-  if (mContent) {
-    nsXBLBinding::UnbindAnonymousContent(mContent->OwnerDoc(), mContent);
-  }
-  nsXBLDocumentInfo* info = mPrototypeBinding->XBLDocumentInfo();
-  NS_RELEASE(info);
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLBinding)
-  // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
-  //     mPrototypeBinding is weak.
-  if (tmp->mContent) {
-    nsXBLBinding::UnbindAnonymousContent(tmp->mContent->OwnerDoc(),
-                                         tmp->mContent);
-  }
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextBinding)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDefaultInsertionPoint)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mInsertionPoints)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnonymousContentList)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLBinding)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
-                                     "mPrototypeBinding->XBLDocumentInfo()");
-  cb.NoteXPCOMChild(tmp->mPrototypeBinding->XBLDocumentInfo());
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNextBinding)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDefaultInsertionPoint)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInsertionPoints)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnonymousContentList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXBLBinding, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXBLBinding, Release)
-
-void nsXBLBinding::SetBaseBinding(nsXBLBinding* aBinding) {
-  if (mNextBinding) {
-    NS_ERROR("Base XBL binding is already defined!");
-    return;
-  }
-
-  mNextBinding = aBinding;  // Comptr handles rel/add
-}
-
-nsXBLBinding* nsXBLBinding::GetBindingWithContent() {
-  if (mContent) {
-    return this;
-  }
-
-  return mNextBinding ? mNextBinding->GetBindingWithContent() : nullptr;
-}
-
-void nsXBLBinding::BindAnonymousContent(nsIContent* aAnonParent,
-                                        nsIContent* aElement) {
-  // We need to ensure two things.
-  // (1) The anonymous content should be fooled into thinking it's in the bound
-  // element's document, assuming that the bound element is in a document
-  // Note that we don't change the current doc of aAnonParent here, since that
-  // quite simply does not matter.  aAnonParent is just a way of keeping refs
-  // to all its kids, which are anonymous content from the point of view of
-  // aElement.
-  // (2) The children's parent back pointer should not be to this synthetic root
-  // but should instead point to the enclosing parent element.
-  Element* element = aElement->AsElement();
-
-  nsAutoScriptBlocker scriptBlocker;
-  BindContext context(*this, *element);
-  for (nsIContent* child = aAnonParent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    child->UnbindFromTree();
-    child->SetFlags(NODE_IS_ANONYMOUS_ROOT);
-    nsresult rv = child->BindToTree(context, *element);
-    if (NS_FAILED(rv)) {
-      // Oh, well... Just give up.
-      // XXXbz This really shouldn't be a void method!
-      child->UnbindFromTree();
-      return;
-    }
-  }
-}
-
-void nsXBLBinding::UnbindAnonymousContent(Document* aDocument,
-                                          nsIContent* aAnonParent,
-                                          bool aNullParent) {
-  nsAutoScriptBlocker scriptBlocker;
-  // Hold a strong ref while doing this, just in case.
-  nsCOMPtr<nsIContent> anonParent = aAnonParent;
-  for (nsIContent* child = aAnonParent->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    child->UnbindFromTree(aNullParent);
-  }
-}
-
-void nsXBLBinding::SetBoundElement(Element* aElement) {
-  mBoundElement = aElement;
-  if (mNextBinding) mNextBinding->SetBoundElement(aElement);
-}
-
-void nsXBLBinding::GenerateAnonymousContent() {
-  NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
-               "Someone forgot a script blocker");
-
-  // Fetch the content element for this binding.
-  Element* content = mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
-
-  if (!content) {
-    // We have no anonymous content.
-    if (mNextBinding) mNextBinding->GenerateAnonymousContent();
-
-    return;
-  }
-
-  // Find out if we're really building kids or if we're just
-  // using the attribute-setting shorthand hack.
-  uint32_t contentCount = content->GetChildCount();
-
-  // Plan to build the content by default.
-  bool hasContent = (contentCount > 0);
-  if (hasContent) {
-    Document* doc = mBoundElement->OwnerDoc();
-
-    nsCOMPtr<nsINode> clonedNode =
-        content->Clone(true, doc->NodeInfoManager(), nullptr, IgnoreErrors());
-    // FIXME: Bug 1399558, Why is this code OK assuming that nsINode::Clone
-    // never fails?
-    mContent = clonedNode->AsElement();
-
-    // Search for <xbl:children> elements in the XBL content. In the presence
-    // of multiple default insertion points, we use the last one in document
-    // order.
-    for (nsIContent* child = mContent; child;
-         child = child->GetNextNode(mContent)) {
-      if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-        XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-        if (point->IsDefaultInsertion()) {
-          mDefaultInsertionPoint = point;
-        } else {
-          mInsertionPoints.AppendElement(point);
-        }
-      }
-    }
-
-    // Do this after looking for <children> as this messes up the parent
-    // pointer which would make the GetNextNode call above fail
-    BindAnonymousContent(mContent, mBoundElement);
-
-    // Insert explicit children into insertion points
-    if (mDefaultInsertionPoint && mInsertionPoints.IsEmpty()) {
-      ExplicitChildIterator iter(mBoundElement);
-      for (nsIContent* child = iter.GetNextChild(); child;
-           child = iter.GetNextChild()) {
-        // Pass aNotify = false because we're just setting up the whole thing.
-        // Furthermore we do it from frame construction, so passing true here
-        // would reenter into it which is... not great.
-        mDefaultInsertionPoint->AppendInsertedChild(child, false);
-      }
-    } else {
-      // It is odd to come into this code if mInsertionPoints is not empty, but
-      // we need to make sure to do the compatibility hack below if the bound
-      // node has any non <xul:template> or <xul:observes> children.
-      ExplicitChildIterator iter(mBoundElement);
-      for (nsIContent* child = iter.GetNextChild(); child;
-           child = iter.GetNextChild()) {
-        XBLChildrenElement* point = FindInsertionPointForInternal(child);
-        if (point) {
-          // Pass aNotify = false because we're just setting up the whole thing.
-          // (see the similar call above for more details).
-          point->AppendInsertedChild(child, false);
-        } else {
-          NodeInfo* ni = child->NodeInfo();
-          if (!child->TextIsOnlyWhitespace() &&
-              (ni->NamespaceID() != kNameSpaceID_XUL ||
-               (!ni->Equals(nsGkAtoms::_template) &&
-                !ni->Equals(nsGkAtoms::observes)))) {
-            // Compatibility hack. For some reason the original XBL
-            // implementation dropped the content of a binding if any child of
-            // the bound element didn't match any of the <children> in the
-            // binding. This became a pseudo-API that we have to maintain.
-
-            // Undo BindAnonymousContent
-            UnbindAnonymousContent(doc, mContent);
-
-            // Clear out our children elements to avoid dangling references.
-            ClearInsertionPoints();
-
-            // Pretend as though there was no content in the binding.
-            mContent = nullptr;
-            return;
-          }
-        }
-      }
-    }
-
-    // Set binding parent on default content if need
-    if (mDefaultInsertionPoint) {
-      mDefaultInsertionPoint->MaybeSetupDefaultContent();
-    }
-    for (uint32_t i = 0; i < mInsertionPoints.Length(); ++i) {
-      mInsertionPoints[i]->MaybeSetupDefaultContent();
-    }
-
-    mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
-  }
-
-  // Always check the content element for potential attributes.
-  // This shorthand hack always happens, even when we didn't
-  // build anonymous content.
-  BorrowedAttrInfo attrInfo;
-  for (uint32_t i = 0; (attrInfo = content->GetAttrInfoAt(i)); ++i) {
-    int32_t namespaceID = attrInfo.mName->NamespaceID();
-    // Hold a strong reference here so that the atom doesn't go away during
-    // UnsetAttr.
-    RefPtr<nsAtom> name = attrInfo.mName->LocalName();
-
-    if (name != nsGkAtoms::includes) {
-      if (!nsContentUtils::HasNonEmptyAttr(mBoundElement, namespaceID, name)) {
-        nsAutoString value2;
-        attrInfo.mValue->ToString(value2);
-        mBoundElement->SetAttr(namespaceID, name, attrInfo.mName->GetPrefix(),
-                               value2, false);
-      }
-    }
-
-    // Conserve space by wiping the attributes off the clone.
-    //
-    // FIXME(emilio): It'd be nice to make `mContent` a `RefPtr<Element>`.
-    if (mContent) mContent->AsElement()->UnsetAttr(namespaceID, name, false);
-  }
-}
-
-nsIURI* nsXBLBinding::GetSourceDocURI() {
-  nsIContent* targetContent =
-      mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
-  if (!targetContent) {
-    return nullptr;
-  }
-
-  return targetContent->OwnerDoc()->GetDocumentURI();
-}
-
-XBLChildrenElement* nsXBLBinding::FindInsertionPointFor(nsIContent* aChild) {
-  // XXX We should get rid of this function as it causes us to traverse the
-  // binding chain multiple times
-  if (mContent) {
-    return FindInsertionPointForInternal(aChild);
-  }
-
-  return mNextBinding ? mNextBinding->FindInsertionPointFor(aChild) : nullptr;
-}
-
-XBLChildrenElement* nsXBLBinding::FindInsertionPointForInternal(
-    nsIContent* aChild) {
-  for (uint32_t i = 0; i < mInsertionPoints.Length(); ++i) {
-    XBLChildrenElement* point = mInsertionPoints[i];
-    if (point->Includes(aChild)) {
-      return point;
-    }
-  }
-
-  return mDefaultInsertionPoint;
-}
-
-void nsXBLBinding::ClearInsertionPoints() {
-  if (mDefaultInsertionPoint) {
-    mDefaultInsertionPoint->ClearInsertedChildren();
-  }
-
-  for (const auto& insertionPoint : mInsertionPoints) {
-    insertionPoint->ClearInsertedChildren();
-  }
-}
-
-nsAnonymousContentList* nsXBLBinding::GetAnonymousNodeList() {
-  if (!mContent) {
-    return mNextBinding ? mNextBinding->GetAnonymousNodeList() : nullptr;
-  }
-
-  if (!mAnonymousContentList) {
-    mAnonymousContentList = new nsAnonymousContentList(mContent);
-  }
-
-  return mAnonymousContentList;
-}
-
-void nsXBLBinding::InstallEventHandlers() {
-  // Don't install handlers if scripts aren't allowed.
-  if (AllowScripts()) {
-    // Fetch the handlers prototypes for this binding.
-    nsXBLPrototypeHandler* handlerChain =
-        mPrototypeBinding->GetPrototypeHandlers();
-
-    if (handlerChain) {
-      EventListenerManager* manager =
-          mBoundElement->GetOrCreateListenerManager();
-      if (!manager) return;
-
-      bool isChromeDoc = nsContentUtils::IsChromeDoc(mBoundElement->OwnerDoc());
-      bool isChromeBinding = mPrototypeBinding->IsChrome();
-      nsXBLPrototypeHandler* curr;
-      for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
-        // Fetch the event type.
-        RefPtr<nsAtom> eventAtom = curr->GetEventName();
-        if (!eventAtom || eventAtom == nsGkAtoms::keyup ||
-            eventAtom == nsGkAtoms::keydown || eventAtom == nsGkAtoms::keypress)
-          continue;
-
-        nsXBLEventHandler* handler = curr->GetEventHandler();
-        if (handler) {
-          // Figure out if we're using capturing or not.
-          EventListenerFlags flags;
-          flags.mCapture = (curr->GetPhase() == NS_PHASE_CAPTURING);
-
-          // If this is a command, add it in the system event group
-          if ((curr->GetType() &
-               (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-              (isChromeBinding ||
-               mBoundElement->IsInNativeAnonymousSubtree())) {
-            flags.mInSystemGroup = true;
-          }
-
-          bool hasAllowUntrustedAttr = curr->HasAllowUntrustedAttr();
-          if ((hasAllowUntrustedAttr && curr->AllowUntrustedEvents()) ||
-              (!hasAllowUntrustedAttr && !isChromeDoc)) {
-            flags.mAllowUntrustedEvents = true;
-          }
-
-          manager->AddEventListenerByType(
-              handler, nsDependentAtomString(eventAtom), flags);
-        }
-      }
-
-      const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
-          mPrototypeBinding->GetKeyEventHandlers();
-      int32_t i;
-      for (i = 0; i < keyHandlers->Count(); ++i) {
-        nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
-        handler->SetIsBoundToChrome(isChromeDoc);
-
-        nsAutoString type;
-        handler->GetEventName(type);
-
-        // If this is a command, add it in the system event group, otherwise
-        // add it to the standard event group.
-
-        // Figure out if we're using capturing or not.
-        EventListenerFlags flags;
-        flags.mCapture = (handler->GetPhase() == NS_PHASE_CAPTURING);
-
-        if ((handler->GetType() &
-             (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-            (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-          flags.mInSystemGroup = true;
-        }
-
-        // For key handlers we have to set mAllowUntrustedEvents flag.
-        // Whether the handling of the event is allowed or not is handled in
-        // nsXBLKeyEventHandler::HandleEvent
-        flags.mAllowUntrustedEvents = true;
-
-        manager->AddEventListenerByType(handler, type, flags);
-      }
-    }
-  }
-
-  if (mNextBinding) mNextBinding->InstallEventHandlers();
-}
-
-nsresult nsXBLBinding::InstallImplementation() {
-  // Always install the base class properties first, so that
-  // derived classes can reference the base class properties.
-
-  if (mNextBinding) {
-    nsresult rv = mNextBinding->InstallImplementation();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  // iterate through each property in the prototype's list and install the
-  // property.
-  if (AllowScripts()) return mPrototypeBinding->InstallImplementation(this);
-
-  return NS_OK;
-}
-
-void nsXBLBinding::AttributeChanged(nsAtom* aAttribute, int32_t aNameSpaceID,
-                                    bool aRemoveFlag, bool aNotify) {
-  // XXX Change if we ever allow multiple bindings in a chain to contribute
-  // anonymous content
-  if (!mContent) {
-    if (mNextBinding)
-      mNextBinding->AttributeChanged(aAttribute, aNameSpaceID, aRemoveFlag,
-                                     aNotify);
-  } else {
-    mPrototypeBinding->AttributeChanged(aAttribute, aNameSpaceID, aRemoveFlag,
-                                        mBoundElement, mContent, aNotify);
-  }
-}
-
-void nsXBLBinding::ExecuteAttachedHandler() {
-  if (mNextBinding) mNextBinding->ExecuteAttachedHandler();
-
-  if (AllowScripts()) mPrototypeBinding->BindingAttached(mBoundElement);
-}
-
-void nsXBLBinding::ExecuteDetachedHandler() {
-  if (AllowScripts()) mPrototypeBinding->BindingDetached(mBoundElement);
-
-  if (mNextBinding) mNextBinding->ExecuteDetachedHandler();
-}
-
-void nsXBLBinding::UnhookEventHandlers() {
-  nsXBLPrototypeHandler* handlerChain =
-      mPrototypeBinding->GetPrototypeHandlers();
-
-  if (handlerChain) {
-    EventListenerManager* manager = mBoundElement->GetExistingListenerManager();
-    if (!manager) {
-      return;
-    }
-
-    bool isChromeBinding = mPrototypeBinding->IsChrome();
-    nsXBLPrototypeHandler* curr;
-    for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
-      nsXBLEventHandler* handler = curr->GetCachedEventHandler();
-      if (!handler) {
-        continue;
-      }
-
-      RefPtr<nsAtom> eventAtom = curr->GetEventName();
-      if (!eventAtom || eventAtom == nsGkAtoms::keyup ||
-          eventAtom == nsGkAtoms::keydown || eventAtom == nsGkAtoms::keypress)
-        continue;
-
-      // Figure out if we're using capturing or not.
-      EventListenerFlags flags;
-      flags.mCapture = (curr->GetPhase() == NS_PHASE_CAPTURING);
-
-      // If this is a command, remove it from the system event group,
-      // otherwise remove it from the standard event group.
-
-      if ((curr->GetType() &
-           (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-          (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-        flags.mInSystemGroup = true;
-      }
-
-      manager->RemoveEventListenerByType(
-          handler, nsDependentAtomString(eventAtom), flags);
-    }
-
-    const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
-        mPrototypeBinding->GetKeyEventHandlers();
-    int32_t i;
-    for (i = 0; i < keyHandlers->Count(); ++i) {
-      nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
-
-      nsAutoString type;
-      handler->GetEventName(type);
-
-      // Figure out if we're using capturing or not.
-      EventListenerFlags flags;
-      flags.mCapture = (handler->GetPhase() == NS_PHASE_CAPTURING);
-
-      // If this is a command, remove it from the system event group, otherwise
-      // remove it from the standard event group.
-
-      if ((handler->GetType() &
-           (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-          (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-        flags.mInSystemGroup = true;
-      }
-
-      manager->RemoveEventListenerByType(handler, type, flags);
-    }
-  }
-}
-
-void nsXBLBinding::ChangeDocument(Document* aOldDocument,
-                                  Document* aNewDocument) {
-  if (aOldDocument == aNewDocument) return;
-
-  // Now the binding dies.  Unhook our prototypes.
-  if (mPrototypeBinding->HasImplementation()) {
-    AutoJSAPI jsapi;
-    // Init might fail here if we've cycle-collected the global object, since
-    // the Unlink phase of cycle collection happens after JS GC finalization.
-    // But in that case, we don't care about fixing the prototype chain, since
-    // everything's going away immediately.
-    if (jsapi.Init(aOldDocument->GetScopeObject())) {
-      JSContext* cx = jsapi.cx();
-
-      JS::Rooted<JSObject*> scriptObject(cx, mBoundElement->GetWrapper());
-      if (scriptObject) {
-        // XXX Stay in sync! What if a layered binding has an
-        // <interface>?!
-        // XXXbz what does that comment mean, really?  It seems to date
-        // back to when there was such a thing as an <interface>, whever
-        // that was...
-
-        // Find the right prototype.
-        JSAutoRealm ar(cx, scriptObject);
-
-        JS::Rooted<JSObject*> base(cx, scriptObject);
-        JS::Rooted<JSObject*> proto(cx);
-        for (; true; base = proto) {  // Will break out on null proto
-          if (!JS_GetPrototype(cx, base, &proto)) {
-            return;
-          }
-          if (!proto) {
-            break;
-          }
-
-          if (JS_GetClass(proto) != &gPrototypeJSClass) {
-            // Clearly not the right class
-            continue;
-          }
-
-          RefPtr<nsXBLDocumentInfo> docInfo =
-              static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(proto));
-          if (!docInfo) {
-            // Not the proto we seek
-            continue;
-          }
-
-          JS::Value protoBinding = ::JS_GetReservedSlot(proto, 0);
-
-          if (protoBinding.toPrivate() != mPrototypeBinding) {
-            // Not the right binding
-            continue;
-          }
-
-          // Alright!  This is the right prototype.  Pull it out of the
-          // proto chain.
-          JS::Rooted<JSObject*> grandProto(cx);
-          if (!JS_GetPrototype(cx, proto, &grandProto)) {
-            return;
-          }
-          ::JS_SetPrototype(cx, base, grandProto);
-          break;
-        }
-
-        mPrototypeBinding->UndefineFields(cx, scriptObject);
-
-        // Don't remove the reference from the document to the
-        // wrapper here since it'll be removed by the element
-        // itself when that's taken out of the document.
-      }
-    }
-  }
-
-  // Remove our event handlers
-  UnhookEventHandlers();
-
-  {
-    nsAutoScriptBlocker scriptBlocker;
-
-    // Then do our ancestors.  This reverses the construction order, so that at
-    // all times things are consistent as far as everyone is concerned.
-    if (mNextBinding) {
-      mNextBinding->ChangeDocument(aOldDocument, aNewDocument);
-    }
-
-    // Update the anonymous content.
-    // XXXbz why not only for style bindings?
-    if (mContent) {
-      nsXBLBinding::UnbindAnonymousContent(aOldDocument, mContent);
-    }
-
-    ClearInsertionPoints();
-  }
-}
-
-// Internal helper methods /////////////////////////////////////////////////////
-
-// Get or create a WeakMap object on a given XBL-hosting global.
-//
-// The scheme is as follows. XBL-hosting globals (either privileged content
-// Windows or XBL scopes) get two lazily-defined WeakMap properties. Each
-// WeakMap is keyed by the grand-proto - i.e. the original prototype of the
-// content before it was bound, and the prototype of the class object that we
-// splice in. The values in the WeakMap are simple dictionary-style objects,
-// mapping from XBL class names to class objects.
-static JSObject* GetOrCreateClassObjectMap(JSContext* cx,
-                                           JS::Handle<JSObject*> scope,
-                                           const char* mapName) {
-  AssertSameCompartment(cx, scope);
-  MOZ_ASSERT(JS_IsGlobalObject(scope));
-  MOZ_ASSERT(scope == xpc::GetXBLScopeOrGlobal(cx, scope));
-
-  // First, see if the map is already defined.
-  JS::Rooted<JS::PropertyDescriptor> desc(cx);
-  if (!JS_GetOwnPropertyDescriptor(cx, scope, mapName, &desc)) {
-    return nullptr;
-  }
-  if (desc.object() && desc.value().isObject() &&
-      JS::IsWeakMapObject(&desc.value().toObject())) {
-    return &desc.value().toObject();
-  }
-
-  // It's not there. Create and define it.
-  JS::Rooted<JSObject*> map(cx, JS::NewWeakMapObject(cx));
-  if (!map || !JS_DefineProperty(cx, scope, mapName, map,
-                                 JSPROP_PERMANENT | JSPROP_READONLY)) {
-    return nullptr;
-  }
-  return map;
-}
-
-static JSObject* GetOrCreateMapEntryForPrototype(JSContext* cx,
-                                                 JS::Handle<JSObject*> proto) {
-  AssertSameCompartment(cx, proto);
-  // We want to hang our class objects off the XBL scope. But since we also
-  // hoist anonymous content into the XBL scope, this creates the potential for
-  // tricky collisions, since we can simultaneously  have a bound in-content
-  // node with grand-proto HTMLDivElement and a bound anonymous node whose
-  // grand-proto is the XBL scope's cross-compartment wrapper to HTMLDivElement.
-  // Since we have to wrap the WeakMap keys into its scope, this distinction
-  // would be lost if we don't do something about it.
-  //
-  // So we define two maps - one class objects that live in content (prototyped
-  // to content prototypes), and the other for class objects that live in the
-  // XBL scope (prototyped to cross-compartment-wrapped content prototypes).
-  const char* name = xpc::IsInContentXBLScope(proto)
-                         ? "__ContentClassObjectMap__"
-                         : "__XBLClassObjectMap__";
-
-  // Now, enter the XBL scope, since that's where we need to operate, and wrap
-  // the proto accordingly. We hang the map off of the content XBL scope for
-  // content, and the Window for chrome (whether add-ons are involved or not).
-  JS::Rooted<JSObject*> scope(
-      cx, xpc::GetXBLScopeOrGlobal(cx, JS::CurrentGlobalOrNull(cx)));
-  NS_ENSURE_TRUE(scope, nullptr);
-  MOZ_ASSERT(JS_IsGlobalObject(scope));
-
-  JS::Rooted<JSObject*> wrappedProto(cx, proto);
-  JSAutoRealm ar(cx, scope);
-  if (!JS_WrapObject(cx, &wrappedProto)) {
-    return nullptr;
-  }
-
-  // Grab the appropriate WeakMap.
-  JS::Rooted<JSObject*> map(cx, GetOrCreateClassObjectMap(cx, scope, name));
-  if (!map) {
-    return nullptr;
-  }
-
-  // See if we already have a map entry for that prototype.
-  JS::Rooted<JS::Value> val(cx);
-  if (!JS::GetWeakMapEntry(cx, map, wrappedProto, &val)) {
-    return nullptr;
-  }
-  if (val.isObject()) {
-    return &val.toObject();
-  }
-
-  // We don't have an entry. Create one and stick it in the map.
-  JS::Rooted<JSObject*> entry(cx);
-  entry = JS_NewObjectWithGivenProto(cx, nullptr, nullptr);
-  if (!entry) {
-    return nullptr;
-  }
-  JS::Rooted<JS::Value> entryVal(cx, JS::ObjectValue(*entry));
-  if (!JS::SetWeakMapEntry(cx, map, wrappedProto, entryVal)) {
-    NS_WARNING(
-        "SetWeakMapEntry failed, probably due to non-preservable WeakMap "
-        "key. XBL binding will fail for this element.");
-    return nullptr;
-  }
-  return entry;
-}
-
-static nsXBLPrototypeBinding* GetProtoBindingFromClassObject(JSObject* obj) {
-  MOZ_ASSERT(JS_GetClass(obj) == &gPrototypeJSClass);
-  return static_cast<nsXBLPrototypeBinding*>(
-      ::JS_GetReservedSlot(obj, 0).toPrivate());
-}
-
-// static
-nsresult nsXBLBinding::DoInitJSClass(JSContext* cx, JS::Handle<JSObject*> obj,
-                                     const nsString& aClassName,
-                                     nsXBLPrototypeBinding* aProtoBinding,
-                                     JS::MutableHandle<JSObject*> aClassObject,
-                                     bool* aNew) {
-  MOZ_ASSERT(obj);
-
-  // Note that, now that NAC reflectors are created in the XBL scope, the
-  // reflector is not necessarily same-compartment with the document. So we'll
-  // end up creating a separate instance of the oddly-named XBL class object
-  // and defining it as a property on the XBL scope's global. This works fine,
-  // but we need to make sure never to assume that the the reflector and
-  // prototype are same-compartment with the bound document.
-  JS::Rooted<JSObject*> global(cx, JS::GetNonCCWObjectGlobal(obj));
-
-  // We must be in obj's realm.
-  MOZ_ASSERT(JS::CurrentGlobalOrNull(cx) == global);
-
-  // We never store class objects in add-on scopes.
-  JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, global));
-  NS_ENSURE_TRUE(xblScope, NS_ERROR_UNEXPECTED);
-
-  JS::Rooted<JSObject*> parent_proto(cx);
-  {
-    JS::RootedObject wrapped(cx, obj);
-    JSAutoRealm ar(cx, xblScope);
-    if (!JS_WrapObject(cx, &wrapped)) {
-      return NS_ERROR_FAILURE;
-    }
-    if (!JS_GetPrototype(cx, wrapped, &parent_proto)) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-  if (!JS_WrapObject(cx, &parent_proto)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Get the map entry for the parent prototype. In the one-off case that the
-  // parent prototype is null, we somewhat hackily just use the WeakMap itself
-  // as a property holder.
-  JS::Rooted<JSObject*> holder(cx);
-  if (parent_proto) {
-    holder = GetOrCreateMapEntryForPrototype(cx, parent_proto);
-  } else {
-    JSAutoRealm innerAR(cx, xblScope);
-    holder =
-        GetOrCreateClassObjectMap(cx, xblScope, "__ContentClassObjectMap__");
-  }
-  if (NS_WARN_IF(!holder)) {
-    return NS_ERROR_FAILURE;
-  }
-  js::AssertSameCompartment(holder, xblScope);
-  JSAutoRealm ar(cx, holder);
-
-  // Look up the class on the property holder. The only properties on the
-  // holder should be class objects. If we don't find the class object, we need
-  // to create and define it.
-  JS::Rooted<JSObject*> proto(cx);
-  JS::Rooted<JS::PropertyDescriptor> desc(cx);
-  if (!JS_GetOwnUCPropertyDescriptor(cx, holder, aClassName.get(),
-                                     aClassName.Length(), &desc)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  *aNew = !desc.object();
-  if (desc.object()) {
-    proto = &desc.value().toObject();
-    DebugOnly<nsXBLPrototypeBinding*> cachedBinding =
-        GetProtoBindingFromClassObject(js::UncheckedUnwrap(proto));
-    MOZ_ASSERT(cachedBinding == aProtoBinding);
-  } else {
-    // We need to create the prototype. First, enter the realm where it's
-    // going to live, and create it.
-    JSAutoRealm ar2(cx, global);
-    proto = JS_NewObjectWithGivenProto(cx, &gPrototypeJSClass, parent_proto);
-    if (!proto) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    // Keep this proto binding alive while we're alive.  Do this first so that
-    // we can guarantee that in XBLFinalize this will be non-null.
-    // Note that we can't just store aProtoBinding in the private and
-    // addref/release the nsXBLDocumentInfo through it, because cycle
-    // collection doesn't seem to work right if the private is not an
-    // nsISupports.
-    nsXBLDocumentInfo* docInfo = aProtoBinding->XBLDocumentInfo();
-    ::JS_SetPrivate(proto, docInfo);
-    NS_ADDREF(docInfo);
-    JS_SetReservedSlot(proto, 0, JS::PrivateValue(aProtoBinding));
-
-    // Don't collect the proto while recording/replaying, to avoid
-    // non-deterministically releasing the docInfo reference.
-    recordreplay::HoldJSObject(proto);
-
-    // Next, enter the realm of the property holder, wrap the proto, and
-    // stick it on.
-    JSAutoRealm ar3(cx, holder);
-    if (!JS_WrapObject(cx, &proto) ||
-        !JS_DefineUCProperty(cx, holder, aClassName.get(), -1, proto,
-                             JSPROP_READONLY | JSPROP_PERMANENT)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  // Whew. We have the proto. Wrap it back into the realm of |obj|,
-  // splice it in, and return it.
-  JSAutoRealm ar4(cx, obj);
-  if (!JS_WrapObject(cx, &proto) || !JS_SetPrototype(cx, obj, proto)) {
-    return NS_ERROR_FAILURE;
-  }
-  aClassObject.set(proto);
-  return NS_OK;
-}
-
-bool nsXBLBinding::AllowScripts() {
-  return mBoundElement && mPrototypeBinding->GetAllowScripts();
-}
-
-nsXBLBinding* nsXBLBinding::RootBinding() {
-  if (mNextBinding) return mNextBinding->RootBinding();
-
-  return this;
-}
-
-bool nsXBLBinding::ResolveAllFields(JSContext* cx,
-                                    JS::Handle<JSObject*> obj) const {
-  if (!mPrototypeBinding->ResolveAllFields(cx, obj)) {
-    return false;
-  }
-
-  if (mNextBinding) {
-    return mNextBinding->ResolveAllFields(cx, obj);
-  }
-
-  return true;
-}
-
-bool nsXBLBinding::LookupMember(
-    JSContext* aCx, JS::Handle<jsid> aId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
-  // We should never enter this function with a pre-filled property descriptor.
-  MOZ_ASSERT(!aDesc.object());
-
-  // Get the string as an nsString before doing anything, so we can make
-  // convenient comparisons during our search.
-  if (!JSID_IS_STRING(aId)) {
-    return true;
-  }
-  nsAutoJSString name;
-  if (!name.init(aCx, JSID_TO_STRING(aId))) {
-    return false;
-  }
-
-  // We have a weak reference to our bound element, so make sure it's alive.
-  if (!mBoundElement || !mBoundElement->GetWrapper()) {
-    return false;
-  }
-
-  // Get the scope of mBoundElement and the associated XBL scope. We should only
-  // be calling into this machinery if we're running in a separate XBL scope.
-  //
-  // Note that we only end up in LookupMember for XrayWrappers from XBL scopes
-  // into content. So for NAC reflectors that live in the XBL scope, we should
-  // never get here. But on the off-chance that someone adds new callsites to
-  // LookupMember, we do a release-mode assertion as belt-and-braces.
-  // We do a release-mode assertion here to be extra safe.
-  //
-  // This code is only called for content XBL, so we don't have to worry about
-  // add-on scopes here.
-  JS::Rooted<JSObject*> boundScope(
-      aCx, JS::GetNonCCWObjectGlobal(mBoundElement->GetWrapper()));
-  MOZ_RELEASE_ASSERT(!xpc::IsInContentXBLScope(boundScope));
-  JS::Rooted<JSObject*> xblScope(aCx, xpc::GetXBLScope(aCx, boundScope));
-  NS_ENSURE_TRUE(xblScope, false);
-  MOZ_ASSERT(boundScope != xblScope);
-
-  // Enter the xbl scope and invoke the internal version.
-  {
-    JSAutoRealm ar(aCx, xblScope);
-    JS::Rooted<jsid> id(aCx, aId);
-    if (!LookupMemberInternal(aCx, name, id, aDesc, xblScope)) {
-      return false;
-    }
-  }
-
-  // Wrap into the caller's scope.
-  return JS_WrapPropertyDescriptor(aCx, aDesc);
-}
-
-bool nsXBLBinding::LookupMemberInternal(
-    JSContext* aCx, nsString& aName, JS::Handle<jsid> aNameAsId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc,
-    JS::Handle<JSObject*> aXBLScope) {
-  // First, see if we have an implementation. If we don't, it means that this
-  // binding doesn't have a class object, and thus doesn't have any members.
-  // Skip it.
-  if (!PrototypeBinding()->HasImplementation()) {
-    if (!mNextBinding) {
-      return true;
-    }
-    return mNextBinding->LookupMemberInternal(aCx, aName, aNameAsId, aDesc,
-                                              aXBLScope);
-  }
-
-  // Find our class object. It's in a protected scope and permanent just in
-  // case, so should be there no matter what.
-  JS::Rooted<JS::Value> classObject(aCx);
-  if (!JS_GetUCProperty(aCx, aXBLScope, PrototypeBinding()->ClassName().get(),
-                        -1, &classObject)) {
-    return false;
-  }
-
-  // The bound element may have been adoped by a document and have a different
-  // wrapper (and different xbl scope) than when the binding was applied, in
-  // this case getting the class object will fail. Behave as if the class
-  // object did not exist.
-  if (classObject.isUndefined()) {
-    return true;
-  }
-
-  MOZ_ASSERT(classObject.isObject());
-
-  // Look for the property on this binding. If it's not there, try the next
-  // binding on the chain.
-  nsXBLProtoImpl* impl = mPrototypeBinding->GetImplementation();
-  JS::Rooted<JSObject*> object(aCx, &classObject.toObject());
-  if (impl && !impl->LookupMember(aCx, aName, aNameAsId, aDesc, object)) {
-    return false;
-  }
-  if (aDesc.object() || !mNextBinding) {
-    return true;
-  }
-
-  return mNextBinding->LookupMemberInternal(aCx, aName, aNameAsId, aDesc,
-                                            aXBLScope);
-}
-
-bool nsXBLBinding::HasField(nsString& aName) {
-  // See if this binding has such a field.
-  return mPrototypeBinding->FindField(aName) ||
-         (mNextBinding && mNextBinding->HasField(aName));
-}
-
-void nsXBLBinding::MarkForDeath() {
-  mMarkedForDeath = true;
-  ExecuteDetachedHandler();
-}
-
-bool nsXBLBinding::ImplementsInterface(REFNSIID aIID) const {
-  return mPrototypeBinding->ImplementsInterface(aIID) ||
-         (mNextBinding && mNextBinding->ImplementsInterface(aIID));
-}
deleted file mode 100644
--- a/dom/xbl/nsXBLBinding.h
+++ /dev/null
@@ -1,176 +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 nsXBLBinding_h_
-#define nsXBLBinding_h_
-
-#include "nsXBLService.h"
-#include "nsCOMPtr.h"
-#include "nsINodeList.h"
-#include "nsClassHashtable.h"
-#include "nsTArray.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsImpl.h"
-#include "js/TypeDecls.h"
-
-class nsXBLPrototypeBinding;
-class nsIContent;
-class nsAtom;
-struct RawServoAuthorStyles;
-
-namespace mozilla {
-namespace dom {
-class Document;
-class XBLChildrenElement;
-}  // namespace dom
-}  // namespace mozilla
-
-class nsAnonymousContentList;
-
-// *********************************************************************/
-// The XBLBinding class
-
-class nsXBLBinding final {
- public:
-  explicit nsXBLBinding(nsXBLPrototypeBinding* aProtoBinding);
-
-  /**
-   * XBLBindings are refcounted.  They are held onto in 3 ways:
-   * 1. The binding manager's binding table holds onto all bindings that are
-   *    currently attached to a content node.
-   * 2. Bindings hold onto their base binding.  This is important since
-   *    the base binding itself may not be attached to anything.
-   * 3. The binding manager holds an additional reference to bindings
-   *    which are queued to fire their constructors.
-   */
-
-  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsXBLBinding)
-
-  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
-
-  nsXBLPrototypeBinding* PrototypeBinding() const { return mPrototypeBinding; }
-  nsIContent* GetAnonymousContent() { return mContent.get(); }
-  nsXBLBinding* GetBindingWithContent();
-
-  nsXBLBinding* GetBaseBinding() const { return mNextBinding; }
-  void SetBaseBinding(nsXBLBinding* aBinding);
-
-  mozilla::dom::Element* GetBoundElement() { return mBoundElement; }
-  void SetBoundElement(mozilla::dom::Element* aElement);
-
-  /*
-   * Does a lookup for a method or attribute provided by one of the bindings'
-   * prototype implementation. If found, |desc| will be set up appropriately,
-   * and wrapped into cx->compartment.
-   *
-   * May only be called when XBL code is being run in a separate scope, because
-   * otherwise we don't have untainted data with which to do a proper lookup.
-   */
-  bool LookupMember(JSContext* aCx, JS::Handle<jsid> aId,
-                    JS::MutableHandle<JS::PropertyDescriptor> aDesc);
-
-  /*
-   * Determines whether the binding has a field with the given name.
-   */
-  bool HasField(nsString& aName);
-
- protected:
-  ~nsXBLBinding();
-
-  /*
-   * Internal version. Requires that aCx is in appropriate xbl scope.
-   */
-  bool LookupMemberInternal(JSContext* aCx, nsString& aName,
-                            JS::Handle<jsid> aNameAsId,
-                            JS::MutableHandle<JS::PropertyDescriptor> aDesc,
-                            JS::Handle<JSObject*> aXBLScope);
-
- public:
-  void MarkForDeath();
-  bool MarkedForDeath() const { return mMarkedForDeath; }
-
-  bool ImplementsInterface(REFNSIID aIID) const;
-
-  void GenerateAnonymousContent();
-  void BindAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement);
-  static void UnbindAnonymousContent(mozilla::dom::Document* aDocument,
-                                     nsIContent* aAnonParent,
-                                     bool aNullParent = true);
-  void InstallEventHandlers();
-  nsresult InstallImplementation();
-
-  void ExecuteAttachedHandler();
-  void ExecuteDetachedHandler();
-  void UnhookEventHandlers();
-
-  nsXBLBinding* RootBinding();
-
-  // Resolve all the fields for this binding and all ancestor bindings on the
-  // object |obj|.  False return means a JS exception was set.
-  bool ResolveAllFields(JSContext* cx, JS::Handle<JSObject*> obj) const;
-
-  void AttributeChanged(nsAtom* aAttribute, int32_t aNameSpaceID,
-                        bool aRemoveFlag, bool aNotify);
-
-  void ChangeDocument(mozilla::dom::Document* aOldDocument,
-                      mozilla::dom::Document* aNewDocument);
-
-  const RawServoAuthorStyles* GetServoStyles() const;
-
-  static nsresult DoInitJSClass(JSContext* cx, JS::Handle<JSObject*> obj,
-                                const nsString& aClassName,
-                                nsXBLPrototypeBinding* aProtoBinding,
-                                JS::MutableHandle<JSObject*> aClassObject,
-                                bool* aNew);
-
-  bool AllowScripts();
-
-  mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild);
-
-  bool HasFilteredInsertionPoints() { return !mInsertionPoints.IsEmpty(); }
-
-  mozilla::dom::XBLChildrenElement* GetDefaultInsertionPoint() {
-    return mDefaultInsertionPoint;
-  }
-
-  // Removes all inserted node from <xbl:children> insertion points under us.
-  void ClearInsertionPoints();
-
-  // Returns a live node list that iterates over the anonymous nodes generated
-  // by this binding.
-  nsAnonymousContentList* GetAnonymousNodeList();
-
-  nsIURI* GetSourceDocURI();
-
-  // MEMBER VARIABLES
- protected:
-  bool mMarkedForDeath;
-
-  nsXBLPrototypeBinding*
-      mPrototypeBinding;  // Weak, but we're holding a ref to the docinfo
-  nsCOMPtr<nsIContent>
-      mContent;  // Strong. Our anonymous content stays around with us.
-  RefPtr<nsXBLBinding> mNextBinding;  // Strong. The derived binding owns the
-                                      // base class bindings.
-
-  mozilla::dom::Element*
-      mBoundElement;  // [WEAK] We have a reference, but we don't own it.
-
-  // The <xbl:children> elements that we found in our <xbl:content> when we
-  // processed this binding. The default insertion point has no includes
-  // attribute and all other insertion points must have at least one includes
-  // attribute. These points must be up-to-date with respect to their parent's
-  // children, even if their parent has another binding attached to it,
-  // preventing us from rendering their contents directly.
-  RefPtr<mozilla::dom::XBLChildrenElement> mDefaultInsertionPoint;
-  nsTArray<RefPtr<mozilla::dom::XBLChildrenElement> > mInsertionPoints;
-  RefPtr<nsAnonymousContentList> mAnonymousContentList;
-
-  mozilla::dom::XBLChildrenElement* FindInsertionPointForInternal(
-      nsIContent* aChild);
-};
-
-#endif  // nsXBLBinding_h_
deleted file mode 100644
--- a/dom/xbl/nsXBLContentSink.cpp
+++ /dev/null
@@ -1,802 +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 "mozilla/ArrayUtils.h"
-
-#include "nsXBLContentSink.h"
-#include "mozilla/dom/Document.h"
-#include "nsBindingManager.h"
-#include "nsGkAtoms.h"
-#include "nsNameSpaceManager.h"
-#include "nsIURI.h"
-#include "nsTextFragment.h"
-#ifdef MOZ_XUL
-#  include "nsXULElement.h"
-#endif
-#include "nsXBLProtoImplProperty.h"
-#include "nsXBLProtoImplMethod.h"
-#include "nsXBLProtoImplField.h"
-#include "nsXBLPrototypeBinding.h"
-#include "nsContentUtils.h"
-#include "nsIConsoleService.h"
-#include "nsIScriptError.h"
-#include "nsNodeInfoManager.h"
-#include "nsIPrincipal.h"
-#include "mozilla/dom/Element.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-nsresult NS_NewXBLContentSink(nsIXMLContentSink** aResult, Document* aDoc,
-                              nsIURI* aURI, nsISupports* aContainer) {
-  NS_ENSURE_ARG_POINTER(aResult);
-
-  RefPtr<nsXBLContentSink> it = new nsXBLContentSink();
-  nsresult rv = it->Init(aDoc, aURI, aContainer);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  it.forget(aResult);
-  return NS_OK;
-}
-
-nsXBLContentSink::nsXBLContentSink()
-    : mState(eXBL_InDocument),
-      mSecondaryState(eXBL_None),
-      mDocInfo(nullptr),
-      mIsChromeOrResource(false),
-      mFoundFirstBinding(false),
-      mBinding(nullptr),
-      mHandler(nullptr),
-      mImplementation(nullptr),
-      mImplMember(nullptr),
-      mImplField(nullptr),
-      mProperty(nullptr),
-      mMethod(nullptr),
-      mField(nullptr) {
-  mPrettyPrintXML = false;
-}
-
-nsXBLContentSink::~nsXBLContentSink() {}
-
-nsresult nsXBLContentSink::Init(Document* aDoc, nsIURI* aURI,
-                                nsISupports* aContainer) {
-  nsresult rv;
-  rv = nsXMLContentSink::Init(aDoc, aURI, aContainer, nullptr);
-  return rv;
-}
-
-void nsXBLContentSink::MaybeStartLayout(bool aIgnorePendingSheets) {}
-
-nsresult nsXBLContentSink::FlushText(bool aReleaseTextNode) {
-  if (mTextLength != 0) {
-    const nsAString& text = Substring(mText, mText + mTextLength);
-    if (mState == eXBL_InHandlers) {
-      NS_ASSERTION(mBinding, "Must have binding here");
-      // Get the text and add it to the event handler.
-      if (mSecondaryState == eXBL_InHandler) mHandler->AppendHandlerText(text);
-      mTextLength = 0;
-      return NS_OK;
-    } else if (mState == eXBL_InImplementation) {
-      NS_ASSERTION(mBinding, "Must have binding here");
-      if (mSecondaryState == eXBL_InConstructor ||
-          mSecondaryState == eXBL_InDestructor) {
-        // Construct a method for the constructor/destructor.
-        nsXBLProtoImplMethod* method;
-        if (mSecondaryState == eXBL_InConstructor)
-          method = mBinding->GetConstructor();
-        else
-          method = mBinding->GetDestructor();
-
-        // Get the text and add it to the constructor/destructor.
-        method->AppendBodyText(text);
-      } else if (mSecondaryState == eXBL_InGetter ||
-                 mSecondaryState == eXBL_InSetter) {
-        // Get the text and add it to the getter/setter
-        if (mSecondaryState == eXBL_InGetter)
-          mProperty->AppendGetterText(text);
-        else
-          mProperty->AppendSetterText(text);
-      } else if (mSecondaryState == eXBL_InBody) {
-        // Get the text and add it to the method
-        if (mMethod) mMethod->AppendBodyText(text);
-      } else if (mSecondaryState == eXBL_InField) {
-        // Get the text and add it to the method
-        if (mField) mField->AppendFieldText(text);
-      }
-      mTextLength = 0;
-      return NS_OK;
-    }
-
-    nsIContent* content = GetCurrentContent();
-    if (content && (content->NodeInfo()->NamespaceEquals(kNameSpaceID_XBL) ||
-                    (content->IsXULElement() &&
-                     !content->IsAnyOfXULElements(nsGkAtoms::label,
-                                                  nsGkAtoms::description)))) {
-      bool isWS = true;
-      if (mTextLength > 0) {
-        const char16_t* cp = mText;
-        const char16_t* end = mText + mTextLength;
-        while (cp < end) {
-          char16_t ch = *cp++;
-          if (!dom::IsSpaceCharacter(ch)) {
-            isWS = false;
-            break;
-          }
-        }
-      }
-
-      if (isWS && mTextLength > 0) {
-        mTextLength = 0;
-        // Make sure to drop the textnode, if any
-        return nsXMLContentSink::FlushText(aReleaseTextNode);
-      }
-    }
-  }
-
-  return nsXMLContentSink::FlushText(aReleaseTextNode);
-}
-
-NS_IMETHODIMP
-nsXBLContentSink::ReportError(const char16_t* aErrorText,
-                              const char16_t* aSourceText,
-                              nsIScriptError* aError, bool* _retval) {
-  MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
-
-  // XXX FIXME This function overrides and calls on
-  // nsXMLContentSink::ReportError, and probably should die.  See bug 347826.
-
-  // XXX We should make sure the binding has no effect, but that it also
-  // gets destroyed properly without leaking.  Perhaps we should even
-  // ensure that the content that was bound is displayed with no
-  // binding.
-
-#ifdef DEBUG
-  // Report the error to stderr.
-  fprintf(stderr, "\n%s\n%s\n\n", NS_LossyConvertUTF16toASCII(aErrorText).get(),
-          NS_LossyConvertUTF16toASCII(aSourceText).get());
-#endif
-
-  // Most of what this does won't be too useful, but whatever...
-  // nsXMLContentSink::ReportError will handle the console logging.
-  return nsXMLContentSink::ReportError(aErrorText, aSourceText, aError,
-                                       _retval);
-}
-
-nsresult nsXBLContentSink::ReportUnexpectedElement(nsAtom* aElementName,
-                                                   uint32_t aLineNumber) {
-  // XXX we should really somehow stop the parse and drop the binding
-  // instead of just letting the XML sink build the content model like
-  // we do...
-  mState = eXBL_Error;
-  AutoTArray<nsString, 1> params;
-  aElementName->ToString(*params.AppendElement());
-
-  return nsContentUtils::ReportToConsole(
-      nsIScriptError::errorFlag, NS_LITERAL_CSTRING("XBL Content Sink"),
-      mDocument, nsContentUtils::eXBL_PROPERTIES, "UnexpectedElement", params,
-      nullptr, EmptyString() /* source line */, aLineNumber);
-}
-
-void nsXBLContentSink::AddMember(nsXBLProtoImplMember* aMember) {
-  // Add this member to our chain.
-  if (mImplMember)
-    mImplMember->SetNext(
-        aMember);  // Already have a chain. Just append to the end.
-  else
-    mImplementation->SetMemberList(
-        aMember);  // We're the first member in the chain.
-
-  mImplMember = aMember;  // Adjust our pointer to point to the new last member
-                          // in the chain.
-}
-
-void nsXBLContentSink::AddField(nsXBLProtoImplField* aField) {
-  // Add this field to our chain.
-  if (mImplField)
-    mImplField->SetNext(
-        aField);  // Already have a chain. Just append to the end.
-  else
-    mImplementation->SetFieldList(
-        aField);  // We're the first member in the chain.
-
-  mImplField = aField;  // Adjust our pointer to point to the new last field in
-                        // the chain.
-}
-
-NS_IMETHODIMP
-nsXBLContentSink::HandleStartElement(const char16_t* aName,
-                                     const char16_t** aAtts,
-                                     uint32_t aAttsCount, uint32_t aLineNumber,
-                                     uint32_t aColumnNumber) {
-  nsresult rv = nsXMLContentSink::HandleStartElement(
-      aName, aAtts, aAttsCount, aLineNumber, aColumnNumber);
-  if (NS_FAILED(rv)) return rv;
-
-  if (mState == eXBL_InBinding && !mBinding) {
-    rv = ConstructBinding(aLineNumber);
-    if (NS_FAILED(rv)) return rv;
-
-    // mBinding may still be null, if the binding had no id.  If so,
-    // we'll deal with that later in the sink.
-  }
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsXBLContentSink::HandleEndElement(const char16_t* aName) {
-  FlushText();
-
-  if (mState != eXBL_InDocument) {
-    int32_t nameSpaceID;
-    RefPtr<nsAtom> prefix, localName;
-    nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID == kNameSpaceID_XBL) {
-      if (mState == eXBL_Error) {
-        // Check whether we've opened this tag before; we may not have if
-        // it was a real XBL tag before the error occurred.
-        if (!GetCurrentContent()->NodeInfo()->Equals(localName, nameSpaceID)) {
-          // OK, this tag was never opened as far as the XML sink is
-          // concerned.  Just drop the HandleEndElement
-          return NS_OK;
-        }
-      } else if (mState == eXBL_InHandlers) {
-        if (localName == nsGkAtoms::handlers) {
-          mState = eXBL_InBinding;
-          mHandler = nullptr;
-        } else if (localName == nsGkAtoms::handler)
-          mSecondaryState = eXBL_None;
-        return NS_OK;
-      } else if (mState == eXBL_InImplementation) {
-        if (localName == nsGkAtoms::implementation)
-          mState = eXBL_InBinding;
-        else if (localName == nsGkAtoms::property) {
-          mSecondaryState = eXBL_None;
-          mProperty = nullptr;
-        } else if (localName == nsGkAtoms::method) {
-          mSecondaryState = eXBL_None;
-          mMethod = nullptr;
-        } else if (localName == nsGkAtoms::field) {
-          mSecondaryState = eXBL_None;
-          mField = nullptr;
-        } else if (localName == nsGkAtoms::constructor ||
-                   localName == nsGkAtoms::destructor)
-          mSecondaryState = eXBL_None;
-        else if (localName == nsGkAtoms::getter ||
-                 localName == nsGkAtoms::setter)
-          mSecondaryState = eXBL_InProperty;
-        else if (localName == nsGkAtoms::parameter ||
-                 localName == nsGkAtoms::body)
-          mSecondaryState = eXBL_InMethod;
-        return NS_OK;
-      } else if (mState == eXBL_InBindings &&
-                 localName == nsGkAtoms::bindings) {
-        mState = eXBL_InDocument;
-      }
-
-      nsresult rv = nsXMLContentSink::HandleEndElement(aName);
-      if (NS_FAILED(rv)) return rv;
-
-      if (mState == eXBL_InBinding && localName == nsGkAtoms::binding) {
-        mState = eXBL_InBindings;
-        if (mBinding) {  // See comment in HandleStartElement()
-          mBinding->Initialize();
-          mBinding = nullptr;  // Clear our current binding ref.
-        }
-      }
-
-      return NS_OK;
-    }
-  }
-
-  return nsXMLContentSink::HandleEndElement(aName);
-}
-
-NS_IMETHODIMP
-nsXBLContentSink::HandleCDataSection(const char16_t* aData, uint32_t aLength) {
-  if (mState == eXBL_InHandlers || mState == eXBL_InImplementation)
-    return AddText(aData, aLength);
-  return nsXMLContentSink::HandleCDataSection(aData, aLength);
-}
-
-#define ENSURE_XBL_STATE(_cond)                     \
-  PR_BEGIN_MACRO                                    \
-  if (!(_cond)) {                                   \
-    ReportUnexpectedElement(aTagName, aLineNumber); \
-    return true;                                    \
-  }                                                 \
-  PR_END_MACRO
-
-bool nsXBLContentSink::OnOpenContainer(const char16_t** aAtts,
-                                       uint32_t aAttsCount,
-                                       int32_t aNameSpaceID, nsAtom* aTagName,
-                                       uint32_t aLineNumber) {
-  if (mState == eXBL_Error) {
-    return true;
-  }
-
-  if (aNameSpaceID != kNameSpaceID_XBL) {
-    // Construct non-XBL nodes
-    return true;
-  }
-
-  bool ret = true;
-  if (aTagName == nsGkAtoms::bindings) {
-    ENSURE_XBL_STATE(mState == eXBL_InDocument);
-
-    NS_ASSERTION(mDocument, "Must have a document!");
-    RefPtr<nsXBLDocumentInfo> info = new nsXBLDocumentInfo(mDocument);
-
-    // We keep a weak ref. We're creating a cycle between doc/binding
-    // manager/doc info.
-    mDocInfo = info;
-
-    if (!mDocInfo) {
-      mState = eXBL_Error;
-      return true;
-    }
-
-    mDocument->BindingManager()->PutXBLDocumentInfo(mDocInfo);
-
-    nsIURI* uri = mDocument->GetDocumentURI();
-
-    mIsChromeOrResource = uri->SchemeIs("chrome") || uri->SchemeIs("resource");
-
-    mState = eXBL_InBindings;
-  } else if (aTagName == nsGkAtoms::binding) {
-    ENSURE_XBL_STATE(mState == eXBL_InBindings);
-    mState = eXBL_InBinding;
-  } else if (aTagName == nsGkAtoms::handlers) {
-    ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
-    mState = eXBL_InHandlers;
-    ret = false;
-  } else if (aTagName == nsGkAtoms::handler) {
-    ENSURE_XBL_STATE(mState == eXBL_InHandlers);
-    mSecondaryState = eXBL_InHandler;
-    ConstructHandler(aAtts, aLineNumber);
-    ret = false;
-  } else if (aTagName == nsGkAtoms::implementation) {
-    ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
-    mState = eXBL_InImplementation;
-    ConstructImplementation(aAtts);
-    // Note that this mState will cause us to return false, so no need
-    // to set ret to false.
-  } else if (aTagName == nsGkAtoms::constructor) {
-    ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
-                     mSecondaryState == eXBL_None);
-    NS_ASSERTION(mBinding, "Must have binding here");
-
-    mSecondaryState = eXBL_InConstructor;
-    nsAutoString name;
-    if (!mCurrentBindingID.IsEmpty()) {
-      name.Assign(mCurrentBindingID);
-      name.AppendLiteral("_XBL_Constructor");
-    } else {
-      name.AppendLiteral("XBL_Constructor");
-    }
-    nsXBLProtoImplAnonymousMethod* newMethod =
-        new nsXBLProtoImplAnonymousMethod(name.get());
-    newMethod->SetLineNumber(aLineNumber);
-    mBinding->SetConstructor(newMethod);
-    AddMember(newMethod);
-  } else if (aTagName == nsGkAtoms::destructor) {
-    ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
-                     mSecondaryState == eXBL_None);
-    NS_ASSERTION(mBinding, "Must have binding here");
-    mSecondaryState = eXBL_InDestructor;
-    nsAutoString name;
-    if (!mCurrentBindingID.IsEmpty()) {
-      name.Assign(mCurrentBindingID);
-      name.AppendLiteral("_XBL_Destructor");
-    } else {
-      name.AppendLiteral("XBL_Destructor");
-    }
-    nsXBLProtoImplAnonymousMethod* newMethod =
-        new nsXBLProtoImplAnonymousMethod(name.get());
-    newMethod->SetLineNumber(aLineNumber);
-    mBinding->SetDestructor(newMethod);
-    AddMember(newMethod);
-  } else if (aTagName == nsGkAtoms::field) {
-    ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
-                     mSecondaryState == eXBL_None);
-    NS_ASSERTION(mBinding, "Must have binding here");
-    mSecondaryState = eXBL_InField;
-    ConstructField(aAtts, aLineNumber);
-  } else if (aTagName == nsGkAtoms::property) {
-    ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
-                     mSecondaryState == eXBL_None);
-    NS_ASSERTION(mBinding, "Must have binding here");
-    mSecondaryState = eXBL_InProperty;
-    ConstructProperty(aAtts, aLineNumber);
-  } else if (aTagName == nsGkAtoms::getter) {
-    ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
-    NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
-    mProperty->SetGetterLineNumber(aLineNumber);
-    mSecondaryState = eXBL_InGetter;
-  } else if (aTagName == nsGkAtoms::setter) {
-    ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
-    NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
-    mProperty->SetSetterLineNumber(aLineNumber);
-    mSecondaryState = eXBL_InSetter;
-  } else if (aTagName == nsGkAtoms::method) {
-    ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
-                     mSecondaryState == eXBL_None);
-    NS_ASSERTION(mBinding, "Must have binding here");
-    mSecondaryState = eXBL_InMethod;
-    ConstructMethod(aAtts);
-  } else if (aTagName == nsGkAtoms::parameter) {
-    ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
-    NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
-    ConstructParameter(aAtts);
-  } else if (aTagName == nsGkAtoms::body) {
-    ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
-    NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
-    // stash away the line number
-    mMethod->SetLineNumber(aLineNumber);
-    mSecondaryState = eXBL_InBody;
-  }
-
-  return ret && mState != eXBL_InImplementation;
-}
-
-#undef ENSURE_XBL_STATE
-
-nsresult nsXBLContentSink::ConstructBinding(uint32_t aLineNumber) {
-  // This is only called from HandleStartElement, so it'd better be an element.
-  RefPtr<Element> binding = GetCurrentContent()->AsElement();
-  binding->GetAttr(kNameSpaceID_None, nsGkAtoms::id, mCurrentBindingID);
-  NS_ConvertUTF16toUTF8 cid(mCurrentBindingID);
-
-  nsresult rv = NS_OK;
-
-  // Don't create a binding with no id. nsXBLPrototypeBinding::Read also
-  // performs this check.
-  if (!cid.IsEmpty()) {
-    mBinding = new nsXBLPrototypeBinding();
-
-    rv = mBinding->Init(cid, mDocInfo, binding, !mFoundFirstBinding);
-    if (NS_SUCCEEDED(rv) &&
-        NS_SUCCEEDED(mDocInfo->SetPrototypeBinding(cid, mBinding))) {
-      if (!mFoundFirstBinding) {
-        mFoundFirstBinding = true;
-        mDocInfo->SetFirstPrototypeBinding(mBinding);
-      }
-      binding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::id, false);
-    } else {
-      delete mBinding;
-      mBinding = nullptr;
-    }
-  } else {
-    nsContentUtils::ReportToConsole(
-        nsIScriptError::errorFlag, NS_LITERAL_CSTRING("XBL Content Sink"),
-        nullptr, nsContentUtils::eXBL_PROPERTIES, "MissingIdAttr",
-        nsTArray<nsString>(), mDocumentURI, EmptyString(), aLineNumber);
-  }
-
-  return rv;
-}
-
-static bool FindValue(const char16_t** aAtts, nsAtom* aAtom,
-                      const char16_t** aResult) {
-  RefPtr<nsAtom> prefix, localName;
-  for (; *aAtts; aAtts += 2) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    // Is this attribute one of the ones we care about?
-    if (nameSpaceID == kNameSpaceID_None && localName == aAtom) {
-      *aResult = aAtts[1];
-
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void nsXBLContentSink::ConstructHandler(const char16_t** aAtts,
-                                        uint32_t aLineNumber) {
-  const char16_t* event = nullptr;
-  const char16_t* modifiers = nullptr;
-  const char16_t* button = nullptr;
-  const char16_t* clickcount = nullptr;
-  const char16_t* keycode = nullptr;
-  const char16_t* charcode = nullptr;
-  const char16_t* phase = nullptr;
-  const char16_t* command = nullptr;
-  const char16_t* action = nullptr;
-  const char16_t* group = nullptr;
-  const char16_t* preventdefault = nullptr;
-  const char16_t* allowuntrusted = nullptr;
-
-  RefPtr<nsAtom> prefix, localName;
-  for (; *aAtts; aAtts += 2) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID != kNameSpaceID_None) {
-      continue;
-    }
-
-    // Is this attribute one of the ones we care about?
-    if (localName == nsGkAtoms::event)
-      event = aAtts[1];
-    else if (localName == nsGkAtoms::modifiers)
-      modifiers = aAtts[1];
-    else if (localName == nsGkAtoms::button)
-      button = aAtts[1];
-    else if (localName == nsGkAtoms::clickcount)
-      clickcount = aAtts[1];
-    else if (localName == nsGkAtoms::keycode)
-      keycode = aAtts[1];
-    else if (localName == nsGkAtoms::key || localName == nsGkAtoms::charcode)
-      charcode = aAtts[1];
-    else if (localName == nsGkAtoms::phase)
-      phase = aAtts[1];
-    else if (localName == nsGkAtoms::command)
-      command = aAtts[1];
-    else if (localName == nsGkAtoms::action)
-      action = aAtts[1];
-    else if (localName == nsGkAtoms::group)
-      group = aAtts[1];
-    else if (localName == nsGkAtoms::preventdefault)
-      preventdefault = aAtts[1];
-    else if (localName == nsGkAtoms::allowuntrusted)
-      allowuntrusted = aAtts[1];
-  }
-
-  if (command && !mIsChromeOrResource) {
-    // Make sure the XBL doc is chrome or resource if we have a command
-    // shorthand syntax.
-    mState = eXBL_Error;
-    nsContentUtils::ReportToConsole(
-        nsIScriptError::errorFlag, NS_LITERAL_CSTRING("XBL Content Sink"),
-        mDocument, nsContentUtils::eXBL_PROPERTIES, "CommandNotInChrome",
-        nsTArray<nsString>(), nullptr, EmptyString() /* source line */,
-        aLineNumber);
-    return;  // Don't even make this handler.
-  }
-
-  // All of our pointers are now filled in. Construct our handler with all of
-  // these parameters.
-  nsXBLPrototypeHandler* newHandler;
-  newHandler = new nsXBLPrototypeHandler(
-      event, phase, action, command, keycode, charcode, modifiers, button,
-      clickcount, group, preventdefault, allowuntrusted, mBinding, aLineNumber);
-
-  // Add this handler to our chain of handlers.
-  if (mHandler) {
-    // Already have a chain. Just append to the end.
-    mHandler->SetNextHandler(newHandler);
-  } else {
-    // We're the first handler in the chain.
-    mBinding->SetPrototypeHandlers(newHandler);
-  }
-  // Adjust our mHandler pointer to point to the new last handler in the
-  // chain.
-  mHandler = newHandler;
-}
-
-void nsXBLContentSink::ConstructImplementation(const char16_t** aAtts) {
-  mImplementation = nullptr;
-  mImplMember = nullptr;
-  mImplField = nullptr;
-
-  if (!mBinding) return;
-
-  const char16_t* name = nullptr;
-
-  RefPtr<nsAtom> prefix, localName;
-  for (; *aAtts; aAtts += 2) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID != kNameSpaceID_None) {
-      continue;
-    }
-
-    // Is this attribute one of the ones we care about?
-    if (localName == nsGkAtoms::name) {
-      name = aAtts[1];
-    } else if (localName == nsGkAtoms::implements) {
-      // Only allow implementation of interfaces via XBL if the principal of
-      // our XBL document is the system principal.
-      if (nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal())) {
-        mBinding->ConstructInterfaceTable(nsDependentString(aAtts[1]));
-      }
-    }
-  }
-
-  NS_NewXBLProtoImpl(mBinding, name, &mImplementation);
-}
-
-void nsXBLContentSink::ConstructField(const char16_t** aAtts,
-                                      uint32_t aLineNumber) {
-  const char16_t* name = nullptr;
-  const char16_t* readonly = nullptr;
-
-  RefPtr<nsAtom> prefix, localName;
-  for (; *aAtts; aAtts += 2) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID != kNameSpaceID_None) {
-      continue;
-    }
-
-    // Is this attribute one of the ones we care about?
-    if (localName == nsGkAtoms::name) {
-      name = aAtts[1];
-    } else if (localName == nsGkAtoms::readonly) {
-      readonly = aAtts[1];
-    }
-  }
-
-  if (name) {
-    // All of our pointers are now filled in. Construct our field with all of
-    // these parameters.
-    mField = new nsXBLProtoImplField(name, readonly);
-    mField->SetLineNumber(aLineNumber);
-    AddField(mField);
-  }
-}
-
-void nsXBLContentSink::ConstructProperty(const char16_t** aAtts,
-                                         uint32_t aLineNumber) {
-  const char16_t* name = nullptr;
-  const char16_t* readonly = nullptr;
-  const char16_t* onget = nullptr;
-  const char16_t* onset = nullptr;
-  bool exposeToUntrustedContent = false;
-
-  RefPtr<nsAtom> prefix, localName;
-  for (; *aAtts; aAtts += 2) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID != kNameSpaceID_None) {
-      continue;
-    }
-
-    // Is this attribute one of the ones we care about?
-    if (localName == nsGkAtoms::name) {
-      name = aAtts[1];
-    } else if (localName == nsGkAtoms::readonly) {
-      readonly = aAtts[1];
-    } else if (localName == nsGkAtoms::onget) {
-      onget = aAtts[1];
-    } else if (localName == nsGkAtoms::onset) {
-      onset = aAtts[1];
-    } else if (localName == nsGkAtoms::exposeToUntrustedContent &&
-               nsDependentString(aAtts[1]).EqualsLiteral("true")) {
-      exposeToUntrustedContent = true;
-    }
-  }
-
-  if (name) {
-    // All of our pointers are now filled in. Construct our property with all of
-    // these parameters.
-    mProperty =
-        new nsXBLProtoImplProperty(name, onget, onset, readonly, aLineNumber);
-    if (exposeToUntrustedContent) {
-      mProperty->SetExposeToUntrustedContent(true);
-    }
-    AddMember(mProperty);
-  }
-}
-
-void nsXBLContentSink::ConstructMethod(const char16_t** aAtts) {
-  mMethod = nullptr;
-
-  const char16_t* name = nullptr;
-  const char16_t* expose = nullptr;
-  if (FindValue(aAtts, nsGkAtoms::name, &name)) {
-    mMethod = new nsXBLProtoImplMethod(name);
-    if (FindValue(aAtts, nsGkAtoms::exposeToUntrustedContent, &expose) &&
-        nsDependentString(expose).EqualsLiteral("true")) {
-      mMethod->SetExposeToUntrustedContent(true);
-    }
-  }
-
-  if (mMethod) {
-    AddMember(mMethod);
-  }
-}
-
-void nsXBLContentSink::ConstructParameter(const char16_t** aAtts) {
-  if (!mMethod) return;
-
-  const char16_t* name = nullptr;
-  if (FindValue(aAtts, nsGkAtoms::name, &name)) {
-    mMethod->AddParameter(nsDependentString(name));
-  }
-}
-
-nsresult nsXBLContentSink::CreateElement(
-    const char16_t** aAtts, uint32_t aAttsCount,
-    mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
-    uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent,
-    FromParser aFromParser) {
-#ifdef MOZ_XUL
-  if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
-#endif
-    return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
-                                           aLineNumber, aColumnNumber, aResult,
-                                           aAppendContent, aFromParser);
-#ifdef MOZ_XUL
-  }
-
-  // Note that this needs to match the code in
-  // nsXBLPrototypeBinding::ReadContentNode.
-
-  *aAppendContent = true;
-  RefPtr<nsXULPrototypeElement> prototype =
-      new nsXULPrototypeElement(aNodeInfo);
-
-  AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
-
-  Element* result;
-  nsresult rv = nsXULElement::CreateFromPrototype(prototype, mDocument, false,
-                                                  false, &result);
-  *aResult = result;
-  return rv;
-#endif
-}
-
-nsresult nsXBLContentSink::AddAttributes(const char16_t** aAtts,
-                                         Element* aElement) {
-  if (aElement->IsXULElement())
-    return NS_OK;  // Nothing to do, since the proto already has the attrs.
-
-  return nsXMLContentSink::AddAttributes(aAtts, aElement);
-}
-
-#ifdef MOZ_XUL
-nsresult nsXBLContentSink::AddAttributesToXULPrototype(
-    const char16_t** aAtts, uint32_t aAttsCount,
-    nsXULPrototypeElement* aElement) {
-  // Add tag attributes to the element
-  nsresult rv;
-
-  // Create storage for the attributes
-  nsXULPrototypeAttribute* attrs = nullptr;
-  if (aAttsCount > 0) {
-    attrs = aElement->mAttributes.AppendElements(aAttsCount);
-  }
-
-  // Copy the attributes into the prototype
-  RefPtr<nsAtom> prefix, localName;
-
-  uint32_t i;
-  for (i = 0; i < aAttsCount; ++i) {
-    int32_t nameSpaceID;
-    nsContentUtils::SplitExpatName(aAtts[i * 2], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-
-    if (nameSpaceID == kNameSpaceID_None) {
-      attrs[i].mName.SetTo(localName);
-    } else {
-      RefPtr<NodeInfo> ni;
-      ni = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
-                                         nsINode::ATTRIBUTE_NODE);
-      attrs[i].mName.SetTo(ni);
-    }
-
-    rv = aElement->SetAttrAt(i, nsDependentString(aAtts[i * 2 + 1]),
-                             mDocumentURI);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return NS_OK;
-}
-#endif
deleted file mode 100644
--- a/dom/xbl/nsXBLContentSink.h
+++ /dev/null
@@ -1,145 +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 nsXBLContentSink_h__
-#define nsXBLContentSink_h__
-
-#include "mozilla/Attributes.h"
-#include "nsXMLContentSink.h"
-#include "nsXBLDocumentInfo.h"
-#include "nsXBLPrototypeHandler.h"
-#include "nsXBLProtoImpl.h"
-#include "nsLayoutCID.h"
-
-/*
- * Enum that describes the primary state of the parsing process
- */
-typedef enum {
-  eXBL_InDocument,       /* outside any bindings */
-  eXBL_InBindings,       /* Inside a <bindings> element */
-  eXBL_InBinding,        /* Inside a <binding> */
-  eXBL_InImplementation, /* Inside a <implementation> */
-  eXBL_InHandlers,       /* Inside a <handlers> */
-  eXBL_Error /* An error has occurred.  Suspend binding construction */
-} XBLPrimaryState;
-
-/*
- * Enum that describes our substate (typically when parsing something
- * like <handlers> or <implementation>).
- */
-typedef enum {
-  eXBL_None,
-  eXBL_InHandler,
-  eXBL_InMethod,
-  eXBL_InProperty,
-  eXBL_InField,
-  eXBL_InBody,
-  eXBL_InGetter,
-  eXBL_InSetter,
-  eXBL_InConstructor,
-  eXBL_InDestructor
-} XBLSecondaryState;
-
-class nsXULPrototypeElement;
-class nsXBLProtoImplMember;
-class nsXBLProtoImplProperty;
-class nsXBLProtoImplMethod;
-class nsXBLProtoImplField;
-class nsXBLPrototypeBinding;
-
-// The XBL content sink overrides the XML content sink to
-// builds its own lightweight data structures for the <resources>,
-// <handlers>, <implementation>, and
-
-class nsXBLContentSink : public nsXMLContentSink {
- public:
-  nsXBLContentSink();
-  ~nsXBLContentSink();
-
-  nsresult Init(mozilla::dom::Document* aDoc, nsIURI* aURL,
-                nsISupports* aContainer);
-
-  // nsIContentSink overrides
-  NS_IMETHOD HandleStartElement(const char16_t* aName, const char16_t** aAtts,
-                                uint32_t aAttsCount, uint32_t aLineNumber,
-                                uint32_t aColumnNumber) override;
-
-  NS_IMETHOD HandleEndElement(const char16_t* aName) override;
-
-  NS_IMETHOD HandleCDataSection(const char16_t* aData,
-                                uint32_t aLength) override;
-
- protected:
-  // nsXMLContentSink overrides
-  virtual void MaybeStartLayout(bool aIgnorePendingSheets) override;
-
-  bool OnOpenContainer(const char16_t** aAtts, uint32_t aAttsCount,
-                       int32_t aNameSpaceID, nsAtom* aTagName,
-                       uint32_t aLineNumber) override;
-
-  bool NotifyForDocElement() override { return false; }
-
-  nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
-                         mozilla::dom::NodeInfo* aNodeInfo,
-                         uint32_t aLineNumber, uint32_t aColumnNumber,
-                         nsIContent** aResult, bool* aAppendContent,
-                         mozilla::dom::FromParser aFromParser) override;
-
-  nsresult AddAttributes(const char16_t** aAtts,
-                         mozilla::dom::Element* aElement) override;
-
-#ifdef MOZ_XUL
-  nsresult AddAttributesToXULPrototype(const char16_t** aAtts,
-                                       uint32_t aAttsCount,
-                                       nsXULPrototypeElement* aElement);
-#endif
-
-  // Our own helpers for constructing XBL prototype objects.
-  nsresult ConstructBinding(uint32_t aLineNumber);
-  void ConstructHandler(const char16_t** aAtts, uint32_t aLineNumber);
-  void ConstructImplementation(const char16_t** aAtts);
-  void ConstructProperty(const char16_t** aAtts, uint32_t aLineNumber);
-  void ConstructMethod(const char16_t** aAtts);
-  void ConstructParameter(const char16_t** aAtts);
-  void ConstructField(const char16_t** aAtts, uint32_t aLineNumber);
-
-  // nsXMLContentSink overrides
-  nsresult FlushText(bool aReleaseTextNode = true) override;
-
-  // nsIExpatSink overrides
-  NS_IMETHOD ReportError(const char16_t* aErrorText,
-                         const char16_t* aSourceText, nsIScriptError* aError,
-                         bool* _retval) override;
-
- protected:
-  nsresult ReportUnexpectedElement(nsAtom* aElementName, uint32_t aLineNumber);
-
-  void AddMember(nsXBLProtoImplMember* aMember);
-  void AddField(nsXBLProtoImplField* aField);
-
-  XBLPrimaryState mState;
-  XBLSecondaryState mSecondaryState;
-  nsXBLDocumentInfo* mDocInfo;
-  bool mIsChromeOrResource;  // For bug #45989
-  bool mFoundFirstBinding;
-
-  nsString mCurrentBindingID;
-
-  nsXBLPrototypeBinding* mBinding;
-  nsXBLPrototypeHandler*
-      mHandler;  // current handler, owned by its PrototypeBinding
-  nsXBLProtoImpl* mImplementation;
-  nsXBLProtoImplMember* mImplMember;
-  nsXBLProtoImplField* mImplField;
-  nsXBLProtoImplProperty* mProperty;
-  nsXBLProtoImplMethod* mMethod;
-  nsXBLProtoImplField* mField;
-};
-
-nsresult NS_NewXBLContentSink(nsIXMLContentSink** aResult,
-                              mozilla::dom::Document* aDoc, nsIURI* aURL,
-                              nsISupports* aContainer);
-#endif  // nsXBLContentSink_h__
deleted file mode 100644
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ /dev/null
@@ -1,311 +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 "mozilla/DebugOnly.h"
-
-#include "nsXBLDocumentInfo.h"
-#include "mozilla/dom/Document.h"
-#include "nsXBLPrototypeBinding.h"
-#include "nsIScriptObjectPrincipal.h"
-#include "nsIScriptContext.h"
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "nsIURI.h"
-#include "nsIConsoleService.h"
-#include "nsIScriptError.h"
-#include "nsIChromeRegistry.h"
-#include "nsIPrincipal.h"
-#include "nsJSPrincipals.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsContentUtils.h"
-#include "nsDOMJSUtils.h"
-#include "nsWindowSizes.h"
-#include "mozilla/Services.h"
-#include "xpcpublic.h"
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/scache/StartupCacheUtils.h"
-#include "nsCCUncollectableMarker.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/URL.h"
-
-using namespace mozilla;
-using namespace mozilla::scache;
-using namespace mozilla::dom;
-
-static const char kXBLCachePrefix[] = "xblcache";
-
-/* Implementation file */
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
-  if (tmp->mBindingTable) {
-    for (auto iter = tmp->mBindingTable->ConstIter(); !iter.Done();
-         iter.Next()) {
-      iter.UserData()->Unlink();
-    }
-  }
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
-  if (tmp->mDocument && nsCCUncollectableMarker::InGeneration(
-                            cb, tmp->mDocument->GetMarkedCCGeneration())) {
-    return NS_SUCCESS_INTERRUPTED_TRAVERSE;
-  }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
-  if (tmp->mBindingTable) {
-    for (auto iter = tmp->mBindingTable->ConstIter(); !iter.Done();
-         iter.Next()) {
-      iter.UserData()->Traverse(cb);
-    }
-  }
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
-  if (tmp->mBindingTable) {
-    for (auto iter = tmp->mBindingTable->ConstIter(); !iter.Done();
-         iter.Next()) {
-      iter.UserData()->Trace(aCallbacks, aClosure);
-    }
-  }
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-static void UnmarkXBLJSObject(JS::GCCellPtr aPtr, const char* aName,
-                              void* aClosure) {
-  JS::ExposeObjectToActiveJS(&aPtr.as<JSObject>());
-}
-
-void nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration) {
-  if (mDocument) {
-    mDocument->MarkUncollectableForCCGeneration(aGeneration);
-  }
-  // Unmark any JS we hold
-  if (mBindingTable) {
-    for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
-      iter.UserData()->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr);
-    }
-  }
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocumentInfo)
-
-nsXBLDocumentInfo::nsXBLDocumentInfo(Document* aDocument)
-    : mDocument(aDocument),
-      mScriptAccess(true),
-      mIsChrome(false),
-      mFirstBinding(nullptr) {
-  nsIURI* uri = aDocument->GetDocumentURI();
-  if (IsChromeURI(uri)) {
-    // Cache whether or not this chrome XBL can execute scripts.
-    nsCOMPtr<nsIXULChromeRegistry> reg =
-        mozilla::services::GetXULChromeRegistryService();
-    if (reg) {
-      bool allow = true;
-      reg->AllowScriptsForPackage(uri, &allow);
-      mScriptAccess = allow;
-    }
-    mIsChrome = true;
-  } else {
-    // If this binding isn't running with system principal, then it's running
-    // from a remote-XUL whitelisted domain. This is already a not-really-
-    // supported configuration (among other things, we don't use XBL scopes in
-    // that configuration for compatibility reasons). But we should still at
-    // least make an effort to prevent binding code from running if content
-    // script is disabled or if the source domain is blacklisted (since the
-    // source domain for remote XBL must always be the same as the source domain
-    // of the bound content).
-    //
-    // If we just ask the binding document if script is enabled, it will
-    // discover that it has no inner window, and return false. So instead, we
-    // short-circuit the normal compartment-managed script-disabling machinery,
-    // and query the policy for the URI directly.
-    bool allow;
-    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-    nsresult rv = ssm->PolicyAllowsScript(uri, &allow);
-    mScriptAccess = NS_SUCCEEDED(rv) && allow;
-  }
-}
-
-nsXBLDocumentInfo::~nsXBLDocumentInfo() { mozilla::DropJSObjects(this); }
-
-nsXBLPrototypeBinding* nsXBLDocumentInfo::GetPrototypeBinding(
-    const nsACString& aRef) {
-  if (!mBindingTable) return nullptr;
-
-  if (aRef.IsEmpty()) {
-    // Return our first binding
-    return mFirstBinding;
-  }
-
-  return mBindingTable->Get(aRef);
-}
-
-nsresult nsXBLDocumentInfo::SetPrototypeBinding(
-    const nsACString& aRef, nsXBLPrototypeBinding* aBinding) {
-  if (!mBindingTable) {
-    mBindingTable =
-        new nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>();
-    mozilla::HoldJSObjects(this);
-  }
-
-  NS_ENSURE_STATE(!mBindingTable->Get(aRef));
-  mBindingTable->Put(aRef, aBinding);
-
-  return NS_OK;
-}
-
-void nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef) {
-  if (mBindingTable) {
-    nsAutoPtr<nsXBLPrototypeBinding> bindingToRemove;
-    mBindingTable->Remove(aRef, &bindingToRemove);
-
-    // We do not want to destroy the binding, so just forget it.
-    bindingToRemove.forget();
-  }
-}
-
-// static
-nsresult nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI,
-                                                  nsXBLDocumentInfo** aDocInfo,
-                                                  Document* aBoundDocument) {
-  *aDocInfo = nullptr;
-
-  nsAutoCString spec(kXBLCachePrefix);
-  nsresult rv = PathifyURI(aURI, spec);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  StartupCache* startupCache = StartupCache::GetSingleton();
-  if (!startupCache) {
-    return NS_ERROR_FAILURE;
-  }
-
-  const char* buf;
-  uint32_t len;
-  rv = startupCache->GetBuffer(spec.get(), &buf, &len);
-  // GetBuffer will fail if the binding is not in the cache.
-  if (NS_FAILED(rv)) return rv;
-
-  nsCOMPtr<nsIObjectInputStream> stream;
-  rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(stream));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // The file compatibility.ini stores the build id. This is checked in
-  // nsAppRunner.cpp and will delete the cache if a different build is
-  // present. However, we check that the version matches here to be safe.
-  uint32_t version;
-  rv = stream->Read32(&version);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (version != XBLBinding_Serialize_Version) {
-    // The version that exists is different than expected, likely created with a
-    // different build, so invalidate the cache.
-    startupCache->InvalidateCache();
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  nsCOMPtr<nsIPrincipal> principal;
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(
-      getter_AddRefs(principal));
-
-  nsCOMPtr<Document> doc;
-  rv = NS_NewXBLDocument(getter_AddRefs(doc), aURI, nullptr, principal);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(doc);
-
-  while (1) {
-    uint8_t flags;
-    nsresult rv = stream->Read8(&flags);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (flags == XBLBinding_Serialize_NoMoreBindings) break;
-
-    rv = nsXBLPrototypeBinding::ReadNewBinding(stream, docInfo, doc, flags);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-  }
-
-  docInfo.forget(aDocInfo);
-  return NS_OK;
-}
-
-nsresult nsXBLDocumentInfo::WritePrototypeBindings() {
-  // Only write out bindings with the system principal
-  if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal()))
-    return NS_OK;
-
-  nsAutoCString spec(kXBLCachePrefix);
-  nsresult rv = PathifyURI(DocumentURI(), spec);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  StartupCache* startupCache = StartupCache::GetSingleton();
-  if (!startupCache) {
-    return rv;
-  }
-
-  nsCOMPtr<nsIObjectOutputStream> stream;
-  nsCOMPtr<nsIStorageStream> storageStream;
-  rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(stream),
-                                           getter_AddRefs(storageStream), true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = stream->Write32(XBLBinding_Serialize_Version);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (mBindingTable) {
-    for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
-      iter.UserData()->Write(stream);
-    }
-  }
-
-  // write a end marker at the end
-  rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  stream->Close();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  uint32_t len;
-  UniquePtr<char[]> buf;
-  rv = NewBufferFromStorageStream(storageStream, &buf, &len);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return startupCache->PutBuffer(spec.get(), std::move(buf), len);
-}
-
-void nsXBLDocumentInfo::SetFirstPrototypeBinding(
-    nsXBLPrototypeBinding* aBinding) {
-  mFirstBinding = aBinding;
-}
-
-#ifdef DEBUG
-void AssertInCompilationScope() {
-  AutoJSContext cx;
-  MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx));
-}
-#endif
-
-size_t nsXBLDocumentInfo::SizeOfIncludingThis(
-    MallocSizeOf aMallocSizeOf) const {
-  size_t n = aMallocSizeOf(this);
-  if (mDocument) {
-    SizeOfState state(aMallocSizeOf);
-    nsWindowSizes windowSizes(state);
-    mDocument->DocAddSizeOfIncludingThis(windowSizes);
-    n += windowSizes.getTotalSize();
-  }
-  if (mBindingTable) {
-    n += mBindingTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
-    for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
-      nsXBLPrototypeBinding* binding = iter.UserData();
-      n += binding->SizeOfIncludingThis(aMallocSizeOf);
-    }
-  }
-  return n;
-}
deleted file mode 100644
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ /dev/null
@@ -1,75 +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 nsXBLDocumentInfo_h__
-#define nsXBLDocumentInfo_h__
-
-#include "mozilla/Attributes.h"
-#include "mozilla/MemoryReporting.h"
-#include "nsCOMPtr.h"
-#include "nsAutoPtr.h"
-#include "nsWeakReference.h"
-#include "mozilla/dom/Document.h"
-#include "nsCycleCollectionParticipant.h"
-
-class nsXBLPrototypeBinding;
-
-class nsXBLDocumentInfo final : public nsSupportsWeakReference {
- public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-
-  explicit nsXBLDocumentInfo(mozilla::dom::Document* aDocument);
-
-  mozilla::dom::Document* GetDocument() const { return mDocument; }
-
-  bool GetScriptAccess() const { return mScriptAccess; }
-
-  nsIURI* DocumentURI() { return mDocument->GetDocumentURI(); }
-
-  nsXBLPrototypeBinding* GetPrototypeBinding(const nsACString& aRef);
-  nsresult SetPrototypeBinding(const nsACString& aRef,
-                               nsXBLPrototypeBinding* aBinding);
-
-  // This removes the binding without deleting it
-  void RemovePrototypeBinding(const nsACString& aRef);
-
-  nsresult WritePrototypeBindings();
-
-  void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
-
-  bool IsChrome() { return mIsChrome; }
-
-  void MarkInCCGeneration(uint32_t aGeneration);
-
-  static nsresult ReadPrototypeBindings(nsIURI* aURI,
-                                        nsXBLDocumentInfo** aDocInfo,
-                                        mozilla::dom::Document* aBoundDocument);
-
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
-
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
-
- private:
-  virtual ~nsXBLDocumentInfo();
-
-  RefPtr<mozilla::dom::Document> mDocument;
-  bool mScriptAccess;
-  bool mIsChrome;
-  // the binding table owns each nsXBLPrototypeBinding
-  nsAutoPtr<nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>>
-      mBindingTable;
-
-  // non-owning pointer to the first binding in the table
-  nsXBLPrototypeBinding* mFirstBinding;
-};
-
-#ifdef DEBUG
-void AssertInCompilationScope();
-#else
-inline void AssertInCompilationScope() {}
-#endif
-
-#endif
deleted file mode 100644
--- a/dom/xbl/nsXBLEventHandler.cpp
+++ /dev/null
@@ -1,161 +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 "nsCOMPtr.h"
-#include "nsAtom.h"
-#include "nsIDOMEventListener.h"
-#include "nsXBLPrototypeHandler.h"
-#include "nsContentUtils.h"
-#include "mozilla/dom/Event.h"         // for Event
-#include "mozilla/dom/EventBinding.h"  // for Event
-#include "mozilla/dom/EventTarget.h"
-#include "mozilla/dom/KeyboardEvent.h"
-#include "mozilla/TextEvents.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler)
-    : mProtoHandler(aHandler) {}
-
-nsXBLEventHandler::~nsXBLEventHandler() {}
-
-NS_IMPL_ISUPPORTS(nsXBLEventHandler, nsIDOMEventListener)
-
-NS_IMETHODIMP
-nsXBLEventHandler::HandleEvent(Event* aEvent) {
-  if (!mProtoHandler) return NS_ERROR_FAILURE;
-
-  uint8_t phase = mProtoHandler->GetPhase();
-  if (phase == NS_PHASE_TARGET) {
-    if (aEvent->EventPhase() != Event_Binding::AT_TARGET) {
-      return NS_OK;
-    }
-  }
-
-  if (!EventMatched(aEvent)) return NS_OK;
-