merge autoland to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 27 Sep 2017 23:54:52 +0200
changeset 383339 69e3f89816455e567f1a20b694fd6afd549c82c7
parent 383338 756e10aa8bbd416cbc49b7739f78fb81d5525477 (current diff)
parent 383336 d4f0e2c17276d8d7b89384ba66985c59616d7ffb (diff)
child 383340 5ebe2e8980c6fd3ede2b6617bbbc4073dd9b0369
push id95539
push userkwierso@gmail.com
push dateThu, 28 Sep 2017 00:01:12 +0000
treeherdermozilla-inbound@72de90e66155 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge autoland to mozilla-central. r=merge a=merge MozReview-Commit-ID: IsAdN1XhVDj
devtools/client/shims/devtools.js
devtools/client/webconsole/local-dev/jsterm-stub.js
devtools/client/webconsole/local-dev/system-stub.js
devtools/shared/platform/README.md
devtools/shared/platform/chrome/clipboard.js
devtools/shared/platform/chrome/moz.build
devtools/shared/platform/chrome/stack.js
devtools/shared/platform/content/.eslintrc.js
devtools/shared/platform/content/clipboard.js
devtools/shared/platform/content/moz.build
devtools/shared/platform/content/stack.js
devtools/shared/platform/content/test/.eslintrc.js
devtools/shared/platform/content/test/mochitest.ini
devtools/shared/platform/content/test/test_clipboard.html
devtools/shared/platform/content/test/test_stack.js
devtools/shared/platform/content/test/xpcshell.ini
devtools/shared/shims/fronts/timeline.js
testing/web-platform/meta/css/css-variables-1/variable-animation-substitute-within-keyframe-fallback.html.ini
testing/web-platform/meta/css/css-variables-1/variable-animation-substitute-within-keyframe-multiple.html.ini
testing/web-platform/meta/css/css-variables-1/variable-animation-substitute-within-keyframe.html.ini
toolkit/components/places/tests/unit/test_418643_removeFolderChildren.js
toolkit/components/places/tests/unit/test_bookmarks_setNullTitle.js
toolkit/components/places/tests/unit/test_placesTxn.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -126,17 +126,17 @@ devtools/client/webconsole/hudservice.js
 devtools/client/webconsole/webconsole-connection-proxy.js
 devtools/client/webconsole/webconsole.js
 devtools/client/webide/**
 !devtools/client/webide/components/webideCli.js
 devtools/server/tests/browser/storage-*.html
 !devtools/server/tests/browser/storage-unsecured-iframe.html
 devtools/server/tests/browser/stylesheets-nested-iframes.html
 devtools/server/tests/unit/xpcshell_debugging_script.js
-devtools/shared/platform/content/test/test_clipboard.html
+devtools/client/shared/webpack/shims/test/test_clipboard.html
 devtools/shared/qrcode/tests/mochitest/test_decode.html
 devtools/shared/tests/mochitest/*.html
 devtools/shared/webconsole/test/test_*.html
 
 # Ignore devtools preferences files
 devtools/client/preferences/**
 devtools/shim/devtools-startup-prefs.js
 
--- a/.gitignore
+++ b/.gitignore
@@ -121,16 +121,20 @@ node_modules/
 testing/talos/.Python
 testing/talos/bin/
 testing/talos/include/
 testing/talos/lib/
 testing/talos/talos/tests/tp5n.zip
 testing/talos/talos/tests/tp5n
 testing/talos/talos/tests/devtools/damp.manifest.develop
 
+# Ignore sync tps logs and reports
+tps.log
+tps_result.json
+
 # Ignore files created when running a reftest.
 lextab.py
 
 # tup database
 /.tup
 
 # Ignore Visual Studio Code workspace files.
 .vscode/*
--- a/.hgignore
+++ b/.hgignore
@@ -145,15 +145,19 @@ GPATH
 ^testing/talos/talos/mitmproxy/mitmweb
 
 # Ignore files created when running a reftest.
 ^lextab.py$
 
 # tup database
 ^\.tup
 
+# Ignore sync tps logs and reports
+tps\.log
+tps_result\.json
+
 # Ignore Visual Studio Code workspace files.
 \.vscode/(?!extensions\.json|tasks\.json)
 
 subinclude:servo/.hgignore
 
 # Ignore Infer output
 ^infer-out/
--- a/accessible/base/AccEvent.h
+++ b/accessible/base/AccEvent.h
@@ -526,17 +526,17 @@ public:
   {
     return AccEvent::GetEventGroups() | (1U << eObjectAttrChangedEvent);
   }
 
   // AccObjectAttrChangedEvent
   nsIAtom* GetAttribute() const { return mAttribute; }
 
 private:
-  nsCOMPtr<nsIAtom> mAttribute;
+  RefPtr<nsIAtom> mAttribute;
 
   virtual ~AccObjectAttrChangedEvent() { }
 };
 
 /**
  * Downcast the generic accessible event object to derived type.
  */
 class downcast_accEvent
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -8187,17 +8187,20 @@
           createUserContextMenu(event, {useAccessKeys: false});
           return;
         }
 
         let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
 
         if (event.target.getAttribute("anonid") == "newtab-popup" ||
             event.target.id == "newtab-popup") {
-          createUserContextMenu(event, {useAccessKeys: false});
+          createUserContextMenu(event, {
+            useAccessKeys: false,
+            showDefaultTab: Services.prefs.getIntPref("privacy.userContext.longPressBehavior") == 1
+          });
         } else {
           document.getElementById("alltabs-popup-separator-1").hidden = !containersEnabled;
           let containersTab = document.getElementById("alltabs_containersTab");
 
           containersTab.hidden = !containersEnabled;
           if (PrivateBrowsingUtils.isWindowPrivate(window)) {
             containersTab.setAttribute("disabled", "true");
           }
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -521,27 +521,28 @@ function checkForMiddleClick(node, event
   }
 }
 
 // Populate a menu with user-context menu items. This method should be called
 // by onpopupshowing passing the event as first argument.
 function createUserContextMenu(event, {
                                         isContextMenu = false,
                                         excludeUserContextId = 0,
+                                        showDefaultTab = false,
                                         useAccessKeys = true
                                       } = {}) {
   while (event.target.hasChildNodes()) {
     event.target.firstChild.remove();
   }
 
   let bundle = document.getElementById("bundle_browser");
   let docfrag = document.createDocumentFragment();
 
   // If we are excluding a userContextId, we want to add a 'no-container' item.
-  if (excludeUserContextId) {
+  if (excludeUserContextId || showDefaultTab) {
     let menuitem = document.createElement("menuitem");
     menuitem.setAttribute("data-usercontextid", "0");
     menuitem.setAttribute("label", bundle.getString("userContextNone.label"));
     menuitem.setAttribute("accesskey", bundle.getString("userContextNone.accesskey"));
 
     // We don't set an oncommand/command attribute because if we have
     // to exclude a userContextId we are generating the contextMenu and
     // isContextMenu will be true.
--- a/browser/components/contextualidentity/test/browser/browser_newtabButton.js
+++ b/browser/components/contextualidentity/test/browser/browser_newtabButton.js
@@ -43,31 +43,46 @@ add_task(async function test_menu_withou
 
   let newTab = document.getElementById("tabbrowser-tabs");
   let newTabButton = document.getAnonymousElementByAttribute(newTab, "anonid", "tabs-newtab-button");
   ok(newTabButton, "New tab button exists");
   ok(!newTabButton.hidden, "New tab button is visible");
   await BrowserTestUtils.waitForCondition(() => !!document.getAnonymousElementByAttribute(newTab, "anonid", "newtab-popup"), "Wait for popup to exist");
   let popup = document.getAnonymousElementByAttribute(newTab, "anonid", "newtab-popup");
 
-  for (let i = 1; i <= 4; i++) {
-    let popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
+  let popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
+  let popupHiddenPromise = BrowserTestUtils.waitForEvent(popup, "popuphidden");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {type: "mousedown"});
+  await popupShownPromise;
+  let contextIdItems = popup.querySelectorAll("menuitem");
+  // 4 + default + manage containers
+  is(contextIdItems.length, 6, "Has 6 menu items");
+  popup.hidePopup();
+  await popupHiddenPromise;
+
+  for (let i = 0; i <= 4; i++) {
+    popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
     EventUtils.synthesizeMouseAtCenter(newTabButton, {type: "mousedown"});
 
     await popupShownPromise;
     let contextIdItem = popup.querySelector(`menuitem[data-usercontextid="${i}"]`);
 
     ok(contextIdItem, `User context id ${i} exists`);
 
-    let waitForTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
+    // waitForNewTab doesn't work for default tabs due to a different code path that doesn't cause a load event
+    let waitForTabPromise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
     EventUtils.synthesizeMouseAtCenter(contextIdItem, {});
 
-    let tab = await waitForTabPromise;
-
-    is(tab.getAttribute("usercontextid"), i, `New tab has UCI equal ${i}`);
+    let tabEvent = await waitForTabPromise;
+    let tab = tabEvent.target;
+    if (i > 0) {
+      is(tab.getAttribute("usercontextid"), i, `New tab has UCI equal ${i}`);
+    } else {
+      ok(!tab.hasAttribute("usercontextid"), `New tab has no UCI`);
+    }
     await BrowserTestUtils.removeTab(tab);
   }
 });
 
 add_task(async function test_no_menu() {
   await SpecialPowers.pushPrefEnv({"set": [
       ["privacy.userContext.enabled", true],
       ["privacy.userContext.longPressBehavior", 0]
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -102,17 +102,27 @@ const clearIndexedDB = async function(op
       resolve();
     });
   });
 
   return Promise.all(promises);
 };
 
 const clearLocalStorage = async function(options) {
-  Services.obs.notifyObservers(null, "extension:purge-localStorage");
+  if (options.since) {
+    return Promise.reject(
+      {message: "Firefox does not support clearing localStorage with 'since'."});
+  }
+  if (options.hostnames) {
+    for (let hostname of options.hostnames) {
+      Services.obs.notifyObservers(null, "extension:purge-localStorage", hostname);
+    }
+  } else {
+    Services.obs.notifyObservers(null, "extension:purge-localStorage");
+  }
 };
 
 const clearPasswords = async function(options) {
   let loginManager = Services.logins;
   let yieldCounter = 0;
 
   if (options.since) {
     // Iterate through the logins and delete any updated after our cutoff.
--- a/browser/components/extensions/schemas/browsing_data.json
+++ b/browser/components/extensions/schemas/browsing_data.json
@@ -31,17 +31,17 @@
             "$ref": "extensionTypes.Date",
             "optional": true,
             "description": "Remove data accumulated on or after this date, represented in milliseconds since the epoch (accessible via the <code>getTime</code> method of the JavaScript <code>Date</code> object). If absent, defaults to 0 (which would remove all browsing data)."
           },
           "hostnames": {
             "type": "array",
             "items": {"type": "string", "format": "hostname"},
             "optional": true,
-            "description": "Only remove data associated with these hostnames (only applies to cookies)."
+            "description": "Only remove data associated with these hostnames (only applies to cookies and localStorage)."
           },
           "originTypes": {
             "type": "object",
             "optional": true,
             "description": "An object whose properties specify which origin types ought to be cleared. If this object isn't specified, it defaults to clearing only \"unprotected\" origins. Please ensure that you <em>really</em> want to remove application data before adding 'protectedWeb' or 'extensions'.",
             "properties": {
               "unprotectedWeb": {
                 "type": "boolean",
--- a/browser/components/extensions/test/browser/browser_ext_browsingData_localStorage.js
+++ b/browser/components/extensions/test/browser/browser_ext_browsingData_localStorage.js
@@ -34,16 +34,27 @@ add_task(async function testLocalStorage
 
     function sendMessageToTabs(tabs, message) {
       return Promise.all(
         tabs.map(tab => { return browser.tabs.sendMessage(tab.id, message); }));
     }
 
     let tabs = await openTabs();
 
+    browser.test.assertRejects(
+      browser.browsingData.removeLocalStorage({since: Date.now()}),
+      "Firefox does not support clearing localStorage with 'since'.",
+      "Expected error received when using unimplemented parameter 'since'."
+    );
+
+    await sendMessageToTabs(tabs, "resetLocalStorage");
+    await browser.browsingData.removeLocalStorage({hostnames: ["example.com"]});
+    await browser.tabs.sendMessage(tabs[0].id, "checkLocalStorageCleared");
+    await browser.tabs.sendMessage(tabs[1].id, "checkLocalStorageSet");
+
     await sendMessageToTabs(tabs, "resetLocalStorage");
     await sendMessageToTabs(tabs, "checkLocalStorageSet");
     await browser.browsingData.removeLocalStorage({});
     await sendMessageToTabs(tabs, "checkLocalStorageCleared");
 
     await sendMessageToTabs(tabs, "resetLocalStorage");
     await sendMessageToTabs(tabs, "checkLocalStorageSet");
     await browser.browsingData.remove({}, {localStorage: true});
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -474,17 +474,20 @@ add_task(async function dont_consume_cli
   is(Services.focus.focusedElement, gURLBar.inputField, "Should have focused the URL bar");
 
   textbox.value = "";
 });
 
 // Dropping text to the searchbar should open the popup
 add_task(async function drop_opens_popup() {
   let promise = promiseEvent(searchPopup, "popupshown");
-  EventUtils.synthesizeDrop(searchIcon, textbox.inputField, [[ {type: "text/plain", data: "foo" } ]], "move", window);
+  // Use a source for the drop that is outside of the search bar area, to avoid
+  // it receiving a mousedown and causing the popup to sometimes open.
+  let homeButton = document.getElementById("home-button");
+  EventUtils.synthesizeDrop(homeButton, textbox.inputField, [[ {type: "text/plain", data: "foo" } ]], "move", window);
   await promise;
 
   isnot(searchPopup.getAttribute("showonlysettings"), "true", "Should show the full popup");
   is(Services.focus.focusedElement, textbox.inputField, "Should have focused the search bar");
   promise = promiseEvent(searchPopup, "popuphidden");
   searchPopup.hidePopup();
   await promise;
 
--- a/browser/config/tooltool-manifests/linux32/releng.manifest
+++ b/browser/config/tooltool-manifests/linux32/releng.manifest
@@ -1,18 +1,10 @@
 [
   {
     "size": 11189216,
     "digest": "18bc52b0599b1308b667e282abb45f47597bfc98a5140cfcab8da71dacf89dd76d0dee22a04ce26fe7ad1f04e2d6596991f9e5b01fd2aaaab5542965f596b0e6",
     "algorithm": "sha512",
     "filename": "gtk3.tar.xz",
     "setup": "setup.sh",
     "unpack": true
-  },
-  {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 161014632,
-    "digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
-    "algorithm": "sha512",
-    "filename": "rustc.tar.xz",
-    "unpack": true
   }
 ]
--- a/browser/config/tooltool-manifests/linux64/base-toolchains.manifest
+++ b/browser/config/tooltool-manifests/linux64/base-toolchains.manifest
@@ -1,18 +1,10 @@
 [
   {
     "size": 12072532,
     "digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
     "algorithm": "sha512",
     "filename": "gtk3.tar.xz",
     "setup": "setup.sh",
     "unpack": true
-  },
-  {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 161014632,
-    "digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
-    "algorithm": "sha512",
-    "filename": "rustc.tar.xz",
-    "unpack": true
   }
 ]
--- a/browser/config/tooltool-manifests/linux64/releng.manifest
+++ b/browser/config/tooltool-manifests/linux64/releng.manifest
@@ -1,18 +1,10 @@
 [
   {
     "size": 12072532,
     "digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
     "algorithm": "sha512",
     "filename": "gtk3.tar.xz",
     "setup": "setup.sh",
     "unpack": true
-  },
-  {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 161014632,
-    "digest": "65bebcf94fc66ea618c58c9ac33f0f206095ecfe3931cc6edb301f4b40480e3b44b0f39aea7a25fed8eef47e63523e7e670082947a3662cdc04c68ebbe5dfc89",
-    "algorithm": "sha512",
-    "filename": "rustc.tar.xz",
-    "unpack": true
   }
 ]
--- a/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
@@ -1,18 +1,10 @@
 [
   {
     "size": 34094283,
     "visibility": "internal",
     "digest": "8811050fe375bcc566c8b85173d86b8a87aa2148edfed93023735c2de44b66a5a28cbaa1cfd396032447fd803e03f308ed941a200c0e2a1ad9fbe16b5606ee7c",
     "algorithm": "sha512",
     "unpack": true,
     "filename": "MacOSX10.11.sdk.tar.xz"
-  },
-  {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 155690216,
-    "digest": "379f542ea16c775e7bcad36823f0068ca6a1f17c2b25e42ef978d51865298ba4207dc89bbb614805f81a123d12e339209a447afbd12c1122e16f4c7c41e7d92b",
-    "algorithm": "sha512",
-    "filename": "rustc.tar.xz",
-    "unpack": true
   }
 ]
--- a/browser/config/tooltool-manifests/win32/releng.manifest
+++ b/browser/config/tooltool-manifests/win32/releng.manifest
@@ -1,24 +1,16 @@
 [
   {
     "size": 266240,
     "digest": "bb345b0e700ffab4d09436981f14b5de84da55a3f18a7f09ebc4364a4488acdeab8d46f447b12ac70f2da1444a68b8ce8b8675f0dae2ccf845e966d1df0f0869",
     "algorithm": "sha512",
     "filename": "mozmake.exe"
   },
   {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 97017057,
-    "digest": "b726645f9d26c5a3048720b3839166021c1cf91a02d2ff2f10c49adced7455c7352e18b5052084d80bf9d1c40ec1bf72d0397921b8cd23262f89fdbd10def58f",
-    "algorithm": "sha512",
-    "filename": "rustc.tar.bz2",
-    "unpack": true
-  },
-  {
     "version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
     "size": 326656969,
     "digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
     "algorithm": "sha512",
     "filename": "vs2015u3.zip",
     "unpack": true
   },
   {
--- a/browser/config/tooltool-manifests/win64/releng.manifest
+++ b/browser/config/tooltool-manifests/win64/releng.manifest
@@ -1,25 +1,16 @@
 [
   {
     "size": 266240,
     "digest": "bb345b0e700ffab4d09436981f14b5de84da55a3f18a7f09ebc4364a4488acdeab8d46f447b12ac70f2da1444a68b8ce8b8675f0dae2ccf845e966d1df0f0869",
     "algorithm": "sha512",
     "filename": "mozmake.exe"
   },
   {
-    "version": "rustc 1.19.0 (0ade33941 2017-07-17) repack",
-    "size": 103602526,
-    "digest": "558d2d18991ad8b250a5d6b46a55e1ffdffc50d6bdd9cb4b3a945dd3d1143836b32e47f1df612bfea97ca2c02333ed43055b6c3030ecb1632385fb6940c1d246",
-    "algorithm": "sha512",
-    "visibility": "public",
-    "filename": "rustc.tar.bz2",
-    "unpack": true
-  },
-  {
     "version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
     "size": 326656969,
     "digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
     "algorithm": "sha512",
     "filename": "vs2015u3.zip",
     "unpack": true
   },
   {
--- a/browser/config/tooltool-manifests/win64/sccache-build.manifest
+++ b/browser/config/tooltool-manifests/win64/sccache-build.manifest
@@ -1,19 +1,10 @@
 [
   {
-    "version": "rustc 1.18.0 (03fc9d622 2017-06-06) repack",
-    "size": 98336380,
-    "digest": "92091d92ce135ee52486c31ae670735dd140ab5b1389f14582c4d9b14cbb393f7180399b9232564a3eb96443b568323070a3c1329deb07b145b28476e8271175",
-    "algorithm": "sha512",
-    "visibility": "public",
-    "filename": "rustc.tar.bz2",
-    "unpack": true
-  },
-  {
     "version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
     "size": 326656969,
     "digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
     "algorithm": "sha512",
     "filename": "vs2015u3.zip",
     "unpack": true
   },
   {
--- a/browser/extensions/formautofill/FormAutofillDoorhanger.jsm
+++ b/browser/extensions/formautofill/FormAutofillDoorhanger.jsm
@@ -62,16 +62,17 @@ const CONTENT = {
             GetStringFromName("addressesSyncCheckbox") : null;
         },
         callback(event) {
           let checked = event.target.checked;
           Services.prefs.setBoolPref("services.sync.engine.addresses", checked);
           log.debug("Set addresses sync to", checked);
         },
       },
+      hideClose: true,
     },
   },
   update: {
     notificationId: "autofill-address",
     message: GetStringFromName("updateAddressMessage"),
     linkMessage: GetStringFromName(autofillOptsKey),
     anchor: {
       id: "autofill-address-notification-icon",
@@ -86,16 +87,17 @@ const CONTENT = {
     secondaryActions: [{
       label: GetStringFromName("createAddressLabel"),
       accessKey: "C",
       callbackState: "create",
     }],
     options: {
       persistWhileVisible: true,
       popupIconURL: "chrome://formautofill/content/icon-address-update.svg",
+      hideClose: true,
     },
   },
   creditCard: {
     notificationId: "autofill-credit-card",
     message: GetStringFromName("saveCreditCardMessage"),
     linkMessage: GetStringFromName(autofillSecurityOptionsKey),
     anchor: {
       id: "autofill-credit-card-notification-icon",
@@ -114,16 +116,17 @@ const CONTENT = {
     }, {
       label: GetStringFromName("neverSaveCreditCardLabel"),
       accessKey: "N",
       callbackState: "disable",
     }],
     options: {
       persistWhileVisible: true,
       popupIconURL: "chrome://formautofill/content/icon-credit-card.svg",
+      hideClose: true,
     },
   },
 };
 
 let FormAutofillDoorhanger = {
   /**
    * Generate the main action and secondary actions from content parameters and
    * promise resolve.
--- a/browser/modules/ContentMetaHandler.jsm
+++ b/browser/modules/ContentMetaHandler.jsm
@@ -1,15 +1,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/. */
 
 "use strict";
 const {utils: Cu, interfaces: Ci, classes: Cc} = Components;
 Cu.importGlobalProperties(["URL"]);
+Cu.import("resource://gre/modules/Services.jsm");
 
 // Debounce time in milliseconds - this should be long enough to account for
 // sync script tags that could appear between desired meta tags
 const TIMEOUT_DELAY = 1000;
 
 // Possible description tags, listed in order from least favourable to most favourable
 const DESCRIPTION_RULES = [
   "twitter:description",
@@ -120,13 +121,18 @@ this.ContentMetaHandler = {
         entry.timeout = null;
 
         // Save description and preview image to moz_places
         chromeGlobal.sendAsyncMessage("Meta:SetPageInfo", {
           url,
           description: entry.description.value,
           previewImageURL: entry.image.value
         });
+
+        // Telemetry for recording the size of page metadata
+        let metadataSize = entry.description.value ? entry.description.value.length : 0;
+        metadataSize += entry.image.value ? entry.image.value.length : 0;
+        Services.telemetry.getHistogramById("PAGE_METADATA_SIZE").add(metadataSize);
         metaTags.delete(url);
       }, TIMEOUT_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
     }
   }
 };
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -173,19 +173,16 @@ menuitem.bookmark-item {
 .searchbar-textbox[focused="true"] {
   border-color: Highlight;
 }
 
 .urlbar-textbox-container {
   -moz-appearance: none;
   -moz-box-align: stretch;
 }
-.urlbar-input-box {
-  margin: 0;
-}
 
 /* ::::: URL Bar Zoom Reset Button ::::: */
 @keyframes urlbar-zoom-reset-pulse {
   0% {
     transform: scale(0);
   }
   75% {
     transform: scale(1.5);
--- a/browser/themes/linux/searchbar.css
+++ b/browser/themes/linux/searchbar.css
@@ -1,20 +1,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/. */
 
 .autocomplete-textbox-container {
   -moz-box-align: stretch;
 }
 
-.textbox-input-box {
-  margin: 0;
-}
-
 .searchbar-engine-image {
   height: 16px;
   width: 16px;
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
   margin-inline-start: -1px;
 }
 
 .search-go-container {
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -289,20 +289,16 @@
 
 %include ../shared/identity-block/identity-block.inc.css
 
 #identity-box:not(:active):-moz-focusring {
   box-shadow: var(--focus-ring-box-shadow);
   border-inline-end-style: none;
   padding-inline-end: 5px;
 }
-.urlbar-input-box {
-  margin: 0;
-  padding: 3px 0 2px;
-}
 
 /* ::::: URL Bar Zoom Reset Button ::::: */
 @keyframes urlbar-zoom-reset-pulse {
   0% {
     transform: scale(0);
   }
   75% {
     transform: scale(1.5);
--- a/browser/themes/osx/searchbar.css
+++ b/browser/themes/osx/searchbar.css
@@ -6,22 +6,16 @@
   border-radius: 10000px;
 }
 
 .searchbar-popup {
   margin-top: 4px;
   margin-inline-start: 3px;
 }
 
-.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box {
-  margin: 0;
-  padding: 3px 0 2px;
-  height: 20px;
-}
-
 .searchbar-engine-image {
   width: 16px;
   height: 16px;
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
 }
 
 .search-go-container,
 .searchbar-search-button-container {
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -441,25 +441,22 @@ toolbarpaletteitem[place=toolbar] > tool
 }
 
 #customization-panelWrapper > .panel-arrowbox {
   position: relative;
   height: 10px;
   margin-bottom: -1px;
 }
 
-/* The overflow button icon _looks_ disabled, but is also shown as [open]. */
-#nav-bar[customizing] > .overflow-button {
-  /* This color is the hard-coded #4c4c4c at 40% opacity as found in toolbarbutton-icons.inc.css */
-  fill: hsla(0,0%,30%,.4);
-}
-
+/* In customize mode, the overflow button should look both 'disabled' and 'open'.
+ * So we make the button fully opaque but fill the icon semi-transparent. */
 #nav-bar[customizing] > .overflow-button > .toolbarbutton-icon {
   background-color: var(--toolbarbutton-active-background);
   opacity: 1;
+  fill-opacity: 0.4;
 }
 
 #customization-panelWrapper > .panel-arrowbox > .panel-arrow[side="top"] {
 %ifdef XP_MACOSX
   list-style-image: var(--panel-arrow-image-vertical,
                         url("chrome://global/skin/arrow/panelarrow-vertical.png"));
   /* The OS X image is 2px narrower than the windows/linux one.
    * Add padding to compensate: */
--- a/browser/themes/shared/urlbar-searchbar.inc.css
+++ b/browser/themes/shared/urlbar-searchbar.inc.css
@@ -47,16 +47,21 @@
 :root[uidensity=touch] .searchbar-textbox {
   min-height: 32px;
 }
 
 #urlbar-container {
   -moz-box-align: center;
 }
 
+.urlbar-input-box,
+.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box {
+  margin: 0;
+}
+
 #urlbar-search-splitter {
   /* The splitter width should equal the location and search bars' combined
      neighboring margin and border width. */
   min-width: 12px;
   margin: 0 -6px;
   position: relative;
   border: none;
   background: transparent;
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -18,31 +18,27 @@
 @media (-moz-windows-default-theme) {
   .menu-accel,
   .menu-iconic-accel {
     color: graytext;
   }
 }
 
 @media (-moz-windows-compositor) {
-  #main-window {
-    -moz-appearance: -moz-win-glass;
-  }
-
-
-  /* On win10, if we don't set this on the entire browser container including
-   * the sidebar, if the sidebar is open the accent color bleeds through in
-   * the titlebar */
-  #browser {
-    -moz-appearance: -moz-win-exclude-glass;
-  }
-
   @media not all and (-moz-os-version: windows-win7) {
     @media not all and (-moz-os-version: windows-win8) {
       @media (-moz-windows-default-theme) {
+        :root[sizemode=normal][tabsintitlebar] {
+          border-top: 1px solid -moz-win-accentcolor;
+        }
+
+        :root[sizemode=normal][tabsintitlebar]:-moz-window-inactive {
+          border-top-color: rgba(0,0,0,.2);
+        }
+
         :root:not(:-moz-lwtheme) {
           background-color: hsl(0, 0%, 78%);
         }
 
         @media (-moz-windows-accent-color-in-titlebar: 0) {
           :root[tabsintitlebar]:not(:-moz-lwtheme) {
             background-color: hsl(235,33%,19%);
             --titlebar-text-color: hsl(240,9%,98%);
@@ -61,16 +57,24 @@
              titlebar text change for inactive windows. */
           opacity: .6;
         }
       }
 
       @media (-moz-windows-default-theme: 0) {
         :root {
           background-color: transparent;
+          -moz-appearance: -moz-win-glass;
+        }
+
+        /* On win10, if we don't set this on the entire browser container including
+         * the sidebar, if the sidebar is open the accent color bleeds through in
+         * the titlebar */
+        #browser {
+          -moz-appearance: -moz-win-exclude-glass;
         }
       }
 
       #titlebar-buttonbox,
       .titlebar-button {
         -moz-appearance: none !important;
       }
 
@@ -225,37 +229,33 @@
           list-style-image: url(chrome://browser/skin/window-controls/close-highcontrast.svg);
         }
       }
     }
   }
 
   @media (-moz-os-version: windows-win7),
          (-moz-os-version: windows-win8) {
-    #main-window[sizemode="maximized"] #titlebar-buttonbox {
-      margin-inline-end: 3px;
+    :root {
+      background-color: transparent;
+      -moz-appearance: -moz-win-borderless-glass;
     }
 
-    #main-window {
-      background-color: transparent;
-      -moz-appearance: -moz-win-borderless-glass;
+    :root[sizemode="maximized"] #titlebar-buttonbox {
+      margin-inline-end: 3px;
     }
 
     /* These should be hidden w/ glass enabled. Windows draws its own buttons. */
     .titlebar-button {
       display: none;
     }
 
     /* The borders on the glass frame are ours, and inside #browser, and on
      * win7 we want to make sure they are "glassy", so we can't use #browser
      * as the exclude-glass container. We use #appcontent instead. */
-    #browser {
-      -moz-appearance: none;
-    }
-
     #appcontent {
       -moz-appearance: -moz-win-exclude-glass;
     }
   }
 
   @media (-moz-os-version: windows-win8) {
     /* Artificially draw window borders that are covered by lwtheme, see bug 591930.
      * Borders for win7 are below, win10 doesn't need them. */
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -110,17 +110,18 @@
  * instead of in the tabs toolbar.
  */
 @media (-moz-os-version: windows-win7) {
   @media (-moz-windows-default-theme) {
     :root:not(:-moz-lwtheme) {
       --tabs-border: #4A4A4F;
     }
 
-    #TabsToolbar:not(:-moz-lwtheme) {
+    #TabsToolbar:not(:-moz-lwtheme),
+    #TabsToolbar:not(:-moz-lwtheme) toolbarbutton[disabled="true"] {
       color: hsl(240,9%,98%);
     }
 
     /* Always show full-height tab separators on tabs with borders. */
     .tabbrowser-tab:not(:-moz-lwtheme)::before {
       border-image: none !important;
     }
 
@@ -515,19 +516,16 @@ html|*.urlbar-input:-moz-lwtheme::placeh
 .searchbar-textbox:-moz-lwtheme > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input::placeholder {
   opacity: 1.0;
   color: #777;
 }
 
 .urlbar-textbox-container {
   -moz-box-align: stretch;
 }
-.urlbar-input-box {
-  margin: 0;
-}
 
 /* ::::: URL Bar Zoom Reset Button ::::: */
 @keyframes urlbar-zoom-reset-pulse {
   0% {
     transform: scale(0);
   }
   75% {
     transform: scale(1.5);
--- a/browser/themes/windows/compacttheme.css
+++ b/browser/themes/windows/compacttheme.css
@@ -25,27 +25,32 @@
     background: transparent !important;
   }
 }
 
 #toolbar-menubar {
   text-shadow: none !important;
 }
 
-@media (-moz-windows-glass) {
-  /* Always show light toolbar elements on aero glass surface. */
-  #TabsToolbar {
-    color: hsl(240,9%,98%);
-  }
+@media (-moz-os-version: windows-win7) {
+  @media (-moz-windows-default-theme) {
+    /* Always show light toolbar elements on aero surface. */
+    #TabsToolbar,
+    #TabsToolbar toolbarbutton[disabled="true"] {
+      color: hsl(240,9%,98%);
+    }
 
-  /* Keep showing the correct color inside the tabs. */
-  .tabbrowser-tab {
-    color: var(--chrome-color) !important;
+    /* Keep showing the correct color inside the tabs. */
+    .tabbrowser-tab {
+      color: var(--chrome-color) !important;
+    }
   }
+}
 
+@media (-moz-windows-glass) {
   /* Make the menubar text readable on aero glass (copied from browser-aero.css). */
   #toolbar-menubar {
     text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
   }
 
   #main-menubar:not(:-moz-window-inactive) {
     background-color: rgba(255,255,255,.5);
     color: black;
--- a/browser/themes/windows/searchbar.css
+++ b/browser/themes/windows/searchbar.css
@@ -1,20 +1,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/. */
 
 .autocomplete-textbox-container {
   -moz-box-align: stretch;
 }
 
-.textbox-input-box {
-  margin: 0;
-}
-
 .searchbar-engine-image {
   height: 16px;
   width: 16px;
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
   margin-inline-start: -1px;
 }
 
 .search-go-container,
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -803,25 +803,35 @@ def compiler(language, host_or_target, c
 
         # If you want to bump the version check here search for
         # cxx_alignof above, and see the associated comment.
         if info.type == 'clang' and not info.version:
             raise FatalCheckError(
                 'Only clang/llvm 3.6 or newer is supported.')
 
         if info.type == 'msvc':
+            # 19.00 is VS2015.
+            # 19.10+ is VS2017+.
             if info.version < '19.00.24213':
                 raise FatalCheckError(
                     'This version (%s) of the MSVC compiler is not '
                     'supported.\n'
                     'You must install Visual C++ 2015 Update 3 or newer in '
                     'order to build.\n'
                     'See https://developer.mozilla.org/en/'
                     'Windows_Build_Prerequisites' % info.version)
 
+            if info.version >= '19.10' and info.version < '19.11.25506':
+                raise FatalCheckError(
+                    'This version (%s) of the MSVC compiler is not supported.\n'
+                    'You must install Visual C++ 2017 15.3 or newer in order '
+                    'to build.\n'
+                    'See https://developer.mozilla.org/en/'
+                    'Windows_Build_Prerequisites' % info.version)
+
         if info.flags:
             raise FatalCheckError(
                 'Unknown compiler or compiler not supported.')
 
         return namespace(
             wrapper=wrapper,
             compiler=compiler,
             flags=flags,
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -153,18 +153,18 @@ protected:
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
   nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
 
 private:
   static already_AddRefed<BasePrincipal>
   CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs,
                           const nsACString& aOriginNoSuffix);
 
-  nsCOMPtr<nsIAtom> mOriginNoSuffix;
-  nsCOMPtr<nsIAtom> mOriginSuffix;
+  RefPtr<nsIAtom> mOriginNoSuffix;
+  RefPtr<nsIAtom> mOriginSuffix;
 
   OriginAttributes mOriginAttributes;
   PrincipalKind mKind;
   bool mHasExplicitDomain;
   bool mInitialized;
 };
 
 inline bool
--- a/devtools/client/canvasdebugger/canvasdebugger.js
+++ b/devtools/client/canvasdebugger/canvasdebugger.js
@@ -15,16 +15,20 @@ const { CallWatcherFront } = require("de
 const { CanvasFront } = require("devtools/shared/fronts/canvas");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const flags = require("devtools/shared/flags");
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const { PluralForm } = require("devtools/shared/plural-form");
 const { Heritage, WidgetMethods, setNamedTimeout, clearNamedTimeout,
         setConditionalTimeout } = require("devtools/client/shared/widgets/view-helpers");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 const CANVAS_ACTOR_RECORDING_ATTEMPT = flags.testing ? 500 : 5000;
 
 const { Task } = require("devtools/shared/task");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
   "resource://gre/modules/FileUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
--- a/devtools/client/debugger/debugger-controller.js
+++ b/devtools/client/debugger/debugger-controller.js
@@ -108,16 +108,20 @@ const { BreadcrumbsWidget } = require("r
 const { SideMenuWidget } = require("resource://devtools/client/shared/widgets/SideMenuWidget.jsm");
 const { VariablesView } = require("resource://devtools/client/shared/widgets/VariablesView.jsm");
 const { VariablesViewController, StackFrameUtils } = require("resource://devtools/client/shared/widgets/VariablesViewController.jsm");
 const EventEmitter = require("devtools/shared/old-event-emitter");
 const { gDevTools } = require("devtools/client/framework/devtools");
 const { ViewHelpers, Heritage, WidgetMethods, setNamedTimeout,
         clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 // React
 const React = require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
 // Used to create the Redux store
 const createStore = require("devtools/client/shared/redux/create-store")({
   getTargetClient: () => DebuggerController.client,
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -9,16 +9,20 @@
 "use strict";
 
 const Services = require("Services");
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/old-event-emitter");
 const {executeSoon} = require("devtools/shared/DevToolsUtils");
 const {Task} = require("devtools/shared/task");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 // constructor
 const Telemetry = require("devtools/client/shared/telemetry");
 const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const ReflowTracker = require("devtools/client/inspector/shared/reflow-tracker");
 const Store = require("devtools/client/inspector/store");
 
 loader.lazyRequireGetter(this, "initCssProperties", "devtools/shared/fronts/css-properties", true);
 loader.lazyRequireGetter(this, "HTMLBreadcrumbs", "devtools/client/inspector/breadcrumbs", true);
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -1190,16 +1190,29 @@ MarkupView.prototype = {
   /**
    * Collapse the node's children.
    */
   collapseNode: function (node) {
     let container = this.getContainer(node);
     container.setExpanded(false);
   },
 
+  _collapseAll: function (container) {
+    container.setExpanded(false);
+    let children = container.getChildContainers() || [];
+    children.forEach(child => this._collapseAll(child));
+  },
+
+  /**
+   * Collapse the entire tree beneath a node.
+   */
+  collapseAll: function (node) {
+    this._collapseAll(this.getContainer(node));
+  },
+
   /**
    * Returns either the innerHTML or the outerHTML for a remote node.
    *
    * @param  {NodeFront} node
    *         The NodeFront to get the outerHTML / innerHTML for.
    * @param  {Boolean} isOuter
    *         If true, makes the function return the outerHTML,
    *         otherwise the innerHTML.
@@ -1429,32 +1442,34 @@ MarkupView.prototype = {
         }
       });
 
       this.emit("begin-editing");
     });
   },
 
   /**
-   * Mark the given node expanded.
+   * Expand or collapse the given node.
    *
    * @param  {NodeFront} node
-   *         The NodeFront to mark as expanded.
+   *         The NodeFront to update.
    * @param  {Boolean} expanded
-   *         Whether the expand or collapse.
-   * @param  {Boolean} expandDescendants
-   *         Whether to expand all descendants too
+   *         Whether the node should be expanded/collapsed.
+   * @param  {Boolean} applyToDescendants
+   *         Whether all descendants should also be expanded/collapsed
    */
-  setNodeExpanded: function (node, expanded, expandDescendants) {
+  setNodeExpanded: function (node, expanded, applyToDescendants) {
     if (expanded) {
-      if (expandDescendants) {
+      if (applyToDescendants) {
         this.expandAll(node);
       } else {
         this.expandNode(node);
       }
+    } else if (applyToDescendants) {
+      this.collapseAll(node);
     } else {
       this.collapseNode(node);
     }
   },
 
   /**
    * Mark the given node selected, and update the inspector.selection
    * object's NodeFront to keep consistent state between UI and selection.
--- a/devtools/client/inspector/markup/test/browser_markup_toggle_03.js
+++ b/devtools/client/inspector/markup/test/browser_markup_toggle_03.js
@@ -1,35 +1,53 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test toggling (expand/collapse) elements by alt-clicking on twisties, which
-// should expand all the descendants
+// should expand/collapse all the descendants
 
 const TEST_URL = URL_ROOT + "doc_markup_toggle.html";
 
 add_task(function* () {
   let {inspector} = yield openInspectorForURL(TEST_URL);
 
   info("Getting the container for the UL parent element");
   let container = yield getContainerForSelector("ul", inspector);
 
-  info("Alt-clicking on the UL parent expander, and waiting for children");
+  info("Alt-clicking on collapsed expander should expand all children");
   let onUpdated = inspector.once("inspector-updated");
   EventUtils.synthesizeMouseAtCenter(container.expander, {altKey: true},
     inspector.markup.doc.defaultView);
   yield onUpdated;
   yield waitForMultipleChildrenUpdates(inspector);
 
   info("Checking that all nodes exist and are expanded");
-  let nodeList = yield inspector.walker.querySelectorAll(
-    inspector.walker.rootNode, "ul, li, span, em");
-  let nodeFronts = yield nodeList.items();
+  let nodeFronts = yield getNodeFronts(inspector);
   for (let nodeFront of nodeFronts) {
     let nodeContainer = getContainerForNodeFront(nodeFront, inspector);
     ok(nodeContainer, "Container for node " + nodeFront.tagName + " exists");
     ok(nodeContainer.expanded,
       "Container for node " + nodeFront.tagName + " is expanded");
   }
+
+  info("Alt-clicking on expanded expander should collapse all children");
+  EventUtils.synthesizeMouseAtCenter(container.expander, {altKey: true},
+    inspector.markup.doc.defaultView);
+  yield waitForMultipleChildrenUpdates(inspector);
+  // No need to wait for inspector-updated here since we are not retrieving new nodes.
+
+  info("Checking that all nodes are collapsed");
+  nodeFronts = yield getNodeFronts(inspector);
+  for (let nodeFront of nodeFronts) {
+    let nodeContainer = getContainerForNodeFront(nodeFront, inspector);
+    ok(!nodeContainer.expanded,
+      "Container for node " + nodeFront.tagName + " is collapsed");
+  }
 });
+
+function* getNodeFronts(inspector) {
+  let nodeList = yield inspector.walker.querySelectorAll(
+    inspector.walker.rootNode, "ul, li, span, em");
+  return nodeList.items();
+}
--- a/devtools/client/inspector/webpack.config.js
+++ b/devtools/client/inspector/webpack.config.js
@@ -94,17 +94,20 @@ module.exports = envConfig => {
         "devtools/client/jsonview/main":
           path.join(__dirname, "./webpack/jsonview-sham.js"),
         "devtools/client/sourceeditor/editor":
           path.join(__dirname, "./webpack/editor-sham.js"),
         "devtools/client/locales": path.join(__dirname, "../locales/en-US"),
         "devtools/shared/DevToolsUtils":
           path.join(__dirname, "./webpack/devtools-utils-sham.js"),
         "devtools/shared/locales": path.join(__dirname, "../../shared/locales/en-US"),
-        "devtools/shared/platform": path.join(__dirname, "../../shared/platform/content"),
+        "devtools/shared/platform/clipboard": path.join(__dirname,
+          "../../client/shared/webpack/shims/platform-clipboard-stub"),
+        "devtools/shared/platform/stack": path.join(__dirname,
+          "../../client/shared/webpack/shims/platform-clipboard-stub"),
         "devtools": path.join(__dirname, "../../"),
         "gcli": path.join(__dirname, "../../shared/gcli/source/lib/gcli"),
         "method": path.join(__dirname, "../../../addon-sdk/source/lib/method"),
         "modules/libpref/init/all":
           path.join(__dirname, "../../../modules/libpref/init/all.js"),
         "devtools/shared/generate-uuid":
           path.join(__dirname, "./webpack/uuid-sham.js"),
         "sdk": path.join(__dirname, "../../../addon-sdk/source/lib/sdk"),
--- a/devtools/client/jsonview/components/json-panel.js
+++ b/devtools/client/jsonview/components/json-panel.js
@@ -33,17 +33,19 @@ define(function (require, exports, modul
    */
   let JsonPanel = createClass({
     displayName: "JsonPanel",
 
     propTypes: {
       data: PropTypes.oneOfType([
         PropTypes.string,
         PropTypes.array,
-        PropTypes.object
+        PropTypes.object,
+        PropTypes.bool,
+        PropTypes.number
       ]),
       jsonTextLength: PropTypes.number,
       searchFilter: PropTypes.string,
       actions: PropTypes.object,
     },
 
     getInitialState: function () {
       return {};
--- a/devtools/client/jsonview/components/main-tabbed-area.js
+++ b/devtools/client/jsonview/components/main-tabbed-area.js
@@ -26,17 +26,19 @@ define(function (require, exports, modul
       jsonText: PropTypes.string,
       tabActive: PropTypes.number,
       actions: PropTypes.object,
       headers: PropTypes.object,
       searchFilter: PropTypes.string,
       json: PropTypes.oneOfType([
         PropTypes.string,
         PropTypes.object,
-        PropTypes.array
+        PropTypes.array,
+        PropTypes.bool,
+        PropTypes.number
       ])
     },
 
     getInitialState: function () {
       return {
         json: {},
         headers: {},
         jsonText: this.props.jsonText,
--- a/devtools/client/memory/initializer.js
+++ b/devtools/client/memory/initializer.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-/* exported initialize, destroy */
+/* exported initialize, destroy, Promise */
 
 "use strict";
 
 const { utils: Cu } = Components;
 const BrowserLoaderModule = {};
 Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
 const { require } = BrowserLoaderModule.BrowserLoader({
   baseURI: "resource://devtools/client/memory/",
@@ -15,16 +15,17 @@ const { require } = BrowserLoaderModule.
 });
 const { Task } = require("devtools/shared/task");
 const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 const App = createFactory(require("devtools/client/memory/app"));
 const Store = require("devtools/client/memory/store");
 const { assert } = require("devtools/shared/DevToolsUtils");
+const Promise = require("Promise");
 
 /**
  * The current target, toolbox, MemoryFront, and HeapAnalysesClient,
  * set by this tool's host.
  */
 var gToolbox, gFront, gHeapAnalysesClient;
 
 /**
--- a/devtools/client/netmonitor/webpack.config.js
+++ b/devtools/client/netmonitor/webpack.config.js
@@ -66,76 +66,43 @@ let webpackConfig = {
       // Make sure webpack is always looking for modules in
       // `webconsole/node_modules` directory first.
       path.resolve(__dirname, "node_modules"), "node_modules"
     ],
     alias: {
       "Services": "devtools-modules/src/Services",
       "react": path.join(__dirname, "node_modules/react"),
 
-      "devtools/client/framework/devtools": path.join(__dirname, "../../client/shims/devtools"),
+      "devtools/client/framework/devtools": path.join(__dirname, "../../client/shared/webpack/shims/framework-devtools-shim"),
       "devtools/client/framework/menu": "devtools-modules/src/menu",
-      "devtools/client/framework/menu-item": path.join(__dirname, "../../client/framework/menu-item"),
-      "devtools/client/locales": path.join(__dirname, "../../client/locales/en-US"),
       "devtools/client/netmonitor/src/utils/menu": "devtools-contextmenu",
 
-      "devtools/client/shared/components/autocomplete-popup": path.join(__dirname, "../../client/shared/components/autocomplete-popup"),
-      "devtools/client/shared/components/reps/reps": path.join(__dirname, "../../client/shared/components/reps/reps"),
-      "devtools/client/shared/components/search-box": path.join(__dirname, "../../client/shared/components/search-box"),
-      "devtools/client/shared/components/splitter/draggable": path.join(__dirname, "../../client/shared/components/splitter/draggable"),
-      "devtools/client/shared/components/splitter/split-box": path.join(__dirname, "../../client/shared/components/splitter/split-box"),
-      "devtools/client/shared/components/stack-trace": path.join(__dirname, "../../client/shared/components/stack-trace"),
-      "devtools/client/shared/components/tabs/tabbar": path.join(__dirname, "../../client/shared/components/tabs/tabbar"),
-      "devtools/client/shared/components/tabs/tabs": path.join(__dirname, "../../client/shared/components/tabs/tabs"),
-      "devtools/client/shared/components/tree/tree-view": path.join(__dirname, "../../client/shared/components/tree/tree-view"),
-      "devtools/client/shared/components/tree/tree-row": path.join(__dirname, "../../client/shared/components/tree/tree-row"),
-      "devtools/client/shared/curl": path.join(__dirname, "../../client/shared/curl"),
-      "devtools/client/shared/file-saver": path.join(__dirname, "../../client/shared/file-saver"),
-      "devtools/client/shared/keycodes": path.join(__dirname, "../../client/shared/keycodes"),
-      "devtools/client/shared/key-shortcuts": path.join(__dirname, "../../client/shared/key-shortcuts"),
-      "devtools/client/shared/prefs": path.join(__dirname, "../../client/shared/prefs"),
-      "devtools/client/shared/scroll": path.join(__dirname, "../../client/shared/scroll"),
-      "devtools/client/shared/source-utils": path.join(__dirname, "../../client/shared/source-utils"),
-      "devtools/client/shared/theme": path.join(__dirname, "../../client/shared/theme"),
-
       "devtools/client/shared/vendor/immutable": "immutable",
       "devtools/client/shared/vendor/react": "react",
       "devtools/client/shared/vendor/react-dom": "react-dom",
       "devtools/client/shared/vendor/react-redux": "react-redux",
       "devtools/client/shared/vendor/redux": "redux",
       "devtools/client/shared/vendor/reselect": "reselect",
       "devtools/client/shared/vendor/jszip": "jszip",
-      "devtools/client/shared/vendor/lodash": path.join(__dirname, "../../client/shared/vendor/lodash"),
-
-      "devtools/client/shared/widgets/tooltip/HTMLTooltip": path.join(__dirname, "../../client/shared/widgets/tooltip/HTMLTooltip"),
-      "devtools/client/shared/widgets/tooltip/ImageTooltipHelper": path.join(__dirname, "../../client/shared/widgets/tooltip/ImageTooltipHelper"),
-      "devtools/client/shared/widgets/tooltip/TooltipToggle": path.join(__dirname, "../../client/shared/widgets/tooltip/TooltipToggle"),
-      "devtools/client/shared/widgets/Chart": path.join(__dirname, "../../client/shared/widgets/Chart"),
 
       "devtools/client/sourceeditor/editor": "devtools-source-editor/src/source-editor",
-      "devtools/client/themes/variables.css": path.join(__dirname, "../../client/themes/variables.css"),
 
-      "devtools/shared/async-utils": path.join(__dirname, "../../shared/async-utils"),
-      "devtools/shared/defer": path.join(__dirname, "../../shared/defer"),
       "devtools/shared/old-event-emitter": "devtools-modules/src/utils/event-emitter",
-      "devtools/shared/fronts/timeline": path.join(__dirname, "../../shared/shims/fronts/timeline"),
-      "devtools/shared/l10n": path.join(__dirname, "../../shared/l10n"),
+      "devtools/shared/fronts/timeline": path.join(__dirname, "../../client/shared/webpack/shims/fronts-timeline-shim"),
+      "devtools/shared/platform/clipboard": path.join(__dirname, "../../client/shared/webpack/shims/platform-clipboard-stub"),
+
+      // Locales need to be explicitly mapped to the en-US subfolder
+      "devtools/client/locales": path.join(__dirname, "../../client/locales/en-US"),
       "devtools/shared/locales": path.join(__dirname, "../../shared/locales/en-US"),
-      "devtools/shared/platform/clipboard": path.join(__dirname, "../../shared/platform/content/clipboard"),
-      "devtools/shared/plural-form": path.join(__dirname, "../../shared/plural-form"),
-      "devtools/shared/css/color": path.join(__dirname, "../../shared/css/color"),
-      "devtools/shared/css/color-db": path.join(__dirname, "../../shared/css/color-db"),
-      "devtools/shared/css/lexer": path.join(__dirname, "../../shared/css/lexer"),
-      "devtools/shared/css/parsing-utils": path.join(__dirname, "../../shared/css/parsing-utils"),
-      "devtools/shared/css/properties-db": path.join(__dirname, "../../shared/css/properties-db"),
-      "devtools/shared/css/generated/properties-db": path.join(__dirname, "../../shared/css/generated/properties-db"),
-      "devtools/shared/task": path.join(__dirname, "../../shared/task"),
-
       "devtools/shim/locales": path.join(__dirname, "../../shared/locales/en-US"),
       "toolkit/locales": path.join(__dirname, "../../../toolkit/locales/en-US"),
+
+      // Unless a path explicitly needs to be rewritten or shimmed, all devtools paths can
+      // be mapped to ../../
+      "devtools": path.join(__dirname, "../../"),
     },
   },
 };
 
 const mappings = [
   [
     /chrome:\/\/devtools\/skin/,
     (result) => {
--- a/devtools/client/performance/performance-controller.js
+++ b/devtools/client/performance/performance-controller.js
@@ -1,28 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 /* globals window, document, PerformanceView, ToolbarView, RecordingsView, DetailsView */
 
-/* exported Cc, Ci, Cu, Cr, loader */
+/* exported Cc, Ci, Cu, Cr, loader, Promise */
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 var BrowserLoaderModule = {};
 Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
 var { loader, require } = BrowserLoaderModule.BrowserLoader({
   baseURI: "resource://devtools/client/performance/",
   window
 });
 var { Task } = require("devtools/shared/task");
 /* exported Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout */
 var { Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
 var { PrefObserver } = require("devtools/client/shared/prefs");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+var Promise = require("Promise");
+
 // Events emitted by various objects in the panel.
 var EVENTS = require("devtools/client/performance/events");
 Object.defineProperty(this, "EVENTS", {
   value: EVENTS,
   enumerable: true,
   writable: false
 });
 
--- a/devtools/client/responsive.html/actions/devices.js
+++ b/devtools/client/responsive.html/actions/devices.js
@@ -31,17 +31,17 @@ const DISPLAYED_DEVICES_PREF = "devtools
 function loadPreferredDevices() {
   let preferredDevices = {
     "added": new Set(),
     "removed": new Set(),
   };
 
   if (Services.prefs.prefHasUserValue(DISPLAYED_DEVICES_PREF)) {
     try {
-      let savedData = Services.prefs.getCharPref(DISPLAYED_DEVICES_PREF);
+      let savedData = Services.prefs.getStringPref(DISPLAYED_DEVICES_PREF);
       savedData = JSON.parse(savedData);
       if (savedData.added && savedData.removed) {
         preferredDevices.added = new Set(savedData.added);
         preferredDevices.removed = new Set(savedData.removed);
       }
     } catch (e) {
       console.error(e);
     }
@@ -58,17 +58,17 @@ function loadPreferredDevices() {
  * - removed: Names of the devices that were explicitly removed by the user
  */
 function updatePreferredDevices(devices) {
   let devicesToSave = {
     added: Array.from(devices.added),
     removed: Array.from(devices.removed),
   };
   devicesToSave = JSON.stringify(devicesToSave);
-  Services.prefs.setCharPref(DISPLAYED_DEVICES_PREF, devicesToSave);
+  Services.prefs.setStringPref(DISPLAYED_DEVICES_PREF, devicesToSave);
 }
 
 module.exports = {
 
   // This function is only exported for testing purposes
   _loadPreferredDevices: loadPreferredDevices,
 
   updatePreferredDevices: updatePreferredDevices,
--- a/devtools/client/responsive.html/test/browser/browser_device_custom.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_custom.js
@@ -11,16 +11,27 @@ const device = {
   height: 570,
   pixelRatio: 1.5,
   userAgent: "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
   touch: true,
   firefoxOS: false,
   os: "android",
 };
 
+const unicodeDevice = {
+  name: "\u00B6\u00C7\u00DA\u00E7\u0126",
+  width: 400,
+  height: 570,
+  pixelRatio: 1.5,
+  userAgent: "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
+  touch: true,
+  firefoxOS: false,
+  os: "android",
+};
+
 const TEST_URL = "data:text/html;charset=utf-8,";
 const Types = require("devtools/client/responsive.html/types");
 
 addRDMTask(TEST_URL, function* ({ ui }) {
   let { toolWindow } = ui;
   let { store, document } = toolWindow;
   let React = toolWindow.require("devtools/client/shared/vendor/react");
   let { Simulate } = React.addons.TestUtils;
@@ -106,16 +117,75 @@ addRDMTask(TEST_URL, function* ({ ui }) 
   is(deviceSelector.value, "", "Device selector reset to no device");
   let selectorOption = [...deviceSelector.options].find(opt => opt.value == device.name);
   ok(!selectorOption, "Custom device option removed from device selector");
 
   info("Ensure device properties like UA have been reset");
   yield testUserAgent(ui, navigator.userAgent);
 });
 
+addRDMTask(TEST_URL, function* ({ ui }) {
+  let { toolWindow } = ui;
+  let { store, document } = toolWindow;
+  let React = toolWindow.require("devtools/client/shared/vendor/react");
+  let { Simulate } = React.addons.TestUtils;
+
+  // Wait until the viewport has been added and the device list has been loaded
+  yield waitUntilState(store, state => state.viewports.length == 1
+    && state.devices.listState == Types.deviceListState.LOADED);
+
+  let deviceSelector = document.querySelector(".viewport-device-selector");
+  let submitButton = document.querySelector("#device-submit-button");
+
+  openDeviceModal(ui);
+
+  info("Reveal device adder form");
+  let adderShow = document.querySelector("#device-adder-show");
+  Simulate.click(adderShow);
+
+  info("Fill out device adder form by setting details to unicode device and save");
+  setDeviceAdder(ui, unicodeDevice);
+  let adderSave = document.querySelector("#device-adder-save");
+  let saved = waitUntilState(store, state => state.devices.custom.length == 1);
+  Simulate.click(adderSave);
+  yield saved;
+
+  info("Verify unicode device defaults to enabled in modal");
+  let deviceCb = [...document.querySelectorAll(".device-input-checkbox")].find(cb => {
+    return cb.value == unicodeDevice.name;
+  });
+  ok(deviceCb, "Custom unicode device checkbox added to modal");
+  ok(deviceCb.checked, "Custom unicode device enabled");
+  Simulate.click(submitButton);
+
+  info("Look for custom unicode device in device selector");
+  let selectorOption = [...deviceSelector.options].find(opt =>
+    opt.value == unicodeDevice.name);
+  ok(selectorOption, "Custom unicode device option added to device selector");
+});
+
+addRDMTask(TEST_URL, function* ({ ui }) {
+  let { toolWindow } = ui;
+  let { store, document } = toolWindow;
+
+  // Wait until the viewport has been added and the device list has been loaded
+  yield waitUntilState(store, state => state.viewports.length == 1
+    && state.devices.listState == Types.deviceListState.LOADED);
+
+  let deviceSelector = document.querySelector(".viewport-device-selector");
+
+  // Check if the unicode custom device is present in the list of device options since
+  // we want to ensure that unicode device names are not forgotten after restarting RDM
+  // see bug 1379687
+  info("Look for custom unicode device in device selector");
+  let selectorOption = [...deviceSelector.options].find(opt =>
+    opt.value == unicodeDevice.name);
+  ok(selectorOption, "Custom unicode device option present in device selector");
+});
+
 function testDeviceAdder(ui, expected) {
   let { document } = ui.toolWindow;
 
   let nameInput = document.querySelector("#device-adder-name input");
   let [ widthInput, heightInput ] = document.querySelectorAll("#device-adder-size input");
   let pixelRatioInput = document.querySelector("#device-adder-pixel-ratio input");
   let userAgentInput = document.querySelector("#device-adder-user-agent input");
   let touchInput = document.querySelector("#device-adder-touch input");
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -59,16 +59,20 @@ const {Heritage} = require("devtools/cli
 
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 const {NetUtil} = require("resource://gre/modules/NetUtil.jsm");
 const {ScratchpadManager} = require("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
 const {addDebuggerToGlobal} = require("resource://gre/modules/jsdebugger.jsm");
 const {OS} = require("resource://gre/modules/osfile.jsm");
 const {Reflect} = require("resource://gre/modules/reflect.jsm");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 XPCOMUtils.defineConstant(this, "SCRATCHPAD_CONTEXT_CONTENT", SCRATCHPAD_CONTEXT_CONTENT);
 XPCOMUtils.defineConstant(this, "SCRATCHPAD_CONTEXT_BROWSER", SCRATCHPAD_CONTEXT_BROWSER);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_SAVE", BUTTON_POSITION_SAVE);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_CANCEL", BUTTON_POSITION_CANCEL);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_DONT_SAVE", BUTTON_POSITION_DONT_SAVE);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_REVERT", BUTTON_POSITION_REVERT);
 
 XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
--- a/devtools/client/shadereditor/shadereditor.js
+++ b/devtools/client/shadereditor/shadereditor.js
@@ -14,16 +14,20 @@ const Services = require("Services");
 const EventEmitter = require("devtools/shared/old-event-emitter");
 const Tooltip = require("devtools/client/shared/widgets/tooltip/Tooltip");
 const Editor = require("devtools/client/sourceeditor/editor");
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const {Heritage, WidgetMethods, setNamedTimeout} =
   require("devtools/client/shared/widgets/view-helpers");
 const {Task} = require("devtools/shared/task");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 // The panel's window global is an EventEmitter firing the following events:
 const EVENTS = {
   // When new programs are received from the server.
   NEW_PROGRAM: "ShaderEditor:NewProgram",
   PROGRAMS_ADDED: "ShaderEditor:ProgramsAdded",
 
   // When the vertex and fragment sources were shown in the editor.
   SOURCES_SHOWN: "ShaderEditor:SourcesShown",
--- a/devtools/client/shared/devices.js
+++ b/devtools/client/shared/devices.js
@@ -58,17 +58,17 @@ let loadLocalDevices = Task.async(functi
 
 // Add a device to the local catalog.
 let addDevice = Task.async(function* (device, type = "phones") {
   yield loadLocalDevices();
   let list = localDevices[type];
   if (!list) {
     list = localDevices[type] = [];
   }
-  list.push(device);
+  list.push(Object.assign({}, device));
   yield asyncStorage.setItem(LOCAL_DEVICES, JSON.stringify(localDevices));
 });
 exports.addDevice = addDevice;
 
 // Remove a device from the local catalog.
 // returns `true` if the device is removed, `false` otherwise.
 let removeDevice = Task.async(function* (device, type = "phones") {
   yield loadLocalDevices();
--- a/devtools/client/shared/moz.build
+++ b/devtools/client/shared/moz.build
@@ -7,16 +7,17 @@
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 DIRS += [
     'components',
     'redux',
     'source-map',
     'vendor',
+    'webpack',
     'widgets',
 ]
 
 DevToolsModules(
     'AppCacheUtils.jsm',
     'autocomplete-popup.js',
     'browser-loader.js',
     'css-angle.js',
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/webpack/moz.build
@@ -0,0 +1,9 @@
+# -*- 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/.
+
+DIRS += [
+    'shims',
+]
rename from devtools/shared/platform/content/.eslintrc.js
rename to devtools/client/shared/webpack/shims/.eslintrc.js
--- a/devtools/shared/platform/content/.eslintrc.js
+++ b/devtools/client/shared/webpack/shims/.eslintrc.js
@@ -1,12 +1,12 @@
 "use strict";
 
 module.exports = {
   // Extend from the devtools eslintrc.
-  "extends": "../../../.eslintrc.js",
+  "extends": "../../../../.eslintrc.js",
 
   "rules": {
     /* eslint-disable max-len */
     // All code in this directory must be content-clean.
     "mozilla/reject-some-requires": ["error", "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm|devtools/shared/platform/(chome|content)/.*)$"],
   },
 };
rename from devtools/client/shims/devtools.js
rename to devtools/client/shared/webpack/shims/framework-devtools-shim.js
rename from devtools/shared/shims/fronts/timeline.js
rename to devtools/client/shared/webpack/shims/fronts-timeline-shim.js
rename from devtools/client/webconsole/local-dev/jsterm-stub.js
rename to devtools/client/shared/webpack/shims/jsterm-stub.js
rename from devtools/shared/platform/content/moz.build
rename to devtools/client/shared/webpack/shims/moz.build
--- a/devtools/shared/platform/content/moz.build
+++ b/devtools/client/shared/webpack/shims/moz.build
@@ -1,16 +1,16 @@
 # -*- 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/.
 
 DevToolsModules(
-    'clipboard.js',
-    'stack.js',
+    'platform-clipboard-stub.js',
+    'platform-stack-stub.js',
 )
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 MOCHITEST_MANIFESTS += [
     'test/mochitest.ini',
 ]
rename from devtools/shared/platform/content/clipboard.js
rename to devtools/client/shared/webpack/shims/platform-clipboard-stub.js
rename from devtools/shared/platform/content/stack.js
rename to devtools/client/shared/webpack/shims/platform-stack-stub.js
rename from devtools/client/webconsole/local-dev/system-stub.js
rename to devtools/client/shared/webpack/shims/system-stub.js
rename from devtools/shared/platform/content/test/.eslintrc.js
rename to devtools/client/shared/webpack/shims/test/.eslintrc.js
--- a/devtools/shared/platform/content/test/.eslintrc.js
+++ b/devtools/client/shared/webpack/shims/test/.eslintrc.js
@@ -1,6 +1,6 @@
 "use strict";
 
 module.exports = {
   // Extend from the common devtools xpcshell eslintrc config.
-  "extends": "../../../../.eslintrc.xpcshell.js"
+  "extends": "../../../../../.eslintrc.xpcshell.js"
 };
rename from devtools/shared/platform/content/test/mochitest.ini
rename to devtools/client/shared/webpack/shims/test/mochitest.ini
rename from devtools/shared/platform/content/test/test_clipboard.html
rename to devtools/client/shared/webpack/shims/test/test_clipboard.html
--- a/devtools/shared/platform/content/test/test_clipboard.html
+++ b/devtools/client/shared/webpack/shims/test/test_clipboard.html
@@ -34,17 +34,17 @@ async function pre_do_tests() {
       ["security.all_resource_uri_content_accessible", true]
     ]
   });
 
   // Load script.
   await (() => new Promise((resolve) => {
     var script = document.createElement("script");
     script.onload = resolve;
-    script.src = "resource://devtools/shared/platform/content/clipboard.js";
+    script.src = "resource://devtools/client/shared/webpack/shims/platform-clipboard-stub.js";
     document.head.appendChild(script);
   }))();
 
   do_tests();
 }
 
 function do_tests() {
   let elt = document.querySelector("#key");
rename from devtools/shared/platform/content/test/test_stack.js
rename to devtools/client/shared/webpack/shims/test/test_stack.js
--- a/devtools/shared/platform/content/test/test_stack.js
+++ b/devtools/client/shared/webpack/shims/test/test_stack.js
@@ -4,24 +4,21 @@
 // There isn't really very much about the content stack.js that we can
 // test, but we'll do what we can.
 
 "use strict";
 
 var Cu = Components.utils;
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 
-// Make sure to explicitly require the content version of this module.
-// We have to use the ".." trick due to the way the loader remaps
-// devtools/shared/platform.
 const {
   callFunctionWithAsyncStack,
   getStack,
   describeNthCaller
-} = require("devtools/shared/platform/../content/stack");
+} = require("devtools/client/shared/webpack/shims/platform-stack-stub");
 
 function f3() {
   return describeNthCaller(2);
 }
 
 function f2() {
   return f3();
 }
rename from devtools/shared/platform/content/test/xpcshell.ini
rename to devtools/client/shared/webpack/shims/test/xpcshell.ini
--- a/devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip.js
@@ -17,96 +17,97 @@ const INLINE_TOOLTIP_CLASS = "inline-too
  *
  * @param {Document} document
  *        The document to attach the SwatchBasedEditorTooltip. This is either the toolbox
  *        document if the tooltip is a popup tooltip or the panel's document if it is an
  *        inline editor.
  * @param {Boolean} useInline
  *        A boolean flag representing whether or not the InlineTooltip should be used.
  */
-function SwatchBasedEditorTooltip(document, useInline) {
-  EventEmitter.decorate(this);
+
+class SwatchBasedEditorTooltip {
+  constructor(document, useInline) {
+    EventEmitter.decorate(this);
+
+    this.useInline = useInline;
 
-  this.useInline = useInline;
+    // Creating a tooltip instance
+    if (useInline) {
+      this.tooltip = new InlineTooltip(document);
+    } else {
+      // This one will consume outside clicks as it makes more sense to let the user
+      // close the tooltip by clicking out
+      // It will also close on <escape> and <enter>
+      this.tooltip = new HTMLTooltip(document, {
+        type: "arrow",
+        consumeOutsideClicks: true,
+        useXulWrapper: true,
+      });
+    }
 
-  // Creating a tooltip instance
-  if (useInline) {
-    this.tooltip = new InlineTooltip(document);
-  } else {
-    // This one will consume outside clicks as it makes more sense to let the user
-    // close the tooltip by clicking out
-    // It will also close on <escape> and <enter>
-    this.tooltip = new HTMLTooltip(document, {
-      type: "arrow",
-      consumeOutsideClicks: true,
-      useXulWrapper: true,
+    // By default, swatch-based editor tooltips revert value change on <esc> and
+    // commit value change on <enter>
+    this.shortcuts = new KeyShortcuts({
+      window: this.tooltip.topWindow
+    });
+    this.shortcuts.on("Escape", (name, event) => {
+      if (!this.tooltip.isVisible()) {
+        return;
+      }
+      this.revert();
+      this.hide();
+      event.stopPropagation();
+      event.preventDefault();
     });
+    this.shortcuts.on("Return", (name, event) => {
+      if (!this.tooltip.isVisible()) {
+        return;
+      }
+      this.commit();
+      this.hide();
+      event.stopPropagation();
+      event.preventDefault();
+    });
+
+    // All target swatches are kept in a map, indexed by swatch DOM elements
+    this.swatches = new Map();
+
+    // When a swatch is clicked, and for as long as the tooltip is shown, the
+    // activeSwatch property will hold the reference to the swatch DOM element
+    // that was clicked
+    this.activeSwatch = null;
+
+    this._onSwatchClick = this._onSwatchClick.bind(this);
   }
 
-  // By default, swatch-based editor tooltips revert value change on <esc> and
-  // commit value change on <enter>
-  this.shortcuts = new KeyShortcuts({
-    window: this.tooltip.topWindow
-  });
-  this.shortcuts.on("Escape", (name, event) => {
-    if (!this.tooltip.isVisible()) {
-      return;
-    }
-    this.revert();
-    this.hide();
-    event.stopPropagation();
-    event.preventDefault();
-  });
-  this.shortcuts.on("Return", (name, event) => {
-    if (!this.tooltip.isVisible()) {
-      return;
-    }
-    this.commit();
-    this.hide();
-    event.stopPropagation();
-    event.preventDefault();
-  });
-
-  // All target swatches are kept in a map, indexed by swatch DOM elements
-  this.swatches = new Map();
-
-  // When a swatch is clicked, and for as long as the tooltip is shown, the
-  // activeSwatch property will hold the reference to the swatch DOM element
-  // that was clicked
-  this.activeSwatch = null;
-
-  this._onSwatchClick = this._onSwatchClick.bind(this);
-}
-
-SwatchBasedEditorTooltip.prototype = {
-  /**
+ /**
    * Reports if the tooltip is currently shown
    *
    * @return {Boolean} True if the tooltip is displayed.
    */
-  isVisible: function () {
+  isVisible() {
     return this.tooltip.isVisible();
-  },
+  }
 
   /**
    * Reports if the tooltip is currently editing the targeted value
    *
    * @return {Boolean} True if the tooltip is editing.
    */
-  isEditing: function () {
+  isEditing() {
     return this.isVisible();
-  },
+  }
 
   /**
    * Show the editor tooltip for the currently active swatch.
    *
    * @return {Promise} a promise that resolves once the editor tooltip is displayed, or
    *         immediately if there is no currently active swatch.
    */
-  show: function () {
+  show() {
     let tooltipAnchor = this.useInline ?
       this.activeSwatch.closest(`.${INLINE_TOOLTIP_CLASS}`) :
       this.activeSwatch;
 
     if (tooltipAnchor) {
       let onShown = this.tooltip.once("shown");
       this.tooltip.show(tooltipAnchor, "topcenter bottomleft");
 
@@ -123,21 +124,21 @@ SwatchBasedEditorTooltip.prototype = {
           this.activeSwatch = null;
         }
       });
 
       return onShown;
     }
 
     return Promise.resolve();
-  },
+  }
 
-  hide: function () {
+  hide() {
     this.tooltip.hide();
-  },
+  }
 
   /**
    * Add a new swatch DOM element to the list of swatch elements this editor
    * tooltip knows about. That means from now on, clicking on that swatch will
    * toggle the editor.
    *
    * @param {node} swatchEl
    *        The element to add
@@ -146,17 +147,17 @@ SwatchBasedEditorTooltip.prototype = {
    *        value change, or revert a change, or commit a change.
    *        - onShow: will be called when one of the swatch tooltip is shown
    *        - onPreview: will be called when one of the sub-classes calls
    *        preview
    *        - onRevert: will be called when the user ESCapes out of the tooltip
    *        - onCommit: will be called when the user presses ENTER or clicks
    *        outside the tooltip.
    */
-  addSwatch: function (swatchEl, callbacks = {}) {
+  addSwatch(swatchEl, callbacks = {}) {
     if (!callbacks.onShow) {
       callbacks.onShow = function () {};
     }
     if (!callbacks.onPreview) {
       callbacks.onPreview = function () {};
     }
     if (!callbacks.onRevert) {
       callbacks.onRevert = function () {};
@@ -164,79 +165,79 @@ SwatchBasedEditorTooltip.prototype = {
     if (!callbacks.onCommit) {
       callbacks.onCommit = function () {};
     }
 
     this.swatches.set(swatchEl, {
       callbacks: callbacks
     });
     swatchEl.addEventListener("click", this._onSwatchClick);
-  },
+  }
 
-  removeSwatch: function (swatchEl) {
+  removeSwatch(swatchEl) {
     if (this.swatches.has(swatchEl)) {
       if (this.activeSwatch === swatchEl) {
         this.hide();
         this.activeSwatch = null;
       }
       swatchEl.removeEventListener("click", this._onSwatchClick);
       this.swatches.delete(swatchEl);
     }
-  },
+  }
 
-  _onSwatchClick: function (event) {
+  _onSwatchClick(event) {
     let swatch = this.swatches.get(event.target);
 
     if (event.shiftKey) {
       event.stopPropagation();
       return;
     }
     if (swatch) {
       this.activeSwatch = event.target;
       this.show();
       swatch.callbacks.onShow();
       event.stopPropagation();
     }
-  },
+  }
 
   /**
    * Not called by this parent class, needs to be taken care of by sub-classes
    */
-  preview: function (value) {
+  preview(value) {
     if (this.activeSwatch) {
       let swatch = this.swatches.get(this.activeSwatch);
       swatch.callbacks.onPreview(value);
     }
-  },
+  }
 
   /**
    * This parent class only calls this on <esc> keypress
    */
-  revert: function () {
+  revert() {
     if (this.activeSwatch) {
       this._reverted = true;
       let swatch = this.swatches.get(this.activeSwatch);
       this.tooltip.once("hidden", () => {
         swatch.callbacks.onRevert();
       });
     }
-  },
+  }
 
   /**
    * This parent class only calls this on <enter> keypress
    */
-  commit: function () {
+  commit() {
     if (this.activeSwatch) {
       let swatch = this.swatches.get(this.activeSwatch);
       swatch.callbacks.onCommit();
     }
-  },
+  }
 
-  destroy: function () {
+  destroy() {
     this.swatches.clear();
     this.activeSwatch = null;
     this.tooltip.off("keypress", this._onTooltipKeypress);
     this.tooltip.destroy();
     this.shortcuts.destroy();
   }
-};
+}
 
 module.exports = SwatchBasedEditorTooltip;
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -1,25 +1,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Services = require("Services");
-const {Task} = require("devtools/shared/task");
 const {colorUtils} = require("devtools/shared/css/color");
 const {ColorWidget} = require("devtools/client/shared/widgets/ColorWidget");
 const {Spectrum} = require("devtools/client/shared/widgets/Spectrum");
 const SwatchBasedEditorTooltip = require("devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip");
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
 
-const {extend} = require("devtools/shared/extend");
-
 const colorWidgetPref = "devtools.inspector.colorWidget.enabled";
 const NEW_COLOR_WIDGET = Services.prefs.getBoolPref(colorWidgetPref);
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
 /**
  * The swatch color picker tooltip class is a specific class meant to be used
  * along with output-parser's generated color swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
@@ -30,37 +27,36 @@ const XHTML_NS = "http://www.w3.org/1999
  *        The document to attach the SwatchColorPickerTooltip. This is either the toolbox
  *        document if the tooltip is a popup tooltip or the panel's document if it is an
  *        inline editor.
  * @param {InspectorPanel} inspector
  *        The inspector panel, needed for the eyedropper.
  * @param {Function} supportsCssColor4ColorFunction
  *        A function for checking the supporting of css-color-4 color function.
  */
-function SwatchColorPickerTooltip(document,
-                                  inspector,
-                                  {supportsCssColor4ColorFunction}) {
-  SwatchBasedEditorTooltip.call(this, document);
 
-  this.inspector = inspector;
+class SwatchColorPickerTooltip extends SwatchBasedEditorTooltip {
+  constructor(document, inspector, {supportsCssColor4ColorFunction}) {
+    super(document);
+    this.inspector = inspector;
 
-  // Creating a spectrum instance. this.spectrum will always be a promise that
-  // resolves to the spectrum instance
-  this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
-  this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
-  this._openEyeDropper = this._openEyeDropper.bind(this);
-  this.cssColor4 = supportsCssColor4ColorFunction();
-}
+    // Creating a spectrum instance. this.spectrum will always be a promise that
+    // resolves to the spectrum instance
+    this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
+    this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
+    this._openEyeDropper = this._openEyeDropper.bind(this);
+    this.cssColor4 = supportsCssColor4ColorFunction();
+  }
 
-SwatchColorPickerTooltip.prototype = extend(SwatchBasedEditorTooltip.prototype, {
   /**
    * Fill the tooltip with a new instance of the spectrum color picker widget
    * initialized with the given color, and return the instance of spectrum
    */
-  setColorPickerContent: function (color) {
+
+  setColorPickerContent(color) {
     let { doc } = this.tooltip;
 
     let container = doc.createElementNS(XHTML_NS, "div");
     container.id = "spectrum-tooltip";
 
     let widget;
     let node = doc.createElementNS(XHTML_NS, "div");
 
@@ -88,85 +84,85 @@ SwatchColorPickerTooltip.prototype = ext
 
     // Wait for the tooltip to be shown before calling widget.show
     // as it expect to be visible in order to compute DOM element sizes.
     this.tooltip.once("shown", () => {
       widget.show();
     });
 
     return widget;
-  },
+  }
 
   /**
    * Overriding the SwatchBasedEditorTooltip.show function to set spectrum's
    * color.
    */
-  show: Task.async(function* () {
+  async show() {
     // set contrast enabled for the spectrum
     let name = this.activeSwatch.dataset.propertyName;
 
     if (this.isContrastCompatible === undefined) {
       let target = this.inspector.target;
-      this.isContrastCompatible = yield target.actorHasMethod(
+      this.isContrastCompatible = await target.actorHasMethod(
         "domnode",
         "getClosestBackgroundColor"
       );
     }
 
     // only enable contrast if it is compatible and if the type of property is color.
     this.spectrum.contrastEnabled = (name === "color") && this.isContrastCompatible;
 
     // Call then parent class' show function
-    yield SwatchBasedEditorTooltip.prototype.show.call(this);
+    await super.show();
 
     // Then set spectrum's color and listen to color changes to preview them
     if (this.activeSwatch) {
       this.currentSwatchColor = this.activeSwatch.nextSibling;
       this._originalColor = this.currentSwatchColor.textContent;
       let color = this.activeSwatch.style.backgroundColor;
       this.spectrum.off("changed", this._onSpectrumColorChange);
 
       this.spectrum.rgb = this._colorToRgba(color);
       this.spectrum.on("changed", this._onSpectrumColorChange);
       this.spectrum.updateUI();
     }
 
     let eyeButton = this.tooltip.container.querySelector("#eyedropper-button");
-    let canShowEyeDropper = yield this.inspector.supportsEyeDropper();
+    let canShowEyeDropper = await this.inspector.supportsEyeDropper();
     if (canShowEyeDropper) {
       eyeButton.disabled = false;
       eyeButton.removeAttribute("title");
       eyeButton.addEventListener("click", this._openEyeDropper);
     } else {
       eyeButton.disabled = true;
       eyeButton.title = L10N.getStr("eyedropper.disabled.title");
     }
     this.emit("ready");
-  }),
+  }
 
-  _onSpectrumColorChange: function (event, rgba, cssColor) {
+  _onSpectrumColorChange(event, rgba, cssColor) {
     this._selectColor(cssColor);
-  },
+  }
 
-  _selectColor: function (color) {
+  _selectColor(color) {
     if (this.activeSwatch) {
       this.activeSwatch.style.backgroundColor = color;
       this.activeSwatch.parentNode.dataset.color = color;
 
       color = this._toDefaultType(color);
       this.currentSwatchColor.textContent = color;
       this.preview(color);
 
       if (this.eyedropperOpen) {
         this.commit();
       }
     }
-  },
+  }
 
-  _openEyeDropper: function () {
+  _openEyeDropper() {
     let {inspector, toolbox, telemetry} = this.inspector;
     telemetry.toolOpened("pickereyedropper");
 
     // cancelling picker(if it is already selected) on opening eye-dropper
     toolbox.highlighterUtils.cancelPicker();
 
     inspector.pickColorFromPage(toolbox, {copyOnSelect: false}).then(() => {
       this.eyedropperOpen = true;
@@ -181,45 +177,45 @@ SwatchColorPickerTooltip.prototype = ext
       toolbox.win.focus();
       this._selectColor(color);
       this._onEyeDropperDone();
     });
 
     inspector.once("color-pick-canceled", () => {
       this._onEyeDropperDone();
     });
-  },
+  }
 
-  _onEyeDropperDone: function () {
+  _onEyeDropperDone() {
     this.eyedropperOpen = false;
     this.activeSwatch = null;
-  },
+  }
 
-  _colorToRgba: function (color) {
+  _colorToRgba(color) {
     color = new colorUtils.CssColor(color, this.cssColor4);
     let rgba = color.getRGBATuple();
     return [rgba.r, rgba.g, rgba.b, rgba.a];
-  },
+  }
 
-  _toDefaultType: function (color) {
+  _toDefaultType(color) {
     let colorObj = new colorUtils.CssColor(color);
     colorObj.setAuthoredUnitFromColor(this._originalColor, this.cssColor4);
     return colorObj.toString();
-  },
+  }
 
   /**
    * Overriding the SwatchBasedEditorTooltip.isEditing function to consider the
    * eyedropper.
    */
-  isEditing: function () {
+  isEditing() {
     return this.tooltip.isVisible() || this.eyedropperOpen;
-  },
+  }
 
-  destroy: function () {
-    SwatchBasedEditorTooltip.prototype.destroy.call(this);
+  destroy() {
+    super.destroy();
     this.inspector = null;
     this.currentSwatchColor = null;
     this.spectrum.off("changed", this._onSpectrumColorChange);
     this.spectrum.destroy();
   }
-});
+}
 
 module.exports = SwatchColorPickerTooltip;
--- a/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
@@ -1,51 +1,50 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const defer = require("devtools/shared/defer");
-const {Task} = require("devtools/shared/task");
 const {CubicBezierWidget} = require("devtools/client/shared/widgets/CubicBezierWidget");
 const SwatchBasedEditorTooltip = require("devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip");
 
-const {extend} = require("devtools/shared/extend");
-
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
 /**
  * The swatch cubic-bezier tooltip class is a specific class meant to be used
  * along with rule-view's generated cubic-bezier swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
  * It just wraps a standard Tooltip and sets its content with an instance of a
  * CubicBezierWidget.
  *
  * @param {Document} document
  *        The document to attach the SwatchCubicBezierTooltip. This is either the toolbox
  *        document if the tooltip is a popup tooltip or the panel's document if it is an
  *        inline editor.
  */
-function SwatchCubicBezierTooltip(document) {
-  SwatchBasedEditorTooltip.call(this, document);
+
+class SwatchCubicBezierTooltip extends SwatchBasedEditorTooltip {
+  constructor(document) {
+    super(document);
 
-  // Creating a cubic-bezier instance.
-  // this.widget will always be a promise that resolves to the widget instance
-  this.widget = this.setCubicBezierContent([0, 0, 1, 1]);
-  this._onUpdate = this._onUpdate.bind(this);
-}
+    // Creating a cubic-bezier instance.
+    // this.widget will always be a promise that resolves to the widget instance
+    this.widget = this.setCubicBezierContent([0, 0, 1, 1]);
+    this._onUpdate = this._onUpdate.bind(this);
+  }
 
-SwatchCubicBezierTooltip.prototype = extend(SwatchBasedEditorTooltip.prototype, {
   /**
    * Fill the tooltip with a new instance of the cubic-bezier widget
    * initialized with the given value, and return a promise that resolves to
    * the instance of the widget
    */
-  setCubicBezierContent: function (bezier) {
+
+  setCubicBezierContent(bezier) {
     let { doc } = this.tooltip;
 
     let container = doc.createElementNS(XHTML_NS, "div");
     container.className = "cubic-bezier-container";
 
     this.tooltip.setContent(container, { width: 510, height: 370 });
 
     let def = defer();
@@ -53,49 +52,49 @@ SwatchCubicBezierTooltip.prototype = ext
     // Wait for the tooltip to be shown before calling instanciating the widget
     // as it expect its DOM elements to be visible.
     this.tooltip.once("shown", () => {
       let widget = new CubicBezierWidget(container, bezier);
       def.resolve(widget);
     });
 
     return def.promise;
-  },
+  }
 
   /**
    * Overriding the SwatchBasedEditorTooltip.show function to set the cubic
    * bezier curve in the widget
    */
-  show: Task.async(function* () {
+  async show() {
     // Call the parent class' show function
-    yield SwatchBasedEditorTooltip.prototype.show.call(this);
+    await super.show();
     // Then set the curve and listen to changes to preview them
     if (this.activeSwatch) {
       this.currentBezierValue = this.activeSwatch.nextSibling;
       this.widget.then(widget => {
         widget.off("updated", this._onUpdate);
         widget.cssCubicBezierValue = this.currentBezierValue.textContent;
         widget.on("updated", this._onUpdate);
         this.emit("ready");
       });
     }
-  }),
+  }
 
-  _onUpdate: function (event, bezier) {
+  _onUpdate(event, bezier) {
     if (!this.activeSwatch) {
       return;
     }
 
     this.currentBezierValue.textContent = bezier + "";
     this.preview(bezier + "");
-  },
+  }
 
-  destroy: function () {
-    SwatchBasedEditorTooltip.prototype.destroy.call(this);
+  destroy() {
+    super.destroy();
     this.currentBezierValue = null;
     this.widget.then(widget => {
       widget.off("updated", this._onUpdate);
       widget.destroy();
     });
   }
-});
+}
 
 module.exports = SwatchCubicBezierTooltip;
--- a/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
@@ -1,20 +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/. */
 
 "use strict";
 
-const {Task} = require("devtools/shared/task");
 const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
 const SwatchBasedEditorTooltip = require("devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip");
 
-const {extend} = require("devtools/shared/extend");
-
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
 /**
  * The swatch-based css filter tooltip class is a specific class meant to be
  * used along with rule-view's generated css filter swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
  * It just wraps a standard Tooltip and sets its content with an instance of a
  * CSSFilterEditorWidget.
@@ -22,94 +19,95 @@ const XHTML_NS = "http://www.w3.org/1999
  * @param {Document} document
  *        The document to attach the SwatchFilterTooltip. This is either the toolbox
  *        document if the tooltip is a popup tooltip or the panel's document if it is an
  *        inline editor.
  * @param {function} cssIsValid
  *        A function to check that css declaration's name and values are valid together.
  *        This can be obtained from "shared/fronts/css-properties.js".
  */
-function SwatchFilterTooltip(document, cssIsValid) {
-  SwatchBasedEditorTooltip.call(this, document);
-  this._cssIsValid = cssIsValid;
+
+class SwatchFilterTooltip extends SwatchBasedEditorTooltip {
+  constructor(document, cssIsValid) {
+    super(document);
+    this._cssIsValid = cssIsValid;
 
-  // Creating a filter editor instance.
-  this.widget = this.setFilterContent("none");
-  this._onUpdate = this._onUpdate.bind(this);
-}
+    // Creating a filter editor instance.
+    this.widget = this.setFilterContent("none");
+    this._onUpdate = this._onUpdate.bind(this);
+  }
 
-SwatchFilterTooltip.prototype = extend(SwatchBasedEditorTooltip.prototype, {
   /**
    * Fill the tooltip with a new instance of the CSSFilterEditorWidget
    * widget initialized with the given filter value, and return a promise
    * that resolves to the instance of the widget when ready.
    */
-  setFilterContent: function (filter) {
+
+  setFilterContent(filter) {
     let { doc } = this.tooltip;
 
     let container = doc.createElementNS(XHTML_NS, "div");
     container.id = "filter-container";
 
     this.tooltip.setContent(container, { width: 510, height: 200 });
 
     return new CSSFilterEditorWidget(container, filter, this._cssIsValid);
-  },
+  }
 
-  show: Task.async(function* () {
+  async show() {
     // Call the parent class' show function
-    yield SwatchBasedEditorTooltip.prototype.show.call(this);
+    await super.show();
     // Then set the filter value and listen to changes to preview them
     if (this.activeSwatch) {
       this.currentFilterValue = this.activeSwatch.nextSibling;
       this.widget.off("updated", this._onUpdate);
       this.widget.on("updated", this._onUpdate);
       this.widget.setCssValue(this.currentFilterValue.textContent);
       this.widget.render();
       this.emit("ready");
     }
-  }),
+  }
 
-  _onUpdate: function (event, filters) {
+  _onUpdate(event, filters) {
     if (!this.activeSwatch) {
       return;
     }
 
     // Remove the old children and reparse the property value to
     // recompute them.
     while (this.currentFilterValue.firstChild) {
       this.currentFilterValue.firstChild.remove();
     }
     let node = this._parser.parseCssProperty("filter", filters, this._options);
     this.currentFilterValue.appendChild(node);
 
     this.preview();
-  },
+  }
 
-  destroy: function () {
-    SwatchBasedEditorTooltip.prototype.destroy.call(this);
+  destroy() {
+    super.destroy();
     this.currentFilterValue = null;
     this.widget.off("updated", this._onUpdate);
     this.widget.destroy();
-  },
+  }
 
   /**
    * Like SwatchBasedEditorTooltip.addSwatch, but accepts a parser object
    * to use when previewing the updated property value.
    *
    * @param {node} swatchEl
    *        @see SwatchBasedEditorTooltip.addSwatch
    * @param {object} callbacks
    *        @see SwatchBasedEditorTooltip.addSwatch
    * @param {object} parser
    *        A parser object; @see OutputParser object
    * @param {object} options
    *        options to pass to the output parser, with
    *          the option |filterSwatch| set.
    */
-  addSwatch: function (swatchEl, callbacks, parser, options) {
-    SwatchBasedEditorTooltip.prototype.addSwatch.call(this, swatchEl,
-                                                      callbacks);
+  addSwatch(swatchEl, callbacks, parser, options) {
+    super.addSwatch(swatchEl, callbacks);
     this._parser = parser;
     this._options = options;
   }
-});
+}
 
 module.exports = SwatchFilterTooltip;
--- a/devtools/client/shared/widgets/tooltip/Tooltip.js
+++ b/devtools/client/shared/widgets/tooltip/Tooltip.js
@@ -82,154 +82,155 @@ const POPUP_EVENTS = ["shown", "hidden",
  *
  * Fires these events:
  * - showing : just before the tooltip shows
  * - shown : when the tooltip is shown
  * - hiding : just before the tooltip closes
  * - hidden : when the tooltip gets hidden
  * - keypress : when any key gets pressed, with keyCode
  */
-function Tooltip(doc, {
+
+class Tooltip {
+  constructor(doc, {
   consumeOutsideClick = false,
   closeOnKeys = [ESCAPE_KEYCODE],
   noAutoFocus = true,
   closeOnEvents = [],
   } = {}) {
-  EventEmitter.decorate(this);
+    EventEmitter.decorate(this);
 
-  this.doc = doc;
-  this.consumeOutsideClick = consumeOutsideClick;
-  this.closeOnKeys = closeOnKeys;
-  this.noAutoFocus = noAutoFocus;
-  this.closeOnEvents = closeOnEvents;
+    this.defaultPosition = "before_start";
+    // px
+    this.defaultOffsetX = 0;
+    // px
+    this.defaultOffsetY = 0;
+    // px
 
-  this.panel = this._createPanel();
+    this.doc = doc;
+    this.consumeOutsideClick = consumeOutsideClick;
+    this.closeOnKeys = closeOnKeys;
+    this.noAutoFocus = noAutoFocus;
+    this.closeOnEvents = closeOnEvents;
 
-  // Create tooltip toggle helper and decorate the Tooltip instance with
-  // shortcut methods.
-  this._toggle = new TooltipToggle(this);
-  this.startTogglingOnHover = this._toggle.start.bind(this._toggle);
-  this.stopTogglingOnHover = this._toggle.stop.bind(this._toggle);
+    this.panel = this._createPanel();
+
+    // Create tooltip toggle helper and decorate the Tooltip instance with
+    // shortcut methods.
+    this._toggle = new TooltipToggle(this);
+    this.startTogglingOnHover = this._toggle.start.bind(this._toggle);
+    this.stopTogglingOnHover = this._toggle.stop.bind(this._toggle);
 
   // Emit show/hide events when the panel does.
-  for (let eventName of POPUP_EVENTS) {
-    this["_onPopup" + eventName] = (name => {
-      return e => {
-        if (e.target === this.panel) {
-          this.emit(name);
-        }
-      };
-    })(eventName);
-    this.panel.addEventListener("popup" + eventName,
-      this["_onPopup" + eventName]);
-  }
+    for (let eventName of POPUP_EVENTS) {
+      this["_onPopup" + eventName] = (name => {
+        return e => {
+          if (e.target === this.panel) {
+            this.emit(name);
+          }
+        };
+      })(eventName);
+      this.panel.addEventListener("popup" + eventName,
+        this["_onPopup" + eventName]);
+    }
 
   // Listen to keypress events to close the tooltip if configured to do so
-  let win = this.doc.querySelector("window");
-  this._onKeyPress = event => {
-    if (this.panel.hidden) {
-      return;
-    }
+    let win = this.doc.querySelector("window");
+    this._onKeyPress = event => {
+      if (this.panel.hidden) {
+        return;
+      }
 
-    this.emit("keypress", event.keyCode);
-    if (this.closeOnKeys.indexOf(event.keyCode) !== -1 &&
-        this.isShown()) {
-      event.stopPropagation();
-      this.hide();
-    }
-  };
-  win.addEventListener("keypress", this._onKeyPress);
+      this.emit("keypress", event.keyCode);
+      if (this.closeOnKeys.indexOf(event.keyCode) !== -1 &&
+          this.isShown()) {
+        event.stopPropagation();
+        this.hide();
+      }
+    };
+    win.addEventListener("keypress", this._onKeyPress);
 
   // Listen to custom emitters' events to close the tooltip
-  this.hide = this.hide.bind(this);
-  for (let {emitter, event, useCapture} of this.closeOnEvents) {
-    for (let add of ["addEventListener", "on"]) {
-      if (add in emitter) {
-        emitter[add](event, this.hide, useCapture);
-        break;
+    this.hide = this.hide.bind(this);
+    for (let {emitter, event, useCapture} of this.closeOnEvents) {
+      for (let add of ["addEventListener", "on"]) {
+        if (add in emitter) {
+          emitter[add](event, this.hide, useCapture);
+          break;
+        }
       }
     }
   }
-}
-
-Tooltip.prototype = {
-  defaultPosition: "before_start",
-  // px
-  defaultOffsetX: 0,
-  // px
-  defaultOffsetY: 0,
-  // px
 
   /**
    * Show the tooltip. It might be wise to append some content first if you
    * don't want the tooltip to be empty. You may access the content of the
    * tooltip by setting a XUL node to t.content.
    * @param {node} anchor
    *        Which node should the tooltip be shown on
    * @param {string} position [optional]
    *        Optional tooltip position. Defaults to before_start
    *        https://developer.mozilla.org/en-US/docs/XUL/PopupGuide/Positioning
    * @param {number} x, y [optional]
    *        The left and top offset coordinates, in pixels.
    */
-  show: function (anchor,
+  show(anchor,
     position = this.defaultPosition,
     x = this.defaultOffsetX,
     y = this.defaultOffsetY) {
     this.panel.hidden = false;
     this.panel.openPopup(anchor, position, x, y);
-  },
+  }
 
   /**
    * Hide the tooltip
    */
-  hide: function () {
+  hide() {
     this.panel.hidden = true;
     this.panel.hidePopup();
-  },
+  }
 
-  isShown: function () {
+  isShown() {
     return this.panel &&
            this.panel.state !== "closed" &&
            this.panel.state !== "hiding";
-  },
+  }
 
-  setSize: function (width, height) {
+  setSize(width, height) {
     this.panel.sizeTo(width, height);
-  },
+  }
 
   /**
    * Empty the tooltip's content
    */
-  empty: function () {
+  empty() {
     while (this.panel.hasChildNodes()) {
       this.panel.firstChild.remove();
     }
-  },
+  }
 
   /**
    * Gets this panel's visibility state.
    * @return boolean
    */
-  isHidden: function () {
+  isHidden() {
     return this.panel.state == "closed" || this.panel.state == "hiding";
-  },
+  }
 
   /**
    * Gets if this panel has any child nodes.
    * @return boolean
    */
-  isEmpty: function () {
+  isEmpty() {
     return !this.panel.hasChildNodes();
-  },
+  }
 
   /**
    * Get rid of references and event listeners
    */
-  destroy: function () {
+  destroy() {
     this.hide();
 
     for (let eventName of POPUP_EVENTS) {
       this.panel.removeEventListener("popup" + eventName,
         this["_onPopup" + eventName]);
     }
 
     let win = this.doc.querySelector("window");
@@ -247,26 +248,26 @@ Tooltip.prototype = {
     this.content = null;
 
     this._toggle.destroy();
 
     this.doc = null;
 
     this.panel.remove();
     this.panel = null;
-  },
+  }
 
   /**
    * Returns the outer container node (that includes the arrow etc.). Happens
    * to be identical to this.panel here, can be different element in other
    * Tooltip implementations.
    */
   get container() {
     return this.panel;
-  },
+  }
 
   /**
    * Set the content of this tooltip. Will first empty the tooltip and then
    * append the new content element.
    * Consider using one of the set<type>Content() functions instead.
    * @param {node} content
    *        A node that can be appended in the tooltip XUL element
    */
@@ -279,33 +280,33 @@ Tooltip.prototype = {
     this.panel.removeAttribute("clamped-dimensions");
     this.panel.removeAttribute("clamped-dimensions-no-min-height");
     this.panel.removeAttribute("clamped-dimensions-no-max-or-min-height");
     this.panel.removeAttribute("wide");
 
     if (content) {
       this.panel.appendChild(content);
     }
-  },
+  }
 
   get content() {
     return this.panel.firstChild;
-  },
+  }
 
   /**
    * Sets some text as the content of this tooltip.
    *
    * @param {array} messages
    *        A list of text messages.
    * @param {string} messagesClass [optional]
    *        A style class for the text messages.
    * @param {string} containerClass [optional]
    *        A style class for the text messages container.
    */
-  setTextContent: function (
+  setTextContent(
     {
       messages,
       messagesClass,
       containerClass
     },
     extraButtons = []) {
     messagesClass = messagesClass || "default-tooltip-simple-text-colors";
     containerClass = containerClass || "default-tooltip-simple-text-colors";
@@ -326,17 +327,17 @@ Tooltip.prototype = {
       let button = this.doc.createElement("button");
       button.className = className;
       button.setAttribute("label", label);
       button.addEventListener("command", command);
       vbox.appendChild(button);
     }
 
     this.content = vbox;
-  },
+  }
 
   /**
    * Load a document into an iframe, and set the iframe
    * to be the tooltip's content.
    *
    * Used by tooltips that want to load their interface
    * into an iframe from a URL.
    *
@@ -352,17 +353,17 @@ Tooltip.prototype = {
    *
    * This function creates an iframe, loads the specified document
    * into it, sets the tooltip's content to the iframe, and returns
    * a promise.
    *
    * When the document is loaded, the function gets the content window
    * and resolves the promise with the content window.
    */
-  setIFrameContent: function ({width, height}, url) {
+  setIFrameContent({width, height}, url) {
     let def = defer();
 
     // Create an iframe
     let iframe = this.doc.createElementNS(XHTML_NS, "iframe");
     iframe.setAttribute("transparent", true);
     iframe.setAttribute("width", width);
     iframe.setAttribute("height", height);
     iframe.setAttribute("flex", "1");
@@ -378,17 +379,17 @@ Tooltip.prototype = {
 
     // load the document from url into the iframe
     iframe.setAttribute("src", url);
 
     // Put the iframe in the tooltip
     this.content = iframe;
 
     return def.promise;
-  },
+  }
 
   /**
    * Create the tooltip panel
    */
   _createPanel() {
     let panel = this.doc.createElement("panel");
     panel.setAttribute("hidden", true);
     panel.setAttribute("ignorekeys", true);
@@ -400,11 +401,11 @@ Tooltip.prototype = {
     panel.setAttribute("type", "arrow");
     panel.setAttribute("level", "top");
 
     panel.setAttribute("class", "devtools-tooltip theme-tooltip-panel");
     this.doc.querySelector("window").appendChild(panel);
 
     return panel;
   }
-};
+}
 
 module.exports = Tooltip;
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -402,66 +402,104 @@ html #webconsole-notificationbox {
   width: 100vw;
 }
 
 .jsterm-input-container {
   background-color: var(--theme-tab-toolbar-background);
   border-top: 1px solid var(--theme-splitter-color);
 }
 
+.jsterm-input-node {
+  /* Always allow scrolling on input - it auto expands in js by setting height,
+     but don't want it to get bigger than the window. 24px = toolbar height. */
+  max-height: calc(90vh - 24px);
+  background-image: var(--theme-command-line-image);
+  background-repeat: no-repeat;
+  background-size: 16px 16px;
+  background-position: 4px 50%;
+  color: var(--theme-content-color1);
+}
+
+.jsterm-complete-node {
+  color: var(--theme-comment);
+}
+
 .theme-light .jsterm-input-container {
   /* For light theme use a white background for the input - it looks better
      than off-white */
   background-color: #fff;
   border-top-color: #e0e0e0;
 }
 
 .theme-firebug .jsterm-input-container {
   border-top: 1px solid #ccc;
 }
 
-.jsterm-input-node,
-.jsterm-complete-node {
+/*  styles for the new HTML frontend */
+
+html .jsterm-stack-node {
+  position: relative;
+}
+
+textarea.jsterm-input-node,
+textarea.jsterm-complete-node {
+  width: 100%;
+  border: none;
+  margin: 0;
+  background-color: transparent;
+  resize: none;
+  font-size: var(--theme-toolbar-font-size);
+  line-height: 16px;
+  overflow-x: hidden;
+  /* Set padding for console input on textarea to make sure it is included in
+     scrollHeight that is used when resizing JSTerminal's input. */
+  padding: 4px 0;
+  padding-inline-start: 20px;
+}
+
+textarea.jsterm-complete-node {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100%;
+  pointer-events: none;
+}
+
+textarea.jsterm-input-node:focus {
+  background-image: var(--theme-command-line-image-focus);
+  box-shadow: none;
+}
+
+
+/*  styles for the old frontend, which can be removed in Bug 1381834 */
+
+textbox.jsterm-input-node,
+textbox.jsterm-complete-node {
   border: none;
   padding: 0;
   padding-inline-start: 20px;
   margin: 0;
   -moz-appearance: none;
   background-color: transparent;
 }
 
-.jsterm-input-node[focused="true"] {
-  background-image: var(--theme-command-line-image-focus);
-  box-shadow: none;
-}
-
-.jsterm-complete-node {
-  color: var(--theme-comment);
-}
-
-.jsterm-input-node {
-  /* Always allow scrolling on input - it auto expands in js by setting height,
-     but don't want it to get bigger than the window. 24px = toolbar height. */
-  max-height: calc(90vh - 24px);
-  background-image: var(--theme-command-line-image);
-  background-repeat: no-repeat;
-  background-size: 16px 16px;
-  background-position: 4px 50%;
-  color: var(--theme-content-color1);
-}
-
-:-moz-any(.jsterm-input-node,
-          .jsterm-complete-node) > .textbox-input-box > .textbox-textarea {
+:-moz-any(textbox.jsterm-input-node,
+          textbox.jsterm-complete-node) > .textbox-input-box > .textbox-textarea {
   overflow-x: hidden;
-  /* Set padding for console input on textbox to make sure it is inlcuded in
+  /* Set padding for console input on textbox to make sure it is included in
      scrollHeight that is used when resizing JSTerminal's input. Note: textbox
      default style has important already */
   padding: 4px 0 !important;
 }
 
+textbox.jsterm-input-node[focused="true"] {
+  background-image: var(--theme-command-line-image-focus);
+  box-shadow: none;
+}
+
 .inlined-variables-view .message-body {
   display: flex;
   flex-direction: column;
   resize: vertical;
   overflow: auto;
   min-height: 200px;
 }
 .inlined-variables-view iframe {
--- a/devtools/client/webaudioeditor/includes.js
+++ b/devtools/client/webaudioeditor/includes.js
@@ -11,16 +11,20 @@ const { Task } = require("devtools/share
 const OldEventEmitter = require("devtools/shared/old-event-emitter");
 const EventEmitter = require("devtools/shared/event-emitter");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const Services = require("Services");
 const { gDevTools } = require("devtools/client/framework/devtools");
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
 
+// Use privileged promise in panel documents to prevent having them to freeze
+// during toolbox destruction. See bug 1402779.
+const Promise = require("Promise");
+
 const STRINGS_URI = "devtools/client/locales/webaudioeditor.properties";
 const L10N = new LocalizationHelper(STRINGS_URI);
 
 loader.lazyRequireGetter(this, "LineGraphWidget",
   "devtools/client/shared/widgets/LineGraphWidget");
 
 // `AUDIO_NODE_DEFINITION` defined in the controller's initialization,
 // which describes all the properties of an AudioNode
--- a/devtools/client/webconsole/jsterm.js
+++ b/devtools/client/webconsole/jsterm.js
@@ -1001,17 +1001,21 @@ JSTerm.prototype = {
   resizeInput: function () {
     let inputNode = this.inputNode;
 
     // Reset the height so that scrollHeight will reflect the natural height of
     // the contents of the input field.
     inputNode.style.height = "auto";
 
     // Now resize the input field to fit its contents.
-    let scrollHeight = inputNode.inputField.scrollHeight;
+    // TODO: remove `inputNode.inputField.scrollHeight` when the old
+    // console UI is removed. See bug 1381834
+    let scrollHeight = inputNode.inputField ?
+      inputNode.inputField.scrollHeight : inputNode.scrollHeight;
+
     if (scrollHeight > 0) {
       inputNode.style.height = scrollHeight + "px";
     }
   },
 
   /**
    * Sets the value of the input field (command line), and resizes the field to
    * fit its contents. This method is preferred over setting "inputNode.value"
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -55,17 +55,18 @@ NewConsoleOutputWrapper.prototype = {
       }
 
       // Do not focus if an input field was clicked
       if (target.closest("input")) {
         return;
       }
 
       // Do not focus if something other than the output region was clicked
-      if (!target.closest(".webconsole-output")) {
+      // (including e.g. the clear messages button in toolbar)
+      if (!target.closest(".webconsole-output-wrapper")) {
         return;
       }
 
       // Do not focus if something is selected
       let selection = this.document.defaultView.getSelection();
       if (selection && !selection.isCollapsed) {
         return;
       }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_input_focus.js
@@ -13,48 +13,43 @@ const TEST_URI =
     console.log("console message 1");
   </script>`;
 
 add_task(function* () {
   let hud = yield openNewTabAndConsole(TEST_URI);
 
   hud.jsterm.clearOutput();
   let inputNode = hud.jsterm.inputNode;
-  ok(inputNode.getAttribute("focused"), "input node is focused after output is cleared");
+  ok(hasFocus(inputNode), "input node is focused after output is cleared");
 
   info("Focus during message logging");
   ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
     content.wrappedJSObject.console.log("console message 2");
   });
   let msg = yield waitFor(() => findMessage(hud, "console message 2"));
-  ok(inputNode.getAttribute("focused"), "input node is focused, first time");
+  ok(hasFocus(inputNode, "input node is focused, first time"));
 
   info("Focus after clicking in the output area");
   yield waitForBlurredInput(hud);
   EventUtils.sendMouseEvent({type: "click"}, msg);
-  ok(inputNode.getAttribute("focused"), "input node is focused, second time");
+  ok(hasFocus(inputNode), "input node is focused, second time");
 
   info("Setting a text selection and making sure a click does not re-focus");
   yield waitForBlurredInput(hud);
   let selection = hud.iframeWindow.getSelection();
   selection.selectAllChildren(msg.querySelector(".message-body"));
   EventUtils.sendMouseEvent({type: "click"}, msg);
-  ok(!inputNode.getAttribute("focused"),
-    "input node not focused after text is selected");
+  ok(!hasFocus(inputNode), "input node not focused after text is selected");
 });
 
 function waitForBlurredInput(hud) {
   let inputNode = hud.jsterm.inputNode;
   return new Promise(resolve => {
     let lostFocus = () => {
-      ok(!inputNode.getAttribute("focused"), "input node is not focused");
+      ok(!hasFocus(inputNode), "input node is not focused");
       resolve();
     };
     inputNode.addEventListener("blur", lostFocus, { once: true });
 
-    // Clicking on a DOM Node outside of the webconsole document. The 'blur' event fires
-    // if we click on something in this document (like the filter box), but the 'focus'
-    // event won't re-fire on the textbox XBL binding when it's clicked on again.
-    // Bug 1304328 is tracking removal of XUL for jsterm, we should be able to click on
-    // the filter textbox instead of the url bar after that.
-    document.getElementById("urlbar").click();
+    // The 'blur' event fires if we focus e.g. the filter box.
+    inputNode.ownerDocument.querySelector("input.text-filter").focus();
   });
 }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_keyboard_accessibility.js
@@ -49,17 +49,17 @@ add_task(function* () {
   let clearShortcut;
   if (Services.appinfo.OS === "Darwin") {
     clearShortcut = WCUL10n.getStr("webconsole.clear.keyOSX");
   } else {
     clearShortcut = WCUL10n.getStr("webconsole.clear.key");
   }
   synthesizeKeyShortcut(clearShortcut);
   yield waitFor(() => findMessages(hud, "").length == 0);
-  is(hud.jsterm.inputNode.getAttribute("focused"), "true", "jsterm input is focused");
+  ok(hasFocus(hud.jsterm.inputNode), "jsterm input is focused");
 
   // Focus filter
   info("try ctrl-f to focus filter");
   synthesizeKeyShortcut(WCUL10n.getStr("webconsole.find.key"));
-  ok(!hud.jsterm.inputNode.getAttribute("focused"), "jsterm input is not focused");
+  ok(!hasFocus(hud.jsterm.inputNode), "jsterm input is not focused");
   is(hud.ui.filterBox, outputScroller.ownerDocument.activeElement,
     "filter input is focused");
 });
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -1,15 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 /* import-globals-from ../../../../framework/test/shared-head.js */
 /* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitFor, findMessage,
-   openContextMenu, hideContextMenu, loadDocument,
+   openContextMenu, hideContextMenu, loadDocument, hasFocus,
    waitForNodeMutation, testOpenInDebugger, checkClickOnNode */
 
 "use strict";
 
 // shared-head.js handles imports, constants, and utility functions
 // Load the shared-head file first.
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
@@ -249,8 +249,15 @@ function* checkClickOnNode(hud, toolbox,
 
   let dbg = toolbox.getPanel("jsdebugger");
   is(
     dbg._selectors.getSelectedSource(dbg._getState()).get("url"),
     url,
     "expected source url"
   );
 }
+
+/**
+ * Returns true if the give node is currently focused.
+ */
+function hasFocus(node) {
+  return node.ownerDocument.activeElement == node;
+}
--- a/devtools/client/webconsole/webconsole.xhtml
+++ b/devtools/client/webconsole/webconsole.xhtml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 <!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" dir="">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     <link rel="stylesheet" href="chrome://devtools/skin/widgets.css"/>
     <link rel="stylesheet" href="resource://devtools/client/themes/light-theme.css"/>
     <link rel="stylesheet" href="chrome://devtools/skin/webconsole.css"/>
     <link rel="stylesheet" href="chrome://devtools/skin/components-frame.css"/>
     <link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
     <link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabs.css"/>
@@ -18,23 +18,23 @@
     <script src="chrome://devtools/content/shared/theme-switching.js"></script>
     <script type="application/javascript"
             src="resource://devtools/client/webconsole/new-console-output/main.js"></script>
   </head>
   <body class="theme-sidebar" role="application">
     <div id="app-wrapper" class="theme-body">
       <div id="output-container" role="document" aria-live="polite"/>
       <div id="jsterm-wrapper">
-        <xul:notificationbox id="webconsole-notificationbox">
+        <div id="webconsole-notificationbox">
           <div class="jsterm-input-container" style="direction:ltr">
-            <xul:stack class="jsterm-stack-node" flex="1">
-              <xul:textbox class="jsterm-complete-node devtools-monospace"
-                       multiline="true" rows="1" tabindex="-1"/>
-              <xul:textbox class="jsterm-input-node devtools-monospace"
-                       multiline="true" rows="1" tabindex="0"
+            <div class="jsterm-stack-node">
+              <textarea class="jsterm-complete-node devtools-monospace"
+                       tabindex="-1"/>
+              <textarea class="jsterm-input-node devtools-monospace"
+                       rows="1" tabindex="0"
                        aria-autocomplete="list"/>
-            </xul:stack>
+            </div>
           </div>
-        </xul:notificationbox>
+        </div>
       </div>
     </div>
   </body>
 </html>
--- a/devtools/client/webconsole/webpack.config.js
+++ b/devtools/client/webconsole/webpack.config.js
@@ -64,75 +64,49 @@ webpackConfig.resolve = {
   modules: [
     // Make sure webpack is always looking for modules in
     // `webconsole/node_modules` directory first.
     path.resolve(__dirname, "node_modules"), "node_modules"
   ],
   alias: {
     "Services": "devtools-modules/src/Services",
 
-    "devtools/client/webconsole/jsterm": path.join(projectPath, "jsterm-stub"),
+    "devtools/client/webconsole/jsterm": path.join(__dirname, "../../client/shared/webpack/shims/jsterm-stub"),
     "devtools/client/webconsole/utils": path.join(__dirname, "new-console-output/test/fixtures/WebConsoleUtils"),
-    "devtools/client/webconsole/new-console-output": path.join(__dirname, "new-console-output"),
-    "devtools/client/webconsole/webconsole-connection-proxy": path.join(__dirname, "webconsole-connection-proxy"),
-    "devtools/client/webconsole/webconsole-l10n": path.join(__dirname, "webconsole-l10n"),
 
     "devtools/client/shared/vendor/immutable": "immutable",
     "devtools/client/shared/vendor/react": "react",
     "devtools/client/shared/vendor/react-dom": "react-dom",
     "devtools/client/shared/vendor/react-redux": "react-redux",
     "devtools/client/shared/vendor/redux": "redux",
     "devtools/client/shared/vendor/reselect": "reselect",
 
-    "devtools/client/locales": path.join(__dirname, "../../client/locales/en-US"),
-    "toolkit/locales": path.join(__dirname, "../../../toolkit/locales/en-US"),
-    "devtools/shared/locales": path.join(__dirname, "../../shared/locales/en-US"),
-    "devtools/shim/locales": path.join(__dirname, "../../shared/locales/en-US"),
-    "devtools/shared/plural-form": path.join(__dirname, "../../shared/plural-form"),
-    "devtools/shared/l10n": path.join(__dirname, "../../shared/l10n"),
-    "devtools/shared/system": path.join(projectPath, "system-stub"),
+    "devtools/shared/system": path.join(__dirname, "../../client/shared/webpack/shims/system-stub"),
 
-    "devtools/client/framework/devtools": path.join(__dirname, "../../client/shims/devtools"),
+    "devtools/client/framework/devtools": path.join(__dirname, "../../client/shared/webpack/shims/framework-devtools-shim"),
     "devtools/client/framework/menu": "devtools-modules/src/menu",
-    "devtools/client/framework/menu-item": path.join(__dirname, "../../client/framework/menu-item"),
     "devtools/client/sourceeditor/editor": "devtools-source-editor/src/source-editor",
 
-    "devtools/client/shared/redux/middleware/thunk": path.join(__dirname, "../../client/shared/redux/middleware/thunk"),
-    "devtools/client/shared/redux/middleware/debounce": path.join(__dirname, "../../client/shared/redux/middleware/debounce"),
+    "devtools/client/shared/zoom-keys": "devtools-modules/src/zoom-keys",
 
-    "devtools/client/shared/components/reps/reps": path.join(__dirname, "../../client/shared/components/reps/reps"),
-    "devtools/client/shared/components/stack-trace": path.join(__dirname, "../../client/shared/components/stack-trace"),
-    "devtools/client/shared/components/search-box": path.join(__dirname, "../../client/shared/components/search-box"),
-    "devtools/client/shared/components/splitter/draggable": path.join(__dirname, "../../client/shared/components/splitter/draggable"),
-    "devtools/client/shared/components/splitter/split-box": path.join(__dirname, "../../client/shared/components/splitter/split-box"),
-    "devtools/client/shared/components/frame": path.join(__dirname, "../../client/shared/components/frame"),
-    "devtools/client/shared/components/autocomplete-popup": path.join(__dirname, "../../client/shared/components/autocomplete-popup"),
-    "devtools/client/shared/components/tabs/tabbar": path.join(__dirname, "../../client/shared/components/tabs/tabbar"),
-    "devtools/client/shared/components/tabs/tabs": path.join(__dirname, "../../client/shared/components/tabs/tabs"),
-    "devtools/client/shared/components/tree/tree-view": path.join(__dirname, "../../client/shared/components/tree/tree-view"),
-    "devtools/client/shared/components/tree/tree-row": path.join(__dirname, "../../client/shared/components/tree/tree-row"),
-
-    "devtools/client/shared/source-utils": path.join(__dirname, "../../client/shared/source-utils"),
-    "devtools/client/shared/key-shortcuts": path.join(__dirname, "../../client/shared/key-shortcuts"),
-    "devtools/client/shared/keycodes": path.join(__dirname, "../../client/shared/keycodes"),
-    "devtools/client/shared/zoom-keys": "devtools-modules/src/zoom-keys",
-    "devtools/client/shared/curl": path.join(__dirname, "../../client/shared/curl"),
-    "devtools/client/shared/scroll": path.join(__dirname, "../../client/shared/scroll"),
-
-    "devtools/shared/fronts/timeline": path.join(__dirname, "../../shared/shims/fronts/timeline"),
-    "devtools/shared/defer": path.join(__dirname, "../../shared/defer"),
+    "devtools/shared/fronts/timeline": path.join(__dirname, "../../client/shared/webpack/shims/fronts-timeline-shim"),
     "devtools/shared/old-event-emitter": "devtools-modules/src/utils/event-emitter",
     "devtools/shared/client/main": path.join(__dirname, "new-console-output/test/fixtures/ObjectClient"),
-    "devtools/shared/platform/clipboard": path.join(__dirname, "../../shared/platform/content/clipboard"),
-    "devtools/shared/platform/stack": path.join(__dirname, "../../shared/platform/content/stack"),
+    "devtools/shared/platform/clipboard": path.join(__dirname, "../../client/shared/webpack/shims/platform-clipboard-stub"),
+    "devtools/shared/platform/stack": path.join(__dirname, "../../client/shared/webpack/shims/platform-stack-stub"),
 
-    "devtools/client/netmonitor/src/utils/request-utils": path.join(__dirname, "../netmonitor/src/utils/request-utils"),
-    "devtools/client/netmonitor/src/components/tabbox-panel": path.join(__dirname, "../netmonitor/src/components/tabbox-panel"),
-    "devtools/client/netmonitor/src/connector/firefox-data-provider": path.join(__dirname, "../netmonitor/src/connector/firefox-data-provider"),
-    "devtools/client/netmonitor/src/constants": path.join(__dirname, "../netmonitor/src/constants"),
+    // Locales need to be explicitly mapped to the en-US subfolder
+    "toolkit/locales": path.join(__dirname, "../../../toolkit/locales/en-US"),
+    "devtools/client/locales": path.join(__dirname, "../../client/locales/en-US"),
+    "devtools/shared/locales": path.join(__dirname, "../../shared/locales/en-US"),
+    "devtools/shim/locales": path.join(__dirname, "../../shared/locales/en-US"),
+
+    // Unless a path explicitly needs to be rewritten or shimmed, all devtools paths can
+    // be mapped to ../../
+    "devtools": path.join(__dirname, "../../"),
   }
 };
 
 const mappings = [
   [
     /utils\/menu/, "devtools-launchpad/src/components/shared/menu"
   ],
   [
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -25,23 +25,16 @@ this.EXPORTED_SYMBOLS = ["DevToolsLoader
  * Used when the tools should be loaded from the Firefox package itself.
  * This is the default case.
  */
 function BuiltinProvider() {}
 BuiltinProvider.prototype = {
   load: function () {
     const paths = {
       // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-      // Modules here are intended to have one implementation for
-      // chrome, and a separate implementation for content.  Here we
-      // map the directory to the chrome subdirectory, but the content
-      // loader will map to the content subdirectory.  See the
-      // README.md in devtools/shared/platform.
-      "devtools/shared/platform": "resource://devtools/shared/platform/chrome",
-      // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
       "devtools": "resource://devtools",
       // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
       "gcli": "resource://devtools/shared/gcli/source/lib/gcli",
       // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
       "acorn": "resource://devtools/shared/acorn",
       // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
       "acorn/util/walk": "resource://devtools/shared/acorn/walk.js",
       // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
--- a/devtools/shared/builtin-modules.js
+++ b/devtools/shared/builtin-modules.js
@@ -167,16 +167,20 @@ function lazyRequireGetter(obj, property
     enumerable: true
   });
 }
 
 // List of pseudo modules exposed to all devtools modules.
 exports.modules = {
   "Services": Object.create(Services),
   promise,
+  // Expose "chrome" Promise, which aren't related to any document
+  // and so are never frozen, even if the browser loader module which
+  // pull it is destroyed. See bug 1402779.
+  Promise,
   PromiseDebugging,
   ChromeUtils,
   ThreadSafeChromeUtils,
   HeapSnapshot,
   FileReader,
 };
 
 defineLazyGetter(exports.modules, "Debugger", () => {
deleted file mode 100644
--- a/devtools/shared/platform/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-This directory is treated specially by the loaders.
-
-In particular, when running in chrome, a resource like
-"devtools/shared/platform/mumble" will be found in the chrome
-subdirectory; and when running in content, it will be found in the
-content subdirectory.
-
-Outside of tests, it's not ok to require a specific version of a file;
-and there is an eslint test to check for that.  That is,
-require("devtools/shared/platform/client/mumble") is an error.
-
-When adding a new file, you must add two copies, one to chrome and one
-to content.  Otherwise, one case or the other will fail to work.
deleted file mode 100644
--- a/devtools/shared/platform/chrome/moz.build
+++ /dev/null
@@ -1,10 +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/.
-
-DevToolsModules(
-    'clipboard.js',
-    'stack.js',
-)
rename from devtools/shared/platform/chrome/clipboard.js
rename to devtools/shared/platform/clipboard.js
--- a/devtools/shared/platform/moz.build
+++ b/devtools/shared/platform/moz.build
@@ -1,10 +1,10 @@
 # -*- 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/.
 
-DIRS += [
-    'chrome',
-    'content',
-]
+DevToolsModules(
+    'clipboard.js',
+    'stack.js',
+)
rename from devtools/shared/platform/chrome/stack.js
rename to devtools/shared/platform/stack.js
--- a/devtools/shared/worker/loader.js
+++ b/devtools/shared/worker/loader.js
@@ -573,23 +573,16 @@ this.worker = new WorkerDebuggerLoader({
   modules: {
     "Debugger": Debugger,
     "Services": Object.create(null),
     "chrome": chrome,
     "xpcInspector": xpcInspector
   },
   paths: {
     // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-    // Modules here are intended to have one implementation for
-    // chrome, and a separate implementation for content.  Here we
-    // map the directory to the chrome subdirectory, but the content
-    // loader will map to the content subdirectory.  See the
-    // README.md in devtools/shared/platform.
-    "devtools/shared/platform": "resource://devtools/shared/platform/chrome",
-    // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
     "devtools": "resource://devtools",
     // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
     "promise": "resource://gre/modules/Promise-backend.js",
     // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
     "source-map": "resource://devtools/shared/sourcemap/source-map.js",
     // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
     "xpcshell-test": "resource://test"
     // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -357,17 +357,17 @@ ForEachPing(nsIContent* aContent, ForEac
   //       implemented an interface that exposed an enumeration of nsIURIs.
 
   // Make sure we are dealing with either an <A> or <AREA> element in the HTML
   // or XHTML namespace.
   if (!IsElementAnchor(aContent)) {
     return;
   }
 
-  nsCOMPtr<nsIAtom> pingAtom = NS_Atomize("ping");
+  RefPtr<nsIAtom> pingAtom = NS_Atomize("ping");
   if (!pingAtom) {
     return;
   }
 
   nsAutoString value;
   aContent->GetAttr(kNameSpaceID_None, pingAtom, value);
   if (value.IsEmpty()) {
     return;
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -1250,28 +1250,49 @@ KeyframeEffectReadOnly::GetKeyframes(JSC
     }
 
     JS::Rooted<JS::Value> keyframeJSValue(aCx);
     if (!ToJSValue(aCx, keyframeDict, &keyframeJSValue)) {
       aRv.Throw(NS_ERROR_FAILURE);
       return;
     }
 
+    RefPtr<RawServoDeclarationBlock> customProperties;
+    // A workaround for CSS Animations in servo backend, custom properties in
+    // keyframe are stored in a servo's declaration block. Find the declaration
+    // block to resolve CSS variables in the keyframe.
+    // This workaround will be solved by bug 1391537.
+    if (isServo && isCSSAnimation) {
+      for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
+        if (propertyValue.mProperty ==
+              nsCSSPropertyID::eCSSPropertyExtra_variable) {
+          customProperties = propertyValue.mServoDeclarationBlock;
+          break;
+        }
+      }
+    }
+
     JS::Rooted<JSObject*> keyframeObject(aCx, &keyframeJSValue.toObject());
     for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
       nsAutoString stringValue;
       if (isServo) {
+        // Don't serialize the custom properties for this keyframe.
+        if (propertyValue.mProperty ==
+              nsCSSPropertyID::eCSSPropertyExtra_variable) {
+          continue;
+        }
         if (propertyValue.mServoDeclarationBlock) {
           const ServoStyleContext* servoStyleContext =
             styleContext ? styleContext->AsServo() : nullptr;
           Servo_DeclarationBlock_SerializeOneValue(
             propertyValue.mServoDeclarationBlock,
             propertyValue.mProperty,
             &stringValue,
-            servoStyleContext);
+            servoStyleContext,
+            customProperties);
         } else {
           RawServoAnimationValue* value =
             mBaseStyleValuesForServo.GetWeak(propertyValue.mProperty);
 
           if (value) {
             Servo_AnimationValue_Serialize(value,
                                            propertyValue.mProperty,
                                            &stringValue);
--- a/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
+++ b/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
@@ -131,23 +131,31 @@
 }
 
 @keyframes anim-background-size {
   to { background-size: 50%, 6px, contain }
 }
 
 :root {
   --var-100px: 100px;
+  --end-color: rgb(255, 0, 0);
 }
 @keyframes anim-variables {
   to { transform: translate(var(--var-100px), 0) }
 }
 @keyframes anim-variables-shorthand {
   to { margin: var(--var-100px) }
 }
+@keyframes anim-custom-property-in-keyframe {
+  to { --end-color: rgb(0, 255, 0); color: var(--end-color) }
+}
+@keyframes anim-only-custom-property-in-keyframe {
+  from { transform: translate(100px, 0) }
+  to { --not-used: 200px }
+}
 </style>
 <body>
 <script>
 "use strict";
 
 function getKeyframes(e) {
   return e.getAnimations()[0].effect.getKeyframes();
 }
@@ -655,16 +663,18 @@ test(function(t) {
    'animations with background-size properties and missing keyframes');
 
 test(function(t) {
   var div = addDiv(t);
   div.style.animation = 'anim-variables 100s';
 
   var frames = getKeyframes(div);
 
+  assert_equals(frames.length, 2, "number of frames");
+
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       transform: "none" },
     { offset: 1, computedOffset: 1, easing: "ease",
       transform: "translate(100px, 0px)" },
   ];
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
@@ -673,16 +683,18 @@ test(function(t) {
    'animations with CSS variables as keyframe values');
 
 test(function(t) {
   var div = addDiv(t);
   div.style.animation = 'anim-variables-shorthand 100s';
 
   var frames = getKeyframes(div);
 
+  assert_equals(frames.length, 2, "number of frames");
+
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       marginBottom: "0px",
       marginLeft: "0px",
       marginRight: "0px",
       marginTop: "0px" },
     { offset: 1, computedOffset: 1, easing: "ease",
       marginBottom: "100px",
@@ -690,11 +702,52 @@ test(function(t) {
       marginRight: "100px",
       marginTop: "100px" },
   ];
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 }, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
    'animations with CSS variables as keyframe values in a shorthand property');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim-custom-property-in-keyframe 100s';
+
+  var frames = getKeyframes(div);
+
+  assert_equals(frames.length, 2, "number of frames");
+
+  var expected = [
+    { offset: 0, computedOffset: 0, easing: "ease",
+      color: "rgb(0, 0, 0)" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      color: "rgb(0, 255, 0)" },
+  ];
+  for (var i = 0; i < frames.length; i++) {
+    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+  }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+   'animations with a CSS variable which is overriden by the value in keyframe');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim-only-custom-property-in-keyframe 100s';
+
+  var frames = getKeyframes(div);
+
+  assert_equals(frames.length, 2, "number of frames");
+
+  var expected = [
+    { offset: 0, computedOffset: 0, easing: "ease",
+      transform: "translate(100px, 0px)" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      transform: "none" },
+  ];
+  for (var i = 0; i < frames.length; i++) {
+    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+  }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+   'animations with only custom property in a keyframe');
+
 done();
 </script>
 </body>
--- a/dom/base/AnonymousContent.cpp
+++ b/dom/base/AnonymousContent.cpp
@@ -182,17 +182,17 @@ AnonymousContent::SetCutoutRectsForEleme
     frame->SchedulePaint();
   }
 }
 
 Element*
 AnonymousContent::GetElementById(const nsAString& aElementId)
 {
   // This can be made faster in the future if needed.
-  nsCOMPtr<nsIAtom> elementId = NS_Atomize(aElementId);
+  RefPtr<nsIAtom> elementId = NS_Atomize(aElementId);
   for (nsIContent* node = mContentNode; node;
        node = node->GetNextNode(mContentNode)) {
     if (!node->IsElement()) {
       continue;
     }
     nsIAtom* id = node->AsElement()->GetID();
     if (id && id == elementId) {
       return node->AsElement();
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -159,17 +159,17 @@ Attr::GetName(nsAString& aName)
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Attr::GetValue(nsAString& aValue)
 {
   Element* element = GetElement();
   if (element) {
-    nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
+    RefPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
     element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
   }
   else {
     aValue = mValue;
   }
 
   return NS_OK;
 }
@@ -178,17 +178,17 @@ void
 Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
 {
   Element* element = GetElement();
   if (!element) {
     mValue = aValue;
     return;
   }
 
-  nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
+  RefPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
   aRv = element->SetAttr(mNodeInfo->NamespaceID(),
                          nameAtom,
                          mNodeInfo->GetPrefixAtom(),
                          aValue,
                          true);
 }
 
 NS_IMETHODIMP
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -220,18 +220,18 @@ CustomElementRegistry::~CustomElementReg
 {
   mozilla::DropJSObjects(this);
 }
 
 CustomElementDefinition*
 CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
                                                      const nsAString* aIs) const
 {
-  nsCOMPtr<nsIAtom> localNameAtom = NS_Atomize(aLocalName);
-  nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
+  RefPtr<nsIAtom> localNameAtom = NS_Atomize(aLocalName);
+  RefPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
 
   CustomElementDefinition* data = mCustomDefinitions.GetWeak(typeAtom);
   if (data && data->mLocalName == localNameAtom) {
     return data;
   }
 
   return nullptr;
 }
@@ -256,17 +256,17 @@ CustomElementRegistry::LookupCustomEleme
 void
 CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
 {
   mozilla::dom::NodeInfo* info = aElement->NodeInfo();
 
   // Candidate may be a custom element through extension,
   // in which case the custom element type name will not
   // match the element tag name. e.g. <button is="x-button">.
-  nsCOMPtr<nsIAtom> typeName = aTypeName;
+  RefPtr<nsIAtom> typeName = aTypeName;
   if (!typeName) {
     typeName = info->NameAtom();
   }
 
   if (mCustomDefinitions.GetWeak(typeName)) {
     return;
   }
 
@@ -275,18 +275,18 @@ CustomElementRegistry::RegisterUnresolve
   *elem = do_GetWeakReference(aElement);
   aElement->AddStates(NS_EVENT_STATE_UNRESOLVED);
 }
 
 void
 CustomElementRegistry::SetupCustomElement(Element* aElement,
                                           const nsAString* aTypeExtension)
 {
-  nsCOMPtr<nsIAtom> tagAtom = aElement->NodeInfo()->NameAtom();
-  nsCOMPtr<nsIAtom> typeAtom = aTypeExtension ?
+  RefPtr<nsIAtom> tagAtom = aElement->NodeInfo()->NameAtom();
+  RefPtr<nsIAtom> typeAtom = aTypeExtension ?
     NS_Atomize(*aTypeExtension) : tagAtom;
 
   if (aTypeExtension && !aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::is)) {
     // Custom element setup in the parser happens after the "is"
     // attribute is added.
     aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *aTypeExtension, true);
   }
 
@@ -425,17 +425,17 @@ CustomElementRegistry::EnqueueLifecycleC
   }
 
   DocGroup* docGroup = aCustomElement->OwnerDoc()->GetDocGroup();
   if (!docGroup) {
     return;
   }
 
   if (aType == nsIDocument::eAttributeChanged) {
-    nsCOMPtr<nsIAtom> attrName = NS_Atomize(aArgs->name);
+    RefPtr<nsIAtom> attrName = NS_Atomize(aArgs->name);
     if (definition->mObservedAttributes.IsEmpty() ||
         !definition->mObservedAttributes.Contains(attrName)) {
       return;
     }
   }
 
   CustomElementReactionsStack* reactionsStack =
     docGroup->CustomElementReactionsStack();
@@ -571,17 +571,17 @@ CustomElementRegistry::Define(const nsAS
     aRv.ThrowTypeError<MSG_NOT_CONSTRUCTOR>(NS_LITERAL_STRING("Argument 2 of CustomElementRegistry.define"));
     return;
   }
 
   /**
    * 2. If name is not a valid custom element name, then throw a "SyntaxError"
    *    DOMException and abort these steps.
    */
-  nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
+  RefPtr<nsIAtom> nameAtom(NS_Atomize(aName));
   if (!nsContentUtils::IsCustomElementName(nameAtom)) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return;
   }
 
   /**
    * 3. If this CustomElementRegistry contains an entry with name name, then
    *    throw a "NotSupportedError" DOMException and abort these steps.
@@ -613,17 +613,17 @@ CustomElementRegistry::Define(const nsAS
    *    2. If the element interface for extends and the HTML namespace is
    *       HTMLUnknownElement (e.g., if extends does not indicate an element
    *       definition in this specification), then throw a "NotSupportedError"
    *       DOMException.
    *    3. Set localName to extends.
    */
   nsAutoString localName(aName);
   if (aOptions.mExtends.WasPassed()) {
-    nsCOMPtr<nsIAtom> extendsAtom(NS_Atomize(aOptions.mExtends.Value()));
+    RefPtr<nsIAtom> extendsAtom(NS_Atomize(aOptions.mExtends.Value()));
     if (nsContentUtils::IsCustomElementName(extendsAtom)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return;
     }
 
     // bgsound and multicol are unknown html element.
     int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(extendsAtom);
     if (tag == eHTMLTag_userdefined ||
@@ -642,17 +642,17 @@ CustomElementRegistry::Define(const nsAS
    */
   if (mIsCustomDefinitionRunning) {
     aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return;
   }
 
   JS::Rooted<JSObject*> constructorPrototype(cx);
   nsAutoPtr<LifecycleCallbacks> callbacksHolder(new LifecycleCallbacks());
-  nsCOMArray<nsIAtom> observedAttributes;
+  nsTArray<RefPtr<nsIAtom>> observedAttributes;
   { // Set mIsCustomDefinitionRunning.
     /**
      * 9. Set this CustomElementRegistry's element definition is running flag.
      */
     AutoSetRunningFlag as(this);
 
     { // Enter constructor's compartment.
       /**
@@ -773,17 +773,17 @@ CustomElementRegistry::Define(const nsAS
 
   /**
    * 11. Let definition be a new custom element definition with name name,
    *     local name localName, constructor constructor, prototype prototype,
    *     observed attributes observedAttributes, and lifecycle callbacks
    *     lifecycleCallbacks.
    */
   // Associate the definition with the custom element.
-  nsCOMPtr<nsIAtom> localNameAtom(NS_Atomize(localName));
+  RefPtr<nsIAtom> localNameAtom(NS_Atomize(localName));
   LifecycleCallbacks* callbacks = callbacksHolder.forget();
 
   /**
    * 12. Add definition to this CustomElementRegistry.
    */
   if (!mConstructors.put(constructorUnwrapped, nameAtom)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
@@ -824,17 +824,17 @@ CustomElementRegistry::Define(const nsAS
   }
 
 }
 
 void
 CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
                            JS::MutableHandle<JS::Value> aRetVal)
 {
-  nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
+  RefPtr<nsIAtom> nameAtom(NS_Atomize(aName));
   CustomElementDefinition* data = mCustomDefinitions.GetWeak(nameAtom);
 
   if (!data) {
     aRetVal.setUndefined();
     return;
   }
 
   aRetVal.setObject(*data->mConstructor->Callback(aCx));
@@ -845,17 +845,17 @@ CustomElementRegistry::WhenDefined(const
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
   RefPtr<Promise> promise = Promise::Create(global, aRv);
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
+  RefPtr<nsIAtom> nameAtom(NS_Atomize(aName));
   if (!nsContentUtils::IsCustomElementName(nameAtom)) {
     promise->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
     return promise.forget();
   }
 
   if (mCustomDefinitions.GetWeak(nameAtom)) {
     promise->MaybeResolve(JS::UndefinedHandleValue);
     return promise.forget();
@@ -1160,17 +1160,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CustomElementDefinition, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CustomElementDefinition, Release)
 
 
 CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,
                                                  nsIAtom* aLocalName,
                                                  Function* aConstructor,
-                                                 nsCOMArray<nsIAtom>&& aObservedAttributes,
+                                                 nsTArray<RefPtr<nsIAtom>>&& aObservedAttributes,
                                                  JSObject* aPrototype,
                                                  LifecycleCallbacks* aCallbacks,
                                                  uint32_t aDocOrder)
   : mType(aType),
     mLocalName(aLocalName),
     mConstructor(new CustomElementConstructor(aConstructor)),
     mObservedAttributes(Move(aObservedAttributes)),
     mPrototype(aPrototype),
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -97,17 +97,17 @@ struct CustomElementData
     eFailed,
     eCustom
   };
 
   explicit CustomElementData(nsIAtom* aType);
   CustomElementData(nsIAtom* aType, State aState);
   // Custom element type, for <button is="x-button"> or <x-button>
   // this would be x-button.
-  nsCOMPtr<nsIAtom> mType;
+  RefPtr<nsIAtom> mType;
   // Element is being created flag as described in the custom elements spec.
   bool mElementIsBeingCreated;
   // Flag to determine if the created callback has been invoked, thus it
   // determines if other callbacks can be enqueued.
   bool mCreatedCallbackInvoked;
   // Custom element state as described in the custom element spec.
   State mState;
   // custom element reaction queue as described in the custom element spec.
@@ -145,32 +145,32 @@ private:
 struct CustomElementDefinition
 {
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
 
   CustomElementDefinition(nsIAtom* aType,
                           nsIAtom* aLocalName,
                           Function* aConstructor,
-                          nsCOMArray<nsIAtom>&& aObservedAttributes,
+                          nsTArray<RefPtr<nsIAtom>>&& aObservedAttributes,
                           JSObject* aPrototype,
                           mozilla::dom::LifecycleCallbacks* aCallbacks,
                           uint32_t aDocOrder);
 
   // The type (name) for this custom element.
-  nsCOMPtr<nsIAtom> mType;
+  RefPtr<nsIAtom> mType;
 
   // The localname to (e.g. <button is=type> -- this would be button).
-  nsCOMPtr<nsIAtom> mLocalName;
+  RefPtr<nsIAtom> mLocalName;
 
   // The custom element constructor.
   RefPtr<CustomElementConstructor> mConstructor;
 
   // The list of attributes that this custom element observes.
-  nsCOMArray<nsIAtom> mObservedAttributes;
+  nsTArray<RefPtr<nsIAtom>> mObservedAttributes;
 
   // The prototype to use for new custom elements of this type.
   JS::Heap<JSObject *> mPrototype;
 
   // The lifecycle callbacks to call for this custom element.
   UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
 
   // A construction stack. Use nullptr to represent an "already constructed marker".
@@ -406,36 +406,36 @@ private:
    */
   void RegisterUnresolvedElement(Element* aElement,
                                  nsIAtom* aTypeName = nullptr);
 
   void UpgradeCandidates(nsIAtom* aKey,
                          CustomElementDefinition* aDefinition,
                          ErrorResult& aRv);
 
-  typedef nsRefPtrHashtable<nsISupportsHashKey, CustomElementDefinition>
+  typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIAtom>, CustomElementDefinition>
     DefinitionMap;
-  typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
+  typedef nsClassHashtable<nsRefPtrHashKey<nsIAtom>, nsTArray<nsWeakPtr>>
     CandidateMap;
   typedef JS::GCHashMap<JS::Heap<JSObject*>,
-                        nsCOMPtr<nsIAtom>,
+                        RefPtr<nsIAtom>,
                         js::MovableCellHasher<JS::Heap<JSObject*>>,
                         js::SystemAllocPolicy> ConstructorMap;
 
   // Hashtable for custom element definitions in web components.
   // Custom prototypes are stored in the compartment where
   // registerElement was called.
   DefinitionMap mCustomDefinitions;
 
   // Hashtable for looking up definitions by using constructor as key.
   // Custom elements' name are stored here and we need to lookup
   // mCustomDefinitions again to get definitions.
   ConstructorMap mConstructors;
 
-  typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
+  typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIAtom>, Promise>
     WhenDefinedPromiseMap;
   WhenDefinedPromiseMap mWhenDefinedPromiseMap;
 
   // The "upgrade candidates map" from the web components spec. Maps from a
   // namespace id and local name to a list of elements to upgrade if that
   // element is registered as a custom element.
   CandidateMap mCandidatesMap;
 
--- a/dom/base/DOMImplementation.cpp
+++ b/dom/base/DOMImplementation.cpp
@@ -56,17 +56,17 @@ DOMImplementation::CreateDocumentType(co
     return nullptr;
   }
 
   aRv = nsContentUtils::CheckQName(aQualifiedName);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIAtom> name = NS_Atomize(aQualifiedName);
+  RefPtr<nsIAtom> name = NS_Atomize(aQualifiedName);
   if (!name) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
 
   // Indicate that there is no internal subset (not just an empty one)
   RefPtr<DocumentType> docType =
     NS_NewDOMDocumentType(mOwner->NodeInfoManager(), name, aPublicId,
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1263,17 +1263,17 @@ Element::SetAttribute(const nsAString& a
   aError = nsContentUtils::CheckQName(aName, false);
   if (aError.Failed()) {
     return;
   }
 
   nsAutoString nameToUse;
   const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
   if (!name) {
-    nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
+    RefPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
     if (!nameAtom) {
       aError.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
     return;
   }
 
@@ -1344,17 +1344,17 @@ Element::GetAttributeNS(const nsAString&
                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
 
   if (nsid == kNameSpaceID_Unknown) {
     // Unknown namespace means no attribute.
     SetDOMStringToNull(aReturn);
     return;
   }
 
-  nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
+  RefPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
   bool hasAttr = GetAttr(nsid, name, aReturn);
   if (!hasAttr) {
     SetDOMStringToNull(aReturn);
   }
 }
 
 void
 Element::SetAttributeNS(const nsAString& aNamespaceURI,
@@ -1376,17 +1376,17 @@ Element::SetAttributeNS(const nsAString&
                    aValue, true);
 }
 
 void
 Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName,
                            ErrorResult& aError)
 {
-  nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
+  RefPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
   int32_t nsid =
     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
 
   if (nsid == kNameSpaceID_Unknown) {
     // If the namespace ID is unknown, it means there can't possibly be an
     // existing attribute. We would need a known namespace ID to pass into
     // UnsetAttr, so we return early if we don't have one.
@@ -1449,17 +1449,17 @@ Element::HasAttributeNS(const nsAString&
     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
 
   if (nsid == kNameSpaceID_Unknown) {
     // Unknown namespace means no attr...
     return false;
   }
 
-  nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
+  RefPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
   return HasAttr(nsid, name);
 }
 
 already_AddRefed<nsIHTMLCollection>
 Element::GetElementsByClassName(const nsAString& aClassNames)
 {
   return nsContentUtils::GetElementsByClassName(this, aClassNames);
 }
@@ -2623,25 +2623,25 @@ Element::SetAttrAndNotify(int32_t aNames
   }
 
   if (CustomElementRegistry::IsCustomElementEnabled()) {
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
-        nsCOMPtr<nsIAtom> oldValueAtom;
+        RefPtr<nsIAtom> oldValueAtom;
         if (oldValue) {
           oldValueAtom = oldValue->GetAsAtom();
         } else {
           // If there is no old value, get the value of the uninitialized
           // attribute that was swapped with aParsedValue.
           oldValueAtom = aParsedValue.GetAsAtom();
         }
-        nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
+        RefPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
         nsAutoString ns;
         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
 
         LifecycleCallbackArgs args = {
           nsDependentAtomString(aName),
           aModType == nsIDOMMutationEvent::ADDITION ?
             VoidString() : nsDependentAtomString(oldValueAtom),
           nsDependentAtomString(newValueAtom),
@@ -2930,17 +2930,17 @@ Element::UnsetAttr(int32_t aNameSpaceID,
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
         nsAutoString ns;
         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
 
-        nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
+        RefPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
         LifecycleCallbackArgs args = {
           nsDependentAtomString(aName),
           nsDependentAtomString(oldValueAtom),
           VoidString(),
           (ns.IsEmpty() ? VoidString() : ns)
         };
 
         nsContentUtils::EnqueueLifecycleCallback(
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -326,17 +326,17 @@ nsIContent::LookupNamespaceURIInternal(c
   }
 
   if (aNamespacePrefix.EqualsLiteral("xmlns")) {
     // Special-case for xmlns prefix
     aNamespaceURI.AssignLiteral("http://www.w3.org/2000/xmlns/");
     return NS_OK;
   }
 
-  nsCOMPtr<nsIAtom> name;
+  RefPtr<nsIAtom> name;
   if (!aNamespacePrefix.IsEmpty()) {
     name = NS_Atomize(aNamespacePrefix);
     NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
   }
   else {
     name = nsGkAtoms::xmlns;
   }
   // Trace up the content parent chain looking for the namespace
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -749,17 +749,17 @@ already_AddRefed<nsIAtom>
 nsAttrValue::GetAsAtom() const
 {
   switch (Type()) {
     case eString:
       return NS_AtomizeMainThread(GetStringValue());
 
     case eAtom:
       {
-        nsCOMPtr<nsIAtom> atom = GetAtomValue();
+        RefPtr<nsIAtom> atom = GetAtomValue();
         return atom.forget();
       }
 
     default:
       {
         nsAutoString val;
         ToString(val);
         return NS_AtomizeMainThread(val);
@@ -908,17 +908,17 @@ nsAttrValue::HashValue() const
       nsString str;
       ToString(str);
       return HashString(str);
     }
     case eAtomArray:
     {
       uint32_t hash = 0;
       uint32_t count = cont->mValue.mAtomArray->Length();
-      for (nsCOMPtr<nsIAtom> *cur = cont->mValue.mAtomArray->Elements(),
+      for (RefPtr<nsIAtom> *cur = cont->mValue.mAtomArray->Elements(),
                              *end = cur + count;
            cur != end; ++cur) {
         hash = AddToHash(hash, cur->get());
       }
       return hash;
     }
     case eDoubleValue:
     {
@@ -1188,17 +1188,17 @@ nsAttrValue::Contains(nsIAtom* aValue, n
       if (Type() == eAtomArray) {
         AtomArray* array = GetAtomArrayValue();
         if (aCaseSensitive == eCaseMatters) {
           return array->Contains(aValue);
         }
 
         nsDependentAtomString val1(aValue);
 
-        for (nsCOMPtr<nsIAtom> *cur = array->Elements(),
+        for (RefPtr<nsIAtom> *cur = array->Elements(),
                                *end = cur + array->Length();
              cur != end; ++cur) {
           // For performance reasons, don't do a full on unicode case
           // insensitive string comparison. This is only used for quirks mode
           // anyway.
           if (nsContentUtils::EqualsIgnoreASCIICase(val1,
                 nsDependentAtomString(*cur))) {
             return true;
@@ -1238,17 +1238,17 @@ nsAttrValue::Contains(const nsAString& a
   return false;
 }
 
 void
 nsAttrValue::ParseAtom(const nsAString& aValue)
 {
   ResetIfSet();
 
-  nsCOMPtr<nsIAtom> atom = NS_Atomize(aValue);
+  RefPtr<nsIAtom> atom = NS_Atomize(aValue);
   if (atom) {
     SetPtrValueAndType(atom.forget().take(), eAtomBase);
   }
 }
 
 void
 nsAttrValue::ParseAtomArray(const nsAString& aValue)
 {
@@ -1270,17 +1270,17 @@ nsAttrValue::ParseAtomArray(const nsAStr
 
   nsAString::const_iterator start(iter);
 
   // get first - and often only - atom
   do {
     ++iter;
   } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
 
-  nsCOMPtr<nsIAtom> classAtom = NS_AtomizeMainThread(Substring(start, iter));
+  RefPtr<nsIAtom> classAtom = NS_AtomizeMainThread(Substring(start, iter));
   if (!classAtom) {
     Reset();
     return;
   }
 
   // skip whitespace
   while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
     hasSpace = true;
@@ -1791,17 +1791,17 @@ nsAttrValue::SetMiscAtomOrString(const n
     // * We're allowing enumerated values because sometimes the empty
     //   string corresponds to a particular enumerated value, especially
     //   for enumerated values that are not limited enumerated.
     // Add other types as needed.
     NS_ASSERTION(len || Type() == eCSSDeclaration || Type() == eEnum,
                  "Empty string?");
     MiscContainer* cont = GetMiscContainer();
     if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
-      nsCOMPtr<nsIAtom> atom = NS_AtomizeMainThread(*aValue);
+      RefPtr<nsIAtom> atom = NS_AtomizeMainThread(*aValue);
       if (atom) {
         cont->mStringBits =
           reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase;
       }
     } else {
       nsStringBuffer* buf = GetStringBuffer(*aValue).take();
       if (buf) {
         cont->mStringBits = reinterpret_cast<uintptr_t>(buf) | eStringBase;
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -79,17 +79,17 @@ public:
     if (aBuf)
       aBuf->ToString(aBuf->StorageSize()/sizeof(char16_t) - 1, *this);
   }
 };
 
 class nsAttrValue {
   friend struct MiscContainer;
 public:
-  typedef nsTArray< nsCOMPtr<nsIAtom> > AtomArray;
+  typedef nsTArray< RefPtr<nsIAtom> > AtomArray;
 
   // This has to be the same as in ValueBaseType
   enum ValueType {
     eString =       0x00, //   00
                           //   01  this value indicates a 'misc' struct
     eAtom =         0x02, //   10
     eInteger =      0x03, // 0011
     eColor =        0x07, // 0111
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -284,18 +284,18 @@ NS_GetContentList(nsINode* aRootNode,
   auto entry = static_cast<ContentListHashEntry*>
                           (gContentListHashTable->Add(&hashKey, fallible));
   if (entry)
     list = entry->mContentList;
 
   if (!list) {
     // We need to create a ContentList and add it to our new entry, if
     // we have an entry
-    nsCOMPtr<nsIAtom> xmlAtom = NS_Atomize(aTagname);
-    nsCOMPtr<nsIAtom> htmlAtom;
+    RefPtr<nsIAtom> xmlAtom = NS_Atomize(aTagname);
+    RefPtr<nsIAtom> htmlAtom;
     if (aMatchNameSpaceId == kNameSpaceID_Unknown) {
       nsAutoString lowercaseName;
       nsContentUtils::ASCIIToLower(aTagname, lowercaseName);
       htmlAtom = NS_Atomize(lowercaseName);
     } else {
       htmlAtom = xmlAtom;
     }
     list = new nsContentList(aRootNode, aMatchNameSpaceId, htmlAtom, xmlAtom);
@@ -557,17 +557,17 @@ nsContentList::NamedItem(const nsAString
     return nullptr;
   }
 
   BringSelfUpToDate(aDoFlush);
 
   uint32_t i, count = mElements.Length();
 
   // Typically IDs and names are atomized
-  nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+  RefPtr<nsIAtom> name = NS_Atomize(aName);
   NS_ENSURE_TRUE(name, nullptr);
 
   for (i = 0; i < count; i++) {
     nsIContent *content = mElements[i];
     // XXX Should this pass eIgnoreCase?
     if (content &&
         ((content->IsHTMLElement() &&
           content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
--- a/dom/base/nsContentList.h
+++ b/dom/base/nsContentList.h
@@ -467,18 +467,18 @@ protected:
    */
   virtual void RemoveFromCaches() override
   {
     RemoveFromHashtable();
   }
 
   nsINode* mRootNode; // Weak ref
   int32_t mMatchNameSpaceId;
-  nsCOMPtr<nsIAtom> mHTMLMatchAtom;
-  nsCOMPtr<nsIAtom> mXMLMatchAtom;
+  RefPtr<nsIAtom> mHTMLMatchAtom;
+  RefPtr<nsIAtom> mXMLMatchAtom;
 
   /**
    * Function to use to determine whether a piece of content matches
    * our criterion
    */
   nsContentListMatchFunc mFunc;
   /**
    * Cleanup closure data with this.
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -847,17 +847,17 @@ nsContentSink::ProcessMETATag(nsIContent
     // documents.
     if (nsGkAtoms::setcookie->Equals(header) && mDocument->IsCookieAverse()) {
       return NS_OK;
     }
 
     nsAutoString result;
     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     if (!result.IsEmpty()) {
-      nsCOMPtr<nsIAtom> fieldAtom(NS_Atomize(header));
+      RefPtr<nsIAtom> fieldAtom(NS_Atomize(header));
       rv = ProcessHeaderData(fieldAtom, result, aContent);
     }
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
                             nsGkAtoms::handheldFriendly, eIgnoreCase)) {
     nsAutoString result;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -250,19 +250,19 @@ const char kLoadAsData[] = "loadAsData";
 nsIXPConnect *nsContentUtils::sXPConnect;
 nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
 nsIPrincipal *nsContentUtils::sSystemPrincipal;
 nsIPrincipal *nsContentUtils::sNullSubjectPrincipal;
 nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
 nsIIOService *nsContentUtils::sIOService;
 nsIUUIDGenerator *nsContentUtils::sUUIDGenerator;
 nsIConsoleService *nsContentUtils::sConsoleService;
-nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
+nsDataHashtable<nsRefPtrHashKey<nsIAtom>, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
 nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
-nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nullptr;
+nsTArray<RefPtr<nsIAtom>>* nsContentUtils::sUserDefinedEvents = nullptr;
 nsIStringBundleService *nsContentUtils::sStringBundleService;
 nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
 nsIContentPolicy *nsContentUtils::sContentPolicyService;
 bool nsContentUtils::sTriedToGetContentPolicy = false;
 nsILineBreaker *nsContentUtils::sLineBreaker;
 nsIWordBreaker *nsContentUtils::sWordBreaker;
 nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
 uint32_t nsContentUtils::sScriptBlockerCount = 0;
@@ -948,21 +948,21 @@ nsContentUtils::InitializeEventTable() {
 #define NON_IDL_EVENT EVENT
 #include "mozilla/EventNameList.h"
 #undef WINDOW_ONLY_EVENT
 #undef NON_IDL_EVENT
 #undef EVENT
     { nullptr }
   };
 
-  sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>(
+  sAtomEventTable = new nsDataHashtable<nsRefPtrHashKey<nsIAtom>, EventNameMapping>(
       ArrayLength(eventArray));
   sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>(
       ArrayLength(eventArray));
-  sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
+  sUserDefinedEvents = new nsTArray<RefPtr<nsIAtom>>(64);
 
   // Subtract one from the length because of the trailing null
   for (uint32_t i = 0; i < ArrayLength(eventArray) - 1; ++i) {
     MOZ_ASSERT(!sAtomEventTable->Lookup(eventArray[i].mAtom),
                "Double-defining event name; fix your EventNameList.h");
     sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]);
     if (ShouldAddEventToStringEventTable(eventArray[i])) {
       sStringEventTable->Put(
@@ -3411,17 +3411,17 @@ nsContentUtils::GetNodeInfoFromQName(con
   NS_ENSURE_SUCCESS(rv, rv);
 
   int32_t nsID;
   sNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsID);
   if (colon) {
     const char16_t* end;
     qName.EndReading(end);
 
-    nsCOMPtr<nsIAtom> prefix =
+    RefPtr<nsIAtom> prefix =
       NS_AtomizeMainThread(Substring(qName.get(), colon));
 
     rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
                                        nsID, aNodeType, aNodeInfo);
   }
   else {
     rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID,
                                        aNodeType, aNodeInfo);
@@ -4381,28 +4381,28 @@ nsContentUtils::GetEventMessageAndAtom(c
   if (sStringEventTable->Get(aName, &mapping)) {
     *aEventMessage =
       mapping.mEventClassID == aEventClassID ? mapping.mMessage :
                                                eUnidentifiedEvent;
     return mapping.mAtom;
   }
 
   // If we have cached lots of user defined event names, clear some of them.
-  if (sUserDefinedEvents->Count() > 127) {
-    while (sUserDefinedEvents->Count() > 64) {
-      nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
+  if (sUserDefinedEvents->Length() > 127) {
+    while (sUserDefinedEvents->Length() > 64) {
+      nsIAtom* first = sUserDefinedEvents->ElementAt(0);
       sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
-      sUserDefinedEvents->RemoveObjectAt(0);
+      sUserDefinedEvents->RemoveElementAt(0);
     }
   }
 
   *aEventMessage = eUnidentifiedEvent;
-  nsCOMPtr<nsIAtom> atom =
+  RefPtr<nsIAtom> atom =
     NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
-  sUserDefinedEvents->AppendObject(atom);
+  sUserDefinedEvents->AppendElement(atom);
   mapping.mAtom = atom;
   mapping.mMessage = eUnidentifiedEvent;
   mapping.mType = EventNameType_None;
   mapping.mEventClassID = eBasicEventClass;
   // This is a slow hashtable call, but at least we cache the result for the
   // following calls. Because GetEventMessageAndAtomForListener utilizes
   // sStringEventTable, it needs to know in which cases sStringEventTable
   // doesn't contain the information it needs so that it can use
@@ -4419,17 +4419,17 @@ nsContentUtils::GetEventMessageAndAtomFo
                                                   nsIAtom** aOnName)
 {
   // Because of SVG/SMIL sStringEventTable contains a subset of the event names
   // comparing to the sAtomEventTable. However, usually sStringEventTable
   // contains the information we need, so in order to reduce hashtable
   // lookups, start from it.
   EventNameMapping mapping;
   EventMessage msg = eUnidentifiedEvent;
-  nsCOMPtr<nsIAtom> atom;
+  RefPtr<nsIAtom> atom;
   if (sStringEventTable->Get(aName, &mapping)) {
     if (mapping.mMaybeSpecialSVGorSMILEvent) {
       // Try the atom version so that we should get the right message for
       // SVG/SMIL.
       atom = NS_AtomizeMainThread(NS_LITERAL_STRING("on") + aName);
       msg = GetEventMessage(atom);
     } else {
       atom = mapping.mAtom;
@@ -4625,17 +4625,17 @@ nsContentUtils::MatchElementId(nsIConten
 
 /* static */
 Element *
 nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
 {
   NS_PRECONDITION(!aId.IsEmpty(), "Will match random elements");
 
   // ID attrs are generally stored as atoms, so just atomize this up front
-  nsCOMPtr<nsIAtom> id(NS_Atomize(aId));
+  RefPtr<nsIAtom> id(NS_Atomize(aId));
   if (!id) {
     // OOM, so just bail
     return nullptr;
   }
 
   return MatchElementId(aContent, id);
 }
 
@@ -5819,17 +5819,17 @@ static void ProcessViewportToken(nsIDocu
     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
                                                         true);
   const nsAString &value =
     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
                                                         true);
 
   /* Check for known keys. If we find a match, insert the appropriate
    * information into the document header. */
-  nsCOMPtr<nsIAtom> key_atom = NS_Atomize(key);
+  RefPtr<nsIAtom> key_atom = NS_Atomize(key);
   if (key_atom == nsGkAtoms::height)
     aDocument->SetHeaderData(nsGkAtoms::viewport_height, value);
   else if (key_atom == nsGkAtoms::width)
     aDocument->SetHeaderData(nsGkAtoms::viewport_width, value);
   else if (key_atom == nsGkAtoms::initial_scale)
     aDocument->SetHeaderData(nsGkAtoms::viewport_initial_scale, value);
   else if (key_atom == nsGkAtoms::minimum_scale)
     aDocument->SetHeaderData(nsGkAtoms::viewport_minimum_scale, value);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -3285,19 +3285,19 @@ private:
 
   static nsNameSpaceManager *sNameSpaceManager;
 
   static nsIIOService *sIOService;
   static nsIUUIDGenerator *sUUIDGenerator;
 
   static nsIConsoleService* sConsoleService;
 
-  static nsDataHashtable<nsISupportsHashKey, EventNameMapping>* sAtomEventTable;
+  static nsDataHashtable<nsRefPtrHashKey<nsIAtom>, EventNameMapping>* sAtomEventTable;
   static nsDataHashtable<nsStringHashKey, EventNameMapping>* sStringEventTable;
-  static nsCOMArray<nsIAtom>* sUserDefinedEvents;
+  static nsTArray<RefPtr<nsIAtom>>* sUserDefinedEvents;
 
   static nsIStringBundleService* sStringBundleService;
   static nsIStringBundle* sStringBundles[PropertiesFile_COUNT];
 
   static nsIContentPolicy* sContentPolicyService;
   static bool sTriedToGetContentPolicy;
 
   static nsILineBreaker* sLineBreaker;
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -678,17 +678,17 @@ nsDOMMutationObserver::Observe(nsINode& 
   if (aOptions.mCharacterDataOldValue.WasPassed() &&
       aOptions.mCharacterDataOldValue.Value() &&
       aOptions.mCharacterData.WasPassed() &&
       !aOptions.mCharacterData.Value()) {
     aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     return;
   }
 
-  nsCOMArray<nsIAtom> filters;
+  nsTArray<RefPtr<nsIAtom>> filters;
   bool allAttrs = true;
   if (aOptions.mAttributeFilter.WasPassed()) {
     allAttrs = false;
     const mozilla::dom::Sequence<nsString>& filtersAsString =
       aOptions.mAttributeFilter.Value();
     uint32_t len = filtersAsString.Length();
     filters.SetCapacity(len);
 
@@ -762,28 +762,28 @@ nsDOMMutationObserver::GetObservingInfo(
     info.mChildList = mr->ChildList();
     info.mAttributes.Construct(mr->Attributes());
     info.mCharacterData.Construct(mr->CharacterData());
     info.mSubtree = mr->Subtree();
     info.mAttributeOldValue.Construct(mr->AttributeOldValue());
     info.mCharacterDataOldValue.Construct(mr->CharacterDataOldValue());
     info.mNativeAnonymousChildList = mr->NativeAnonymousChildList();
     info.mAnimations = mr->Animations();
-    nsCOMArray<nsIAtom>& filters = mr->AttributeFilter();
-    if (filters.Count()) {
+    nsTArray<RefPtr<nsIAtom>>& filters = mr->AttributeFilter();
+    if (filters.Length()) {
       info.mAttributeFilter.Construct();
       mozilla::dom::Sequence<nsString>& filtersAsStrings =
         info.mAttributeFilter.Value();
-      nsString* strings = filtersAsStrings.AppendElements(filters.Count(),
+      nsString* strings = filtersAsStrings.AppendElements(filters.Length(),
                                                           mozilla::fallible);
       if (!strings) {
         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
         return;
       }
-      for (int32_t j = 0; j < filters.Count(); ++j) {
+      for (size_t j = 0; j < filters.Length(); ++j) {
         filters[j]->ToString(strings[j]);
       }
     }
     info.mObservedNode = mr->Target();
   }
 }
 
 // static
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -106,18 +106,18 @@ public:
   }
 
   void GetChangedAnimations(AnimationArray& aRetVal) const
   {
     aRetVal = mChangedAnimations;
   }
 
   nsCOMPtr<nsINode>             mTarget;
-  nsCOMPtr<nsIAtom>             mType;
-  nsCOMPtr<nsIAtom>             mAttrName;
+  RefPtr<nsIAtom>             mType;
+  RefPtr<nsIAtom>             mAttrName;
   nsString                      mAttrNamespace;
   nsString                      mPrevValue;
   RefPtr<nsSimpleContentList> mAddedNodes;
   RefPtr<nsSimpleContentList> mRemovedNodes;
   nsCOMPtr<nsINode>             mPreviousSibling;
   nsCOMPtr<nsINode>             mNextSibling;
   AnimationArray                mAddedAnimations;
   AnimationArray                mRemovedAnimations;
@@ -212,18 +212,18 @@ public:
                    : mAttributeOldValue;
   }
   void SetAttributeOldValue(bool aOldValue)
   {
     NS_ASSERTION(!mParent, "Shouldn't have parent");
     mAttributeOldValue = aOldValue;
   }
 
-  nsCOMArray<nsIAtom>& AttributeFilter() { return mAttributeFilter; }
-  void SetAttributeFilter(nsCOMArray<nsIAtom>&& aFilter)
+  nsTArray<RefPtr<nsIAtom>>& AttributeFilter() { return mAttributeFilter; }
+  void SetAttributeFilter(nsTArray<RefPtr<nsIAtom>>&& aFilter)
   {
     NS_ASSERTION(!mParent, "Shouldn't have parent");
     mAttributeFilter.Clear();
     mAttributeFilter = mozilla::Move(aFilter);
   }
 
   void AddClone(nsMutationReceiverBase* aClone)
   {
@@ -300,18 +300,18 @@ protected:
     if (AllAttributes()) {
       return true;
     }
 
     if (aNameSpaceID != kNameSpaceID_None) {
       return false;
     }
 
-    nsCOMArray<nsIAtom>& filters = AttributeFilter();
-    for (int32_t i = 0; i < filters.Count(); ++i) {
+    nsTArray<RefPtr<nsIAtom>>& filters = AttributeFilter();
+    for (size_t i = 0; i < filters.Length(); ++i) {
       if (filters[i] == aAttr) {
         return true;
       }
     }
     return false;
   }
 
   // The target for the MutationObserver.observe() method.
@@ -331,17 +331,17 @@ private:
   bool                               mChildList;
   bool                               mCharacterData;
   bool                               mCharacterDataOldValue;
   bool                               mNativeAnonymousChildList;
   bool                               mAttributes;
   bool                               mAllAttributes;
   bool                               mAttributeOldValue;
   bool                               mAnimations;
-  nsCOMArray<nsIAtom>                mAttributeFilter;
+  nsTArray<RefPtr<nsIAtom>>          mAttributeFilter;
 };
 
 
 class nsMutationReceiver : public nsMutationReceiverBase
 {
 protected:
   virtual ~nsMutationReceiver() { Disconnect(false); }
 
--- a/dom/base/nsDOMTokenList.h
+++ b/dom/base/nsDOMTokenList.h
@@ -83,25 +83,25 @@ public:
   void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv);
   void Stringify(nsAString& aResult);
 
 protected:
   virtual ~nsDOMTokenList();
 
   nsresult CheckToken(const nsAString& aStr);
   nsresult CheckTokens(const nsTArray<nsString>& aStr);
-  void RemoveDuplicatesInternal(nsTArray<nsCOMPtr<nsIAtom>>* aArray,
+  void RemoveDuplicatesInternal(nsTArray<RefPtr<nsIAtom>>* aArray,
                                 uint32_t aStart);
   void AddInternal(const nsAttrValue* aAttr,
                    const nsTArray<nsString>& aTokens);
   void RemoveInternal(const nsAttrValue* aAttr,
                       const nsTArray<nsString>& aTokens);
   void ReplaceInternal(const nsAttrValue* aAttr,
                        const nsAString& aToken,
                        const nsAString& aNewToken);
   inline const nsAttrValue* GetParsedAttr();
 
   nsCOMPtr<Element> mElement;
-  nsCOMPtr<nsIAtom> mAttrAtom;
+  RefPtr<nsIAtom> mAttrAtom;
   const mozilla::dom::DOMTokenListSupportedTokenArray mSupportedTokens;
 };
 
 #endif // nsDOMTokenList_h___
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -324,17 +324,17 @@ nsDOMWindowUtils::GetDocCharsetIsForced(
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
                                       nsAString& aValue)
 {
   nsIDocument* doc = GetDocument();
   if (doc) {
-    nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+    RefPtr<nsIAtom> name = NS_Atomize(aName);
     doc->GetHeaderData(name, aValue);
     return NS_OK;
   }
 
   aValue.Truncate();
   return NS_OK;
 }
 
@@ -2966,17 +2966,17 @@ nsDOMWindowUtils::GetUnanimatedComputedS
     return NS_ERROR_INVALID_ARG;
   }
 
   nsIPresShell* shell = GetPresShell();
   if (!shell) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIAtom> pseudo = nsCSSPseudoElements::GetPseudoAtom(aPseudoElement);
+  RefPtr<nsIAtom> pseudo = nsCSSPseudoElements::GetPseudoAtom(aPseudoElement);
   RefPtr<nsStyleContext> styleContext =
     nsComputedDOMStyle::GetUnanimatedStyleContextNoFlush(element,
                                                          pseudo, shell);
 
   if (styleContext->IsServo()) {
     RefPtr<RawServoAnimationValue> value =
       Servo_ComputedValues_ExtractAnimationValue(styleContext->AsServo(),
                                                  propertyID).Consume();
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -595,17 +595,17 @@ public:
   {
     return mElements.SafeElementAt(aIndex)->AsElement();
   }
 
   virtual Element* GetFirstNamedElement(const nsAString& aName,
                                         bool& aFound) override
   {
     aFound = false;
-    nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+    RefPtr<nsIAtom> name = NS_Atomize(aName);
     for (uint32_t i = 0; i < mElements.Length(); i++) {
       MOZ_DIAGNOSTIC_ASSERT(mElements[i]);
       Element* element = mElements[i]->AsElement();
       if (element->GetID() == name ||
           (element->HasName() &&
            element->GetParsedAttr(nsGkAtoms::name)->GetAtomValue() == name)) {
         aFound = true;
         return element;
@@ -5968,17 +5968,17 @@ nsDocument::GetCustomElementRegistry()
 static CSSPseudoElementType
 GetPseudoElementType(const nsString& aString, ErrorResult& aRv)
 {
   MOZ_ASSERT(!aString.IsEmpty(), "GetPseudoElementType aString should be non-null");
   if (aString.Length() <= 2 || aString[0] != ':' || aString[1] != ':') {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return CSSPseudoElementType::NotPseudo;
   }
-  nsCOMPtr<nsIAtom> pseudo = NS_Atomize(Substring(aString, 1));
+  RefPtr<nsIAtom> pseudo = NS_Atomize(Substring(aString, 1));
   return nsCSSPseudoElements::GetPseudoType(pseudo,
       nsCSSProps::EnabledState::eInUASheets);
 }
 
 already_AddRefed<Element>
 nsDocument::CreateElement(const nsAString& aTagName,
                           const ElementCreationOptionsOrString& aOptions,
                           ErrorResult& rv)
@@ -6307,17 +6307,17 @@ nsDocument::CustomElementConstructor(JSC
     return true;
   }
 
   RefPtr<mozilla::dom::CustomElementRegistry> registry = window->CustomElements();
   if (!registry) {
     return true;
   }
 
-  nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
+  RefPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
   CustomElementDefinition* definition =
     registry->mCustomDefinitions.GetWeak(typeAtom);
   if (!definition) {
     return true;
   }
 
   RefPtr<Element> element;
 
@@ -7002,17 +7002,17 @@ nsDocument::GetAnonymousElementByAttribu
   return NS_OK;
 }
 
 Element*
 nsIDocument::GetAnonymousElementByAttribute(Element& aElement,
                                             const nsAString& aAttrName,
                                             const nsAString& aAttrValue)
 {
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttrName);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttrName);
 
   return GetAnonymousElementByAttribute(&aElement, attribute, aAttrValue);
 }
 
 
 NS_IMETHODIMP
 nsDocument::GetAnonymousNodes(nsIDOMElement* aElement,
                               nsIDOMNodeList** aResult)
@@ -7408,17 +7408,17 @@ nsDocument::GetBoxObjectFor(Element* aEl
   RefPtr<BoxObject> boxObject;
   auto entry = mBoxObjectTable->LookupForAdd(aElement);
   if (entry) {
     boxObject = entry.Data();
     return boxObject.forget();
   }
 
   int32_t namespaceID;
-  nsCOMPtr<nsIAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID);
+  RefPtr<nsIAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID);
 #ifdef MOZ_XUL
   if (namespaceID == kNameSpaceID_XUL) {
     if (tag == nsGkAtoms::browser ||
         tag == nsGkAtoms::editor ||
         tag == nsGkAtoms::iframe) {
       boxObject = new ContainerBoxObject();
     } else if (tag == nsGkAtoms::menu) {
       boxObject = new MenuBoxObject();
@@ -8706,17 +8706,17 @@ nsDocument::RetrieveRelevantHeaders(nsIC
     };
 
     nsAutoCString headerVal;
     const char *const *name = headers;
     while (*name) {
       rv =
         httpChannel->GetResponseHeader(nsDependentCString(*name), headerVal);
       if (NS_SUCCEEDED(rv) && !headerVal.IsEmpty()) {
-        nsCOMPtr<nsIAtom> key = NS_Atomize(*name);
+        RefPtr<nsIAtom> key = NS_Atomize(*name);
         SetHeaderData(key, NS_ConvertASCIItoUTF16(headerVal));
       }
       ++name;
     }
   } else {
     nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(aChannel);
     if (fileChannel) {
       nsCOMPtr<nsIFile> file;
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -139,17 +139,17 @@ public:
   {
   }
 
   ~nsDocHeaderData(void)
   {
     delete mNext;
   }
 
-  nsCOMPtr<nsIAtom> mField;
+  RefPtr<nsIAtom> mField;
   nsString          mData;
   nsDocHeaderData*  mNext;
 };
 
 class nsDOMStyleSheetList : public mozilla::dom::StyleSheetList,
                             public nsStubDocumentObserver
 {
 public:
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -292,17 +292,17 @@ nsGenericDOMDataNode::SetTextInternal(ui
   nsIDocument *document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
 
   bool haveMutationListeners = aNotify &&
     nsContentUtils::HasMutationListeners(this,
       NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED,
       this);
 
-  nsCOMPtr<nsIAtom> oldValue;
+  RefPtr<nsIAtom> oldValue;
   if (haveMutationListeners) {
     oldValue = GetCurrentValueAtom();
   }
 
   if (aNotify) {
     CharacterDataChangeInfo info = {
       aOffset == textLength,
       aOffset,
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -806,17 +806,17 @@ SetUserDataProperty(uint16_t aCategory, 
 }
 
 nsresult
 nsINode::SetUserData(const nsAString &aKey, nsIVariant *aData, nsIVariant **aResult)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetSetUserData);
   *aResult = nullptr;
 
-  nsCOMPtr<nsIAtom> key = NS_Atomize(aKey);
+  RefPtr<nsIAtom> key = NS_Atomize(aKey);
   if (!key) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv;
   void *data;
   if (aData) {
     rv = SetUserDataProperty(DOM_USER_DATA, this, key, aData, &data);
@@ -859,17 +859,17 @@ nsINode::SetUserData(JSContext* aCx, con
   aError = nsContentUtils::XPConnect()->VariantToJS(aCx, GetWrapper(), oldData,
                                                     aRetval);
 }
 
 nsIVariant*
 nsINode::GetUserData(const nsAString& aKey)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetSetUserData);
-  nsCOMPtr<nsIAtom> key = NS_Atomize(aKey);
+  RefPtr<nsIAtom> key = NS_Atomize(aKey);
   if (!key) {
     return nullptr;
   }
 
   return static_cast<nsIVariant*>(GetProperty(DOM_USER_DATA, key));
 }
 
 void
--- a/dom/base/nsIdentifierMapEntry.h
+++ b/dom/base/nsIdentifierMapEntry.h
@@ -54,17 +54,17 @@ public:
     }
 
     AtomOrString(AtomOrString&& aOther)
       : mAtom(aOther.mAtom.forget())
       , mString(aOther.mString)
     {
     }
 
-    nsCOMPtr<nsIAtom> mAtom;
+    RefPtr<nsIAtom> mAtom;
     const nsString mString;
   };
 
   typedef const AtomOrString& KeyType;
   typedef const AtomOrString* KeyTypePointer;
 
   typedef mozilla::dom::Element Element;
   typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -94,17 +94,17 @@ nsNameSpaceManager::RegisterNameSpace(co
                                       int32_t& aNameSpaceID)
 {
   if (aURI.IsEmpty()) {
     aNameSpaceID = kNameSpaceID_None; // xmlns="", see bug 75700 for details
 
     return NS_OK;
   }
 
-  nsCOMPtr<nsIAtom> atom = NS_Atomize(aURI);
+  RefPtr<nsIAtom> atom = NS_Atomize(aURI);
   nsresult rv = NS_OK;
   if (!mURIToIDTable.Get(atom, &aNameSpaceID)) {
     aNameSpaceID = mURIArray.Length();
 
     rv = AddNameSpace(atom.forget(), aNameSpaceID);
     if (NS_FAILED(rv)) {
       aNameSpaceID = kNameSpaceID_Unknown;
     }
@@ -136,17 +136,17 @@ nsNameSpaceManager::GetNameSpaceURI(int3
 int32_t
 nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI,
                                    bool aInChromeDoc)
 {
   if (aURI.IsEmpty()) {
     return kNameSpaceID_None; // xmlns="", see bug 75700 for details
   }
 
-  nsCOMPtr<nsIAtom> atom = NS_Atomize(aURI);
+  RefPtr<nsIAtom> atom = NS_Atomize(aURI);
   return GetNameSpaceID(atom, aInChromeDoc);
 }
 
 int32_t
 nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI,
                                    bool aInChromeDoc)
 {
   if (aURI == nsGkAtoms::_empty) {
@@ -229,34 +229,34 @@ nsNameSpaceManager::HasElementCreator(in
          aNameSpaceID == kNameSpaceID_MathML ||
          aNameSpaceID == kNameSpaceID_SVG ||
          false;
 }
 
 nsresult nsNameSpaceManager::AddNameSpace(already_AddRefed<nsIAtom> aURI,
                                           const int32_t aNameSpaceID)
 {
-  nsCOMPtr<nsIAtom> uri = aURI;
+  RefPtr<nsIAtom> uri = aURI;
   if (aNameSpaceID < 0) {
     // We've wrapped...  Can't do anything else here; just bail.
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   MOZ_ASSERT(aNameSpaceID == (int32_t) mURIArray.Length());
   mURIArray.AppendElement(uri.forget());
   mURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
 
   return NS_OK;
 }
 
 nsresult
 nsNameSpaceManager::AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI,
                                          const int32_t aNameSpaceID)
 {
-  nsCOMPtr<nsIAtom> uri = aURI;
+  RefPtr<nsIAtom> uri = aURI;
   if (aNameSpaceID < 0) {
     // We've wrapped...  Can't do anything else here; just bail.
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   MOZ_ASSERT(aNameSpaceID == (int32_t) mURIArray.Length());
   mURIArray.AppendElement(uri.forget());
   mDisabledURIToIDTable.Put(mURIArray.LastElement(), aNameSpaceID);
--- a/dom/base/nsNameSpaceManager.h
+++ b/dom/base/nsNameSpaceManager.h
@@ -68,16 +68,16 @@ public:
   bool mSVGDisabled;
 
 private:
   bool Init();
   nsresult AddNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID);
   nsresult AddDisabledNameSpace(already_AddRefed<nsIAtom> aURI, const int32_t aNameSpaceID);
   ~nsNameSpaceManager() {};
 
-  nsDataHashtable<nsISupportsHashKey, int32_t> mURIToIDTable;
-  nsDataHashtable<nsISupportsHashKey, int32_t> mDisabledURIToIDTable;
-  nsTArray<nsCOMPtr<nsIAtom>> mURIArray;
+  nsDataHashtable<nsRefPtrHashKey<nsIAtom>, int32_t> mURIToIDTable;
+  nsDataHashtable<nsRefPtrHashKey<nsIAtom>, int32_t> mDisabledURIToIDTable;
+  nsTArray<RefPtr<nsIAtom>> mURIArray;
 
   static mozilla::StaticRefPtr<nsNameSpaceManager> sInstance;
 };
 
 #endif // nsNameSpaceManager_h___
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -276,17 +276,17 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
                                int32_t aNamespaceID, uint16_t aNodeType,
                                NodeInfo** aNodeInfo)
 {
 #ifdef DEBUG
   {
-    nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
+    RefPtr<nsIAtom> nameAtom = NS_Atomize(aName);
     CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
   }
 #endif
 
   NodeInfo::NodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
 
   uint32_t index =
     GetNodeInfoInnerHashValue(&tmpKey) % RECENTLY_USED_NODEINFOS_SIZE;
@@ -302,17 +302,17 @@ nsNodeInfoManager::GetNodeInfo(const nsA
   if (node) {
     RefPtr<NodeInfo> nodeInfo = static_cast<NodeInfo*>(node);
     mRecentlyUsedNodeInfos[index] = nodeInfo;
     nodeInfo.forget(aNodeInfo);
 
     return NS_OK;
   }
 
-  nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
+  RefPtr<nsIAtom> nameAtom = NS_Atomize(aName);
   NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
 
   RefPtr<NodeInfo> newNodeInfo =
     new NodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this);
   NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
   PLHashEntry *he;
   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -43,17 +43,17 @@ public:
 
   bool Equals(nsIAtom *aPropertyName)
   {
     return mName == aPropertyName;
   }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
-  nsCOMPtr<nsIAtom>  mName;           // property name
+  RefPtr<nsIAtom>  mName;           // property name
   PLDHashTable       mObjectValueMap; // map of object/value pairs
   NSPropertyDtorFunc mDtorFunc;       // property specific value dtor function
   void*              mDtorData;       // pointer to pass to dtor
   bool               mTransfer;       // whether to transfer in
                                       // TransferOrDeleteAllPropertiesFor
 
   PropertyList*      mNext;
 };
--- a/dom/base/nsReferencedElement.cpp
+++ b/dom/base/nsReferencedElement.cpp
@@ -110,17 +110,17 @@ nsReferencedElement::Reset(nsIContent* a
       if (observer) {
         load->AddObserver(observer);
       }
       // Keep going so we set up our watching stuff a bit
     }
   }
 
   if (aWatch) {
-    nsCOMPtr<nsIAtom> atom = NS_Atomize(ref);
+    RefPtr<nsIAtom> atom = NS_Atomize(ref);
     if (!atom)
       return;
     atom.swap(mWatchID);
   }
 
   mReferencingImage = aReferenceImage;
 
   HaveNewDocument(doc, aWatch, ref);
@@ -132,17 +132,17 @@ nsReferencedElement::ResetWithID(nsICont
 {
   nsIDocument *doc = aFromContent->OwnerDoc();
   if (!doc)
     return;
 
   // XXX Need to take care of XBL/XBL2
 
   if (aWatch) {
-    nsCOMPtr<nsIAtom> atom = NS_Atomize(aID);
+    RefPtr<nsIAtom> atom = NS_Atomize(aID);
     if (!atom)
       return;
     atom.swap(mWatchID);
   }
 
   mReferencingImage = false;
 
   HaveNewDocument(doc, aWatch, aID);
--- a/dom/base/nsReferencedElement.h
+++ b/dom/base/nsReferencedElement.h
@@ -177,17 +177,17 @@ private:
     virtual ~DocumentLoadNotification() {}
 
     virtual void SetTo(Element* aTo) override { }
 
     nsString mRef;
   };
   friend class DocumentLoadNotification;
 
-  nsCOMPtr<nsIAtom>      mWatchID;
+  RefPtr<nsIAtom>      mWatchID;
   nsCOMPtr<nsIDocument>  mWatchDocument;
   RefPtr<Element> mElement;
   RefPtr<Notification> mPendingNotification;
   bool                   mReferencingImage;
 };
 
 inline void
 ImplCycleCollectionUnlink(nsReferencedElement& aField)
--- a/dom/base/nsTextNode.cpp
+++ b/dom/base/nsTextNode.cpp
@@ -85,17 +85,17 @@ private:
 
   // This doesn't need to be a strong pointer because it's only non-null
   // while we're bound to the document tree, and it points to an ancestor
   // so the ancestor must be bound to the document tree the whole time
   // and can't be deleted.
   nsIContent* mGrandparent;
   // What attribute we're showing
   int32_t mNameSpaceID;
-  nsCOMPtr<nsIAtom> mAttrName;
+  RefPtr<nsIAtom> mAttrName;
 };
 
 nsTextNode::~nsTextNode()
 {
 }
 
 // Use the CC variant of this, even though this class does not define
 // a new CC participant, to make QIing to the CC interfaces faster.
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -919,23 +919,23 @@ nsIAtom** const kURLAttributesMathML[] =
   &nsGkAtoms::href,
   &nsGkAtoms::src,
   &nsGkAtoms::cdgroup_,
   &nsGkAtoms::altimg_,
   &nsGkAtoms::definitionURL_,
   nullptr
 };
 
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsHTML = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesHTML = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sPresAttributesHTML = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsSVG = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesSVG = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsMathML = nullptr;
-nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesMathML = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sElementsHTML = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sAttributesHTML = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sPresAttributesHTML = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sElementsSVG = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sAttributesSVG = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sElementsMathML = nullptr;
+nsTHashtable<nsRefPtrHashKey<nsIAtom>>* nsTreeSanitizer::sAttributesMathML = nullptr;
 nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
 
 nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
  : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle)
  , mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments)
  , mDropNonCSSPresentation(aFlags &
      nsIParserUtils::SanitizerDropNonCSSPresentation)
  , mDropForms(aFlags & nsIParserUtils::SanitizerDropForms)
@@ -1140,28 +1140,28 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
       }
     }
   }
   return didSanitize;
 }
 
 void
 nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
-                                    nsTHashtable<nsISupportsHashKey>* aAllowed,
+                                    nsTHashtable<nsRefPtrHashKey<nsIAtom>>* aAllowed,
                                     nsIAtom*** aURLs,
                                     bool aAllowXLink,
                                     bool aAllowStyle,
                                     bool aAllowDangerousSrc)
 {
   uint32_t ac = aElement->GetAttrCount();
 
   for (int32_t i = ac - 1; i >= 0; --i) {
     const nsAttrName* attrName = aElement->GetAttrNameAt(i);
     int32_t attrNs = attrName->NamespaceID();
-    nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
+    RefPtr<nsIAtom> attrLocal = attrName->LocalName();
 
     if (kNameSpaceID_None == attrNs) {
       if (aAllowStyle && nsGkAtoms::style == attrLocal) {
         nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
         nsIDocument* document = aElement->OwnerDoc();
         // Pass the CSS Loader object to the parser, to allow parser error
         // reports to include the outer window ID.
         nsCSSParser parser(document->CSSLoader());
@@ -1473,57 +1473,64 @@ nsTreeSanitizer::SanitizeChildren(nsINod
 }
 
 void
 nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
 {
   const nsAttrName* attrName;
   while ((attrName = aElement->GetAttrNameAt(0))) {
     int32_t attrNs = attrName->NamespaceID();
-    nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
+    RefPtr<nsIAtom> attrLocal = attrName->LocalName();
     aElement->UnsetAttr(attrNs, attrLocal, false);
   }
 }
 
 void
 nsTreeSanitizer::InitializeStatics()
 {
   NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
 
-  sElementsHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsHTML));
+  sElementsHTML =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kElementsHTML));
   for (uint32_t i = 0; kElementsHTML[i]; i++) {
     sElementsHTML->PutEntry(*kElementsHTML[i]);
   }
 
-  sAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesHTML));
+  sAttributesHTML =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kAttributesHTML));
   for (uint32_t i = 0; kAttributesHTML[i]; i++) {
     sAttributesHTML->PutEntry(*kAttributesHTML[i]);
   }
 
-  sPresAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kPresAttributesHTML));
+  sPresAttributesHTML =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kPresAttributesHTML));
   for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
     sPresAttributesHTML->PutEntry(*kPresAttributesHTML[i]);
   }
 
-  sElementsSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsSVG));
+  sElementsSVG =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kElementsSVG));
   for (uint32_t i = 0; kElementsSVG[i]; i++) {
     sElementsSVG->PutEntry(*kElementsSVG[i]);
   }
 
-  sAttributesSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesSVG));
+  sAttributesSVG =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kAttributesSVG));
   for (uint32_t i = 0; kAttributesSVG[i]; i++) {
     sAttributesSVG->PutEntry(*kAttributesSVG[i]);
   }
 
-  sElementsMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsMathML));
+  sElementsMathML =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kElementsMathML));
   for (uint32_t i = 0; kElementsMathML[i]; i++) {
     sElementsMathML->PutEntry(*kElementsMathML[i]);
   }
 
-  sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML));
+  sAttributesMathML =
+    new nsTHashtable<nsRefPtrHashKey<nsIAtom>>(ArrayLength(kAttributesMathML));
   for (uint32_t i = 0; kAttributesMathML[i]; i++) {
     sAttributesMathML->PutEntry(*kAttributesMathML[i]);
   }
 
   nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
   principal.forget(&sNullPrincipal);
 }
 
--- a/dom/base/nsTreeSanitizer.h
+++ b/dom/base/nsTreeSanitizer.h
@@ -125,17 +125,17 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
      * @param aAllowed the whitelist of permitted local names to use
      * @param aURLs the local names of URL-valued attributes
      * @param aAllowXLink whether XLink attributes are allowed
      * @param aAllowStyle whether the style attribute is allowed
      * @param aAllowDangerousSrc whether to leave the value of the src
      *                           attribute unsanitized
      */
     void SanitizeAttributes(mozilla::dom::Element* aElement,
-                            nsTHashtable<nsISupportsHashKey>* aAllowed,
+                            nsTHashtable<nsRefPtrHashKey<nsIAtom>>* aAllowed,
                             nsIAtom*** aURLs,
                             bool aAllowXLink,
                             bool aAllowStyle,
                             bool aAllowDangerousSrc);
 
     /**
      * Remove the named URL attribute from the element if the URL fails a
      * security check.
@@ -181,47 +181,47 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
     /**
      * Removes all attributes from an element node.
      */
     void RemoveAllAttributes(nsIContent* aElement);
 
     /**
      * The whitelist of HTML elements.
      */
-    static nsTHashtable<nsISupportsHashKey>* sElementsHTML;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sElementsHTML;
 
     /**
      * The whitelist of non-presentational HTML attributes.
      */
-    static nsTHashtable<nsISupportsHashKey>* sAttributesHTML;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sAttributesHTML;
 
     /**
      * The whitelist of presentational HTML attributes.
      */
-    static nsTHashtable<nsISupportsHashKey>* sPresAttributesHTML;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sPresAttributesHTML;
 
     /**
      * The whitelist of SVG elements.
      */
-    static nsTHashtable<nsISupportsHashKey>* sElementsSVG;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sElementsSVG;
 
     /**
      * The whitelist of SVG attributes.
      */
-    static nsTHashtable<nsISupportsHashKey>* sAttributesSVG;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sAttributesSVG;
 
     /**
      * The whitelist of SVG elements.
      */
-    static nsTHashtable<nsISupportsHashKey>* sElementsMathML;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sElementsMathML;
 
     /**
      * The whitelist of MathML attributes.
      */
-    static nsTHashtable<nsISupportsHashKey>* sAttributesMathML;
+    static nsTHashtable<nsRefPtrHashKey<nsIAtom>>* sAttributesMathML;
 
     /**
      * Reusable null principal for URL checks.
      */
     static nsIPrincipal* sNullPrincipal;
 };
 
 #endif // nsTreeSanitizer_h_
--- a/dom/base/nsXMLNameSpaceMap.h
+++ b/dom/base/nsXMLNameSpaceMap.h
@@ -12,17 +12,17 @@
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 
 struct nsNameSpaceEntry
 {
   explicit nsNameSpaceEntry(nsIAtom* aPrefix)
     : prefix(aPrefix) {}
 
-  nsCOMPtr<nsIAtom> prefix;
+  RefPtr<nsIAtom> prefix;
   MOZ_INIT_OUTSIDE_CTOR int32_t nameSpaceID;
 };
 
 /**
  * nsXMLNameSpaceMap contains a set of prefixes which are mapped onto
  * namespaces.  It allows the set to be searched by prefix or by namespace ID.
  */
 class nsXMLNameSpaceMap
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -1071,17 +1071,17 @@ protected:
     mozilla::gfx::Float ShadowBlurSigma() const
     {
       return std::min(SIGMA_MAX, shadowBlur / 2.0f);
     }
 
     nsTArray<ClipState> clipsAndTransforms;
 
     RefPtr<gfxFontGroup> fontGroup;
-    nsCOMPtr<nsIAtom> fontLanguage;
+    RefPtr<nsIAtom> fontLanguage;
     nsFont fontFont;
 
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasGradient>> gradientStyles;
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasPattern>> patternStyles;
     EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
 
     nsString font;
     TextAlign textAlign;
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -203,17 +203,17 @@ private:
   // mParentObject pre QI-ed and cached (inner window)
   // (it is needed for off main thread access)
   // It is obtained in BindToOwner and reset in DisconnectFromOwner.
   nsPIDOMWindowInner* MOZ_NON_OWNING_REF mOwnerWindow;
   bool                       mHasOrHasHadOwnerWindow;
 
   struct {
     nsTArray<nsString> mStrings;
-    nsTArray<nsCOMPtr<nsIAtom>> mAtoms;
+    nsTArray<RefPtr<nsIAtom>> mAtoms;
   } mKeepingAliveTypes;
 
   bool mIsKeptAlive;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(DOMEventTargetHelper,
                               NS_DOMEVENTTARGETHELPER_IID)
 
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -199,17 +199,17 @@ DataTransfer::~DataTransfer()
 // static
 already_AddRefed<DataTransfer>
 DataTransfer::Constructor(const GlobalObject& aGlobal,
                           const nsAString& aEventType, bool aIsExternal,
                           ErrorResult& aRv)
 {
   nsAutoCString onEventType("on");
   AppendUTF16toUTF8(aEventType, onEventType);
-  nsCOMPtr<nsIAtom> eventTypeAtom = NS_Atomize(onEventType);
+  RefPtr<nsIAtom> eventTypeAtom = NS_Atomize(onEventType);
   if (!eventTypeAtom) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
 
   EventMessage eventMessage = nsContentUtils::GetEventMessage(eventTypeAtom);
   RefPtr<DataTransfer> transfer = new DataTransfer(aGlobal.GetAsSupports(),
                                                      eventMessage, aIsExternal,
@@ -692,17 +692,17 @@ void
 DataTransfer::TypesListMayHaveChanged()
 {
   DataTransferBinding::ClearCachedTypesValue(this);
 }
 
 already_AddRefed<DataTransfer>
 DataTransfer::MozCloneForEvent(const nsAString& aEvent, ErrorResult& aRv)
 {
-  nsCOMPtr<nsIAtom> atomEvt = NS_Atomize(aEvent);
+  RefPtr<nsIAtom> atomEvt = NS_Atomize(aEvent);
   if (!atomEvt) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
   EventMessage eventMessage = nsContentUtils::GetEventMessage(atomEvt);
 
   RefPtr<DataTransfer> dt;
   nsresult rv = Clone(mParent, eventMessage, false, false, getter_AddRefs(dt));
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -685,32 +685,32 @@ EventListenerManager::ListenerCanHandle(
 }
 
 void
 EventListenerManager::AddEventListenerByType(
                         EventListenerHolder aListenerHolder,
                         const nsAString& aType,
                         const EventListenerFlags& aFlags)
 {
-  nsCOMPtr<nsIAtom> atom;
+  RefPtr<nsIAtom> atom;
   EventMessage message = mIsMainThreadELM ?
     nsContentUtils::GetEventMessageAndAtomForListener(aType,
                                                       getter_AddRefs(atom)) :
     eUnidentifiedEvent;
   AddEventListenerInternal(Move(aListenerHolder),
                            message, atom, aType, aFlags);
 }
 
 void
 EventListenerManager::RemoveEventListenerByType(
                         EventListenerHolder aListenerHolder,
                         const nsAString& aType,
                         const EventListenerFlags& aFlags)
 {
-  nsCOMPtr<nsIAtom> atom;
+  RefPtr<nsIAtom> atom;
   EventMessage message = mIsMainThreadELM ?
     nsContentUtils::GetEventMessageAndAtomForListener(aType,
                                                       getter_AddRefs(atom)) :
     eUnidentifiedEvent;
   RemoveEventListenerInternal(Move(aListenerHolder),
                               message, atom, aType, aFlags);
 }
 
@@ -927,17 +927,17 @@ EventListenerManager::CompileEventHandle
   // Activate JSAPI, and make sure that exceptions are reported on the right
   // Window.
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(global))) {
     return NS_ERROR_UNEXPECTED;
   }
   JSContext* cx = jsapi.cx();
 
-  nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
+  RefPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
   nsIAtom* attrName = typeAtom;
 
   // Flag us as not a string so we don't keep trying to compile strings which
   // can't be compiled.
   aListener->mHandlerIsString = false;
 
   // mTarget may not be an Element if it's a window and we're
   // getting an inline event listener forwarded from <html:body> or
@@ -1493,17 +1493,17 @@ EventListenerManager::MutationListenerBi
   }
   return bits;
 }
 
 bool
 EventListenerManager::HasListenersFor(const nsAString& aEventName)
 {
   if (mIsMainThreadELM) {
-    nsCOMPtr<nsIAtom> atom = NS_Atomize(NS_LITERAL_STRING("on") + aEventName);
+    RefPtr<nsIAtom> atom = NS_Atomize(NS_LITERAL_STRING("on") + aEventName);
     return HasListenersFor(atom);
   }
 
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     Listener* listener = &mListeners.ElementAt(i);
     if (listener->mTypeString == aEventName) {
       return true;
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -178,17 +178,17 @@ protected:
 class EventListenerManager final : public EventListenerManagerBase
 {
   ~EventListenerManager();
 
 public:
   struct Listener
   {
     EventListenerHolder mListener;
-    nsCOMPtr<nsIAtom> mTypeAtom; // for the main thread
+    RefPtr<nsIAtom> mTypeAtom; // for the main thread
     nsString mTypeString; // for non-main-threads
     EventMessage mEventMessage;
 
     enum ListenerType : uint8_t
     {
       eNoListener,
       eNativeListener,
       eJSEventListener,
@@ -626,17 +626,17 @@ protected:
   // members, please add them to EventListemerManagerBase and check the size
   // at build time.
 
   already_AddRefed<nsIScriptGlobalObject>
   GetScriptGlobalAndDocument(nsIDocument** aDoc);
 
   nsAutoTObserverArray<Listener, 2> mListeners;
   dom::EventTarget* MOZ_NON_OWNING_REF mTarget;
-  nsCOMPtr<nsIAtom> mNoListenerForEventAtom;
+  RefPtr<nsIAtom> mNoListenerForEventAtom;
 
   friend class ELMCreationDetector;
   static uint32_t sMainThreadCreatedCount;
 };
 
 } // namespace mozilla
 
 /**
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -32,46 +32,41 @@ NS_IMPL_ISUPPORTS(EventListenerChange, n
 
 EventListenerChange::~EventListenerChange()
 {
 }
 
 EventListenerChange::EventListenerChange(dom::EventTarget* aTarget) :
   mTarget(aTarget)
 {
-  mChangedListenerNames = nsArrayBase::Create();
 }
 
 void
 EventListenerChange::AddChangedListenerName(nsIAtom* aEventName)
 {
-  mChangedListenerNames->AppendElement(aEventName, false);
+  mChangedListenerNames.AppendElement(aEventName);
 }
 
 NS_IMETHODIMP
 EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget)
 {
   NS_ENSURE_ARG_POINTER(aTarget);
   NS_ADDREF(*aTarget = mTarget);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EventListenerChange::GetCountOfEventListenerChangesAffectingAccessibility(
   uint32_t* aCount)
 {
   *aCount = 0;
 
-  uint32_t length;
-  nsresult rv = mChangedListenerNames->GetLength(&length);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  size_t length = mChangedListenerNames.Length();
   for (size_t i = 0; i < length; i++) {
-    nsCOMPtr<nsIAtom> listenerName =
-      do_QueryElementAt(mChangedListenerNames, i);
+    RefPtr<nsIAtom> listenerName = mChangedListenerNames[i];
 
     // These are the event listener changes which may make an element
     // accessible or inaccessible.
     if (listenerName == nsGkAtoms::onclick ||
         listenerName == nsGkAtoms::onmousedown ||
         listenerName == nsGkAtoms::onmouseup) {
       *aCount += 1;
     }
--- a/dom/events/EventListenerService.h
+++ b/dom/events/EventListenerService.h
@@ -36,18 +36,17 @@ public:
   void AddChangedListenerName(nsIAtom* aEventName);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEVENTLISTENERCHANGE
 
 protected:
   virtual ~EventListenerChange();
   nsCOMPtr<dom::EventTarget> mTarget;
-  nsCOMPtr<nsIMutableArray> mChangedListenerNames;
-
+  nsTArray<RefPtr<nsIAtom>> mChangedListenerNames;
 };
 
 class EventListenerInfo final : public nsIEventListenerInfo
 {
 public:
   EventListenerInfo(const nsAString& aType,
                     already_AddRefed<nsIDOMEventListener> aListener,
                     bool aCapturing,
--- a/dom/events/EventTarget.cpp
+++ b/dom/events/EventTarget.cpp
@@ -36,17 +36,17 @@ EventTarget::SetEventHandler(const nsASt
                              EventHandlerNonNull* aHandler,
                              ErrorResult& aRv)
 {
   if (!StringBeginsWith(aType, NS_LITERAL_STRING("on"))) {
     aRv.Throw(NS_ERROR_INVALID_ARG);
     return;
   }
   if (NS_IsMainThread()) {
-    nsCOMPtr<nsIAtom> type = NS_Atomize(aType);
+    RefPtr<nsIAtom> type = NS_Atomize(aType);
     SetEventHandler(type, EmptyString(), aHandler);
     return;
   }
   SetEventHandler(nullptr,
                   Substring(aType, 2), // Remove "on"
                   aHandler);
 }
 
--- a/dom/events/EventTarget.h
+++ b/dom/events/EventTarget.h
@@ -55,17 +55,17 @@ public:
                                    EventListener* aCallback,
                                    const EventListenerOptionsOrBoolean& aOptions,
                                    ErrorResult& aRv);
   bool DispatchEvent(Event& aEvent, CallerType aCallerType, ErrorResult& aRv);
 
   // Note, this takes the type in onfoo form!
   EventHandlerNonNull* GetEventHandler(const nsAString& aType)
   {
-    nsCOMPtr<nsIAtom> type = NS_Atomize(aType);
+    RefPtr<nsIAtom> type = NS_Atomize(aType);
     return GetEventHandler(type, EmptyString());
   }
 
   // Note, this takes the type in onfoo form!
   void SetEventHandler(const nsAString& aType, EventHandlerNonNull* aHandler,
                        ErrorResult& rv);
 
   // Note, for an event 'foo' aType will be 'onfoo'.
--- a/dom/events/InternalMutationEvent.h
+++ b/dom/events/InternalMutationEvent.h
@@ -32,19 +32,19 @@ public:
                "Duplicate() must be overridden by sub class");
     InternalMutationEvent* result = new InternalMutationEvent(false, mMessage);
     result->AssignMutationEventData(*this, true);
     result->mFlags = mFlags;
     return result;
   }
 
   nsCOMPtr<nsIDOMNode> mRelatedNode;
-  nsCOMPtr<nsIAtom>    mAttrName;
-  nsCOMPtr<nsIAtom>    mPrevAttrValue;
-  nsCOMPtr<nsIAtom>    mNewAttrValue;
+  RefPtr<nsIAtom>    mAttrName;
+  RefPtr<nsIAtom>    mPrevAttrValue;
+  RefPtr<nsIAtom>    mNewAttrValue;
   unsigned short       mAttrChange;
 
   void AssignMutationEventData(const InternalMutationEvent& aEvent,
                                bool aCopyTargets)
   {
     AssignEventData(aEvent, aCopyTargets);
 
     mRelatedNode = aEvent.mRelatedNode;
--- a/dom/events/JSEventHandler.h
+++ b/dom/events/JSEventHandler.h
@@ -255,17 +255,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(JSEventHandler)
 
   bool IsBlackForCC();
 
 protected:
   virtual ~JSEventHandler();
 
   nsISupports* mTarget;
-  nsCOMPtr<nsIAtom> mEventName;
+  RefPtr<nsIAtom> mEventName;
   TypedEventHandler mTypedHandler;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(JSEventHandler, NS_JSEVENTHANDLER_IID)
 
 } // namespace mozilla
 
 /**
--- a/dom/html/HTMLAllCollection.cpp
+++ b/dom/html/HTMLAllCollection.cpp
@@ -107,17 +107,17 @@ DocAllResultMatch(Element* aElement, int
          val->GetAtomValue() == aAtom;
 }
 
 nsContentList*
 HTMLAllCollection::GetDocumentAllList(const nsAString& aID)
 {
   return mNamedMap.LookupForAdd(aID).OrInsert(
     [this, &aID] () {
-      nsCOMPtr<nsIAtom> id = NS_Atomize(aID);
+      RefPtr<nsIAtom> id = NS_Atomize(aID);
       return new nsContentList(mDocument, DocAllResultMatch, nullptr,
                                nullptr, true, id);
     });
 }
 
 void
 HTMLAllCollection::NamedGetter(const nsAString& aID,
                                bool& aFound,
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -253,17 +253,17 @@ TableRowsCollection::Item(uint32_t aInde
   return CallQueryInterface(node, aReturn);
 }
 
 Element*
 TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
 {
   EnsureInitialized();
   aFound = false;
-  nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
+  RefPtr<nsIAtom> nameAtom = NS_Atomize(aName);
   NS_ENSURE_TRUE(nameAtom, nullptr);
 
   for (auto& node : mRows) {
     if (node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
                           nameAtom, eCaseMatters) ||
         node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
                           nameAtom, eCaseMatters)) {
       aFound = true;
--- a/dom/html/nsDOMStringMap.cpp
+++ b/dom/html/nsDOMStringMap.cpp
@@ -95,17 +95,17 @@ nsDOMStringMap::NamedSetter(const nsAStr
   }
 
   nsresult res = nsContentUtils::CheckQName(attr, false);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return;
   }
 
-  nsCOMPtr<nsIAtom> attrAtom = NS_Atomize(attr);
+  RefPtr<nsIAtom> attrAtom = NS_Atomize(attr);
   MOZ_ASSERT(attrAtom, "Should be infallible");
 
   res = mElement->SetAttr(kNameSpaceID_None, attrAtom, aValue, true);
   if (NS_FAILED(res)) {
     rv.Throw(res);
   }
 }
 
@@ -119,17 +119,17 @@ nsDOMStringMap::NamedDeleter(const nsASt
   }
 
   nsAutoString attr;
   if (!DataPropToAttr(aProp, attr)) {
     found = false;
     return;
   }
 
-  nsCOMPtr<nsIAtom> attrAtom = NS_Atomize(attr);
+  RefPtr<nsIAtom> attrAtom = NS_Atomize(attr);
   MOZ_ASSERT(attrAtom, "Should be infallible");
 
   found = mElement->HasAttr(kNameSpaceID_None, attrAtom);
 
   if (found) {
     mRemovingProp = true;
     mElement->UnsetAttr(kNameSpaceID_None, attrAtom, true);
     mRemovingProp = false;
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2195,17 +2195,17 @@ nsGenericHTMLFormElement::AddFormIdObser
   NS_ASSERTION(GetUncomposedDoc(), "When adding a form id observer, "
                                    "we should be in a document!");
 
   nsAutoString formId;
   nsIDocument* doc = OwnerDoc();
   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
   NS_ASSERTION(!formId.IsEmpty(),
                "@form value should not be the empty string!");
-  nsCOMPtr<nsIAtom> atom = NS_Atomize(formId);
+  RefPtr<nsIAtom> atom = NS_Atomize(formId);
 
   return doc->AddIDTargetObserver(atom, FormIdUpdated, this, false);
 }
 
 void
 nsGenericHTMLFormElement::RemoveFormIdObserver()
 {
   /**
@@ -2224,17 +2224,17 @@ nsGenericHTMLFormElement::RemoveFormIdOb
   if (!doc) {
     return;
   }
 
   nsAutoString formId;
   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
   NS_ASSERTION(!formId.IsEmpty(),
                "@form value should not be the empty string!");
-  nsCOMPtr<nsIAtom> atom = NS_Atomize(formId);
+  RefPtr<nsIAtom> atom = NS_Atomize(formId);
 
   doc->RemoveIDTargetObserver(atom, FormIdUpdated, this, false);
 }
 
 
 /* static */
 bool
 nsGenericHTMLFormElement::FormIdUpdated(Element* aOldElement,
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -296,18 +296,18 @@ NS_NewHTMLElement(Element** aResult, alr
     JSContext* cx = aes.cx();
     ErrorResult rv;
 
     // Step 5.
     if (definition->IsCustomBuiltIn()) {
       // SetupCustomElement() should be called with an element that don't have
       // CustomElementData setup, if not we will hit the assertion in
       // SetCustomElementData().
-      nsCOMPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
-      nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
+      RefPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
+      RefPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
       // Built-in element
       *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
       (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
       if (synchronousCustomElements) {
         CustomElementRegistry::Upgrade(*aResult, definition, rv);
       } else {
         nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
       }
--- a/dom/ipc/PURLClassifierInfo.ipdlh
+++ b/dom/ipc/PURLClassifierInfo.ipdlh
@@ -5,17 +5,17 @@
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace dom {
 
 struct ClassifierInfo {
   nsCString list;
   nsCString provider;
-  nsCString prefix;
+  nsCString fullhash;
 };
 
 union MaybeInfo {
   ClassifierInfo;
   void_t;
 };
 
 } // namespace dom
--- a/dom/ipc/URLClassifierChild.h
+++ b/dom/ipc/URLClassifierChild.h
@@ -27,17 +27,17 @@ public:
 
   mozilla::ipc::IPCResult Recv__delete__(const MaybeInfo& aInfo,
                                          const nsresult& aResult) override
   {
     MOZ_ASSERT(mCallback);
     if (aInfo.type() == MaybeInfo::TClassifierInfo) {
       mCallback->OnClassifyComplete(aResult, aInfo.get_ClassifierInfo().list(),
                                     aInfo.get_ClassifierInfo().provider(),
-                                    aInfo.get_ClassifierInfo().prefix());
+                                    aInfo.get_ClassifierInfo().fullhash());
     }
     return IPC_OK();
   }
 
 private:
   ~URLClassifierChildBase() = default;
 
   nsCOMPtr<nsIURIClassifierCallback> mCallback;
--- a/dom/ipc/URLClassifierParent.h
+++ b/dom/ipc/URLClassifierParent.h
@@ -18,22 +18,22 @@ template<typename BaseProtocol>
 class URLClassifierParentBase : public nsIURIClassifierCallback,
                                 public BaseProtocol
 {
 public:
   // nsIURIClassifierCallback.
   NS_IMETHOD OnClassifyComplete(nsresult aErrorCode,
                                 const nsACString& aList,
                                 const nsACString& aProvider,
-                                const nsACString& aPrefix)
+                                const nsACString& aFullHash)
   {
     if (mIPCOpen) {
       ClassifierInfo info = ClassifierInfo(nsCString(aList),
                                            nsCString(aProvider),
-                                           nsCString(aPrefix));
+                                           nsCString(aFullHash));
       Unused << BaseProtocol::Send__delete__(this, info, aErrorCode);
     }
     return NS_OK;
   }
 
   // Custom.
   void ClassificationFailed()
   {
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -320,17 +320,17 @@ DecoderTraits::IsSupportedType(const Med
 }
 
 /* static */
 bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
 {
   // Forbid playing media in video documents if the user has opted
   // not to, using either the legacy WMF specific pref, or the newer
   // catch-all pref.
-  if (!Preferences::GetBool("media.windows-media-foundation.play-stand-alone", true) ||
+  if (!Preferences::GetBool("media.wmf.play-stand-alone", true) ||
       !Preferences::GetBool("media.play-stand-alone", true)) {
     return false;
   }
 
   Maybe<MediaContainerType> type = MakeMediaContainerType(aType);
   if (!type) {
     return false;
   }
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -3126,22 +3126,26 @@ MediaFormatReader::GetMozDebugReaderData
   nsCString result;
   nsAutoCString audioDecoderName("unavailable");
   nsAutoCString videoDecoderName = audioDecoderName;
   nsAutoCString audioType("none");
   nsAutoCString videoType("none");
 
   if (HasAudio()) {
     MutexAutoLock lock(mAudio.mMutex);
-    audioDecoderName = mAudio.mDescription;
+    audioDecoderName = mAudio.mDecoder
+                       ? mAudio.mDecoder->GetDescriptionName()
+                       : mAudio.mDescription;
     audioType = mInfo.mAudio.mMimeType;
   }
   if (HasVideo()) {
     MutexAutoLock mon(mVideo.mMutex);
-    videoDecoderName = mVideo.mDescription;
+    videoDecoderName = mVideo.mDecoder
+                       ? mVideo.mDecoder->GetDescriptionName()
+                       : mVideo.mDescription;
     videoType = mInfo.mVideo.mMimeType;
   }
 
   result += nsPrintfCString(
     "Audio Decoder(%s): %s\n", audioType.get(), audioDecoderName.get());
   result += nsPrintfCString("Audio Frames Decoded: %" PRIu64 "\n",
                             mAudio.mNumSamplesOutputTotal);
   if (HasAudio()) {
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -535,16 +535,32 @@ Promise::PerformMicroTaskCheckpoint()
     }
     aso.CheckForInterrupt();
     context->AfterProcessMicrotask();
   } while (!microtaskQueue.empty());
 
   return true;
 }
 
+bool
+Promise::IsWorkerDebuggerMicroTaskEmpty()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "Wrong thread!");
+
+  CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
+  if (!context) {
+    return true;
+  }
+
+  std::queue<nsCOMPtr<nsIRunnable>>* microtaskQueue =
+    &context->GetDebuggerPromiseMicroTaskQueue();
+
+  return microtaskQueue->empty();
+}
+
 void
 Promise::PerformWorkerMicroTaskCheckpoint()
 {
   MOZ_ASSERT(!NS_IsMainThread(), "Wrong thread!");
 
   CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
   if (!context) {
     return;
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -107,16 +107,17 @@ public:
 
   // Called by DOM to let us execute our callbacks.  May be called recursively.
   // Returns true if at least one microtask was processed.
   static bool PerformMicroTaskCheckpoint();
 
   static void PerformWorkerMicroTaskCheckpoint();
 
   static void PerformWorkerDebuggerMicroTaskCheckpoint();
+  static bool IsWorkerDebuggerMicroTaskEmpty();
 
   // WebIDL
 
   nsIGlobalObject* GetParentObject() const
   {
     return mGlobal;
   }
 
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -671,17 +671,17 @@ nsSMILAnimationController::GetTargetIden
   Element* targetElem = aAnimElem->GetTargetElementContent();
   if (!targetElem)
     // Animation has no target elem -- skip it.
     return false;
 
   // Look up target (animated) attribute
   // SMILANIM section 3.1, attributeName may
   // have an XMLNS prefix to indicate the XML namespace.
-  nsCOMPtr<nsIAtom> attributeName;
+  RefPtr<nsIAtom> attributeName;
   int32_t attributeNamespaceID;
   if (!aAnimElem->GetTargetAttributeName(&attributeNamespaceID,
                                          getter_AddRefs(attributeName)))
     // Animation has no target attr -- skip it.
     return false;
 
   // animateTransform can only animate transforms, conversely transforms
   // can only be animated by animateTransform
--- a/dom/storage/LocalStorageManager.cpp
+++ b/dom/storage/LocalStorageManager.cpp
@@ -370,22 +370,27 @@ LocalStorageManager::Observe(const char*
 {
   OriginAttributesPattern pattern;
   if (!pattern.Init(aOriginAttributesPattern)) {
     NS_ERROR("Cannot parse origin attributes pattern");
     return NS_ERROR_FAILURE;
   }
 
   // Clear everything, caches + database
-  if (!strcmp(aTopic, "cookie-cleared") ||
-      !strcmp(aTopic, "extension:purge-localStorage-caches")) {
+  if (!strcmp(aTopic, "cookie-cleared")) {
     ClearCaches(LocalStorageCache::kUnloadComplete, pattern, EmptyCString());
     return NS_OK;
   }
 
+  // Clear everything, caches + database
+  if (!strcmp(aTopic, "extension:purge-localStorage-caches")) {
+    ClearCaches(LocalStorageCache::kUnloadComplete, pattern, aOriginScope);
+    return NS_OK;
+  }
+
   // Clear from caches everything that has been stored
   // while in session-only mode
   if (!strcmp(aTopic, "session-only-cleared")) {
     ClearCaches(LocalStorageCache::kUnloadSession, pattern, aOriginScope);
     return NS_OK;
   }
 
   // Clear everything (including so and pb data) from caches and database
--- a/dom/storage/StorageObserver.cpp
+++ b/dom/storage/StorageObserver.cpp
@@ -148,16 +148,60 @@ StorageObserver::Notify(const char* aTop
 }
 
 void
 StorageObserver::NoteBackgroundThread(nsIEventTarget* aBackgroundThread)
 {
   mBackgroundThread = aBackgroundThread;
 }
 
+nsresult
+StorageObserver::ClearMatchingOrigin(const char16_t* aData,
+                                     nsACString& aOriginScope)
+{
+  nsresult rv;
+
+  NS_ConvertUTF16toUTF8 domain(aData);
+
+  nsAutoCString convertedDomain;
+  nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
+  if (converter) {
+    // Convert the domain name to the ACE format
+    rv = converter->ConvertUTF8toACE(domain, convertedDomain);
+  } else {
+    // In case the IDN service is not available, this is the best we can come
+    // up with!
+    rv = NS_EscapeURL(domain,
+                      esc_OnlyNonASCII | esc_AlwaysCopy,
+                      convertedDomain,
+                      fallible);
+  }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCString originScope;
+  rv = CreateReversedDomain(convertedDomain, originScope);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (XRE_IsParentProcess()) {
+    StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
+    if (NS_WARN_IF(!storageChild)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    storageChild->SendClearMatchingOrigin(originScope);
+  }
+
+  aOriginScope = originScope;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 StorageObserver::Observe(nsISupports* aSubject,
                          const char* aTopic,
                          const char16_t* aData)
 {
   nsresult rv;
 
   // Start the thread that opens the database.
@@ -271,62 +315,51 @@ StorageObserver::Observe(nsISupports* aS
 
     Notify("session-only-cleared", NS_ConvertUTF8toUTF16(originSuffix),
            originScope);
 
     return NS_OK;
   }
 
   if (!strcmp(aTopic, "extension:purge-localStorage")) {
-    StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
-    if (NS_WARN_IF(!storageChild)) {
-      return NS_ERROR_FAILURE;
-    }
+    const char topic[] = "extension:purge-localStorage-caches";
+
+    if (aData) {
+      nsCString originScope;
+      rv = ClearMatchingOrigin(aData, originScope);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
-    storageChild->AsyncClearAll();
+      Notify(topic, EmptyString(), originScope);
+    } else {
+      StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
+      if (NS_WARN_IF(!storageChild)) {
+        return NS_ERROR_FAILURE;
+      }
 
-    if (XRE_IsParentProcess()) {
-      storageChild->SendClearAll();
+      storageChild->AsyncClearAll();
+
+      if (XRE_IsParentProcess()) {
+        storageChild->SendClearAll();
+      }
+
+      Notify(topic);
     }
 
-    Notify("extension:purge-localStorage-caches");
-
     return NS_OK;
   }
 
   // Clear everything (including so and pb data) from caches and database
-  // for the gived domain and subdomains.
+  // for the given domain and subdomains.
   if (!strcmp(aTopic, "browser:purge-domain-data")) {
-    // Convert the domain name to the ACE format
-    nsAutoCString aceDomain;
-    nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
-    if (converter) {
-      rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain);
-      NS_ENSURE_SUCCESS(rv, rv);
-    } else {
-      // In case the IDN service is not available, this is the best we can come
-      // up with!
-      rv = NS_EscapeURL(NS_ConvertUTF16toUTF8(aData),
-                        esc_OnlyNonASCII | esc_AlwaysCopy,
-                        aceDomain,
-                        fallible);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    nsAutoCString originScope;
-    rv = CreateReversedDomain(aceDomain, originScope);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (XRE_IsParentProcess()) {
-      StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
-      if (NS_WARN_IF(!storageChild)) {
-        return NS_ERROR_FAILURE;
-      }
-
-      storageChild->SendClearMatchingOrigin(originScope);
+    nsCString originScope;
+    rv = ClearMatchingOrigin(aData, originScope);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
     }
 
     Notify("domain-data-cleared", EmptyString(), originScope);
 
     return NS_OK;
   }
 
   // Clear all private-browsing caches
--- a/dom/storage/StorageObserver.h
+++ b/dom/storage/StorageObserver.h
@@ -52,16 +52,20 @@ public:
               const nsACString& aOriginScope = EmptyCString());
 
   void
   NoteBackgroundThread(nsIEventTarget* aBackgroundThread);
 
 private:
   virtual ~StorageObserver() {}
 
+  nsresult
+  ClearMatchingOrigin(const char16_t* aData,
+                      nsACString& aOriginScope);
+
   static void TestingPrefChanged(const char* aPrefName, void* aClosure);
 
   static StorageObserver* sSelf;
 
   nsCOMPtr<nsIEventTarget> mBackgroundThread;
 
   // Weak references
   nsTObserverArray<StorageObserverSink*> mSinks;
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -545,17 +545,17 @@ nsSVGElement::ParseAttribute(int32_t aNa
       }
     }
 
     if (!foundMatch) {
       // Check for nsSVGEnum attribute
       EnumAttributesInfo enumInfo = GetEnumInfo();
       for (i = 0; i < enumInfo.mEnumCount; i++) {
         if (aAttribute == *enumInfo.mEnumInfo[i].mName) {
-          nsCOMPtr<nsIAtom> valAtom = NS_Atomize(aValue);
+          RefPtr<nsIAtom> valAtom = NS_Atomize(aValue);
           rv = enumInfo.mEnums[i].SetBaseValueAtom(valAtom, this);
           if (NS_FAILED(rv)) {
             enumInfo.Reset(i);
           } else {
             aResult.SetTo(valAtom);
             didSetResult = true;
           }
           foundMatch = true;
@@ -1285,17 +1285,17 @@ MappedAttrParser::ParseMappedAttrValue(n
     if (mBackend == StyleBackendType::Gecko) {
       nsCSSExpandedDataBlock block;
       mDecl->AsGecko()->ExpandTo(&block);
       nsCSSValue cssValue(PromiseFlatString(aMappedAttrValue), eCSSUnit_Ident);
       block.AddLonghandProperty(propertyID, cssValue);
       mDecl->AsGecko()->ValueAppended(propertyID);
       mDecl->AsGecko()->CompressFrom(&block);
     } else {
-      nsCOMPtr<nsIAtom> atom = NS_Atomize(aMappedAttrValue);
+      RefPtr<nsIAtom> atom = NS_Atomize(aMappedAttrValue);
       Servo_DeclarationBlock_SetIdentStringValue(mDecl->AsServo()->Raw(), propertyID, atom);
     }
   }
 }
 
 already_AddRefed<DeclarationBlock>
 MappedAttrParser::GetDeclarationBlock()
 {
--- a/dom/webidl/ChannelWrapper.webidl
+++ b/dom/webidl/ChannelWrapper.webidl
@@ -127,16 +127,28 @@ interface ChannelWrapper {
   readonly attribute long long windowId;
 
   [Cached, Constant]
   readonly attribute long long parentWindowId;
 
   [Cached, Pure]
   readonly attribute nsISupports? browserElement;
 
+  /**
+   * Returns an array of objects that combine the url and frameId from the
+   * ancestorPrincipals and ancestorOuterWindowIDs on loadInfo.
+   * The immediate parent is the first entry, the last entry is always the top
+   * level frame.  It will be an empty list for toplevel window loads and
+   * non-subdocument resource loads within a toplevel window.  For the latter,
+   * originURL will provide information on what window is doing the load.  It
+   * will be null if the request is not associated with a window (e.g. XHR with
+   * mozBackgroundRequest = true).
+   */
+  [Cached, Frozen, GetterThrows, Pure]
+  readonly attribute sequence<MozFrameAncestorInfo>? frameAncestors;
 
   [Throws]
   object getRequestHeaders();
 
   [Throws]
   object getResponseHeaders();
 
   [Throws]
@@ -152,8 +164,22 @@ dictionary MozProxyInfo {
   required ByteString type;
 
   required boolean proxyDNS;
 
   ByteString? username = null;
 
   unsigned long failoverTimeout;
 };
+
+/**
+ * MozFrameAncestorInfo combines loadInfo::AncestorPrincipals with
+ * loadInfo::AncestorOuterWindowIDs for easier access in the WebRequest API.
+ *
+ * url represents the parent of the loading window.
+ * frameId is the outerWindowID for the parent of the loading window.
+ *
+ * For further details see nsILoadInfo.idl and nsIDocument::AncestorPrincipals.
+ */
+dictionary MozFrameAncestorInfo {
+  required ByteString url;
+  required unsigned long long frameId;
+};
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -6124,16 +6124,17 @@ WorkerPrivate::EnterDebuggerEventLoop()
   AssertIsOnWorkerThread();
 
   JSContext* cx = GetJSContext();
   MOZ_ASSERT(cx);
 
   uint32_t currentEventLoopLevel = ++mDebuggerEventLoopLevel;
 
   while (currentEventLoopLevel <= mDebuggerEventLoopLevel) {
+
     bool debuggerRunnablesPending = false;
 
     {
       MutexAutoLock lock(mMutex);
 
       debuggerRunnablesPending = !mDebuggerQueue.IsEmpty();
     }
 
@@ -6142,25 +6143,28 @@ WorkerPrivate::EnterDebuggerEventLoop()
       SetGCTimerMode(IdleTimer);
     }
 
     // Wait for something to do
     {
       MutexAutoLock lock(mMutex);
 
       while (mControlQueue.IsEmpty() &&
-             !(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty())) {
+             !(debuggerRunnablesPending = !mDebuggerQueue.IsEmpty()) &&
+             Promise::IsWorkerDebuggerMicroTaskEmpty()) {
         WaitForWorkerEvents();
       }
 
       ProcessAllControlRunnablesLocked();
 
       // XXXkhuey should we abort JS on the stack here if we got Abort above?
     }
-
+    if (!Promise::IsWorkerDebuggerMicroTaskEmpty()) {
+      Promise::PerformWorkerDebuggerMicroTaskCheckpoint();
+    }
     if (debuggerRunnablesPending) {
       // Start the periodic GC timer if it is not already running.
       SetGCTimerMode(PeriodicTimer);
 
       WorkerRunnable* runnable = nullptr;
 
       {
         MutexAutoLock lock(mMutex);
--- a/dom/workers/test/WorkerDebugger_promise_debugger.js
+++ b/dom/workers/test/WorkerDebugger_promise_debugger.js
@@ -17,14 +17,18 @@ self.onmessage = function (event) {
         }
         // This then-handler should be executed inside the nested event loop,
         // within the context of the debugger's global.
         Promise.resolve().then(function () {
           postMessage("resumed");
           leaveEventLoop();
         });
       };
-      postMessage("paused");
+      // Test bug 1392540 where DOM Promises from debugger principal
+      // where frozen while hitting a worker breakpoint.
+      Promise.resolve().then(() => {
+        postMessage("paused");
+      });
       enterEventLoop();
     };
     postMessage("resolved");
   });
 };
--- a/dom/xbl/XBLChildrenElement.h
+++ b/dom/xbl/XBLChildrenElement.h
@@ -140,17 +140,17 @@ public:
 protected:
   ~XBLChildrenElement();
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
 
 private:
   nsTArray<nsIContent*> mInsertedChildren; // WEAK
-  nsTArray<nsCOMPtr<nsIAtom> > mIncludes;
+  nsTArray<RefPtr<nsIAtom> > mIncludes;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class nsAnonymousContentList : public nsINodeList
 {
 public:
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -400,17 +400,17 @@ nsXBLBinding::GenerateAnonymousContent()
   // 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.
-    nsCOMPtr<nsIAtom> name = attrInfo.mName->LocalName();
+    RefPtr<nsIAtom> 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);
       }
@@ -500,17 +500,17 @@ nsXBLBinding::InstallEventHandlers()
         return;
 
       bool isChromeDoc =
         nsContentUtils::IsChromeDoc(mBoundElement->OwnerDoc());
       bool isChromeBinding = mPrototypeBinding->IsChrome();
       nsXBLPrototypeHandler* curr;
       for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
         // Fetch the event type.
-        nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
+        RefPtr<nsIAtom> eventAtom = curr->GetEventName();
         if (!eventAtom ||
             eventAtom == nsGkAtoms::keyup ||
             eventAtom == nsGkAtoms::keydown ||
             eventAtom == nsGkAtoms::keypress)
           continue;
 
         nsXBLEventHandler* handler = curr->GetEventHandler();
         if (handler) {
@@ -652,17 +652,17 @@ nsXBLBinding::UnhookEventHandlers()
     bool isChromeBinding = mPrototypeBinding->IsChrome();
     nsXBLPrototypeHandler* curr;
     for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
       nsXBLEventHandler* handler = curr->GetCachedEventHandler();
       if (!handler) {
         continue;
       }
 
-      nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
+      RefPtr<nsIAtom> 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;
--- a/dom/xbl/nsXBLContentSink.cpp
+++ b/dom/xbl/nsXBLContentSink.cpp
@@ -269,17 +269,17 @@ nsXBLContentSink::HandleStartElement(con
 
 NS_IMETHODIMP
 nsXBLContentSink::HandleEndElement(const char16_t *aName)
 {
   FlushText();
 
   if (mState != eXBL_InDocument) {
     int32_t nameSpaceID;
-    nsCOMPtr<nsIAtom> prefix, localName;
+    RefPtr<nsIAtom> 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,
@@ -569,17 +569,17 @@ nsXBLContentSink::ConstructBinding(uint3
   }
 
   return rv;
 }
 
 static bool
 FindValue(const char16_t **aAtts, nsIAtom *aAtom, const char16_t **aResult)
 {
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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];
@@ -602,17 +602,17 @@ nsXBLContentSink::ConstructHandler(const
   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;
 
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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;
     }
@@ -700,17 +700,17 @@ nsXBLContentSink::ConstructImplementatio
   mImplMember = nullptr;
   mImplField = nullptr;
 
   if (!mBinding)
     return;
 
   const char16_t* name = nullptr;
 
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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;
     }
@@ -732,17 +732,17 @@ nsXBLContentSink::ConstructImplementatio
 }
 
 void
 nsXBLContentSink::ConstructField(const char16_t **aAtts, uint32_t aLineNumber)
 {
   const char16_t* name     = nullptr;
   const char16_t* readonly = nullptr;
 
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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;
     }
@@ -769,17 +769,17 @@ 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;
 
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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;
     }
@@ -903,17 +903,17 @@ nsXBLContentSink::AddAttributesToXULProt
   if (aAttsCount > 0) {
     attrs = new nsXULPrototypeAttribute[aAttsCount];
   }
 
   aElement->mAttributes    = attrs;
   aElement->mNumAttributes = aAttsCount;
 
   // Copy the attributes into the prototype
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> 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) {
--- a/dom/xbl/nsXBLEventHandler.h
+++ b/dom/xbl/nsXBLEventHandler.h
@@ -100,17 +100,17 @@ public:
 private:
   nsXBLKeyEventHandler();
   virtual ~nsXBLKeyEventHandler();
 
   bool ExecuteMatchedHandlers(nsIDOMKeyEvent* aEvent, uint32_t aCharCode,
                               const IgnoreModifierState& aIgnoreModifierState);
 
   nsTArray<nsXBLPrototypeHandler*> mProtoHandlers;
-  nsCOMPtr<nsIAtom> mEventType;
+  RefPtr<nsIAtom> mEventType;
   uint8_t mPhase;
   uint8_t mType;
   bool mIsBoundToChrome;
   bool mUsingContentXBLScope;
 };
 
 already_AddRefed<nsXBLEventHandler>
 NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler,
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -80,18 +80,18 @@ public:
   nsIContent* GetElement() { return mElement; }
 
   nsXBLAttributeEntry* GetNext() { return mNext; }
   void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; }
 
 protected:
   nsIContent* mElement;
 
-  nsCOMPtr<nsIAtom> mSrcAttribute;
-  nsCOMPtr<nsIAtom> mDstAttribute;
+  RefPtr<nsIAtom> mSrcAttribute;
+  RefPtr<nsIAtom> mDstAttribute;
   int32_t mDstNameSpace;
   nsXBLAttributeEntry* mNext;
 };
 
 // =============================================================================
 
 // Implementation /////////////////////////////////////////////////////////////////
 
@@ -345,17 +345,17 @@ nsXBLPrototypeBinding::AttributeChanged(
 
     nsCOMPtr<nsIContent> realElement = LocateInstance(aChangedElement, content,
                                                       aAnonymousContent,
                                                       element);
 
     if (realElement) {
       // Hold a strong reference here so that the atom doesn't go away during
       // UnsetAttr.
-      nsCOMPtr<nsIAtom> dstAttr = xblAttr->GetDstAttribute();
+      RefPtr<nsIAtom> dstAttr = xblAttr->GetDstAttribute();
       int32_t dstNs = xblAttr->GetDstNameSpace();
 
       if (aRemoveFlag)
         realElement->UnsetAttr(dstNs, dstAttr, aNotify);
       else {
         bool attrPresent = true;
         nsAutoString value;
         // Check to see if the src attribute is xbl:text.  If so, then we need to obtain the
@@ -632,19 +632,19 @@ nsXBLPrototypeBinding::ConstructAttribut
       char* str = ToNewCString(inherits);
       char* newStr;
       // XXX We should use a strtok function that tokenizes PRUnichars
       // so that we don't have to convert from Unicode to ASCII and then back
 
       char* token = nsCRT::strtok( str, ", ", &newStr );
       while( token != nullptr ) {
         // Build an atom out of this attribute.
-        nsCOMPtr<nsIAtom> atom;
+        RefPtr<nsIAtom> atom;
         int32_t atomNsID = kNameSpaceID_None;
-        nsCOMPtr<nsIAtom> attribute;
+        RefPtr<nsIAtom> attribute;
         int32_t attributeNsID = kNameSpaceID_None;
 
         // Figure out if this token contains a :.
         NS_ConvertASCIItoUTF16 attrTok(token);
         int32_t index = attrTok.Find("=", true);
         nsresult rv;
         if (index != -1) {
           // This attribute maps to something different.
@@ -768,17 +768,17 @@ nsXBLPrototypeBinding::AddResourceListen
   return NS_OK;
 }
 
 void
 nsXBLPrototypeBinding::CreateKeyHandlers()
 {
   nsXBLPrototypeHandler* curr = mPrototypeHandler;
   while (curr) {
-    nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
+    RefPtr<nsIAtom> eventAtom = curr->GetEventName();
     if (eventAtom == nsGkAtoms::keyup ||
         eventAtom == nsGkAtoms::keydown ||
         eventAtom == nsGkAtoms::keypress) {
       uint8_t phase = curr->GetPhase();
       uint8_t type = curr->GetType();
 
       int32_t count = mKeyHandlers.Count();
       int32_t i;
@@ -975,18 +975,18 @@ nsXBLPrototypeBinding::Read(nsIObjectInp
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = aStream->ReadString(attrName);
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = aStream->ReadString(attrValue);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCOMPtr<nsIAtom> atomPrefix = NS_Atomize(attrPrefix);
-      nsCOMPtr<nsIAtom> atomName = NS_Atomize(attrName);
+      RefPtr<nsIAtom> atomPrefix = NS_Atomize(attrPrefix);
+      RefPtr<nsIAtom> atomName = NS_Atomize(attrName);
       mBinding->SetAttr(attrNamespace, atomName, atomPrefix, attrValue, false);
     }
   }
 
   // Finally, read in the resources.
   while (true) {
     XBLBindingSerializeDetails type;
     rv = aStream->Read8(&type);
@@ -1224,24 +1224,24 @@ nsXBLPrototypeBinding::ReadContentNode(n
     return NS_OK;
   }
 
   // Otherwise, it's an element, so read its tag, attributes and children.
   nsAutoString prefix, tag;
   rv = aStream->ReadString(prefix);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIAtom> prefixAtom;
+  RefPtr<nsIAtom> prefixAtom;
   if (!prefix.IsEmpty())
     prefixAtom = NS_Atomize(prefix);
 
   rv = aStream->ReadString(tag);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIAtom> tagAtom = NS_Atomize(tag);
+  RefPtr<nsIAtom> tagAtom = NS_Atomize(tag);
   RefPtr<NodeInfo> nodeInfo =
     aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsIDOMNode::ELEMENT_NODE);
 
   uint32_t attrCount;
   rv = aStream->Read32(&attrCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create XUL prototype elements, or regular elements for other namespaces.
@@ -1269,22 +1269,22 @@ nsXBLPrototypeBinding::ReadContentNode(n
       nsAutoString prefix, name, val;
       rv = aStream->ReadString(prefix);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = aStream->ReadString(name);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = aStream->ReadString(val);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(name);
+      RefPtr<nsIAtom> nameAtom = NS_Atomize(name);
       if (namespaceID == kNameSpaceID_None) {
         attrs[i].mName.SetTo(nameAtom);
       }
       else {
-        nsCOMPtr<nsIAtom> prefixAtom;
+        RefPtr<nsIAtom> prefixAtom;
         if (!prefix.IsEmpty())
           prefixAtom = NS_Atomize(prefix);
 
         RefPtr<NodeInfo> ni =
           aNim->GetNodeInfo(nameAtom, prefixAtom,
                             namespaceID, nsIDOMNode::ATTRIBUTE_NODE);
         attrs[i].mName.SetTo(ni);
       }
@@ -1312,21 +1312,21 @@ nsXBLPrototypeBinding::ReadContentNode(n
       nsAutoString prefix, name, val;
       rv = aStream->ReadString(prefix);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = aStream->ReadString(name);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = aStream->ReadString(val);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCOMPtr<nsIAtom> prefixAtom;
+      RefPtr<nsIAtom> prefixAtom;
       if (!prefix.IsEmpty())
         prefixAtom = NS_Atomize(prefix);
 
-      nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(name);
+      RefPtr<nsIAtom> nameAtom = NS_Atomize(name);
       content->SetAttr(namespaceID, nameAtom, prefixAtom, val, false);
     }
 
 #ifdef MOZ_XUL
   }
 #endif
 
   // Now read the attribute forwarding entries (xbl:inherits)
@@ -1339,18 +1339,18 @@ nsXBLPrototypeBinding::ReadContentNode(n
     nsAutoString srcAttribute, destAttribute;
     rv = aStream->ReadString(srcAttribute);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = ReadNamespace(aStream, destNamespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = aStream->ReadString(destAttribute);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIAtom> srcAtom = NS_Atomize(srcAttribute);
-    nsCOMPtr<nsIAtom> destAtom = NS_Atomize(destAttribute);
+    RefPtr<nsIAtom> srcAtom = NS_Atomize(srcAttribute);
+    RefPtr<nsIAtom> destAtom = NS_Atomize(destAttribute);
 
     EnsureAttributeTable();
     AddToAttributeTable(srcNamespaceID, srcAtom, destNamespaceID, destAtom, content);
 
     rv = ReadNamespace(aStream, srcNamespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -1610,17 +1610,17 @@ nsXBLPrototypeBinding::ResolveBaseBindin
 
   if (!prefix.IsEmpty()) {
     mBinding->LookupNamespaceURI(prefix, nameSpace);
     if (!nameSpace.IsEmpty()) {
       int32_t nameSpaceID =
         nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace,
                                                            nsContentUtils::IsChromeDoc(doc));
 
-      nsCOMPtr<nsIAtom> tagName = NS_Atomize(display);
+      RefPtr<nsIAtom> tagName = NS_Atomize(display);
       // Check the white list
       if (!CheckTagNameWhiteList(nameSpaceID, tagName)) {
         const char16_t* params[] = { display.get() };
         nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
                                         NS_LITERAL_CSTRING("XBL"), nullptr,
                                         nsContentUtils::eXBL_PROPERTIES,
                                        "InvalidExtendsBinding",
                                         params, ArrayLength(params),
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -263,17 +263,17 @@ public:
   nsIContent* LocateInstance(nsIContent* aBoundElt,
                              nsIContent* aTemplRoot,
                              nsIContent* aCopyRoot,
                              nsIContent* aTemplChild);
 
   bool ChromeOnlyContent() { return mChromeOnlyContent; }
   bool BindToUntrustedContent() { return mBindToUntrustedContent; }
 
-  typedef nsClassHashtable<nsISupportsHashKey, nsXBLAttributeEntry> InnerAttributeTable;
+  typedef nsClassHashtable<nsRefPtrHashKey<nsIAtom>, nsXBLAttributeEntry> InnerAttributeTable;
 
 protected:
   // Ensure that mAttributeTable has been created.
   void EnsureAttributeTable();
   // Ad an entry to the attribute table
   void AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
                            int32_t aDestNamespaceID, nsIAtom* aDestTag,
                            nsIContent* aContent);
@@ -350,14 +350,14 @@ protected:
     enum { ALLOW_MEMMOVE = true };
 
   private:
     nsIID mKey;
   };
   nsInterfaceHashtable<IIDHashKey, nsIContent> mInterfaceTable; // A table of cached interfaces that we support.
 
   int32_t mBaseNameSpaceID;    // If we extend a tagname/namespace, then that information will
-  nsCOMPtr<nsIAtom> mBaseTag;  // be stored in here.
+  RefPtr<nsIAtom> mBaseTag;  // be stored in here.
 
   nsCOMArray<nsXBLKeyEventHandler> mKeyHandlers;
 };
 
 #endif
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -289,17 +289,17 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
   // event at the element.  It will take care of retargeting it to its
   // command element, if applicable, and executing the event handler.
   if (isXULKey) {
     return DispatchXULKeyCommand(aEvent);
   }
 
   // Look for a compiled handler on the element.
   // Should be compiled and bound with "on" in front of the name.
-  nsCOMPtr<nsIAtom> onEventAtom = NS_Atomize(NS_LITERAL_STRING("onxbl") +
+  RefPtr<nsIAtom> onEventAtom = NS_Atomize(NS_LITERAL_STRING("onxbl") +
                                              nsDependentAtomString(mEventName));
 
   // Compile the handler and bind it to the element.
   nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
   nsCOMPtr<nsPIWindowRoot> winRoot = do_QueryInterface(aTarget);
   if (winRoot) {
     if (nsCOMPtr<nsPIDOMWindowOuter> window = winRoot->GetWindow()) {
       nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
@@ -656,17 +656,17 @@ nsXBLPrototypeHandler::GetModifiersMask(
   }
 
   return modifiersMask;
 }
 
 already_AddRefed<nsIAtom>
 nsXBLPrototypeHandler::GetEventName()
 {
-  nsCOMPtr<nsIAtom> eventName = mEventName;
+  RefPtr<nsIAtom> eventName = mEventName;
   return eventName.forget();
 }
 
 already_AddRefed<nsIController>
 nsXBLPrototypeHandler::GetController(EventTarget* aTarget)
 {
   // XXX Fix this so there's a generic interface that describes controllers,
   // This code should have no special knowledge of what objects might have controllers.
--- a/dom/xbl/nsXBLPrototypeHandler.h
+++ b/dom/xbl/nsXBLPrototypeHandler.h
@@ -239,14 +239,14 @@ protected:
                              // in order to be matched.
 
   // The primary filter information for mouse/key events.
   int32_t mDetail;           // For key events, contains a charcode or keycode. For
                              // mouse events, stores the button info.
 
   // Prototype handlers are chained. We own the next handler in the chain.
   nsXBLPrototypeHandler* mNextHandler;
-  nsCOMPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
+  RefPtr<nsIAtom> mEventName; // The type of the event, e.g., "keypress"
   RefPtr<nsXBLEventHandler> mHandler;
   nsXBLPrototypeBinding* mPrototypeBinding; // the binding owns us
 };
 
 #endif
--- a/dom/xbl/nsXBLWindowKeyHandler.cpp
+++ b/dom/xbl/nsXBLWindowKeyHandler.cpp
@@ -505,17 +505,17 @@ nsXBLWindowKeyHandler::HandleEvent(nsIDO
 
   // If this event was handled by APZ then don't do the default action, and
   // preventDefault to prevent any other listeners from handling the event.
   if (widgetKeyboardEvent->mFlags.mHandledByAPZ) {
     aEvent->PreventDefault();
     return NS_OK;
   }
 
-  nsCOMPtr<nsIAtom> eventTypeAtom =
+  RefPtr<nsIAtom> eventTypeAtom =
     ConvertEventToDOMEventType(*widgetKeyboardEvent);
   return WalkHandlers(keyEvent, eventTypeAtom);
 }
 
 void
 nsXBLWindowKeyHandler::HandleEventOnCaptureInDefaultEventGroup(
                          nsIDOMKeyEvent* aEvent)
 {
@@ -805,17 +805,17 @@ nsXBLWindowKeyHandler::HasHandlerForEven
   NS_ENSURE_SUCCESS(rv, false);
 
   bool isDisabled;
   nsCOMPtr<Element> el = GetElement(&isDisabled);
   if (el && isDisabled) {
     return false;
   }
 
-  nsCOMPtr<nsIAtom> eventTypeAtom =
+  RefPtr<nsIAtom> eventTypeAtom =
     ConvertEventToDOMEventType(*widgetKeyboardEvent);
   return WalkHandlersInternal(aEvent, eventTypeAtom, mHandler, false,
                               aOutReservedForChrome);
 }
 
 already_AddRefed<Element>
 nsXBLWindowKeyHandler::GetElement(bool* aIsDisabled)
 {
--- a/dom/xml/ProcessingInstruction.cpp
+++ b/dom/xml/ProcessingInstruction.cpp
@@ -17,17 +17,17 @@ NS_NewXMLProcessingInstruction(nsNodeInf
                                const nsAString& aTarget,
                                const nsAString& aData)
 {
   using mozilla::dom::ProcessingInstruction;
   using mozilla::dom::XMLStylesheetProcessingInstruction;
 
   NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
 
-  nsCOMPtr<nsIAtom> target = NS_Atomize(aTarget);
+  RefPtr<nsIAtom> target = NS_Atomize(aTarget);
   MOZ_ASSERT(target);
 
   if (target == nsGkAtoms::xml_stylesheet) {
     RefPtr<XMLStylesheetProcessingInstruction> pi =
       new XMLStylesheetProcessingInstruction(aNodeInfoManager, aData);
     return pi.forget();
   }
 
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -940,17 +940,17 @@ nsXMLContentSink::HandleStartElement(con
   MOZ_ASSERT(eXMLContentSinkState_InEpilog != mState);
 
   FlushText();
   DidAddContent();
 
   mState = eXMLContentSinkState_InDocumentElement;
 
   int32_t nameSpaceID;
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> prefix, localName;
   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
                                  getter_AddRefs(localName), &nameSpaceID);
 
   if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName, aLineNumber)) {
     return NS_OK;
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
@@ -1046,17 +1046,17 @@ nsXMLContentSink::HandleEndElement(const
   nsCOMPtr<nsIContent> content;
   sn->mContent.swap(content);
   uint32_t numFlushed = sn->mNumFlushed;
 
   PopContent();
   NS_ASSERTION(content, "failed to pop content");
 #ifdef DEBUG
   // Check that we're closing the right thing
-  nsCOMPtr<nsIAtom> debugNameSpacePrefix, debugTagAtom;
+  RefPtr<nsIAtom> debugNameSpacePrefix, debugTagAtom;
   int32_t debugNameSpaceID;
   nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix),
                                  getter_AddRefs(debugTagAtom),
                                  &debugNameSpaceID);
   // Check if we are closing a template element because template
   // elements do not get pushed on the stack, the template
   // element content is pushed instead.
   bool isTemplateElement = debugTagAtom == nsGkAtoms::_template &&
@@ -1149,17 +1149,17 @@ nsXMLContentSink::HandleDoctypeDecl(cons
                                     nsISupports* aCatalogData)
 {
   FlushText();
 
   nsresult rv = NS_OK;
 
   NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment");
 
-  nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+  RefPtr<nsIAtom> name = NS_Atomize(aName);
   NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
 
   // Create a new doctype node
   nsCOMPtr<nsIDOMDocumentType> docType;
   rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager,
                              name, aPublicId, aSystemId, aSubset);
   if (NS_FAILED(rv) || !docType) {
     return rv;
@@ -1398,17 +1398,17 @@ nsXMLContentSink::ReportError(const char
   return NS_OK;
 }
 
 nsresult
 nsXMLContentSink::AddAttributes(const char16_t** aAtts,
                                 nsIContent* aContent)
 {
   // Add tag attributes to the content attributes
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> prefix, localName;
   while (*aAtts) {
     int32_t nameSpaceID;
     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
                                    getter_AddRefs(localName), &nameSpaceID);
 
     // Add attribute to content
     aContent->SetAttr(nameSpaceID, localName, prefix,
                       nsDependentString(aAtts[1]), false);
--- a/dom/xslt/base/txExpandedName.cpp
+++ b/dom/xslt/base/txExpandedName.cpp
@@ -17,17 +17,17 @@ txExpandedName::init(const nsAString& aQ
     const nsString& qName = PromiseFlatString(aQName);
     const char16_t* colon;
     bool valid = XMLUtils::isValidQName(qName, &colon);
     if (!valid) {
         return NS_ERROR_FAILURE;
     }
 
     if (colon) {
-        nsCOMPtr<nsIAtom> prefix = NS_Atomize(Substring(qName.get(), colon));
+        RefPtr<nsIAtom> prefix = NS_Atomize(Substring(qName.get(), colon));
         int32_t namespaceID = aResolver->lookupNamespace(prefix);
         if (namespaceID == kNameSpaceID_Unknown)
             return NS_ERROR_FAILURE;
         mNamespaceID = namespaceID;
 
         const char16_t *end;
         qName.EndReading(end);
         mLocalName = NS_Atomize(Substring(colon + 1, end));
--- a/dom/xslt/base/txExpandedName.h
+++ b/dom/xslt/base/txExpandedName.h
@@ -59,12 +59,12 @@ public:
 
     bool operator != (const txExpandedName& rhs) const
     {
         return ((mLocalName != rhs.mLocalName) ||
                 (mNamespaceID != rhs.mNamespaceID));
     }
 
     int32_t mNamespaceID;
-    nsCOMPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mLocalName;
 };
 
 #endif
--- a/dom/xslt/base/txExpandedNameMap.h
+++ b/dom/xslt/base/txExpandedNameMap.h
@@ -89,17 +89,17 @@ protected:
         uint32_t mCurrentPos;
     };
 
     friend class iterator_base;
 
     friend class txMapItemComparator;
     struct MapItem {
         int32_t mNamespaceID;
-        nsCOMPtr<nsIAtom> mLocalName;
+        RefPtr<nsIAtom> mLocalName;
         void* mValue;
     };
 
     nsTArray<MapItem> mItems;
 };
 
 template<class E>
 class txExpandedNameMap : public txExpandedNameMap_base
--- a/dom/xslt/base/txNamespaceMap.cpp
+++ b/dom/xslt/base/txNamespaceMap.cpp
@@ -22,17 +22,17 @@ txNamespaceMap::mapNamespace(nsIAtom* aP
 {
     nsIAtom* prefix = aPrefix == nsGkAtoms::_empty ? nullptr : aPrefix;
 
     int32_t nsId;
     if (prefix && aNamespaceURI.IsEmpty()) {
         // Remove the mapping
         int32_t index = mPrefixes.IndexOf(prefix);
         if (index >= 0) {
-            mPrefixes.RemoveObjectAt(index);
+            mPrefixes.RemoveElementAt(index);
             mNamespaces.RemoveElementAt(index);
         }
 
         return NS_OK;
     }
 
     if (aNamespaceURI.IsEmpty()) {
         // Set default to empty namespace
@@ -47,22 +47,22 @@ txNamespaceMap::mapNamespace(nsIAtom* aP
     int32_t index = mPrefixes.IndexOf(prefix);
     if (index >= 0) {
         mNamespaces.ElementAt(index) = nsId;
 
         return NS_OK;
     }
 
     // New mapping
-    if (!mPrefixes.AppendObject(prefix)) {
+    if (!mPrefixes.AppendElement(prefix)) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (mNamespaces.AppendElement(nsId) == nullptr) {
-        mPrefixes.RemoveObjectAt(mPrefixes.Count() - 1);
+        mPrefixes.RemoveElementAt(mPrefixes.Length() - 1);
 
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     return NS_OK;
 }
 
 int32_t
@@ -84,15 +84,15 @@ txNamespaceMap::lookupNamespace(nsIAtom*
     }
 
     return kNameSpaceID_Unknown;
 }
 
 int32_t
 txNamespaceMap::lookupNamespaceWithDefault(const nsAString& aPrefix)
 {
-    nsCOMPtr<nsIAtom> prefix = NS_Atomize(aPrefix);
+    RefPtr<nsIAtom> prefix = NS_Atomize(aPrefix);
     if (prefix != nsGkAtoms::_poundDefault) {
         return lookupNamespace(prefix);
     }
 
     return lookupNamespace(nullptr);
 }
--- a/dom/xslt/base/txNamespaceMap.h
+++ b/dom/xslt/base/txNamespaceMap.h
@@ -31,13 +31,13 @@ public:
     }
 
     nsresult mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI);
     int32_t lookupNamespace(nsIAtom* aPrefix);
     int32_t lookupNamespaceWithDefault(const nsAString& aPrefix);
 
 private:
     nsAutoRefCnt mRefCnt;
-    nsCOMArray<nsIAtom> mPrefixes;
+    nsTArray<RefPtr<nsIAtom>> mPrefixes;
     nsTArray<int32_t> mNamespaces;
 };
 
 #endif //TRANSFRMX_TXNAMESPACEMAP_H
--- a/dom/xslt/xpath/txExpr.h
+++ b/dom/xslt/xpath/txExpr.h
@@ -444,18 +444,18 @@ public:
      */
     txNameTest(nsIAtom* aPrefix, nsIAtom* aLocalName, int32_t aNSID,
                uint16_t aNodeType);
 
     NodeTestType getType() override;
 
     TX_DECL_NODE_TEST
 
-    nsCOMPtr<nsIAtom> mPrefix;
-    nsCOMPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
     int32_t mNamespace;
 private:
     uint16_t mNodeType;
 };
 
 /*
  * This class represents a NodeType as defined by the XPath spec
  */
@@ -491,17 +491,17 @@ public:
     }
 
     NodeTestType getType() override;
 
     TX_DECL_NODE_TEST
 
 private:
     NodeType mNodeType;
-    nsCOMPtr<nsIAtom> mNodeName;
+    RefPtr<nsIAtom> mNodeName;
 };
 
 /**
  * Class representing a nodetest combined with a predicate. May only be used
  * if the predicate is not sensitive to the context-nodelist.
  */
 class txPredicatedNodeTest : public txNodeTest
 {
@@ -826,18 +826,18 @@ class VariableRefExpr : public Expr {
 
 public:
 
     VariableRefExpr(nsIAtom* aPrefix, nsIAtom* aLocalName, int32_t aNSID);
 
     TX_DECL_EXPR
 
 private:
-    nsCOMPtr<nsIAtom> mPrefix;
-    nsCOMPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
     int32_t mNamespace;
 };
 
 /**
  *  Represents a PathExpr
 **/
 class PathExpr : public Expr {
 
@@ -975,18 +975,18 @@ class txNamedAttributeStep : public Expr
 public:
     txNamedAttributeStep(int32_t aNsID, nsIAtom* aPrefix,
                          nsIAtom* aLocalName);
 
     TX_DECL_EXPR
 
 private:
     int32_t mNamespace;
-    nsCOMPtr<nsIAtom> mPrefix;
-    nsCOMPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
 };
 
 /**
  *
  */
 class txUnionNodeTest : public txNodeTest
 {
 public:
--- a/dom/xslt/xpath/txExprParser.cpp
+++ b/dom/xslt/xpath/txExprParser.cpp
@@ -358,17 +358,17 @@ txExprParser::createFilterOrStep(txExprL
     switch (tok->mType) {
         case Token::FUNCTION_NAME_AND_PAREN:
             rv = createFunctionCall(lexer, aContext, getter_Transfers(expr));
             NS_ENSURE_SUCCESS(rv, rv);
             break;
         case Token::VAR_REFERENCE :
             lexer.nextToken();
             {
-                nsCOMPtr<nsIAtom> prefix, lName;
+                RefPtr<nsIAtom> prefix, lName;
                 int32_t nspace;
                 nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
                                            aContext, getter_AddRefs(lName),
                                            nspace);
                 NS_ENSURE_SUCCESS(rv, rv);
                 expr = new VariableRefExpr(prefix, lName, nspace);
             }
             break;
@@ -419,17 +419,17 @@ txExprParser::createFunctionCall(txExprL
 
     nsAutoPtr<FunctionCall> fnCall;
 
     Token* tok = lexer.nextToken();
     NS_ASSERTION(tok->mType == Token::FUNCTION_NAME_AND_PAREN,
                  "FunctionCall expected");
 
     //-- compare function names
-    nsCOMPtr<nsIAtom> prefix, lName;
+    RefPtr<nsIAtom> prefix, lName;
     int32_t namespaceID;
     nsresult rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
                                getter_AddRefs(lName), namespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
 
     txCoreFunctionCall::eType type;
     if (namespaceID == kNameSpaceID_None &&
         txCoreFunctionCall::getTypeFromAtom(lName, type)) {
@@ -477,17 +477,17 @@ txExprParser::createLocationStep(txExprL
 
     //-- get Axis Identifier or AbbreviatedStep, if present
     Token* tok = lexer.peek();
     switch (tok->mType) {
         case Token::AXIS_IDENTIFIER:
         {
             //-- eat token
             lexer.nextToken();
-            nsCOMPtr<nsIAtom> axis = NS_Atomize(tok->Value());
+            RefPtr<nsIAtom> axis = NS_Atomize(tok->Value());
             if (axis == nsGkAtoms::ancestor) {
                 axisIdentifier = LocationStep::ANCESTOR_AXIS;
             }
             else if (axis == nsGkAtoms::ancestorOrSelf) {
                 axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
             }
             else if (axis == nsGkAtoms::attribute) {
                 axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
@@ -551,17 +551,17 @@ txExprParser::createLocationStep(txExprL
     //-- get NodeTest unless an AbbreviatedStep was found
     nsresult rv = NS_OK;
     if (!nodeTest) {
         tok = lexer.peek();
 
         if (tok->mType == Token::CNAME) {
             lexer.nextToken();
             // resolve QName
-            nsCOMPtr<nsIAtom> prefix, lName;
+            RefPtr<nsIAtom> prefix, lName;
             int32_t nspace;
             rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
                               aContext, getter_AddRefs(lName),
                               nspace, true);
             NS_ENSURE_SUCCESS(rv, rv);
 
             nodeTest =
               new txNameTest(prefix, lName, nspace,
--- a/dom/xslt/xpath/txFunctionCall.cpp
+++ b/dom/xslt/xpath/txFunctionCall.cpp
@@ -107,17 +107,17 @@ FunctionCall::argsSensitiveTo(ContextSen
 
     return false;
 }
 
 #ifdef TX_TO_STRING
 void
 FunctionCall::toString(nsAString& aDest)
 {
-    nsCOMPtr<nsIAtom> functionNameAtom;
+    RefPtr<nsIAtom> functionNameAtom;
     if (NS_FAILED(getNameAtom(getter_AddRefs(functionNameAtom)))) {
         NS_ERROR("Can't get function name.");
         return;
     }
 
 
 
     aDest.Append(nsDependentAtomString(functionNameAtom) +
--- a/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
+++ b/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
@@ -289,33 +289,33 @@ already_AddRefed<nsIAtom>
 txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
 {
     if (aNode.isDocument()) {
         return nullptr;
     }
 
     if (aNode.isContent()) {
         if (aNode.mNode->IsElement()) {
-            nsCOMPtr<nsIAtom> localName =
+            RefPtr<nsIAtom> localName =
                 aNode.Content()->NodeInfo()->NameAtom();
             return localName.forget();
         }
 
         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
             nsAutoString target;
             node->GetNodeName(target);
 
             return NS_Atomize(target);
         }
 
         return nullptr;
     }
 
-    nsCOMPtr<nsIAtom> localName = aNode.Content()->
+    RefPtr<nsIAtom> localName = aNode.Content()->
         GetAttrNameAt(aNode.mIndex)->LocalName();
 
     return localName.forget();
 }
 
 nsIAtom*
 txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
 {
--- a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
+++ b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
@@ -115,17 +115,17 @@ public:
 private:
     txArgumentType GetParamType(const nsXPTParamInfo &aParam,
                                 nsIInterfaceInfo *aInfo);
 
     nsCOMPtr<nsISupports> mHelper;
     nsIID mIID;
     uint16_t mMethodIndex;
 #ifdef TX_TO_STRING
-    nsCOMPtr<nsIAtom> mName;
+    RefPtr<nsIAtom> mName;
 #endif
     nsCOMPtr<nsISupports> mState;
 };
 
 txXPCOMExtensionFunctionCall::txXPCOMExtensionFunctionCall(nsISupports *aHelper,
                                                            const nsIID &aIID,
                                                            uint16_t aMethodIndex,
 #ifdef TX_TO_STRING
--- a/dom/xslt/xpath/txXPathTreeWalker.h
+++ b/dom/xslt/xpath/txXPathTreeWalker.h
@@ -200,17 +200,17 @@ inline bool
 txXPathNodeUtils::localNameEquals(const txXPathNode& aNode,
                                   nsIAtom* aLocalName)
 {
     if (aNode.isContent() &&
         aNode.Content()->IsElement()) {
         return aNode.Content()->NodeInfo()->Equals(aLocalName);
     }
 
-    nsCOMPtr<nsIAtom> localName = txXPathNodeUtils::getLocalName(aNode);
+    RefPtr<nsIAtom> localName = txXPathNodeUtils::getLocalName(aNode);
 
     return localName == aLocalName;
 }
 
 /* static */
 inline bool
 txXPathNodeUtils::isRoot(const txXPathNode& aNode)
 {
--- a/dom/xslt/xslt/txBufferingHandler.cpp
+++ b/dom/xslt/xslt/txBufferingHandler.cpp
@@ -95,19 +95,19 @@ public:
           mNsID(aNsID)
     {
         MOZ_COUNT_CTOR_INHERITED(txStartElementAtomTransaction, txOutputTransaction);
     }
     virtual ~txStartElementAtomTransaction()
     {
         MOZ_COUNT_DTOR_INHERITED(txStartElementAtomTransaction, txOutputTransaction);
     }
-    nsCOMPtr<nsIAtom> mPrefix;
-    nsCOMPtr<nsIAtom> mLocalName;
-    nsCOMPtr<nsIAtom> mLowercaseLocalName;
+    RefPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mLowercaseLocalName;
     int32_t mNsID;
 };
 
 class txStartElementTransaction : public txOutputTransaction
 {
 public:
     txStartElementTransaction(nsIAtom* aPrefix,
                               const nsAString& aLocalName, int32_t aNsID)
@@ -117,17 +117,17 @@ public:
           mNsID(aNsID)
     {
         MOZ_COUNT_CTOR_INHERITED(txStartElementTransaction, txOutputTransaction);
     }
     virtual ~txStartElementTransaction()
     {
         MOZ_COUNT_DTOR_INHERITED(txStartElementTransaction, txOutputTransaction);
     }
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mPrefix;
     nsString mLocalName;
     int32_t mNsID;
 };
 
 class txAttributeTransaction : public txOutputTransaction
 {
 public:
     txAttributeTransaction(nsIAtom* aPrefix,
@@ -140,17 +140,17 @@ public:
           mValue(aValue)
     {
         MOZ_COUNT_CTOR_INHERITED(txAttributeTransaction, txOutputTransaction);
     }
     virtual ~txAttributeTransaction()
     {
         MOZ_COUNT_DTOR_INHERITED(txAttributeTransaction, txOutputTransaction);
     }
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mPrefix;
     nsString mLocalName;
     int32_t mNsID;
     nsString mValue;
 };
 
 class txAttributeAtomTransaction : public txOutputTransaction
 {
 public:
@@ -165,19 +165,19 @@ public:
           mValue(aValue)
     {
         MOZ_COUNT_CTOR_INHERITED(txAttributeAtomTransaction, txOutputTransaction);
     }
     virtual ~txAttributeAtomTransaction()
     {
         MOZ_COUNT_DTOR_INHERITED(txAttributeAtomTransaction, txOutputTransaction);
     }
-    nsCOMPtr<nsIAtom> mPrefix;
-    nsCOMPtr<nsIAtom> mLocalName;
-    nsCOMPtr<nsIAtom> mLowercaseLocalName;
+    RefPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mLowercaseLocalName;
     int32_t mNsID;
     nsString mValue;
 };
 
 txBufferingHandler::txBufferingHandler() : mCanAddAttribute(false)
 {
     MOZ_COUNT_CTOR(txBufferingHandler);
     mBuffer = new txResultBuffer();
--- a/dom/xslt/xslt/txExecutionState.h
+++ b/dom/xslt/xslt/txExecutionState.h
@@ -82,17 +82,17 @@ public:
 
     /**
      * Struct holding information about a current template rule
      */
     class TemplateRule {
     public:
         txStylesheet::ImportFrame* mFrame;
         int32_t mModeNsId;
-        nsCOMPtr<nsIAtom> mModeLocalName;
+        RefPtr<nsIAtom> mModeLocalName;
         txVariableMap* mParams;
     };
 
     // Stack functions
     nsresult pushEvalContext(txIEvalContext* aContext);
     txIEvalContext* popEvalContext();
 
     /**
--- a/dom/xslt/xslt/txInstructions.cpp
+++ b/dom/xslt/xslt/txInstructions.cpp
@@ -108,17 +108,17 @@ txAttribute::execute(txExecutionState& a
     NS_ENSURE_SUCCESS(rv, rv);
 
     const char16_t* colon;
     if (!XMLUtils::isValidQName(name, &colon) ||
         TX_StringEqualsAtom(name, nsGkAtoms::xmlns)) {
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> prefix;
+    RefPtr<nsIAtom> prefix;
     uint32_t lnameStart = 0;
     if (colon) {
         prefix = NS_Atomize(Substring(name.get(), colon));
         lnameStart = colon - name.get() + 1;
     }
 
     int32_t nsId = kNameSpaceID_None;
     if (mNamespace) {
@@ -224,17 +224,17 @@ nsresult
 txCopyBase::copyNode(const txXPathNode& aNode, txExecutionState& aEs)
 {
     switch (txXPathNodeUtils::getNodeType(aNode)) {
         case txXPathNodeType::ATTRIBUTE_NODE:
         {
             nsAutoString nodeValue;
             txXPathNodeUtils::appendNodeValue(aNode, nodeValue);
 
-            nsCOMPtr<nsIAtom> localName =
+            RefPtr<nsIAtom> localName =
                 txXPathNodeUtils::getLocalName(aNode);
             return aEs.mResultHandler->
                 attribute(txXPathNodeUtils::getPrefix(aNode),
                           localName, nullptr,
                           txXPathNodeUtils::getNamespaceID(aNode),
                           nodeValue);
         }
         case txXPathNodeType::COMMENT_NODE:
@@ -252,17 +252,17 @@ txCopyBase::copyNode(const txXPathNode& 
             while (hasChild) {
                 copyNode(walker.getCurrentPosition(), aEs);
                 hasChild = walker.moveToNextSibling();
             }
             break;
         }
         case txXPathNodeType::ELEMENT_NODE:
         {
-            nsCOMPtr<nsIAtom> localName =
+            RefPtr<nsIAtom> localName =
                 txXPathNodeUtils::getLocalName(aNode);
             nsresult rv = aEs.mResultHandler->
                 startElement(txXPathNodeUtils::getPrefix(aNode),
                              localName, nullptr,
                              txXPathNodeUtils::getNamespaceID(aNode));
             NS_ENSURE_SUCCESS(rv, rv);
 
             // Copy attributes
@@ -335,17 +335,17 @@ txCopy::execute(txExecutionState& aEs)
 
             rv = aEs.pushBool(false);
             NS_ENSURE_SUCCESS(rv, rv);
 
             break;
         }
         case txXPathNodeType::ELEMENT_NODE:
         {
-            nsCOMPtr<nsIAtom> localName =
+            RefPtr<nsIAtom> localName =
                 txXPathNodeUtils::getLocalName(node);
             rv = aEs.mResultHandler->
                 startElement(txXPathNodeUtils::getPrefix(node),
                              localName, nullptr,
                              txXPathNodeUtils::getNamespaceID(node));
             NS_ENSURE_SUCCESS(rv, rv);
 
             // XXX copy namespace nodes once we have them
@@ -821,17 +821,17 @@ nsresult
 txStartElement::execute(txExecutionState& aEs)
 {
     nsAutoString name;
     nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
     NS_ENSURE_SUCCESS(rv, rv);
 
 
     int32_t nsId = kNameSpaceID_None;
-    nsCOMPtr<nsIAtom> prefix;
+    RefPtr<nsIAtom> prefix;
     uint32_t lnameStart = 0;
 
     const char16_t* colon;
     if (XMLUtils::isValidQName(name, &colon)) {
         if (colon) {
             prefix = NS_Atomize(Substring(name.get(), colon));
             lnameStart = colon - name.get() + 1;
         }
--- a/dom/xslt/xslt/txInstructions.h
+++ b/dom/xslt/xslt/txInstructions.h
@@ -186,19 +186,19 @@ class txLREAttribute : public txInstruct
 {
 public:
     txLREAttribute(int32_t aNamespaceID, nsIAtom* aLocalName,
                    nsIAtom* aPrefix, nsAutoPtr<Expr>&& aValue);
 
     TX_DECL_TXINSTRUCTION
 
     int32_t mNamespaceID;
-    nsCOMPtr<nsIAtom> mLocalName;
-    nsCOMPtr<nsIAtom> mLowercaseLocalName;
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mLowercaseLocalName;
+    RefPtr<nsIAtom> mPrefix;
     nsAutoPtr<Expr> mValue;
 };
 
 class txMessage : public txInstruction
 {
 public:
     explicit txMessage(bool aTerminate);
 
@@ -353,19 +353,19 @@ class txStartLREElement : public txInstr
 {
 public:
     txStartLREElement(int32_t aNamespaceID, nsIAtom* aLocalName,
                       nsIAtom* aPrefix);
 
     TX_DECL_TXINSTRUCTION
 
     int32_t mNamespaceID;
-    nsCOMPtr<nsIAtom> mLocalName;
-    nsCOMPtr<nsIAtom> mLowercaseLocalName;
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mLowercaseLocalName;
+    RefPtr<nsIAtom> mPrefix;
 };
 
 class txText : public txInstruction
 {
 public:
     txText(const nsAString& aStr, bool aDOE);
 
     TX_DECL_TXINSTRUCTION
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -100,17 +100,17 @@ txMozillaXMLOutput::~txMozillaXMLOutput(
 
 nsresult
 txMozillaXMLOutput::attribute(nsIAtom* aPrefix,
                               nsIAtom* aLocalName,
                               nsIAtom* aLowercaseLocalName,
                               const int32_t aNsID,
                               const nsString& aValue)
 {
-    nsCOMPtr<nsIAtom> owner;
+    RefPtr<nsIAtom> owner;
     if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) {
         if (aLowercaseLocalName) {
             aLocalName = aLowercaseLocalName;
         }
         else {
             owner = TX_ToLowerCaseAtom(aLocalName);
             NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
 
@@ -122,17 +122,17 @@ txMozillaXMLOutput::attribute(nsIAtom* a
 }
 
 nsresult
 txMozillaXMLOutput::attribute(nsIAtom* aPrefix,
                               const nsAString& aLocalName,
                               const int32_t aNsID,
                               const nsString& aValue)
 {
-    nsCOMPtr<nsIAtom> lname;
+    RefPtr<nsIAtom> lname;
 
     if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) {
         nsAutoString lnameStr;
         nsContentUtils::ASCIIToLower(aLocalName, lnameStr);
         lname = NS_Atomize(lnameStr);
     }
     else {
         lname = NS_Atomize(aLocalName);
@@ -431,17 +431,17 @@ nsresult
 txMozillaXMLOutput::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
                                  nsIAtom* aLowercaseLocalName,
                                  const int32_t aNsID)
 {
     NS_PRECONDITION(aNsID != kNameSpaceID_None || !aPrefix,
                     "Can't have prefix without namespace");
 
     if (mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) {
-        nsCOMPtr<nsIAtom> owner;
+        RefPtr<nsIAtom> owner;
         if (!aLowercaseLocalName) {
             owner = TX_ToLowerCaseAtom(aLocalName);
             NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
 
             aLowercaseLocalName = owner;
         }
         return startElementInternal(nullptr,
                                     aLowercaseLocalName,
@@ -452,17 +452,17 @@ txMozillaXMLOutput::startElement(nsIAtom
 }
 
 nsresult
 txMozillaXMLOutput::startElement(nsIAtom* aPrefix,
                                  const nsAString& aLocalName,
                                  const int32_t aNsID)
 {
     int32_t nsId = aNsID;
-    nsCOMPtr<nsIAtom> lname;
+    RefPtr<nsIAtom> lname;
 
     if (mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) {
         nsId = kNameSpaceID_XHTML;
 
         nsAutoString lnameStr;
         nsContentUtils::ASCIIToLower(aLocalName, lnameStr);
         lname = NS_Atomize(lnameStr);
     }
@@ -753,17 +753,17 @@ txMozillaXMLOutput::endHTMLElement(nsICo
         // handle HTTP-EQUIV data
         nsAutoString httpEquiv;
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, httpEquiv);
         if (!httpEquiv.IsEmpty()) {
             nsAutoString value;
             aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value);
             if (!value.IsEmpty()) {
                 nsContentUtils::ASCIIToLower(httpEquiv);
-                nsCOMPtr<nsIAtom> header = NS_Atomize(httpEquiv);
+                RefPtr<nsIAtom> header = NS_Atomize(httpEquiv);
                 processHTTPEquiv(header, value);
             }
         }
     }
 
     return NS_OK;
 }
 
@@ -888,17 +888,17 @@ txMozillaXMLOutput::createResultDocument
         else {
             qName.Assign(aName);
         }
 
         nsCOMPtr<nsIDOMDocumentType> documentType;
 
         nsresult rv = nsContentUtils::CheckQName(qName);
         if (NS_SUCCEEDED(rv)) {
-            nsCOMPtr<nsIAtom> doctypeName = NS_Atomize(qName);
+            RefPtr<nsIAtom> doctypeName = NS_Atomize(qName);
             if (!doctypeName) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
 
             // Indicate that there is no internal subset (not just an empty one)
             rv = NS_NewDOMDocumentType(getter_AddRefs(documentType),
                                        mNodeInfoManager,
                                        doctypeName,
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -392,17 +392,17 @@ txMozillaXSLTProcessor::SetSourceContent
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 txMozillaXSLTProcessor::AddXSLTParamNamespace(const nsString& aPrefix,
                                               const nsString& aNamespace)
 {
-    nsCOMPtr<nsIAtom> pre = NS_Atomize(aPrefix);
+    RefPtr<nsIAtom> pre = NS_Atomize(aPrefix);
     return mParamNamespaceMap.mapNamespace(pre, aNamespace);
 }
 
 
 class txXSLTParamContext : public txIParseContext,
                            public txIEvalContext
 {
 public:
@@ -516,17 +516,17 @@ txMozillaXSLTProcessor::AddXSLTParam(con
         // Evaluate
         rv = expr->evaluate(&paramContext, getter_AddRefs(value));
         NS_ENSURE_SUCCESS(rv, rv);
     }
     else {
         value = new StringResult(aValue, nullptr);
     }
 
-    nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+    RefPtr<nsIAtom> name = NS_Atomize(aName);
     int32_t nsId = kNameSpaceID_Unknown;
     rv = nsContentUtils::NameSpaceManager()->
         RegisterNameSpace(aNamespace, nsId);
     NS_ENSURE_SUCCESS(rv, rv);
 
     txExpandedName varName(nsId, name);
     txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
     if (var) {
@@ -939,17 +939,17 @@ txMozillaXSLTProcessor::SetParameter(con
             return NS_ERROR_FAILURE;
         }
     }
 
     int32_t nsId = kNameSpaceID_Unknown;
     nsresult rv = nsContentUtils::NameSpaceManager()->
         RegisterNameSpace(aNamespaceURI, nsId);
     NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
+    RefPtr<nsIAtom> localName = NS_Atomize(aLocalName);
     txExpandedName varName(nsId, localName);
 
     txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
     if (var) {
         var->setValue(value);
         return NS_OK;
     }
 
@@ -961,17 +961,17 @@ NS_IMETHODIMP
 txMozillaXSLTProcessor::GetParameter(const nsAString& aNamespaceURI,
                                      const nsAString& aLocalName,
                                      nsIVariant **aResult)
 {
     int32_t nsId = kNameSpaceID_Unknown;
     nsresult rv = nsContentUtils::NameSpaceManager()->
         RegisterNameSpace(aNamespaceURI, nsId);
     NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
+    RefPtr<nsIAtom> localName = NS_Atomize(aLocalName);
     txExpandedName varName(nsId, localName);
 
     txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
     if (var) {
         return var->getValue(aResult);
     }
     return NS_OK;
 }
@@ -979,17 +979,17 @@ txMozillaXSLTProcessor::GetParameter(con
 NS_IMETHODIMP
 txMozillaXSLTProcessor::RemoveParameter(const nsAString& aNamespaceURI,
                                         const nsAString& aLocalName)
 {
     int32_t nsId = kNameSpaceID_Unknown;
     nsresult rv = nsContentUtils::NameSpaceManager()->
         RegisterNameSpace(aNamespaceURI, nsId);
     NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
+    RefPtr<nsIAtom> localName = NS_Atomize(aLocalName);
     txExpandedName varName(nsId, localName);
 
     mVariables.remove(varName);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 txMozillaXSLTProcessor::ClearParameters()
--- a/dom/xslt/xslt/txPatternParser.cpp
+++ b/dom/xslt/xslt/txPatternParser.cpp
@@ -124,17 +124,17 @@ nsresult txPatternParser::createLocPathP
                 aLexer.peek()->mType == Token::UNION_OP) {
                 aPattern = new txRootPattern();
                 return NS_OK;
             }
             break;
         case Token::FUNCTION_NAME_AND_PAREN:
             // id(Literal) or key(Literal, Literal)
             {
-                nsCOMPtr<nsIAtom> nameAtom =
+                RefPtr<nsIAtom> nameAtom =
                     NS_Atomize(aLexer.nextToken()->Value());
                 if (nameAtom == nsGkAtoms::id) {
                     rv = createIdPattern(aLexer, stepPattern);
                 }
                 else if (nameAtom == nsGkAtoms::key) {
                     rv = createKeyPattern(aLexer, aContext, stepPattern);
                 }
                 if (NS_FAILED(rv))
@@ -234,17 +234,17 @@ nsresult txPatternParser::createKeyPatte
         return NS_ERROR_XPATH_PARSE_FAILURE;
 
     if (!aContext->allowed(txIParseContext::KEY_FUNCTION))
         return NS_ERROR_XSLT_CALL_TO_KEY_NOT_ALLOWED;
 
     const char16_t* colon;
     if (!XMLUtils::isValidQName(PromiseFlatString(key), &colon))
         return NS_ERROR_XPATH_PARSE_FAILURE;
-    nsCOMPtr<nsIAtom> prefix, localName;
+    RefPtr<nsIAtom> prefix, localName;
     int32_t namespaceID;
     nsresult rv = resolveQName(key, getter_AddRefs(prefix), aContext,
                                getter_AddRefs(localName), namespaceID);
     if (NS_FAILED(rv))
         return rv;
 
     aPattern  = new txKeyPattern(prefix, localName, namespaceID, value);
     return NS_OK;
@@ -273,17 +273,17 @@ nsresult txPatternParser::createStepPatt
         isAttr = true;
     }
 
     txNodeTest* nodeTest;
     if (aLexer.peek()->mType == Token::CNAME) {
         tok = aLexer.nextToken();
 
         // resolve QName
-        nsCOMPtr<nsIAtom> prefix, lName;
+        RefPtr<nsIAtom> prefix, lName;
         int32_t nspace;
         rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
                           getter_AddRefs(lName), nspace, true);
         if (NS_FAILED(rv)) {
             // XXX error report namespace resolve failed
             return rv;
         }
 
--- a/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
+++ b/dom/xslt/xslt/txStylesheetCompileHandlers.cpp
@@ -312,17 +312,17 @@ static nsresult
 getYesNoAttr(txStylesheetAttr* aAttributes,
              int32_t aAttrCount,
              nsIAtom* aName,
              bool aRequired,
              txStylesheetCompilerState& aState,
              txThreeState& aRes)
 {
     aRes = eNotSet;
-    nsCOMPtr<nsIAtom> atom;
+    RefPtr<nsIAtom> atom;
     nsresult rv = getAtomAttr(aAttributes, aAttrCount, aName, aRequired,
                               aState, getter_AddRefs(atom));
     if (!atom) {
         return rv;
     }
 
     if (atom == nsGkAtoms::yes) {
         aRes = eTrue;
@@ -1009,17 +1009,17 @@ txFnStartStripSpace(int32_t aNamespaceID
 
     bool strip = aLocalName == nsGkAtoms::stripSpace;
 
     nsAutoPtr<txStripSpaceItem> stripItem(new txStripSpaceItem);
     nsWhitespaceTokenizer tokenizer(attr->mValue);
     while (tokenizer.hasMoreTokens()) {
         const nsAString& name = tokenizer.nextToken();
         int32_t ns = kNameSpaceID_None;
-        nsCOMPtr<nsIAtom> prefix, localName;
+        RefPtr<nsIAtom> prefix, localName;
         rv = XMLUtils::splitQName(name, getter_AddRefs(prefix),
                                   getter_AddRefs(localName));
         if (NS_FAILED(rv)) {
             // check for "*" or "prefix:*"
             uint32_t length = name.Length();
             const char16_t* c;
             name.BeginReading(c);
             if (length == 2 || c[length-1] != '*') {
@@ -1955,17 +1955,17 @@ txFnStartNumber(int32_t aNamespaceID,
                 nsIAtom* aLocalName,
                 nsIAtom* aPrefix,
                 txStylesheetAttr* aAttributes,
                 int32_t aAttrCount,
                 txStylesheetCompilerState& aState)
 {
     nsresult rv = NS_OK;
 
-    nsCOMPtr<nsIAtom> levelAtom;
+    RefPtr<nsIAtom> levelAtom;
     rv = getAtomAttr(aAttributes, aAttrCount, nsGkAtoms::level, false,
                      aState, getter_AddRefs(levelAtom));
     NS_ENSURE_SUCCESS(rv, rv);
 
     txXSLTNumber::LevelType level = txXSLTNumber::eLevelSingle;
     if (levelAtom == nsGkAtoms::multiple) {
         level = txXSLTNumber::eLevelMultiple;
     }
@@ -2849,17 +2849,17 @@ txHandlerTable::txHandlerTable(const Han
 
 nsresult
 txHandlerTable::init(const txElementHandler* aHandlers, uint32_t aCount)
 {
     nsresult rv = NS_OK;
 
     uint32_t i;
     for (i = 0; i < aCount; ++i) {
-        nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aHandlers->mLocalName);
+        RefPtr<nsIAtom> nameAtom = NS_Atomize(aHandlers->mLocalName);
         txExpandedName name(aHandlers->mNamespaceID, nameAtom);
         rv = mHandlers.add(name, aHandlers);
         NS_ENSURE_SUCCESS(rv, rv);
 
         ++aHandlers;
     }
     return NS_OK;
 }
--- a/dom/xslt/xslt/txStylesheetCompiler.cpp
+++ b/dom/xslt/xslt/txStylesheetCompiler.cpp
@@ -127,17 +127,17 @@ txStylesheetCompiler::startElement(const
     for (i = 0; i < aAttrCount; ++i) {
         rv = XMLUtils::splitExpatName(aAttrs[i * 2],
                                       getter_AddRefs(atts[i].mPrefix),
                                       getter_AddRefs(atts[i].mLocalName),
                                       &atts[i].mNamespaceID);
         NS_ENSURE_SUCCESS(rv, rv);
         atts[i].mValue.Append(aAttrs[i * 2 + 1]);
 
-        nsCOMPtr<nsIAtom> prefixToBind;
+        RefPtr<nsIAtom> prefixToBind;
         if (atts[i].mPrefix == nsGkAtoms::xmlns) {
             prefixToBind = atts[i].mLocalName;
         }
         else if (atts[i].mNamespaceID == kNameSpaceID_XMLNS) {
             prefixToBind = nsGkAtoms::_empty;
         }
 
         if (prefixToBind) {
@@ -151,17 +151,17 @@ txStylesheetCompiler::startElement(const
             }
 
             rv = mElementContext->mMappings->
                 mapNamespace(prefixToBind, atts[i].mValue);
             NS_ENSURE_SUCCESS(rv, rv);
         }
     }
 
-    nsCOMPtr<nsIAtom> prefix, localname;
+    RefPtr<nsIAtom> prefix, localname;
     int32_t namespaceID;
     rv = XMLUtils::splitExpatName(aName, getter_AddRefs(prefix),
                                   getter_AddRefs(localname), &namespaceID);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return startElementInternal(namespaceID, localname, prefix, atts.get(),
                                 aAttrCount);
 }
@@ -857,17 +857,17 @@ public:
     explicit txErrorFunctionCall(nsIAtom* aName)
       : mName(aName)
     {
     }
 
     TX_DECL_FUNCTION
 
 private:
-    nsCOMPtr<nsIAtom> mName;
+    RefPtr<nsIAtom> mName;
 };
 
 nsresult
 txErrorFunctionCall::evaluate(txIEvalContext* aContext,
                               txAExprResult** aResult)
 {
     *aResult = nullptr;
 
--- a/dom/xslt/xslt/txStylesheetCompiler.h
+++ b/dom/xslt/xslt/txStylesheetCompiler.h
@@ -189,18 +189,18 @@ private:
     txListIterator mToplevelIterator;
     nsTArray<txInstruction**> mGotoTargetPointers;
     mozilla::net::ReferrerPolicy mReferrerPolicy;
 };
 
 struct txStylesheetAttr
 {
     int32_t mNamespaceID;
-    nsCOMPtr<nsIAtom> mLocalName;
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mLocalName;
+    RefPtr<nsIAtom> mPrefix;
     nsString mValue;
 };
 
 class txStylesheetCompiler final : private txStylesheetCompilerState,
                                    public txACompileObserver
 {
 public:
     friend class txStylesheetCompilerState;
--- a/dom/xslt/xslt/txUnknownHandler.cpp
+++ b/dom/xslt/xslt/txUnknownHandler.cpp
@@ -117,17 +117,17 @@ txUnknownHandler::startElement(nsIAtom* 
                                nsIAtom* aLowercaseLocalName, int32_t aNsID)
 {
     if (!mFlushed) {
         // Make sure that mEs->mResultHandler == this is true, otherwise we'll
         // leak mEs->mResultHandler in createHandlerAndFlush.
         NS_ASSERTION(mEs->mResultHandler == this,
                      "We're leaking mEs->mResultHandler.");
 
-        nsCOMPtr<nsIAtom> owner;
+        RefPtr<nsIAtom> owner;
         if (!aLowercaseLocalName) {
             owner = TX_ToLowerCaseAtom(aLocalName);
             NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
 
             aLowercaseLocalName = owner;
         }
 
         bool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix &&
--- a/dom/xslt/xslt/txXSLTNumber.cpp
+++ b/dom/xslt/xslt/txXSLTNumber.cpp
@@ -114,17 +114,17 @@ txXSLTNumber::getValueList(Expr* aValueE
     // Parse count- and from-attributes
 
     if (!aCountPattern) {
         txNodeTest* nodeTest;
         uint16_t nodeType = txXPathNodeUtils::getNodeType(currNode);
         switch (nodeType) {
             case txXPathNodeType::ELEMENT_NODE:
             {
-                nsCOMPtr<nsIAtom> localName =
+                RefPtr<nsIAtom> localName =
                     txXPathNodeUtils::getLocalName(currNode);
                 int32_t namespaceID = txXPathNodeUtils::getNamespaceID(currNode);
                 nodeTest = new txNameTest(0, localName, namespaceID,
                                           txXPathNodeType::ELEMENT_NODE);
                 break;
             }
             case txXPathNodeType::TEXT_NODE:
             case txXPathNodeType::CDATA_SECTION_NODE:
--- a/dom/xslt/xslt/txXSLTPatterns.cpp
+++ b/dom/xslt/xslt/txXSLTPatterns.cpp
@@ -300,18 +300,18 @@ txRootPattern::toString(nsAString& aDest
  * This looks like the id() function, but may only have LITERALs as
  * argument.
  */
 txIdPattern::txIdPattern(const nsAString& aString)
 {
     nsWhitespaceTokenizer tokenizer(aString);
     while (tokenizer.hasMoreTokens()) {
         // this can fail, XXX move to a Init(aString) method
-        nsCOMPtr<nsIAtom> atom = NS_Atomize(tokenizer.nextToken());
-        mIds.AppendObject(atom);
+        RefPtr<nsIAtom> atom = NS_Atomize(tokenizer.nextToken());
+        mIds.AppendElement(atom);
     }
 }
 
 nsresult
 txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
                      bool& aMatched)
 {
     if (!txXPathNodeUtils::isElement(aNode)) {
@@ -320,17 +320,17 @@ txIdPattern::matches(const txXPathNode& 
         return NS_OK;
     }
 
     // Get a ID attribute, if there is
     nsIContent* content = txXPathNativeNode::getContent(aNode);
     NS_ASSERTION(content, "a Element without nsIContent");
 
     nsIAtom* id = content->GetID();
-    aMatched = id && mIds.IndexOf(id) > -1;
+    aMatched = id && mIds.IndexOf(id) != mIds.NoIndex;
 
     return NS_OK;
 }
 
 double txIdPattern::getDefaultPriority()
 {
     return 0.5;
 }
@@ -341,17 +341,17 @@ TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(txI
 #ifdef TX_TO_STRING
 void
 txIdPattern::toString(nsAString& aDest)
 {
 #ifdef DEBUG
     aDest.AppendLiteral("txIdPattern{");
 #endif
     aDest.AppendLiteral("id('");
-    uint32_t k, count = mIds.Count() - 1;
+    uint32_t k, count = mIds.Length() - 1;
     for (k = 0; k < count; ++k) {
         nsAutoString str;
         mIds[k]->ToString(str);
         aDest.Append(str);
         aDest.Append(char16_t(' '));
     }
     nsAutoString str;
     mIds[count]->ToString(str);
--- a/dom/xslt/xslt/txXSLTPatterns.h
+++ b/dom/xslt/xslt/txXSLTPatterns.h
@@ -188,17 +188,17 @@ private:
 class txIdPattern : public txPattern
 {
 public:
     explicit txIdPattern(const nsAString& aString);
 
     TX_DECL_PATTERN;
 
 private:
-    nsCOMArray<nsIAtom> mIds;
+    nsTArray<RefPtr<nsIAtom>> mIds;
 };
 
 class txKeyPattern : public txPattern
 {
 public:
     txKeyPattern(nsIAtom* aPrefix, nsIAtom* aLocalName,
                  int32_t aNSID, const nsAString& aValue)
         : mName(aNSID, aLocalName),
@@ -209,17 +209,17 @@ public:
     {
     }
 
     TX_DECL_PATTERN;
 
 private:
     txExpandedName mName;
 #ifdef TX_TO_STRING
-    nsCOMPtr<nsIAtom> mPrefix;
+    RefPtr<nsIAtom> mPrefix;
 #endif
     nsString mValue;
 };
 
 class txStepPattern : public txPattern,
                       public PredicateList
 {
 public:
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -137,17 +137,17 @@ const nsForwardReference::Phase nsForwar
 int32_t XULDocument::gRefCnt = 0;
 
 LazyLogModule XULDocument::gXULLog("XULDocument");
 
 //----------------------------------------------------------------------
 
 struct BroadcastListener {
     nsWeakPtr mListener;
-    nsCOMPtr<nsIAtom> mAttribute;
+    RefPtr<nsIAtom> mAttribute;
 };
 
 struct BroadcasterMapEntry : public PLDHashEntryHdr
 {
     Element* mBroadcaster;  // [WEAK]
     nsTArray<BroadcastListener*> mListeners;  // [OWNING] of BroadcastListener objects
 };
 
@@ -649,18 +649,18 @@ CanBroadcast(int32_t aNameSpaceID, nsIAt
 struct nsAttrNameInfo
 {
   nsAttrNameInfo(int32_t aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix) :
     mNamespaceID(aNamespaceID), mName(aName), mPrefix(aPrefix) {}
   nsAttrNameInfo(const nsAttrNameInfo& aOther) :
     mNamespaceID(aOther.mNamespaceID), mName(aOther.mName),
     mPrefix(aOther.mPrefix) {}
   int32_t           mNamespaceID;
-  nsCOMPtr<nsIAtom> mName;
-  nsCOMPtr<nsIAtom> mPrefix;
+  RefPtr<nsIAtom> mName;
+  RefPtr<nsIAtom> mPrefix;
 };
 
 void
 XULDocument::SynchronizeBroadcastListener(Element *aBroadcaster,
                                           Element *aListener,
                                           const nsAString &aAttr)
 {
     if (!nsContentUtils::IsSafeToRunScript()) {
@@ -705,17 +705,17 @@ XULDocument::SynchronizeBroadcastListene
             // which could define JS properties that mask XBL
             // properties, etc.
             ExecuteOnBroadcastHandlerFor(aBroadcaster, aListener, name);
 #endif
         }
     }
     else {
         // Find out if the attribute is even present at all.
-        nsCOMPtr<nsIAtom> name = NS_Atomize(aAttr);
+        RefPtr<nsIAtom> name = NS_Atomize(aAttr);
 
         nsAutoString value;
         if (aBroadcaster->GetAttr(kNameSpaceID_None, name, value)) {
             aListener->SetAttr(kNameSpaceID_None, name, value, notify);
         } else {
             aListener->UnsetAttr(kNameSpaceID_None, name, notify);
         }
 
@@ -786,17 +786,17 @@ XULDocument::AddBroadcastListenerFor(Ele
 
         entry->mBroadcaster = &aBroadcaster;
 
         // N.B. placement new to construct the nsTArray object in-place
         new (&entry->mListeners) nsTArray<BroadcastListener*>();
     }
 
     // Only add the listener if it's not there already!
-    nsCOMPtr<nsIAtom> attr = NS_Atomize(aAttr);
+    RefPtr<nsIAtom> attr = NS_Atomize(aAttr);
 
     for (size_t i = entry->mListeners.Length() - 1; i != (size_t)-1; --i) {
         BroadcastListener* bl = entry->mListeners[i];
         nsCOMPtr<Element> blListener = do_QueryReferent(bl->mListener);
 
         if (blListener == &aListener && bl->mAttribute == attr)
             return;
     }
@@ -830,17 +830,17 @@ XULDocument::RemoveBroadcastListenerFor(
     // If we haven't added any broadcast listeners, then there sure
     // aren't any to remove.
     if (! mBroadcasterMap)
         return;
 
     auto entry = static_cast<BroadcasterMapEntry*>
                             (mBroadcasterMap->Search(&aBroadcaster));
     if (entry) {
-        nsCOMPtr<nsIAtom> attr = NS_Atomize(aAttr);
+        RefPtr<nsIAtom> attr = NS_Atomize(aAttr);
         for (size_t i = entry->mListeners.Length() - 1; i != (size_t)-1; --i) {
             BroadcastListener* bl = entry->mListeners[i];
             nsCOMPtr<Element> blListener = do_QueryReferent(bl->mListener);
 
             if (blListener == &aListener && bl->mAttribute == attr) {
                 entry->mListeners.RemoveElementAt(i);
                 delete bl;
 
@@ -1204,17 +1204,17 @@ XULDocument::GetElementsByAttribute(cons
     *aReturn = GetElementsByAttribute(aAttribute, aValue).take();
     return NS_OK;
 }
 
 already_AddRefed<nsINodeList>
 XULDocument::GetElementsByAttribute(const nsAString& aAttribute,
                                     const nsAString& aValue)
 {
-    nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
+    RefPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
     void* attrValue = new nsString(aValue);
     RefPtr<nsContentList> list = new nsContentList(this,
                                             MatchAttribute,
                                             nsContentUtils::DestroyMatchString,
                                             attrValue,
                                             true,
                                             attrAtom,
                                             kNameSpaceID_Unknown);
@@ -1235,17 +1235,17 @@ XULDocument::GetElementsByAttributeNS(co
 }
 
 already_AddRefed<nsINodeList>
 XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
                                       const nsAString& aAttribute,
                                       const nsAString& aValue,
                                       ErrorResult& aRv)
 {
-    nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
+    RefPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
     void* attrValue = new nsString(aValue);
 
     int32_t nameSpaceId = kNameSpaceID_Wildcard;
     if (!aNamespaceURI.EqualsLiteral("*")) {
       nsresult rv =
         nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
                                                               nameSpaceId);
       if (NS_FAILED(rv)) {
@@ -1272,17 +1272,17 @@ XULDocument::Persist(const nsAString& aI
     // localstore, _don't_ re-enter and try to set them again!
     if (mApplyingPersistedAttrs)
         return NS_OK;
 
     Element* element = nsDocument::GetElementById(aID);
     if (!element)
         return NS_OK;
 
-    nsCOMPtr<nsIAtom> tag;
+    RefPtr<nsIAtom> tag;
     int32_t nameSpaceID;
 
     RefPtr<mozilla::dom::NodeInfo> ni = element->GetExistingAttrNameFromQName(aAttr);
     nsresult rv;
     if (ni) {
         tag = ni->NameAtom();
         nameSpaceID = ni->NamespaceID();
     }
@@ -2137,17 +2137,17 @@ XULDocument::ApplyPersistentAttributesTo
         attrs->GetNext(attrstr);
 
         nsAutoString value;
         rv = mLocalStore->GetValue(uri, aID, attrstr, value);
         if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
         }
 
-        nsCOMPtr<nsIAtom> attr = NS_Atomize(attrstr);
+        RefPtr<nsIAtom> attr = NS_Atomize(attrstr);
         if (NS_WARN_IF(!attr)) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         uint32_t cnt = aElements.Count();
 
         for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
             nsCOMPtr<nsIContent> element = aElements.SafeObjectAt(i);
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -758,17 +758,17 @@ protected:
         mAttr(aOther.mAttr), mAttrName(aOther.mAttrName),
         mSetAttr(aOther.mSetAttr), mNeedsAttrChange(aOther.mNeedsAttrChange) {}
 
       nsCOMPtr<Element>       mBroadcaster;
       nsCOMPtr<Element>       mListener;
       // Note if mAttrName isn't used, this is the name of the attr, otherwise
       // this is the value of the attribute.
       nsString                mAttr;
-      nsCOMPtr<nsIAtom>       mAttrName;
+      RefPtr<nsIAtom>       mAttrName;
       bool                    mSetAttr;
       bool                    mNeedsAttrChange;
 
       class Comparator {
         public:
           static bool Equals(const nsDelayedBroadcastUpdate& a, const nsDelayedBroadcastUpdate& b) {
             return a.mBroadcaster == b.mBroadcaster && a.mListener == b.mListener && a.mAttrName == b.mAttrName;
           }
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -391,17 +391,17 @@ XULContentSinkImpl::FlushText(bool aCrea
 
 //----------------------------------------------------------------------
 
 nsresult
 XULContentSinkImpl::NormalizeAttributeString(const char16_t *aExpatName,
                                              nsAttrName &aName)
 {
     int32_t nameSpaceID;
-    nsCOMPtr<nsIAtom> prefix, localName;
+    RefPtr<nsIAtom> prefix, localName;
     nsContentUtils::SplitExpatName(aExpatName, getter_AddRefs(prefix),
                                    getter_AddRefs(localName), &nameSpaceID);
 
     if (nameSpaceID == kNameSpaceID_None) {
         aName.SetTo(localName);
 
         return NS_OK;
     }
@@ -445,17 +445,17 @@ XULContentSinkImpl::HandleStartElement(c
   if (mState == eInEpilog)
       return NS_ERROR_UNEXPECTED;
 
   if (mState != eInScript) {
       FlushText();
   }
 
   int32_t nameSpaceID;
-  nsCOMPtr<nsIAtom> prefix, localName;
+  RefPtr<nsIAtom> prefix, localName;
   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
                                  getter_AddRefs(localName), &nameSpaceID);
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
                                            nsIDOMNode::ELEMENT_NODE);
 
   nsresult rv = NS_OK;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -379,17 +379,17 @@ nsXULElement::Clone(mozilla::dom::NodeIn
 }
 
 //----------------------------------------------------------------------
 
 already_AddRefed<nsINodeList>
 nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
                                      const nsAString& aValue)
 {
-    nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
+    RefPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
     void* attrValue = new nsString(aValue);
     RefPtr<nsContentList> list =
         new nsContentList(this,
                           XULDocument::MatchAttribute,
                           nsContentUtils::DestroyMatchString,
                           attrValue,
                           true,
                           attrAtom,
@@ -398,17 +398,17 @@ nsXULElement::GetElementsByAttribute(con
 }
 
 already_AddRefed<nsINodeList>
 nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
                                        const nsAString& aAttribute,
                                        const nsAString& aValue,
                                        ErrorResult& rv)
 {
-    nsCOMPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
+    RefPtr<nsIAtom> attrAtom(NS_Atomize(aAttribute));
 
     int32_t nameSpaceId = kNameSpaceID_Wildcard;
     if (!aNamespaceURI.EqualsLiteral("*")) {
       rv =
         nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
                                                               nameSpaceId);
       if (rv.Failed()) {
           return nullptr;
--- a/dom/xul/nsXULPrototypeDocument.cpp
+++ b/dom/xul/nsXULPrototypeDocument.cpp
@@ -151,17 +151,17 @@ nsXULPrototypeDocument::Read(nsIObjectIn
     nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
 
     tmp = aStream->Read32(&count);
     if (NS_FAILED(tmp)) {
       rv = tmp;
     }
     nsAutoString namespaceURI, prefixStr, localName;
     bool prefixIsNull;
-    nsCOMPtr<nsIAtom> prefix;
+    RefPtr<nsIAtom> prefix;
     for (i = 0; i < count; ++i) {
         tmp = aStream->ReadString(namespaceURI);
         if (NS_FAILED(tmp)) {
           rv = tmp;
         }
         tmp = aStream->ReadBoolean(&prefixIsNull);
         if (NS_FAILED(tmp)) {
           rv = tmp;
--- a/dom/xul/templates/nsContentTestNode.h
+++ b/dom/xul/templates/nsContentTestNode.h
@@ -35,14 +35,14 @@ public:
     {
         mTag = aTag;
         mDocument = aDocument;
     }
 
 protected:
     nsXULTemplateQueryProcessorRDF *mProcessor;
     nsIDOMDocument* mDocument;
-    nsCOMPtr<nsIAtom> mRefVariable;
-    nsCOMPtr<nsIAtom> mTag;
+    RefPtr<nsIAtom> mRefVariable;
+    RefPtr<nsIAtom> mTag;
 };
 
 #endif // nsContentTestNode_h__
 
--- a/dom/xul/templates/nsRDFBinding.h
+++ b/dom/xul/templates/nsRDFBinding.h
@@ -19,19 +19,19 @@ class nsBindingValues;
 
 /*
  * a  <binding> descriptors
  */
 class RDFBinding {
 
 public:
 
-    nsCOMPtr<nsIAtom>        mSubjectVariable;
+    RefPtr<nsIAtom>        mSubjectVariable;
     nsCOMPtr<nsIRDFResource> mPredicate;
-    nsCOMPtr<nsIAtom>        mTargetVariable;
+    RefPtr<nsIAtom>        mTargetVariable;
 
     // indicates whether a binding is dependant on the result from a
     // previous binding
     bool                     mHasDependency;
 
     RDFBinding*              mNext;
 
 private:
--- a/dom/xul/templates/nsRDFConInstanceTestNode.h
+++ b/dom/xul/templates/nsRDFConInstanceTestNode.h
@@ -74,15 +74,15 @@ public:
     protected:
         nsCOMPtr<nsIRDFResource> mContainer;
         Test mContainerTest;
         Test mEmptyTest;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
-    nsCOMPtr<nsIAtom> mContainerVariable;
+    RefPtr<nsIAtom> mContainerVariable;
     Test mContainer;
     Test mEmpty;
 };
 
 #endif // nsRDFConInstanceTestNode_h__
 
--- a/dom/xul/templates/nsRDFConMemberTestNode.h
+++ b/dom/xul/templates/nsRDFConMemberTestNode.h
@@ -65,13 +65,13 @@ public:
 
     protected:
         nsCOMPtr<nsIRDFResource> mContainer;
         nsCOMPtr<nsIRDFNode> mMember;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
-    nsCOMPtr<nsIAtom> mContainerVariable;
-    nsCOMPtr<nsIAtom> mMemberVariable;
+    RefPtr<nsIAtom> mContainerVariable;
+    RefPtr<nsIAtom> mMemberVariable;
 };
 
 #endif // nsRDFConMemberTestNode_h__
--- a/dom/xul/templates/nsRDFPropertyTestNode.h
+++ b/dom/xul/templates/nsRDFPropertyTestNode.h
@@ -89,16 +89,16 @@ public:
     protected:
         nsCOMPtr<nsIRDFResource> mSource;
         nsCOMPtr<nsIRDFResource> mProperty;
         nsCOMPtr<nsIRDFNode> mTarget;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
-    nsCOMPtr<nsIAtom>        mSourceVariable;
+    RefPtr<nsIAtom>        mSourceVariable;
     nsCOMPtr<nsIRDFResource> mSource;
     nsCOMPtr<nsIRDFResource> mProperty;
-    nsCOMPtr<nsIAtom>        mTargetVariable;
+    RefPtr<nsIAtom>        mTargetVariable;
     nsCOMPtr<nsIRDFNode>     mTarget;
 };
 
 #endif // nsRDFPropertyTestNode_h__
--- a/dom/xul/templates/nsRDFQuery.h
+++ b/dom/xul/templates/nsRDFQuery.h
@@ -96,18 +96,18 @@ public:
 
     nsIAtom* GetMemberVariable() override { return mMemberVariable; }
 
     bool IsSimple() { return mSimple; }
 
     void SetSimple() { mSimple = true; }
 
     // the reference and member variables for the query
-    nsCOMPtr<nsIAtom> mRefVariable;
-    nsCOMPtr<nsIAtom> mMemberVariable;
+    RefPtr<nsIAtom> mRefVariable;
+    RefPtr<nsIAtom> mMemberVariable;
 
 protected:
 
     nsXULTemplateQueryProcessorRDF* mProcessor;
 
     // true if the query is a simple rule (one with a default query)
     bool mSimple;
 
--- a/dom/xul/templates/nsRuleNetwork.h
+++ b/dom/xul/templates/nsRuleNetwork.h
@@ -182,17 +182,17 @@ public:
 
 //----------------------------------------------------------------------
 
 /**
  * An assignment of a value to a variable
  */
 class nsAssignment {
 public:
-    const nsCOMPtr<nsIAtom> mVariable;
+    const RefPtr<nsIAtom> mVariable;
     nsCOMPtr<nsIRDFNode> mValue;
 
     nsAssignment(nsIAtom* aVariable, nsIRDFNode* aValue)
         : mVariable(aVariable),
           mValue(aValue)
         { MOZ_COUNT_CTOR(nsAssignment); }
 
     nsAssignment(const nsAssignment& aAssignment)
--- a/dom/xul/templates/nsTemplateRule.h
+++ b/dom/xul/templates/nsTemplateRule.h
@@ -71,20 +71,20 @@ public:
     bool
     CheckMatch(nsIXULTemplateResult* aResult);
 
     bool
     CheckMatchStrings(const nsAString& aLeftString,
                       const nsAString& aRightString);
 protected:
 
-    nsCOMPtr<nsIAtom>   mSourceVariable;
+    RefPtr<nsIAtom>   mSourceVariable;
     nsString            mSource;
     ConditionRelation   mRelation;
-    nsCOMPtr<nsIAtom>   mTargetVariable;
+    RefPtr<nsIAtom>   mTargetVariable;
     nsTArray<nsString>  mTargetList;
     bool                mIgnoreCase;
     bool                mNegate;
 
    nsTemplateCondition* mNext;
 };
 
 /**
@@ -199,18 +199,18 @@ public:
     {
         cb.NoteXPCOMChild(mRuleNode);
         cb.NoteXPCOMChild(mAction);
     }
 
 protected:
 
     struct Binding {
-        nsCOMPtr<nsIAtom>        mSourceVariable;
-        nsCOMPtr<nsIAtom>        mTargetVariable;
+        RefPtr<nsIAtom>        mSourceVariable;
+        RefPtr<nsIAtom>        mTargetVariable;
         nsString                 mExpr;
         Binding*                 mNext;
         Binding*                 mParent;
     };
 
     // backreference to the query set which owns this rule
     nsTemplateQuerySet* mQuerySet;
 
@@ -221,23 +221,23 @@ protected:
     // which contains the content to generate
     nsCOMPtr<nsIContent> mAction;
 
     // the rule filter set by the builder's SetRuleFilter function
     nsCOMPtr<nsIXULTemplateRuleFilter> mRuleFilter;
 
     // indicates that the rule will only match when generating content
     // to be inserted into a container with this tag
-    nsCOMPtr<nsIAtom> mTag;
+    RefPtr<nsIAtom> mTag;
 
     // linked-list of the bindings for the rule, owned by the rule.
     Binding* mBindings;
 
-    nsCOMPtr<nsIAtom> mRefVariable;
-    nsCOMPtr<nsIAtom> mMemberVariable;
+    RefPtr<nsIAtom> mRefVariable;
+    RefPtr<nsIAtom> mMemberVariable;
 
     nsTemplateCondition* mConditions; // owned by nsTemplateRule
 };
 
 /** nsTemplateQuerySet
  *
  *  A single <queryset> which holds the query node and the rules for it.
  *  All builders have at least one queryset, which may be created with an
@@ -262,17 +262,17 @@ public:
     nsCOMPtr<nsIContent> mQueryNode;
 
     // compiled opaque query object returned by the query processor's
     // CompileQuery call
     nsCOMPtr<nsISupports> mCompiledQuery;
 
     // indicates that the query will only generate content to be inserted into
     // a container with this tag
-    nsCOMPtr<nsIAtom> mTag;
+    RefPtr<nsIAtom> mTag;
 
     explicit nsTemplateQuerySet(int32_t aPriority)
         : mPriority(aPriority)
     {
         MOZ_COUNT_CTOR(nsTemplateQuerySet);
     }
 
     ~nsTemplateQuerySet()
--- a/dom/xul/templates/nsXMLBinding.h
+++ b/dom/xul/templates/nsXMLBinding.h
@@ -23,17 +23,17 @@ class XPathResult;
 /**
  * Classes related to storing bindings for XML handling.
  */
 
 /**
  * a <binding> description
  */
 struct nsXMLBinding {
-  nsCOMPtr<nsIAtom> mVar;
+  RefPtr<nsIAtom> mVar;
   nsAutoPtr<mozilla::dom::XPathExpression> mExpr;
 
   nsAutoPtr<nsXMLBinding> mNext;
 
   nsXMLBinding(nsIAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr)
     : mVar(aVar), mExpr(aExpr), mNext(nullptr)
   {
     MOZ_COUNT_CTOR(nsXMLBinding);
--- a/dom/xul/templates/nsXULContentBuilder.cpp
+++ b/dom/xul/templates/nsXULContentBuilder.cpp
@@ -727,17 +727,17 @@ nsXULContentBuilder::CopyAttributesToEle
     // Copy all attributes from the template to the new element
     uint32_t numAttribs = aTemplateNode->GetAttrCount();
 
     for (uint32_t attr = 0; attr < numAttribs; attr++) {
         const nsAttrName* name = aTemplateNode->GetAttrNameAt(attr);
         int32_t attribNameSpaceID = name->NamespaceID();
         // Hold a strong reference here so that the atom doesn't go away
         // during UnsetAttr.
-        nsCOMPtr<nsIAtom> attribName = name->LocalName();
+        RefPtr<nsIAtom> attribName = name->LocalName();
 
         // XXXndeakin ignore namespaces until bug 321182 is fixed
         if (attribName != nsGkAtoms::id && attribName != nsGkAtoms::uri) {
             nsAutoString attribValue;
             aTemplateNode->GetAttr(attribNameSpaceID, attribName, attribValue);
             if (!attribValue.IsEmpty()) {
                 nsAutoString value;
                 rv = SubstituteText(aResult, attribValue, value);
@@ -796,17 +796,17 @@ nsXULContentBuilder::AddPersistentAttrib
             persist.Truncate();
         }
 
         attribute.Trim(" ");
 
         if (attribute.IsEmpty())
             break;
 
-        nsCOMPtr<nsIAtom> tag;
+        RefPtr<nsIAtom> tag;
         int32_t nameSpaceID;
 
         RefPtr<mozilla::dom::NodeInfo> ni =
             aTemplateNode->GetExistingAttrNameFromQName(attribute);
         if (ni) {
             tag = ni->NameAtom();
             nameSpaceID = ni->NamespaceID();
         }
@@ -1769,17 +1769,17 @@ nsXULContentBuilder::CompareResultToNode
         nsresult rv = mQueryProcessor->CompareResults(aResult, match->mResult,
                                                       nullptr, mSortState.sortHints,
                                                       aSortOrder);
         NS_ENSURE_SUCCESS(rv, rv);
     }
     else {
         // iterate over each sort key and compare. If the nodes are equal,
         // continue to compare using the next sort key. If not equal, stop.
-        int32_t length = mSortState.sortKeys.Count();
+        int32_t length = mSortState.sortKeys.Length();
         for (int32_t t = 0; t < length; t++) {
             nsresult rv = mQueryProcessor->CompareResults(aResult, match->mResult,
                                                           mSortState.sortKeys[t],
                                                           mSortState.sortHints, aSortOrder);
             NS_ENSURE_SUCCESS(rv, rv);
 
             if (*aSortOrder)
                 break;
--- a/dom/xul/templates/nsXULSortService.cpp
+++ b/dom/xul/templates/nsXULSortService.cpp
@@ -39,17 +39,17 @@ XULSortServiceImpl::SetSortHints(nsICont
     direction.AssignLiteral("descending");
   else if (aSortState->direction == nsSortState_ascending)
     direction.AssignLiteral("ascending");
   aNode->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
                  direction, true);
 
   // for trees, also set the sort info on the currently sorted column
   if (aNode->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
-    if (aSortState->sortKeys.Count() >= 1) {
+    if (aSortState->sortKeys.Length() >= 1) {
       nsAutoString sortkey;
       aSortState->sortKeys[0]->ToString(sortkey);
       SetSortColumnHints(aNode, sortkey, direction);
     }
   }
 }
 
 void
@@ -179,17 +179,17 @@ testSortCallback(const void *data1, cons
   int32_t sortOrder = 0;
 
   if (sortState->direction == nsSortState_natural && sortState->processor) {
     // sort in natural order
     sortState->processor->CompareResults(left->result, right->result,
                                          nullptr, sortState->sortHints, &sortOrder);
   }
   else {
-    int32_t length = sortState->sortKeys.Count();
+    int32_t length = sortState->sortKeys.Length();
     for (int32_t t = 0; t < length; t++) {
       // for templates, use the query processor to do sorting
       if (sortState->processor) {
         sortState->processor->CompareResults(left->result, right->result,
                                              sortState->sortKeys[t],
                                              sortState->sortHints, &sortOrder);
         if (sortOrder)
           break;
@@ -342,35 +342,35 @@ XULSortServiceImpl::InitializeSortState(
   // The latter is for backwards compatibility, and is equivalent to concatenating
   // both values in the sort attribute
   nsAutoString sort(aSortKey);
   aSortState->sortKeys.Clear();
   if (sort.IsEmpty()) {
     nsAutoString sortResource, sortResource2;
     aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource, sortResource);
     if (!sortResource.IsEmpty()) {
-      nsCOMPtr<nsIAtom> sortkeyatom = NS_Atomize(sortResource);
-      aSortState->sortKeys.AppendObject(sortkeyatom);
+      RefPtr<nsIAtom> sortkeyatom = NS_Atomize(sortResource);
+      aSortState->sortKeys.AppendElement(sortkeyatom);
       sort.Append(sortResource);
 
       aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource2, sortResource2);
       if (!sortResource2.IsEmpty()) {
-        nsCOMPtr<nsIAtom> sortkeyatom2 = NS_Atomize(sortResource2);
-        aSortState->sortKeys.AppendObject(sortkeyatom2);
+        RefPtr<nsIAtom> sortkeyatom2 = NS_Atomize(sortResource2);
+        aSortState->sortKeys.AppendElement(sortkeyatom2);
         sort.Append(' ');
         sort.Append(sortResource2);
       }
     }
   }
   else {
     nsWhitespaceTokenizer tokenizer(sort);
     while (tokenizer.hasMoreTokens()) {
-      nsCOMPtr<nsIAtom> keyatom = NS_Atomize(tokenizer.nextToken());
+      RefPtr<nsIAtom> keyatom = NS_Atomize(tokenizer.nextToken());
       NS_ENSURE_TRUE(keyatom, NS_ERROR_OUT_OF_MEMORY);
-      aSortState->sortKeys.AppendObject(keyatom);
+      aSortState->sortKeys.AppendElement(keyatom);
     }
   }
 
   aSortState->sort.Assign(sort);
   aSortState->direction = nsSortState_natural;
 
   bool noNaturalState = false;
   nsWhitespaceTokenizer tokenizer(aSortHints);
--- a/dom/xul/templates/nsXULSortService.h
+++ b/dom/xul/templates/nsXULSortService.h
@@ -33,17 +33,17 @@ struct nsSortState
   MOZ_INIT_OUTSIDE_CTOR bool inbetweenSeparatorSort;
   MOZ_INIT_OUTSIDE_CTOR bool sortStaticsLast;
   MOZ_INIT_OUTSIDE_CTOR bool isContainerRDFSeq;
 
   uint32_t sortHints;
 
   MOZ_INIT_OUTSIDE_CTOR nsSortState_direction direction;
   nsAutoString sort;
-  nsCOMArray<nsIAtom> sortKeys;
+  nsTArray<RefPtr<nsIAtom>> sortKeys;
 
   nsCOMPtr<nsIXULTemplateQueryProcessor> processor;
   nsCOMPtr<nsIContent> lastContainer;
   MOZ_INIT_OUTSIDE_CTOR bool lastWasFirst, lastWasLast;
 
   nsSortState()
     : initialized(false),
       isContainerRDFSeq(false),
--- a/dom/xul/templates/nsXULTemplateBuilder.cpp
+++ b/dom/xul/templates/nsXULTemplateBuilder.cpp
@@ -1690,17 +1690,17 @@ nsXULTemplateBuilder::SubstituteTextRepl
     nsAutoString replacementText;
 
     // The symbol "rdf:*" is special, and means "this guy's URI"
     if (aVariable.EqualsLiteral("rdf:*")){
         c->result->GetId(replacementText);
     }
     else {
         // Got a variable; get the value it's assigned to
-        nsCOMPtr<nsIAtom> var = NS_Atomize(aVariable);
+        RefPtr<nsIAtom> var = NS_Atomize(aVariable);
         c->result->GetBindingFor(var, replacementText);
     }
 
     c->str += replacementText;
 }
 
 bool
 nsXULTemplateBuilder::IsTemplateElement(nsIContent* aContent)
@@ -1928,27 +1928,27 @@ nsXULTemplateBuilder::CompileTemplate(ns
         if (ni->Equals(nsGkAtoms::rule, kNameSpaceID_XUL)) {
             nsCOMPtr<nsIContent> action;
             nsXULContentUtils::FindChildByTag(rulenode,
                                               kNameSpaceID_XUL,
                                               nsGkAtoms::action,
                                               getter_AddRefs(action));
 
             if (action){
-                nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
+                RefPtr<nsIAtom> memberVariable = mMemberVariable;
                 if (!memberVariable) {
                     memberVariable = DetermineMemberVariable(action);
                     if (!memberVariable) {
                         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_NO_MEMBERVAR);
                         continue;
                     }
                 }
 
                 if (hasQuery) {
-                    nsCOMPtr<nsIAtom> tag;
+                    RefPtr<nsIAtom> tag;
                     DetermineRDFQueryRef(aQuerySet->mQueryNode,
                                          getter_AddRefs(tag));
                     if (tag)
                         aQuerySet->SetTag(tag);
 
                     if (! aQuerySet->mCompiledQuery) {
                         nsCOMPtr<nsIDOMNode> query(do_QueryInterface(aQuerySet->mQueryNode));
 
@@ -1984,17 +1984,17 @@ nsXULTemplateBuilder::CompileTemplate(ns
                         if (hasQuerySet) {
                             aQuerySet = new nsTemplateQuerySet(++*aPriority);
                             if (!mQuerySets.AppendElement(aQuerySet)) {
                                 delete aQuerySet;
                                 return NS_ERROR_OUT_OF_MEMORY;
                             }
                         }
 
-                        nsCOMPtr<nsIAtom> tag;
+                        RefPtr<nsIAtom> tag;
                         DetermineRDFQueryRef(conditions, getter_AddRefs(tag));
                         if (tag)
                             aQuerySet->SetTag(tag);
 
                         hasQuerySet = true;
 
                         nsCOMPtr<nsIDOMNode> conditionsnode(do_QueryInterface(conditions));
 
@@ -2046,22 +2046,22 @@ nsXULTemplateBuilder::CompileTemplate(ns
             aQuerySet->mQueryNode = rulenode;
             hasQuery = true;
         }
         else if (ni->Equals(nsGkAtoms::action, kNameSpaceID_XUL)) {
             // the query must appear before the action
             if (! hasQuery)
                 continue;
 
-            nsCOMPtr<nsIAtom> tag;
+            RefPtr<nsIAtom> tag;
             DetermineRDFQueryRef(aQuerySet->mQueryNode, getter_AddRefs(tag));
             if (tag)
                 aQuerySet->SetTag(tag);
 
-            nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
+            RefPtr<nsIAtom> memberVariable = mMemberVariable;
             if (!memberVariable) {
                 memberVariable = DetermineMemberVariable(rulenode);
                 if (!memberVariable) {
                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_NO_MEMBERVAR);
                     continue;
                 }
             }
 
@@ -2153,17 +2153,17 @@ nsXULTemplateBuilder::DetermineMemberVar
          child;
          child = child->GetNextSibling()) {
         nsAutoString uri;
         child->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
         if (!uri.IsEmpty() && uri[0] == char16_t('?')) {
             return NS_Atomize(uri);
         }
 
-        nsCOMPtr<nsIAtom> result = DetermineMemberVariable(child);
+        RefPtr<nsIAtom> result = DetermineMemberVariable(child);
         if (result) {
             return result.forget();
         }
     }
 
     return nullptr;
 }
 
@@ -2204,17 +2204,17 @@ nsresult
 nsXULTemplateBuilder::CompileSimpleQuery(nsIContent* aRuleElement,
                                          nsTemplateQuerySet* aQuerySet,
                                          bool* aCanUseTemplate)
 {
     // compile a simple query, which is a query with no <query> or
     // <conditions>. This means that a default query is used.
     nsCOMPtr<nsIDOMNode> query(do_QueryInterface(aRuleElement));
 
-    nsCOMPtr<nsIAtom> memberVariable;
+    RefPtr<nsIAtom> memberVariable;
     if (mMemberVariable)
         memberVariable = mMemberVariable;
     else
         memberVariable = NS_Atomize("rdf:*");
 
     // since there is no <query> node for a simple query, the query node will
     // be either the <rule> node if multiple rules are used, or the <template> node.
     aQuerySet->mQueryNode = aRuleElement;
@@ -2234,34 +2234,34 @@ nsXULTemplateBuilder::CompileSimpleQuery
         return NS_ERROR_OUT_OF_MEMORY;
 
     rule->SetVars(mRefVariable, memberVariable);
 
     nsAutoString tag;
     aRuleElement->GetAttr(kNameSpaceID_None, nsGkAtoms::parent, tag);
 
     if (!tag.IsEmpty()) {
-        nsCOMPtr<nsIAtom> tagatom = NS_Atomize(tag);
+        RefPtr<nsIAtom> tagatom = NS_Atomize(tag);
         aQuerySet->SetTag(tagatom);
     }
 
     *aCanUseTemplate = true;
 
     return AddSimpleRuleBindings(rule, aRuleElement);
 }
 
 nsresult
 nsXULTemplateBuilder::CompileConditions(nsTemplateRule* aRule,
                                         nsIContent* aCondition)
 {
     nsAutoString tag;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::parent, tag);
 
     if (!tag.IsEmpty()) {
-        nsCOMPtr<nsIAtom> tagatom = NS_Atomize(tag);
+        RefPtr<nsIAtom> tagatom = NS_Atomize(tag);
         aRule->SetTag(tagatom);
     }
 
     nsTemplateCondition* currentCondition = nullptr;
 
     for (nsIContent* node = aCondition->GetFirstChild();
          node;
          node = node->GetNextSibling()) {
@@ -2298,17 +2298,17 @@ nsXULTemplateBuilder::CompileWhereCondit
     // subject
     nsAutoString subject;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::subject, subject);
     if (subject.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_WHERE_NO_SUBJECT);
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> svar;
+    RefPtr<nsIAtom> svar;
     if (subject[0] == char16_t('?'))
         svar = NS_Atomize(subject);
 
     nsAutoString relstring;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relstring);
     if (relstring.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_WHERE_NO_RELATION);
         return NS_OK;
@@ -2322,17 +2322,17 @@ nsXULTemplateBuilder::CompileWhereCondit
         return NS_OK;
     }
 
     // multiple
     bool shouldMultiple =
       aCondition->AttrValueIs(kNameSpaceID_None, nsGkAtoms::multiple,
                               nsGkAtoms::_true, eCaseMatters);
 
-    nsCOMPtr<nsIAtom> vvar;
+    RefPtr<nsIAtom> vvar;
     if (!shouldMultiple && (value[0] == char16_t('?'))) {
         vvar = NS_Atomize(value);
     }
 
     // ignorecase
     bool shouldIgnoreCase =
       aCondition->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ignorecase,
                               nsGkAtoms::_true, eCaseMatters);
@@ -2413,17 +2413,17 @@ nsXULTemplateBuilder::CompileBinding(nsT
     // subject
     nsAutoString subject;
     aBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::subject, subject);
     if (subject.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BINDING_BAD_SUBJECT);
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> svar;
+    RefPtr<nsIAtom> svar;
     if (subject[0] == char16_t('?')) {
         svar = NS_Atomize(subject);
     }
     else {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BINDING_BAD_SUBJECT);
         return NS_OK;
     }
 
@@ -2439,17 +2439,17 @@ nsXULTemplateBuilder::CompileBinding(nsT
     nsAutoString object;
     aBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::object, object);
 
     if (object.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BINDING_BAD_OBJECT);
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> ovar;
+    RefPtr<nsIAtom> ovar;
     if (object[0] == char16_t('?')) {
         ovar = NS_Atomize(object);
     }
     else {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BINDING_BAD_OBJECT);
         return NS_OK;
     }
 
@@ -2514,17 +2514,17 @@ nsXULTemplateBuilder::AddBindingsFor(nsX
 {
     // We should *only* be recieving "rdf:"-style variables. Make
     // sure...
     if (!StringBeginsWith(aVariable, NS_LITERAL_STRING("rdf:")))
         return;
 
     nsTemplateRule* rule = static_cast<nsTemplateRule*>(aClosure);
 
-    nsCOMPtr<nsIAtom> var = NS_Atomize(aVariable);
+    RefPtr<nsIAtom> var = NS_Atomize(aVariable);
 
     // Strip it down to the raw RDF property by clobbering the "rdf:"
     // prefix
     nsAutoString property;
     property.Assign(Substring(aVariable, uint32_t(4), aVariable.Length() - 4));
 
     if (! rule->HasBinding(rule->GetMemberVariable(), property, var))
         // In the simple syntax, the binding is always from the
--- a/dom/xul/templates/nsXULTemplateBuilder.h
+++ b/dom/xul/templates/nsXULTemplateBuilder.h
@@ -418,18 +418,18 @@ protected:
     /**
      * Set to true if the rules have already been compiled
      */
     bool          mQueriesCompiled;
 
     /**
      * The default reference and member variables.
      */
-    nsCOMPtr<nsIAtom> mRefVariable;
-    nsCOMPtr<nsIAtom> mMemberVariable;
+    RefPtr<nsIAtom> mRefVariable;
+    RefPtr<nsIAtom> mMemberVariable;
 
     /**
      * The match map contains nsTemplateMatch objects, one for each unique
      * match found, keyed by the resource for that match. A particular match
      * will contain a linked list of all of the matches for that unique result
      * id. Only one is active at a time. When a match is retracted, look in
      * the match map, remove it, and apply the next valid match in sequence to
      * make active.
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
@@ -1181,17 +1181,17 @@ nsXULTemplateQueryProcessorRDF::CompileE
                 continue;
             }
 
             // check for <content tag='tag'/> which indicates that matches
             // should only be generated for items inside content with that tag
             nsAutoString tagstr;
             condition->GetAttr(kNameSpaceID_None, nsGkAtoms::tag, tagstr);
 
-            nsCOMPtr<nsIAtom> tag;
+            RefPtr<nsIAtom> tag;
             if (! tagstr.IsEmpty()) {
                 tag = NS_Atomize(tagstr);
             }
 
             nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(condition->GetComposedDoc());
             if (! doc)
                 return NS_ERROR_FAILURE;
 
@@ -1291,17 +1291,17 @@ nsXULTemplateQueryProcessorRDF::CompileT
     //
     // XXXwaterson Some day it would be cool to allow the 'predicate'
     // to be bound to a variable.
 
     // subject
     nsAutoString subject;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::subject, subject);
 
-    nsCOMPtr<nsIAtom> svar;
+    RefPtr<nsIAtom> svar;
     nsCOMPtr<nsIRDFResource> sres;
     if (subject.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_BAD_SUBJECT);
         return NS_OK;
     }
     if (subject[0] == char16_t('?'))
         svar = NS_Atomize(subject);
     else
@@ -1317,17 +1317,17 @@ nsXULTemplateQueryProcessorRDF::CompileT
         return NS_OK;
     }
     gRDFService->GetUnicodeResource(predicate, getter_AddRefs(pres));
 
     // object
     nsAutoString object;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::object, object);
 
-    nsCOMPtr<nsIAtom> ovar;
+    RefPtr<nsIAtom> ovar;
     nsCOMPtr<nsIRDFNode> onode;
     if (object.IsEmpty()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_BAD_OBJECT);
         return NS_OK;
     }
 
     if (object[0] == char16_t('?')) {
         ovar = NS_Atomize(object);
@@ -1394,28 +1394,28 @@ nsXULTemplateQueryProcessorRDF::CompileM
     nsAutoString container;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::container, container);
 
     if (!container.IsEmpty() && container[0] != char16_t('?')) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_MEMBER_NOCONTAINERVAR);
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> containervar = NS_Atomize(container);
+    RefPtr<nsIAtom> containervar = NS_Atomize(container);
 
     // child
     nsAutoString child;
     aCondition->GetAttr(kNameSpaceID_None, nsGkAtoms::child, child);
 
     if (!child.IsEmpty() && child[0] != char16_t('?')) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_MEMBER_NOCHILDVAR);
         return NS_OK;
     }
 
-    nsCOMPtr<nsIAtom> childvar = NS_Atomize(child);
+    RefPtr<nsIAtom> childvar = NS_Atomize(child);
 
     TestNode* testnode =
         new nsRDFConMemberTestNode(aParentNode,
                                    this,
                                    containervar,
                                    childvar);
 
     // add testnode to mAllTests first. If adding to mRDFTests fails, just
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.h
@@ -287,17 +287,17 @@ protected:
     // containment properties that are checked to determine if a resource is
     // a container
     nsResourceSet mContainmentProperties;
 
     // the end node of the default simple node hierarchy
     TestNode* mSimpleRuleMemberTest;
 
     // the reference variable
-    nsCOMPtr<nsIAtom> mRefVariable;
+    RefPtr<nsIAtom> mRefVariable;
 
     // the last ref that was calculated, used for simple rules
     nsCOMPtr<nsIXULTemplateResult> mLastRef;
 
     /**
      * A map between nsIRDFNodes that form the left-hand side (the subject) of
      * a <binding> and an array of nsIXULTemplateResults. When a new assertion
      * is added to the graph involving a particular rdf node, it is looked up
--- a/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
@@ -45,18 +45,18 @@ nsXULTemplateResultSetStorage::nsXULTemp
     if (NS_FAILED(rv)) {
         mStatement = nullptr;
         return;
     }
     for (uint32_t c = 0; c < count; c++) {
         nsAutoCString name;
         rv = aStatement->GetColumnName(c, name);
         if (NS_SUCCEEDED(rv)) {
-            nsCOMPtr<nsIAtom> columnName = NS_Atomize(NS_LITERAL_CSTRING("?") + name);
-            mColumnNames.AppendObject(columnName);
+            RefPtr<nsIAtom> columnName = NS_Atomize(NS_LITERAL_CSTRING("?") + name);
+            mColumnNames.AppendElement(columnName);
         }
     }
 }
 
 NS_IMETHODIMP
 nsXULTemplateResultSetStorage::HasMoreElements(bool *aResult)
 {
     if (!mStatement) {
@@ -84,32 +84,32 @@ nsXULTemplateResultSetStorage::GetNext(n
     NS_ADDREF(result);
     return NS_OK;
 }
 
 
 int32_t
 nsXULTemplateResultSetStorage::GetColumnIndex(nsIAtom* aColumnName)
 {
-    int32_t count = mColumnNames.Count();
+    int32_t count = mColumnNames.Length();
     for (int32_t c = 0; c < count; c++) {
         if (mColumnNames[c] == aColumnName)
             return c;
     }
 
     return -1;
 }
 
 void
 nsXULTemplateResultSetStorage::FillColumnValues(nsCOMArray<nsIVariant>& aArray)
 {
     if (!mStatement)
         return;
 
-    int32_t count = mColumnNames.Count();
+    int32_t count = mColumnNames.Length();
 
     for (int32_t c = 0; c < count; c++) {
         RefPtr<nsVariant> value = new nsVariant();
 
         int32_t type;
         mStatement->GetTypeOfIndex(c, &type);
 
         if (type == mStatement->VALUE_TYPE_INTEGER) {
--- a/dom/xul/templates/nsXULTemplateQueryProcessorStorage.h
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorStorage.h
@@ -21,17 +21,17 @@
 class nsXULTemplateQueryProcessorStorage;
 
 class nsXULTemplateResultSetStorage final : public nsISimpleEnumerator
 {
 private:
 
     nsCOMPtr<mozIStorageStatement> mStatement;
 
-    nsCOMArray<nsIAtom> mColumnNames;
+    nsTArray<RefPtr<nsIAtom>> mColumnNames;
 
     ~nsXULTemplateResultSetStorage() {}
 
 public:
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
--- a/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp
@@ -267,17 +267,17 @@ nsXULTemplateQueryProcessorXML::CompileQ
             // ignore assignments without a variable or an expression
             if (!var.IsEmpty() && !expr.IsEmpty()) {
                 compiledexpr = CreateExpression(expr, condition, rv);
                 if (rv.Failed()) {
                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
                     return rv.StealNSResult();
                 }
 
-                nsCOMPtr<nsIAtom> varatom = NS_Atomize(var);
+                RefPtr<nsIAtom> varatom = NS_Atomize(var);
 
                 query->AddBinding(varatom, Move(compiledexpr));
             }
         }
     }
 
     query.forget(_retval);
 
--- a/dom/xul/templates/nsXULTemplateQueryProcessorXML.h
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorXML.h
@@ -69,17 +69,17 @@ class nsXMLQuery final : public nsISuppo
           mResultsExpr(aResultsExpr)
     { }
 
   protected:
     ~nsXMLQuery() {}
 
     nsXULTemplateQueryProcessorXML* mProcessor;
 
-    nsCOMPtr<nsIAtom> mMemberVariable;
+    RefPtr<nsIAtom> mMemberVariable;
 
     nsAutoPtr<mozilla::dom::XPathExpression> mResultsExpr;
 
     RefPtr<nsXMLBindingSet> mRequiredBindings;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXMLQuery, NS_IXMLQUERY_IID)
 
--- a/dom/xul/templates/nsXULTemplateResultXML.cpp
+++ b/dom/xul/templates/nsXULTemplateResultXML.cpp
@@ -19,17 +19,17 @@ NS_IMPL_ISUPPORTS(nsXULTemplateResultXML
 
 nsXULTemplateResultXML::nsXULTemplateResultXML(nsXMLQuery* aQuery,
                                                nsIContent* aNode,
                                                nsXMLBindingSet* aBindings)
     : mQuery(aQuery), mNode(aNode)
 {
     // If the node has an id, create the uri from it. Otherwise, there isn't
     // anything to identify the node with so just use a somewhat random number.
-    nsCOMPtr<nsIAtom> id = mNode->GetID();
+    RefPtr<nsIAtom> id = mNode->GetID();
     if (id) {
       nsCOMPtr<nsIURI> uri = mNode->GetBaseURI();
       nsAutoCString spec;
       uri->GetSpec(spec);
 
       mId = NS_ConvertUTF8toUTF16(spec);
 
       nsAutoString idstr;
--- a/dom/xul/templates/nsXULTreeBuilder.cpp
+++ b/dom/xul/templates/nsXULTreeBuilder.cpp
@@ -1384,17 +1384,17 @@ nsIContent*
 nsXULTreeBuilder::GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol)
 {
     nsCOMPtr<nsIContent> row;
     GetTemplateActionRowFor(aRow, getter_AddRefs(row));
     if (!row) {
         return nullptr;
     }
 
-    nsCOMPtr<nsIAtom> colAtom(aCol.GetAtom());
+    RefPtr<nsIAtom> colAtom(aCol.GetAtom());
     int32_t colIndex(aCol.GetIndex());
 
     nsIContent* result = nullptr;
     uint32_t j = 0;
     for (nsIContent* child = row->GetFirstChild();
          child;
          child = child->GetNextSibling()) {
         if (child->NodeInfo()->Equals(nsGkAtoms::treecell, kNameSpaceID_XUL)) {
--- a/dom/xul/templates/nsXULTreeBuilder.h
+++ b/dom/xul/templates/nsXULTreeBuilder.h
@@ -285,17 +285,17 @@ protected:
     /**
      * The rows in the view
      */
     nsTreeRows mRows;
 
     /**
      * The currently active sort variable
      */
-    nsCOMPtr<nsIAtom> mSortVariable;
+    RefPtr<nsIAtom> mSortVariable;
 
     enum Direction {
         eDirection_Descending = -1,
         eDirection_Natural    =  0,
         eDirection_Ascending  = +1
     };
 
     /**
--- a/editor/composer/nsComposerCommands.cpp
+++ b/editor/composer/nsComposerCommands.cpp
@@ -1591,17 +1591,17 @@ GetListState(mozilla::HTMLEditor* aHTMLE
 
 nsresult
 RemoveOneProperty(mozilla::HTMLEditor* aHTMLEditor,
                   const nsAString& aProp)
 {
   MOZ_ASSERT(aHTMLEditor);
 
   /// XXX Hack alert! Look in nsIEditProperty.h for this
-  nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
+  RefPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
   NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
 
   return aHTMLEditor->RemoveInlineProperty(styleAtom, EmptyString());
 }
 
 
 // the name of the attribute here should be the contents of the appropriate
 // tag, e.g. 'b' for bold, 'i' for italics.
@@ -1622,14 +1622,14 @@ RemoveTextProperty(mozilla::HTMLEditor* 
 // tag, e.g. 'b' for bold, 'i' for italics.
 nsresult
 SetTextProperty(mozilla::HTMLEditor* aHTMLEditor,
                 const nsAString& aProp)
 {
   MOZ_ASSERT(aHTMLEditor);
 
   /// XXX Hack alert! Look in nsIEditProperty.h for this
-  nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
+  RefPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
   NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
 
   return aHTMLEditor->SetInlineProperty(styleAtom,
                                         EmptyString(), EmptyString());
 }
--- a/editor/libeditor/CSSEditUtils.cpp
+++ b/editor/libeditor/CSSEditUtils.cpp
@@ -315,17 +315,17 @@ CSSEditUtils::~CSSEditUtils()
 
 // Answers true if we have some CSS equivalence for the HTML style defined
 // by aProperty and/or aAttribute for the node aNode
 bool
 CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
                                     nsIAtom* aProperty,
                                     const nsAString* aAttribute)
 {
-  nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
   return IsCSSEditableProperty(aNode, aProperty, attribute);
 }
 
 bool
 CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
                                     nsIAtom* aProperty,
                                     nsIAtom* aAttribute)
 {
@@ -907,17 +907,17 @@ CSSEditUtils::SetCSSEquivalentToHTMLStyl
 
 int32_t
 CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
                                           nsIAtom* aHTMLProperty,
                                           const nsAString* aAttribute,
                                           const nsAString* aValue,
                                           bool aSuppressTransaction)
 {
-  nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
   return SetCSSEquivalentToHTMLStyle(aElement, aHTMLProperty, attribute,
                                      aValue, aSuppressTransaction);
 }
 
 int32_t
 CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
                                           nsIAtom* aHTMLProperty,
                                           nsIAtom* aAttribute,
@@ -956,17 +956,17 @@ CSSEditUtils::SetCSSEquivalentToHTMLStyl
 nsresult
 CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
                                              nsIAtom* aHTMLProperty,
                                              const nsAString* aAttribute,
                                              const nsAString* aValue,
                                              bool aSuppressTransaction)
 {
   nsCOMPtr<Element> element = do_QueryInterface(aNode);
-  nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
 
   return RemoveCSSEquivalentToHTMLStyle(element, aHTMLProperty, attribute,
                                         aValue, aSuppressTransaction);
 }
 
 nsresult
 CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement,
                                              nsIAtom* aHTMLProperty,
@@ -1070,32 +1070,32 @@ CSSEditUtils::IsCSSEquivalentToHTMLInlin
 bool
 CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
                                                   nsIAtom* aProperty,
                                                   const nsAString* aAttribute,
                                                   nsAString& aValue,
                                                   StyleType aStyleType)
 {
   MOZ_ASSERT(aNode && aProperty);
-  nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
   return IsCSSEquivalentToHTMLInlineStyleSet(aNode,
                                              aProperty, attribute,
                                              aValue, aStyleType);
 }
 
 bool
 CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode,
                                                   nsIAtom* aProperty,
                                                   const nsAString* aAttribute,
                                                   nsAString& aValue,
                                                   StyleType aStyleType)
 {
   MOZ_ASSERT(aNode && aProperty);
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
   return IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, attribute,
                                              aValue, aStyleType);
 }
 
 bool
 CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
                 nsINode* aNode,
                 nsIAtom* aHTMLProperty,
--- a/editor/libeditor/ChangeAttributeTransaction.h
+++ b/editor/libeditor/ChangeAttributeTransaction.h
@@ -47,17 +47,17 @@ public:
 
 private:
   virtual ~ChangeAttributeTransaction();
 
   // The element to operate upon
   nsCOMPtr<dom::Element> mElement;
 
   // The attribute to change
-  nsCOMPtr<nsIAtom> mAttribute;
+  RefPtr<nsIAtom> mAttribute;
 
   // The value to set the attribute to (ignored if mRemoveAttribute==true)
   nsString mValue;
 
   // True if the operation is to remove mAttribute from mElement
   bool mRemoveAttribute;
 
   // True if the mAttribute was set on mElement at the time of execution
--- a/editor/libeditor/ChangeStyleTransaction.h
+++ b/editor/libeditor/ChangeStyleTransaction.h
@@ -94,17 +94,17 @@ private:
    * is false, just remove the style attribute.
    */
   nsresult SetStyle(bool aAttributeWasSet, nsAString& aValue);
 
   // The element to operate upon.
   nsCOMPtr<dom::Element> mElement;
 
   // The CSS property to change.
-  nsCOMPtr<nsIAtom> mProperty;
+  RefPtr<nsIAtom> mProperty;
 
   // The value to set the property to (ignored if mRemoveProperty==true).
   nsString mValue;
 
   // true if the operation is to remove mProperty from mElement.
   bool mRemoveProperty;
 
   // The value to set the property to for undo.
--- a/editor/libeditor/CreateElementTransaction.h
+++ b/editor/libeditor/CreateElementTransaction.h
@@ -55,17 +55,17 @@ public:
 
 protected:
   virtual ~CreateElementTransaction();
 
   // The document into which the new node will be inserted.
   RefPtr<EditorBase> mEditorBase;
 
   // The tag (mapping to object type) for the new element.
-  nsCOMPtr<nsIAtom> mTag;
+  RefPtr<nsIAtom> mTag;
 
   // The node into which the new node will be inserted.
   nsCOMPtr<nsINode> mParent;
 
   // The index in mParent for the new node.
   int32_t mOffsetInParent;
 
   // The new node to insert.
--- a/editor/libeditor/EditAggregateTransaction.h
+++ b/editor/libeditor/EditAggregateTransaction.h
@@ -45,14 +45,14 @@ public:
    * Get the name assigned to this transaction.
    */
   NS_IMETHOD GetName(nsIAtom** aName);
 
 protected:
   virtual ~EditAggregateTransaction();
 
   nsTArray<RefPtr<EditTransactionBase>> mChildren;
-  nsCOMPtr<nsIAtom> mName;
+  RefPtr<nsIAtom> mName;
 };
 
 } // namespace mozilla
 
 #endif // #ifndef EditAggregateTransaction_h
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1250,17 +1250,17 @@ EditorBase::SetAttribute(nsIDOMElement* 
                          const nsAString& aAttribute,
                          const nsAString& aValue)
 {
   if (NS_WARN_IF(aAttribute.IsEmpty())) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
 
   return SetAttribute(element, attribute, aValue);
 }
 
 nsresult
 EditorBase::SetAttribute(Element* aElement,
                          nsIAtom* aAttribute,
                          const nsAString& aValue)
@@ -1295,17 +1295,17 @@ NS_IMETHODIMP
 EditorBase::RemoveAttribute(nsIDOMElement* aElement,
                             const nsAString& aAttribute)
 {
   if (NS_WARN_IF(aAttribute.IsEmpty())) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
 
   return RemoveAttribute(element, attribute);
 }
 
 nsresult
 EditorBase::RemoveAttribute(Element* aElement,
                             nsIAtom* aAttribute)
 {
@@ -1409,17 +1409,17 @@ EditorBase::SetSpellcheckUserOverride(bo
 }
 
 NS_IMETHODIMP
 EditorBase::CreateNode(const nsAString& aTag,
                        nsIDOMNode* aParent,
                        int32_t aPosition,
                        nsIDOMNode** aNewNode)
 {
-  nsCOMPtr<nsIAtom> tag = NS_Atomize(aTag);
+  RefPtr<nsIAtom> tag = NS_Atomize(aTag);
   nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
   NS_ENSURE_STATE(parent);
   *aNewNode = GetAsDOMNode(CreateNode(tag, parent, aPosition).take());
   NS_ENSURE_STATE(*aNewNode);
   return NS_OK;
 }
 
 already_AddRefed<Element>
@@ -2279,17 +2279,17 @@ EditorBase::CloneAttribute(const nsAStri
   if (NS_WARN_IF(aAttribute.IsEmpty())) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
   nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
   NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
 
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
   return CloneAttribute(attribute, destElement, sourceElement);
 }
 
 nsresult
 EditorBase::CloneAttribute(nsIAtom* aAttribute,
                            Element* aDestElement,
                            Element* aSourceElement)
 {
@@ -4731,31 +4731,31 @@ EditorBase::SetAttributeOrEquivalent(nsI
                                      const nsAString& aAttribute,
                                      const nsAString& aValue,
                                      bool aSuppressTransaction)
 {
   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_NULL_POINTER;
   }
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
   return SetAttributeOrEquivalent(element, attribute, aValue,
                                   aSuppressTransaction);
 }
 
 NS_IMETHODIMP
 EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
                                         const nsAString& aAttribute,
                                         bool aSuppressTransaction)
 {
   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_NULL_POINTER;
   }
-  nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
+  RefPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
   return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
 }
 
 nsresult
 EditorBase::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent)
 {
   // NOTE: When you change this method, you should also change:
   //   * editor/libeditor/tests/test_texteditor_keyevent_handling.html
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
@@ -354,17 +354,17 @@ HTMLEditor::CheckSelectionStateForAnonym
     return NS_OK;
   }
 
   // what's its tag?
   nsAutoString focusTagName;
   rv = focusElement->GetTagName(focusTagName);
   NS_ENSURE_SUCCESS(rv, rv);
   ToLowerCase(focusTagName);
-  nsCOMPtr<nsIAtom> focusTagAtom = NS_Atomize(focusTagName);
+  RefPtr<nsIAtom> focusTagAtom = NS_Atomize(focusTagName);
 
   nsCOMPtr<nsIDOMElement> absPosElement;
   if (mIsAbsolutelyPositioningEnabled) {
     // Absolute Positioning support is enabled, is the selection contained
     // in an absolutely positioned element ?
     rv =
       GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(absPosElement));
     NS_ENSURE_SUCCESS(rv, rv);
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -991,17 +991,17 @@ HTMLEditRules::GetIndentState(bool* aCan
       nsIAtom& marginProperty =
         MarginPropertyAtomForIndent(*mHTMLEditor->mCSSEditUtils, curNode);
       nsAutoString value;
       // retrieve its specified value
       NS_ENSURE_STATE(mHTMLEditor);
       mHTMLEditor->mCSSEditUtils->GetSpecifiedProperty(*curNode,
                                                        marginProperty, value);
       float f;
-      nsCOMPtr<nsIAtom> unit;
+      RefPtr<nsIAtom> unit;
       // get its number part and its unit
       NS_ENSURE_STATE(mHTMLEditor);
       mHTMLEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
       // if the number part is strictly positive, outdent is possible
       if (0 < f) {
         *aCanOutdent = true;
         break;
       }
@@ -1181,17 +1181,17 @@ HTMLEditRules::AppendInnerFormatNodes(ns
 
 nsresult
 HTMLEditRules::GetFormatString(nsIDOMNode* aNode,
                                nsAString& outFormat)
 {
   NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
 
   if (HTMLEditUtils::IsFormatNode(aNode)) {
-    nsCOMPtr<nsIAtom> atom = EditorBase::GetTag(aNode);
+    RefPtr<nsIAtom> atom = EditorBase::GetTag(aNode);
     atom->ToString(outFormat);
   } else {
     outFormat.Truncate();
   }
   return NS_OK;
 }
 
 void
@@ -3178,17 +3178,17 @@ HTMLEditRules::WillMakeList(Selection* a
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = false;
 
   // deduce what tag to use for list items
-  nsCOMPtr<nsIAtom> itemType;
+  RefPtr<nsIAtom> itemType;
   if (aItemType) {
     itemType = NS_Atomize(*aItemType);
     NS_ENSURE_TRUE(itemType, NS_ERROR_OUT_OF_MEMORY);
   } else if (listType == nsGkAtoms::dl) {
     itemType = nsGkAtoms::dd;
   } else {
     itemType = nsGkAtoms::li;
   }
@@ -4212,17 +4212,17 @@ HTMLEditRules::WillOutdent(Selection& aS
       if (useCSS && IsBlockNode(curNode)) {
         nsIAtom& marginProperty =
           MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, curNode);
         nsAutoString value;
         htmlEditor->mCSSEditUtils->GetSpecifiedProperty(curNode,
                                                          marginProperty,
                                                          value);
         float f;
-        nsCOMPtr<nsIAtom> unit;
+        RefPtr<nsIAtom> unit;
         NS_ENSURE_STATE(htmlEditor);
         htmlEditor->mCSSEditUtils->ParseLength(value, &f,
                                                getter_AddRefs(unit));
         if (f > 0) {
           ChangeIndentation(*curNode->AsElement(), Change::minus);
           continue;
         }
       }
@@ -4290,17 +4290,17 @@ HTMLEditRules::WillOutdent(Selection& aS
           break;
         } else if (useCSS) {
           nsIAtom& marginProperty =
             MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, curNode);
           nsAutoString value;
           htmlEditor->mCSSEditUtils->GetSpecifiedProperty(*n, marginProperty,
                                                            value);
           float f;
-          nsCOMPtr<nsIAtom> unit;
+          RefPtr<nsIAtom> unit;
           htmlEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
           if (f > 0 && !(HTMLEditUtils::IsList(curParent) &&
                          HTMLEditUtils::IsList(curNode))) {
             curBlockQuote = n->AsElement();
             firstBQChild = curNode;
             lastBQChild = curNode;
             curBlockQuoteIsIndentedWithCSS = true;
             break;
@@ -6696,17 +6696,17 @@ HTMLEditRules::ReturnInListItem(Selectio
     NS_ENSURE_SUCCESS(rv, rv);
     if (isEmptyNode) {
       rv = CreateMozBR(prevItem->AsDOMNode(), 0);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
       rv = htmlEditor->IsEmptyNode(&aListItem, &isEmptyNode, true);
       NS_ENSURE_SUCCESS(rv, rv);
       if (isEmptyNode) {
-        nsCOMPtr<nsIAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
+        RefPtr<nsIAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
         if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
           nsCOMPtr<nsINode> list = aListItem.GetParentNode();
           int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
 
           nsIAtom* listAtom = nodeAtom == nsGkAtoms::dt ? nsGkAtoms::dd
                                                         : nsGkAtoms::dt;
           nsCOMPtr<Element> newListItem =
             htmlEditor->CreateNode(listAtom, list, itemOffset + 1);
@@ -8616,17 +8616,17 @@ HTMLEditRules::ChangeIndentation(Element
   RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
 
   nsIAtom& marginProperty =
     MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, aElement);
   nsAutoString value;
   htmlEditor->mCSSEditUtils->GetSpecifiedProperty(aElement, marginProperty,
                                                   value);
   float f;
-  nsCOMPtr<nsIAtom> unit;
+  RefPtr<nsIAtom> unit;
   htmlEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
   if (!f) {
     nsAutoString defaultLengthUnit;
     htmlEditor->mCSSEditUtils->GetDefaultLengthUnit(defaultLengthUnit);
     unit = NS_Atomize(defaultLengthUnit);
   }
   int8_t multiplier = aChange == Change::plus ? +1 : -1;
   if (nsGkAtoms::in == unit) {
--- a/editor/libeditor/HTMLEditUtils.cpp
+++ b/editor/libeditor/HTMLEditUtils.cpp
@@ -83,17 +83,17 @@ HTMLEditUtils::IsFormatNode(nsINode* aNo
 /**
  * IsNodeThatCanOutdent() returns true if aNode is a list, list item or
  * blockquote.
  */
 bool
 HTMLEditUtils::IsNodeThatCanOutdent(nsIDOMNode* aNode)
 {
   MOZ_ASSERT(aNode);
-  nsCOMPtr<nsIAtom> nodeAtom = EditorBase::GetTag(aNode);
+  RefPtr<nsIAtom> nodeAtom = EditorBase::GetTag(aNode);
   return (nodeAtom == nsGkAtoms::ul)
       || (nodeAtom == nsGkAtoms::ol)
       || (nodeAtom == nsGkAtoms::dl)
       || (nodeAtom == nsGkAtoms::li)
       || (nodeAtom == nsGkAtoms::dd)
       || (nodeAtom == nsGkAtoms::dt)
       || (nodeAtom == nsGkAtoms::blockquote);
 }
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -1950,17 +1950,17 @@ HTMLEditor::MakeOrChangeList(const nsASt
       *selection->GetRangeAt(0)->GetStartContainer()->AsContent();
     int32_t offset = selection->GetRangeAt(0)->StartOffset();
 
     if (isCollapsed) {
       // have to find a place to put the list
       nsCOMPtr<nsIContent> parent = node;
       nsCOMPtr<nsIContent> topChild = node;
 
-      nsCOMPtr<nsIAtom> listAtom = NS_Atomize(aListType);
+      RefPtr<nsIAtom> listAtom = NS_Atomize(aListType);
       while (!CanContainTag(*parent, *listAtom)) {
         topChild = parent;
         parent = parent->GetParent();
       }
 
       if (parent != node) {
         // we need to split up to the child of parent
         offset = SplitNodeDeep(*topChild, *node, offset);
@@ -2087,17 +2087,17 @@ HTMLEditor::InsertBasicBlock(const nsASt
       *selection->GetRangeAt(0)->GetStartContainer()->AsContent();
     int32_t offset = selection->GetRangeAt(0)->StartOffset();
 
     if (isCollapsed) {
       // have to find a place to put the block
       nsCOMPtr<nsIContent> parent = node;
       nsCOMPtr<nsIContent> topChild = node;
 
-      nsCOMPtr<nsIAtom> blockAtom = NS_Atomize(aBlockType);
+      RefPtr<nsIAtom> blockAtom = NS_Atomize(aBlockType);
       while (!CanContainTag(*parent, *blockAtom)) {
         NS_ENSURE_TRUE(parent->GetParent(), NS_ERROR_FAILURE);
         topChild = parent;
         parent = parent->GetParent();
       }
 
       if (parent != node) {
         // we need to split up to the child of parent
@@ -2518,17 +2518,17 @@ HTMLEditor::CreateElementWithDefaults(co
     realTagName.Assign('a');
   } else {
     realTagName = tagName;
   }
   // We don't use editor's CreateElement because we don't want to go through
   // the transaction system
 
   // New call to use instead to get proper HTML element, bug 39919
-  nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
+  RefPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
   RefPtr<Element> newElement = CreateHTMLContent(realTagAtom);
   if (!newElement) {
     return nullptr;
   }
 
   // Mark the new element dirty, so it will be formatted
   ErrorResult rv;
   newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString(), rv);
--- a/editor/libeditor/HTMLEditorObjectResizer.cpp
+++ b/editor/libeditor/HTMLEditorObjectResizer.cpp
@@ -185,17 +185,17 @@ HTMLEditor::CreateResizer(int16_t aLocat
   return Move(ret);
 }
 
 ManualNACPtr
 HTMLEditor::CreateShadow(nsIContent& aParentContent,
                          Element& aOriginalObject)
 {
   // let's create an image through the element factory
-  nsCOMPtr<nsIAtom> name;
+  RefPtr<nsIAtom> name;
   if (HTMLEditUtils::IsImage(&aOriginalObject)) {
     name = nsGkAtoms::img;
   } else {
     name = nsGkAtoms::span;
   }
 
   return CreateAnonymousElement(name, aParentContent,
                                 NS_LITERAL_STRING("mozResizingShadow"), true);
@@ -219,17 +219,17 @@ HTMLEditor::SetAllResizersPosition()
   int32_t w = mResizedObjectWidth;
   int32_t h = mResizedObjectHeight;
 
   // now let's place all the resizers around the image
 
   // get the size of resizers
   nsAutoString value;
   float resizerWidth, resizerHeight;
-  nsCOMPtr<nsIAtom> dummyUnit;
+  RefPtr<nsIAtom> dummyUnit;
   mCSSEditUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::width,
                                      value);
   mCSSEditUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
   mCSSEditUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::height,
                                      value);
   mCSSEditUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
 
   int32_t rw  = (int32_t)((resizerWidth + 1) / 2);
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -54,17 +54,17 @@ IsEmptyTextNode(HTMLEditor* aThis, nsINo
          isEmptyTextNode;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetInlineProperty(const nsAString& aProperty,
                               const nsAString& aAttribute,
                               const nsAString& aValue)
 {
-  nsCOMPtr<nsIAtom> property = NS_Atomize(aProperty);
+  RefPtr<nsIAtom> property = NS_Atomize(aProperty);
   return SetInlineProperty(property, aAttribute, aValue);
 }
 
 nsresult
 HTMLEditor::SetInlineProperty(nsIAtom* aProperty,
                               const nsAString& aAttribute,
                               const nsAString& aValue)
 {
@@ -210,17 +210,17 @@ HTMLEditor::IsSimpleModifiableNode(nsICo
         element->IsHTMLElement(nsGkAtoms::em)) ||
        (aProperty == nsGkAtoms::strike &&
         element->IsHTMLElement(nsGkAtoms::s)))) {
     return true;
   }
 
   // Now look for things like <font>
   if (aAttribute && !aAttribute->IsEmpty()) {
-    nsCOMPtr<nsIAtom> atom = NS_Atomize(*aAttribute);
+    RefPtr<nsIAtom> atom = NS_Atomize(*aAttribute);
     MOZ_ASSERT(atom);
 
     nsString attrValue;
     if (element->IsHTMLElement(aProperty) &&
         IsOnlyAttribute(element, *aAttribute) &&
         element->GetAttr(kNameSpaceID_None, atom, attrValue) &&
         attrValue.Equals(*aValue, nsCaseInsensitiveStringComparator())) {
       // This is not quite correct, because it excludes cases like
@@ -319,17 +319,17 @@ HTMLEditor::SetInlinePropertyOnTextNode(
 }
 
 nsresult
 HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode,
                                         nsIAtom& aProperty,
                                         const nsAString* aAttribute,
                                         const nsAString& aValue)
 {
-  nsCOMPtr<nsIAtom> attrAtom = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
+  RefPtr<nsIAtom> attrAtom = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
 
   // If this is an element that can't be contained in a span, we have to
   // recurse to its children.
   if (!TagCanContain(*nsGkAtoms::span, aNode)) {
     if (aNode.HasChildren()) {
       nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
 
       // Populate the list.
@@ -701,17 +701,17 @@ HTMLEditor::RemoveStyleInside(nsIContent
         rv =
           CloneAttribute(nsGkAtoms::_class, spanNode, aNode.AsElement());
         NS_ENSURE_SUCCESS(rv, rv);
       }
       nsresult rv = RemoveContainer(&aNode);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
       // otherwise we just want to eliminate the attribute
-      nsCOMPtr<nsIAtom> attribute = NS_Atomize(*aAttribute);
+      RefPtr<nsIAtom> attribute = NS_Atomize(*aAttribute);
       if (aNode.HasAttr(kNameSpaceID_None, attribute)) {
         // if this matching attribute is the ONLY one on the node,
         // then remove the whole node.  Otherwise just nix the attribute.
         if (IsOnlyAttribute(&aNode, *aAttribute)) {
           nsresult rv = RemoveContainer(&aNode);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
@@ -728,17 +728,17 @@ HTMLEditor::RemoveStyleInside(nsIContent
   }
 
   if (!aChildrenOnly &&
       mCSSEditUtils->IsCSSEditableProperty(&aNode, aProperty, aAttribute)) {
     // the HTML style defined by aProperty/aAttribute has a CSS equivalence in
     // this implementation for the node aNode; let's check if it carries those
     // css styles
     if (aNode.IsElement()) {
-      nsCOMPtr<nsIAtom> attribute =
+      RefPtr<nsIAtom> attribute =
         aAttribute ? NS_Atomize(*aAttribute) : nullptr;
       bool hasAttribute =
         mCSSEditUtils->HaveCSSEquivalentStyles(
                          aNode, aProperty, attribute, CSSEditUtils::eSpecified);
       if (hasAttribute) {
         // yes, tmp has the corresponding css declarations in its style
         // attribute
         // let's remove them
@@ -1074,17 +1074,17 @@ HTMLEditor::GetInlinePropertyBase(nsIAto
 NS_IMETHODIMP
 HTMLEditor::GetInlineProperty(const nsAString& aProperty,
                               const nsAString& aAttribute,
                               const nsAString& aValue,
                               bool* aFirst,
                               bool* aAny,
                               bool* aAll)
 {
-  nsCOMPtr<nsIAtom> property = NS_Atomize(aProperty);
+  RefPtr<nsIAtom> property = NS_Atomize(aProperty);
   return GetInlineProperty(property, aAttribute, aValue, aFirst, aAny, aAll);
 }
 
 nsresult
 HTMLEditor::GetInlineProperty(nsIAtom* aProperty,
                               const nsAString& aAttribute,
                               const nsAString& aValue,
                               bool* aFirst,
@@ -1105,17 +1105,17 @@ NS_IMETHODIMP
 HTMLEditor::GetInlinePropertyWithAttrValue(const nsAString& aProperty,
                                            const nsAString& aAttribute,
                                            const nsAString& aValue,
                                            bool* aFirst,
                                            bool* aAny,
                                            bool* aAll,
                                            nsAString& outValue)
 {
-  nsCOMPtr<nsIAtom> property = NS_Atomize(aProperty);
+  RefPtr<nsIAtom> property = NS_Atomize(aProperty);
   return GetInlinePropertyWithAttrValue(property, aAttribute, aValue, aFirst,
                                         aAny, aAll, outValue);
 }
 
 nsresult
 HTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom* aProperty,
                                            const nsAString& aAttribute,
                                            const nsAString& aValue,
@@ -1145,17 +1145,17 @@ HTMLEditor::RemoveAllInlineProperties()
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::RemoveInlineProperty(const nsAString& aProperty,
                                  const nsAString& aAttribute)
 {
-  nsCOMPtr<nsIAtom> property = NS_Atomize(aProperty);
+  RefPtr<nsIAtom> property = NS_Atomize(aProperty);
   return RemoveInlineProperty(property, aAttribute);
 }
 
 nsresult
 HTMLEditor::RemoveInlineProperty(nsIAtom* aProperty,
                                  const nsAString& aAttribute)
 {
   return RemoveInlinePropertyImpl(aProperty, &aAttribute);
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -1956,17 +1956,17 @@ HTMLEditor::SwitchTableCellHeaderType(ns
   // Save current selection to restore when done
   // This is needed so ReplaceContainer can monitor selection
   //  when replacing nodes
   RefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
   AutoSelectionRestorer selectionRestorer(selection, this);
 
   // Set to the opposite of current type
-  nsCOMPtr<nsIAtom> atom = EditorBase::GetTag(aSourceCell);
+  RefPtr<nsIAtom> atom = EditorBase::GetTag(aSourceCell);
   nsIAtom* newCellType = atom == nsGkAtoms::td ? nsGkAtoms::th : nsGkAtoms::td;
 
   // This creates new node, moves children, copies attributes (true)
   //   and manages the selection!
   nsCOMPtr<Element> newNode = ReplaceContainer(sourceCell, newCellType,
       nullptr, nullptr, EditorBase::eCloneAttributes);
   NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
 
--- a/editor/libeditor/PlaceholderTransaction.cpp
+++ b/editor/libeditor/PlaceholderTransaction.cpp
@@ -162,17 +162,17 @@ PlaceholderTransaction::Merge(nsITransac
 //  finished the initial batch and we know we will be told when the batch ends.
 //  we can remeber the selection then.
   } else {
     // merge typing or IME or deletion transactions if the selection matches
     if ((mName.get() == nsGkAtoms::TypingTxnName ||
          mName.get() == nsGkAtoms::IMETxnName    ||
          mName.get() == nsGkAtoms::DeleteTxnName) && !mCommitted) {
       if (absorbingTransaction) {
-        nsCOMPtr<nsIAtom> atom;
+        RefPtr<nsIAtom> atom;
         absorbingTransaction->GetTxnName(getter_AddRefs(atom));
         if (atom && atom == mName) {
           // check if start selection of next placeholder matches
           // end selection of this placeholder
           bool isSame;
           absorbingTransaction->StartSelectionEquals(&mEndSel, &isSame);
           if (isSame) {
             mAbsorb = true;  // we need to start absorbing again
--- a/editor/reftests/reftest.list
+++ b/editor/reftests/reftest.list
@@ -77,17 +77,17 @@ fails-if(Android) needs-focus != spellch
 needs-focus == spellcheck-non-latin-arabic.html spellcheck-non-latin-arabic-ref.html
 needs-focus == spellcheck-non-latin-chinese-simplified.html spellcheck-non-latin-chinese-simplified-ref.html
 needs-focus == spellcheck-non-latin-chinese-traditional.html spellcheck-non-latin-chinese-traditional-ref.html
 needs-focus == spellcheck-non-latin-hebrew.html spellcheck-non-latin-hebrew-ref.html
 needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese-ref.html
 needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean-ref.html
 == unneeded_scroll.html unneeded_scroll-ref.html
 == caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html
-fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-3) asserts-if(webrender&&!browserIsRemote,0-1) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html # bug 959132 for assertions
+fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-3) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html # bug 959132 for assertions
 fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html
 == selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html
 == 672709.html 672709-ref.html
 == 338427-1.html 338427-1-ref.html
 skip-if(Android) needs-focus == 674212-spellcheck.html 674212-spellcheck-ref.html
 skip-if(Android) needs-focus == 338427-2.html 338427-2-ref.html
--- a/editor/txtsvc/nsFilteredContentIterator.h
+++ b/editor/txtsvc/nsFilteredContentIterator.h
@@ -61,21 +61,21 @@ protected:
   nsresult AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir);
   void CheckAdvNode(nsIDOMNode* aNode, bool& aDidSkip, eDirectionType aDir);
   nsresult SwitchDirections(bool aChangeToForward);
 
   nsCOMPtr<nsIContentIterator> mCurrentIterator;
   nsCOMPtr<nsIContentIterator> mIterator;
   nsCOMPtr<nsIContentIterator> mPreIterator;
 
-  nsCOMPtr<nsIAtom> mBlockQuoteAtom;
-  nsCOMPtr<nsIAtom> mScriptAtom;
-  nsCOMPtr<nsIAtom> mTextAreaAtom;
-  nsCOMPtr<nsIAtom> mSelectAreaAtom;
-  nsCOMPtr<nsIAtom> mMapAtom;
+  RefPtr<nsIAtom> mBlockQuoteAtom;
+  RefPtr<nsIAtom> mScriptAtom;
+  RefPtr<nsIAtom> mTextAreaAtom;
+  RefPtr<nsIAtom> mSelectAreaAtom;
+  RefPtr<nsIAtom> mMapAtom;
 
   nsCOMPtr<nsITextServicesFilter> mFilter;
   RefPtr<nsRange>               mRange;
   bool                            mDidSkip;
   bool                            mIsOutOfRange;
   eDirectionType                  mDirection;
 };
 
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -63,17 +63,17 @@ public:
     void Flush();
 
     void UpdateUserFonts(gfxUserFontSet* aUserFontSet);
 
 protected:
     ~nsFontCache() {}
 
     nsDeviceContext*          mContext; // owner
-    nsCOMPtr<nsIAtom>         mLocaleLanguage;
+    RefPtr<nsIAtom>         mLocaleLanguage;
     nsTArray<nsFontMetrics*>  mFontMetrics;
 };
 
 NS_IMPL_ISUPPORTS(nsFontCache, nsIObserver)
 
 // The Init and Destroy methods are necessary because it's not
 // safe to call AddObserver from a constructor or RemoveObserver
 // from a destructor.  That should be fixed.
--- a/gfx/src/nsFontMetrics.h
+++ b/gfx/src/nsFontMetrics.h
@@ -244,17 +244,17 @@ private:
       return GetMetrics(mOrientation);
     }
 
     const gfxFont::Metrics&
     GetMetrics(const gfxFont::Orientation aFontOrientation) const;
 
     nsFont mFont;
     RefPtr<gfxFontGroup> mFontGroup;
-    nsCOMPtr<nsIAtom> mLanguage;
+    RefPtr<nsIAtom> mLanguage;
     // Pointer to the device context for which this fontMetrics object was
     // created.
     nsDeviceContext* MOZ_NON_OWNING_REF mDeviceContext;
     int32_t mP2A;
 
     // The font orientation (horizontal or vertical) for which these metrics
     // have been initialized. This determines which line metrics (ascent and
     // descent) they will return.
--- a/gfx/src/nsThebesFontEnumerator.cpp
+++ b/gfx/src/nsThebesFontEnumerator.cpp
@@ -43,17 +43,17 @@ nsThebesFontEnumerator::EnumerateFonts(c
     nsTArray<nsString> fontList;
 
     nsAutoCString generic;
     if (aGeneric)
         generic.Assign(aGeneric);
     else
         generic.SetIsVoid(true);
 
-    nsCOMPtr<nsIAtom> langGroupAtom;
+    RefPtr<nsIAtom> langGroupAtom;
     if (aLangGroup) {
         nsAutoCString lowered;
         lowered.Assign(aLangGroup);
         ToLowerCase(lowered);
         langGroupAtom = NS_Atomize(lowered);
     }
 
     nsresult rv = gfxPlatform::GetPlatform()->GetFontList(langGroupAtom, generic, fontList);
@@ -151,17 +151,17 @@ public:
         nsCOMPtr<nsIRunnable> runnable = new EnumerateFontsResult(
             rv, Move(mEnumerateFontsPromise), Move(fontList));
         NS_DispatchToMainThread(runnable.forget());
 
         return NS_OK;
     }
 
 private:
-    nsCOMPtr<nsIAtom> mLangGroupAtom;
+    RefPtr<nsIAtom> mLangGroupAtom;
     nsAutoCStringN<16> mGeneric;
     UniquePtr<EnumerateFontsPromise> mEnumerateFontsPromise;
 };
 
 NS_IMETHODIMP
 nsThebesFontEnumerator::EnumerateAllFontsAsync(JSContext* aCx,
                                                JS::MutableHandleValue aRval)
 {
@@ -187,17 +187,17 @@ nsThebesFontEnumerator::EnumerateFontsAs
     }
 
     auto enumerateFontsPromise = MakeUnique<EnumerateFontsPromise>(promise);
 
     nsCOMPtr<nsIThread> thread;
     nsresult rv = NS_NewNamedThread("FontEnumThread", getter_AddRefs(thread));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIAtom> langGroupAtom;
+    RefPtr<nsIAtom> langGroupAtom;
     if (aLangGroup) {
         nsAutoCStringN<16> lowered;
         lowered.Assign(aLangGroup);
         ToLowerCase(lowered);
         langGroupAtom = NS_Atomize(lowered);
     }
 
     nsAutoCString generic;
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -180,17 +180,17 @@ struct gfxFontStyle {
         NS_ASSERTION(sizeAdjust >= 0.0, "Not meant to be called when sizeAdjust = -1.0");
         gfxFloat adjustedSize = std::max(NS_round(size*(sizeAdjust/aspect)), 1.0);
         return std::min(adjustedSize, FONT_MAX_SIZE);
     }
 
     PLDHashNumber Hash() const {
         return ((style + (systemFont << 7) +
             (weight << 8)) + uint32_t(size*1000) + uint32_t(sizeAdjust*1000)) ^
-            nsISupportsHashKey::HashKey(language);
+            nsRefPtrHashKey<nsIAtom>::HashKey(language);
     }
 
     int8_t ComputeWeight() const;
 
     // Adjust this style to simulate sub/superscript (as requested in the
     // variantSubSuper field) using size and baselineOffset instead.
     void AdjustForSubSuperscript(int32_t aAppUnitsPerDevPixel);
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2350,17 +2350,17 @@ gfxPlatform::InitAcceleration()
       gfxCriticalNote << "Cannot evaluate keyed mutex feature status";
       gfxVars::SetAllowD3D11KeyedMutex(true);
     }
 #endif
   }
 
   if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
 #ifdef XP_WIN
-    Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
+      Preferences::GetBool("media.wmf.dxva.enabled", true) &&
 #endif
       NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
                                                discardFailureId, &status))) {
       if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
         sLayersSupportsHardwareVideoDecoding = true;
       }
   }
 
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -658,20 +658,20 @@ private:
   DECL_GFX_PREF(Once, "layout.scroll.root-frame-containers",   LayoutUseContainersForRootFrames, bool, true);
   // This pref is to be set by test code only.
   DECL_GFX_PREF(Live, "layout.scrollbars.always-layerize-track", AlwaysLayerizeScrollbarTrackTestOnly, bool, false);
   DECL_GFX_PREF(Live, "layout.smaller-painted-layers",         LayoutSmallerPaintedLayers, bool, false);
 
   DECL_GFX_PREF(Once, "media.hardware-video-decoding.force-enabled",
                                                                HardwareVideoDecodingForceEnabled, bool, false);
 #ifdef XP_WIN
-  DECL_GFX_PREF(Live, "media.windows-media-foundation.allow-d3d11-dxva", PDMWMFAllowD3D11, bool, true);
-  DECL_GFX_PREF(Live, "media.windows-media-foundation.max-dxva-videos", PDMWMFMaxDXVAVideos, uint32_t, 8);
-  DECL_GFX_PREF(Live, "media.windows-media-foundation.use-nv12-format", PDMWMFUseNV12Format, bool, true);
-  DECL_GFX_PREF(Once, "media.windows-media-foundation.use-sync-texture", PDMWMFUseSyncTexture, bool, true);
+  DECL_GFX_PREF(Live, "media.wmf.dxva.d3d11.enabled", PDMWMFAllowD3D11, bool, true);
+  DECL_GFX_PREF(Live, "media.wmf.dxva.max-videos", PDMWMFMaxDXVAVideos, uint32_t, 8);
+  DECL_GFX_PREF(Live, "media.wmf.use-nv12-format", PDMWMFUseNV12