Merge autoland to mozilla-central. a=merge
authorOana Pop Rus <opoprus@mozilla.com>
Thu, 28 Mar 2019 19:29:18 +0200
changeset 525376 1ef00231db5339e9208c4ceda5e570a69eff8af4
parent 525359 4e2ea1a75e878ae392e4775f2eddd9f83d1b008e (current diff)
parent 525375 db92f218cea95be1596b1be70ccb80db7024eae7 (diff)
child 525380 e31357c7759379d2279b6883cb09c91997bfaa5d
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.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. a=merge
browser/base/content/test/chrome/.eslintrc.js
browser/components/about/test/unit/.eslintrc.js
browser/components/aboutconfig/test/browser/.eslintrc.js
browser/components/attribution/test/xpcshell/.eslintrc.js
browser/components/contextualidentity/test/browser/.eslintrc.js
browser/components/dirprovider/tests/unit/.eslintrc.js
browser/components/downloads/test/browser/.eslintrc.js
browser/components/enterprisepolicies/tests/browser/.eslintrc.js
browser/components/migration/tests/unit/.eslintrc.js
browser/components/newtab/test/browser/.eslintrc.js
browser/components/newtab/test/xpcshell/.eslintrc.js
browser/components/originattributes/test/browser/.eslintrc.js
browser/components/originattributes/test/mochitest/.eslintrc.js
browser/components/payments/test/browser/.eslintrc.js
browser/components/payments/test/mochitest/.eslintrc.js
browser/components/payments/test/unit/.eslintrc.js
browser/components/places/tests/browser/.eslintrc.js
browser/components/places/tests/chrome/.eslintrc.js
browser/components/places/tests/unit/.eslintrc.js
browser/components/privatebrowsing/test/browser/.eslintrc.js
browser/components/protocolhandler/test/browser/.eslintrc.js
browser/components/resistfingerprinting/test/browser/.eslintrc.js
browser/components/resistfingerprinting/test/chrome/.eslintrc.js
browser/components/search/test/browser/.eslintrc.js
browser/components/search/test/unit/.eslintrc.js
browser/components/sessionstore/test/unit/.eslintrc.js
browser/components/shell/test/unit/.eslintrc.js
browser/components/syncedtabs/test/browser/.eslintrc.js
browser/components/syncedtabs/test/xpcshell/.eslintrc.js
browser/components/tests/browser/.eslintrc.js
browser/components/tests/unit/.eslintrc.js
browser/components/translation/test/unit/.eslintrc.js
browser/components/urlbar/tests/browser/.eslintrc.js
browser/components/urlbar/tests/unit/.eslintrc.js
browser/extensions/formautofill/test/browser/.eslintrc.js
browser/extensions/formautofill/test/browser/creditCard/.eslintrc.js
browser/extensions/formautofill/test/mochitest/.eslintrc.js
browser/extensions/formautofill/test/unit/.eslintrc.js
browser/extensions/webcompat-reporter/test/browser/.eslintrc.js
browser/modules/test/browser/.eslintrc.js
browser/modules/test/unit/.eslintrc.js
browser/tools/mozscreenshots/tests/xpcshell/.eslintrc.js
caps/tests/unit/.eslintrc.js
docshell/test/browser/.eslintrc.js
docshell/test/chrome/.eslintrc.js
docshell/test/mochitest/.eslintrc.js
docshell/test/unit/.eslintrc.js
docshell/test/unit_ipc/.eslintrc.js
dom/abort/tests/unit/.eslintrc.js
dom/animation/test/chrome/.eslintrc.js
dom/base/test/unit/.eslintrc.js
dom/base/test/unit_ipc/.eslintrc.js
dom/cache/test/browser/.eslintrc.js
dom/cache/test/mochitest/.eslintrc.js
dom/cache/test/xpcshell/.eslintrc.js
dom/canvas/test/chrome/.eslintrc.js
dom/console/tests/xpcshell/.eslintrc.js
dom/credentialmanagement/tests/browser/.eslintrc.js
dom/encoding/test/unit/.eslintrc.js
dom/indexedDB/test/unit/.eslintrc.js
dom/localstorage/test/unit/.eslintrc.js
dom/media/tests/mochitest/identity/.eslintrc.js
dom/notification/test/browser/.eslintrc.js
dom/notification/test/chrome/.eslintrc.js
dom/notification/test/mochitest/.eslintrc.js
dom/notification/test/unit/.eslintrc.js
dom/plugins/test/unit/.eslintrc.js
dom/presentation/tests/mochitest/.eslintrc.js
dom/presentation/tests/xpcshell/.eslintrc.js
dom/promise/tests/unit/.eslintrc.js
dom/quota/test/unit/.eslintrc.js
dom/security/featurepolicy/test/mochitest/.eslintrc.js
dom/security/test/unit/.eslintrc.js
dom/tests/browser/.eslintrc.js
dom/tests/mochitest/ajax/offline/.eslintrc.js
dom/tests/unit/.eslintrc.js
dom/webauthn/tests/browser/.eslintrc.js
dom/webgpu/mochitest/.eslintrc.js
dom/workers/test/xpcshell/.eslintrc.js
extensions/cookie/test/unit/.eslintrc.js
extensions/pref/autoconfig/test/unit/.eslintrc.js
extensions/spellcheck/hunspell/tests/unit/.eslintrc.js
gfx/tests/browser/.eslintrc.js
gfx/tests/chrome/.eslintrc.js
gfx/tests/mochitest/.eslintrc.js
image/test/browser/.eslintrc.js
image/test/unit/.eslintrc.js
intl/uconv/tests/unit/.eslintrc.js
layout/inspector/tests/chrome/.eslintrc.js
layout/style/test/chrome/.eslintrc.js
layout/tools/layout-debug/tests/browser/.eslintrc.js
layout/tools/layout-debug/tests/unit/.eslintrc.js
mobile/android/tests/browser/chrome/.eslintrc.js
modules/libjar/test/mochitest/.eslintrc.js
modules/libjar/test/unit/.eslintrc.js
modules/libjar/zipwriter/test/unit/.eslintrc.js
modules/libmar/tests/unit/.eslintrc.js
modules/libpref/test/unit/.eslintrc.js
modules/libpref/test/unit_ipc/.eslintrc.js
netwerk/cookie/test/browser/.eslintrc.js
netwerk/cookie/test/mochitest/.eslintrc.js
netwerk/cookie/test/unit/.eslintrc.js
netwerk/test/browser/.eslintrc.js
netwerk/test/mochitests/.eslintrc.js
netwerk/test/unit/.eslintrc.js
netwerk/test/unit_ipc/.eslintrc.js
parser/xml/test/unit/.eslintrc.js
remote/test/browser/.eslintrc.js
remote/test/unit/.eslintrc.js
security/manager/ssl/tests/mochitest/browser/.eslintrc.js
security/manager/ssl/tests/mochitest/stricttransportsecurity/.eslintrc.js
security/manager/ssl/tests/unit/.eslintrc.js
services/common/tests/unit/.eslintrc.js
services/crypto/component/tests/unit/.eslintrc.js
services/crypto/tests/unit/.eslintrc.js
services/fxaccounts/tests/browser/.eslintrc.js
services/fxaccounts/tests/mochitest/.eslintrc.js
services/fxaccounts/tests/xpcshell/.eslintrc.js
services/settings/test/unit/.eslintrc.js
services/sync/tests/unit/.eslintrc.js
storage/test/unit/.eslintrc.js
testing/mochitest/chrome/.eslintrc.js
testing/mochitest/tests/browser/.eslintrc.js
testing/modules/tests/browser/.eslintrc.js
testing/xpcshell/example/unit/.eslintrc.js
toolkit/components/aboutmemory/tests/xpcshell/.eslintrc.js
toolkit/components/aboutperformance/tests/browser/.eslintrc.js
toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js
toolkit/components/autocomplete/tests/unit/.eslintrc.js
toolkit/components/captivedetect/test/unit/.eslintrc.js
toolkit/components/cleardata/tests/unit/.eslintrc.js
toolkit/components/cloudstorage/tests/unit/.eslintrc.js
toolkit/components/commandlines/test/unit/.eslintrc.js
toolkit/components/commandlines/test/unit_unix/.eslintrc.js
toolkit/components/commandlines/test/unit_win/.eslintrc.js
toolkit/components/contentprefs/tests/mochitest/.eslintrc.js
toolkit/components/contentprefs/tests/unit_cps2/.eslintrc.js
toolkit/components/contextualidentity/tests/unit/.eslintrc.js
toolkit/components/crashes/tests/xpcshell/.eslintrc.js
toolkit/components/crashmonitor/test/unit/.eslintrc.js
toolkit/components/ctypes/tests/chrome/.eslintrc.js
toolkit/components/ctypes/tests/unit/.eslintrc.js
toolkit/components/downloads/test/browser/.eslintrc.js
toolkit/components/downloads/test/unit/.eslintrc.js
toolkit/components/featuregates/test/unit/.eslintrc.js
toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js
toolkit/components/kvstore/test/xpcshell/.eslintrc.js
toolkit/components/lz4/tests/xpcshell/.eslintrc.js
toolkit/components/mediasniffer/test/unit/.eslintrc.js
toolkit/components/normandy/test/browser/.eslintrc.js
toolkit/components/normandy/test/unit/.eslintrc.js
toolkit/components/passwordmgr/test/unit/.eslintrc.js
toolkit/components/places/tests/browser/.eslintrc.js
toolkit/components/places/tests/chrome/.eslintrc.js
toolkit/components/places/tests/unit/.eslintrc.js
toolkit/components/promiseworker/tests/xpcshell/.eslintrc.js
toolkit/components/remotebrowserutils/tests/browser/.eslintrc.js
toolkit/components/remotepagemanager/tests/browser/.eslintrc.js
toolkit/components/reputationservice/test/unit/.eslintrc.js
toolkit/components/satchel/test/browser/.eslintrc.js
toolkit/components/satchel/test/unit/.eslintrc.js
toolkit/components/search/tests/xpcshell/.eslintrc.js
toolkit/components/startup/tests/browser/.eslintrc.js
toolkit/components/startup/tests/unit/.eslintrc.js
toolkit/components/telemetry/tests/browser/.eslintrc.js
toolkit/components/telemetry/tests/unit/.eslintrc.js
toolkit/components/terminator/tests/xpcshell/.eslintrc.js
toolkit/components/timermanager/tests/unit/.eslintrc.js
toolkit/components/url-classifier/tests/browser/.eslintrc.js
toolkit/components/url-classifier/tests/unit/.eslintrc.js
toolkit/components/urlformatter/tests/unit/.eslintrc.js
toolkit/components/utils/test/browser/.eslintrc.js
toolkit/components/utils/test/unit/.eslintrc.js
toolkit/components/viewsource/test/browser/.eslintrc.js
toolkit/components/windowcreator/tests/unit/.eslintrc.js
toolkit/components/xulstore/tests/chrome/.eslintrc.js
toolkit/components/xulstore/tests/xpcshell/.eslintrc.js
toolkit/content/tests/browser/.eslintrc.js
toolkit/content/tests/chrome/.eslintrc.js
toolkit/content/tests/mochitest/.eslintrc.js
toolkit/content/tests/unit/.eslintrc.js
toolkit/crashreporter/test/browser/.eslintrc.js
toolkit/crashreporter/test/unit/.eslintrc.js
toolkit/crashreporter/test/unit_ipc/.eslintrc.js
toolkit/forgetaboutsite/test/browser/.eslintrc.js
toolkit/forgetaboutsite/test/unit/.eslintrc.js
toolkit/modules/subprocess/test/xpcshell/.eslintrc.js
toolkit/modules/tests/browser/.eslintrc.js
toolkit/modules/tests/chrome/.eslintrc.js
toolkit/modules/tests/xpcshell/.eslintrc.js
toolkit/mozapps/downloads/tests/browser/.eslintrc.js
toolkit/mozapps/downloads/tests/unit/.eslintrc.js
toolkit/mozapps/extensions/test/mochitest/.eslintrc.js
toolkit/mozapps/update/tests/browser/.eslintrc.js
toolkit/mozapps/update/tests/chrome/.eslintrc.js
toolkit/mozapps/update/tests/unit_aus_update/.eslintrc.js
toolkit/mozapps/update/tests/unit_base_updater/.eslintrc.js
toolkit/mozapps/update/tests/unit_service_updater/.eslintrc.js
tools/code-coverage/tests/mochitest/.eslintrc.js
tools/code-coverage/tests/xpcshell/.eslintrc.js
tools/profiler/tests/chrome/.eslintrc.js
uriloader/exthandler/tests/unit/.eslintrc.js
widget/tests/browser/.eslintrc.js
widget/tests/unit/.eslintrc.js
xpcom/tests/unit/.eslintrc.js
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,10 +1,42 @@
 "use strict";
 
+const xpcshellTestConfig = require("eslint-plugin-mozilla/lib/configs/xpcshell-test.js");
+const browserTestConfig = require("eslint-plugin-mozilla/lib/configs/browser-test.js");
+const mochitestTestConfig = require("eslint-plugin-mozilla/lib/configs/mochitest-test.js");
+const chromeTestConfig = require("eslint-plugin-mozilla/lib/configs/chrome-test.js");
+
+/**
+ * Some configurations have overrides, which can't be specified within overrides,
+ * so we need to remove them.
+ */
+function removeOverrides(config) {
+  config = {...config};
+  delete config.overrides;
+  return config;
+}
+
+const xpcshellTestPaths = [
+  "**/test*/unit*/",
+  "**/test*/xpcshell/",
+];
+
+const browserTestPaths = [
+  "**/test*/**/browser/",
+];
+
+const mochitestTestPaths = [
+  "**/test*/mochitest/",
+];
+
+const chromeTestPaths = [
+  "**/test*/chrome/",
+];
+
 module.exports = {
   // New rules and configurations should generally be added in
   // tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js to
   // allow external repositories that use the plugin to pick them up as well.
   "extends": [
     "plugin:mozilla/recommended"
   ],
   "plugins": [
@@ -79,10 +111,56 @@ module.exports = {
       "toolkit/modules/**",
       "toolkit/mozapps/**",
       "tools/leak-gauge/leak-gauge.html",
       "xpcom/tests/unit/test_iniParser.js",
     ],
     "rules": {
       "no-throw-literal": "off",
     }
+  }, {
+    ...removeOverrides(xpcshellTestConfig),
+    "files": xpcshellTestPaths.map(path => `${path}**`),
+    "excludedFiles": "devtools/**"
+  }, {
+    // If it is an xpcshell head file, we turn off global unused variable checks, as it
+    // would require searching the other test files to know if they are used or not.
+    // This would be expensive and slow, and it isn't worth it for head files.
+    // We could get developers to declare as exported, but that doesn't seem worth it.
+    "files": xpcshellTestPaths.map(path => `${path}head*.js`),
+
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }, {
+    ...browserTestConfig,
+    "files": browserTestPaths.map(path => `${path}**`),
+    "excludedFiles": "devtools/**"
+  }, {
+    ...removeOverrides(mochitestTestConfig),
+    "files": mochitestTestPaths.map(path => `${path}**`),
+    "excludedFiles": [
+      "devtools/**",
+      "security/manager/ssl/tests/mochitest/browser/**",
+      "testing/mochitest/**",
+    ],
+  }, {
+    ...removeOverrides(chromeTestConfig),
+    "files": chromeTestPaths.map(path => `${path}**`),
+    "excludedFiles": [
+      "devtools/**",
+    ],
+  }, {
+    "env": {
+      // Ideally we wouldn't be using the simpletest env here, but our uses of
+      // js files mean we pick up everything from the global scope, which could
+      // be any one of a number of html files. So we just allow the basics...
+      "mozilla/simpletest": true,
+    },
+    "files": [
+      ...mochitestTestPaths.map(path => `${path}/**/*.js`),
+      ...chromeTestPaths.map(path => `${path}/**/*.js`),
+    ],
   }]
 };
--- a/accessible/tests/browser/.eslintrc.js
+++ b/accessible/tests/browser/.eslintrc.js
@@ -1,14 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
   "rules": {
     "mozilla/no-aArgs": "error",
     "mozilla/reject-importGlobalProperties": ["error", "everything"],
     "mozilla/var-only-at-top-level": "error",
 
     "block-scoped-var": "error",
     "camelcase": "error",
     "comma-dangle": ["error", "never"],
--- a/accessible/tests/mochitest/.eslintrc.js
+++ b/accessible/tests/mochitest/.eslintrc.js
@@ -1,14 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ],
   "rules": {
     // XXX These are rules that are enabled in the recommended configuration, but
     // disabled here due to failures when initially implemented. They should be
     // removed (and hence enabled) at some stage.
     "no-nested-ternary": "off",
     "no-undef": "off",
   }
 };
deleted file mode 100644
--- a/browser/base/content/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
--- a/browser/branding/aurora/locales/en-US/brand.dtd
+++ b/browser/branding/aurora/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShorterName      "Firefox">
 <!ENTITY  brandShortName        "Firefox Developer Edition">
 <!ENTITY  brandFullName         "Firefox Developer Edition">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName      "Firefox">
 <!ENTITY  vendorShortName       "Mozilla">
 <!ENTITY  trademarkInfo.part1   " ">
--- a/browser/branding/aurora/locales/en-US/brand.ftl
+++ b/browser/branding/aurora/locales/en-US/brand.ftl
@@ -7,13 +7,16 @@
 ## Firefox and Mozilla must be treated as a brand, and kept in English.
 ## It cannot be:
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
+-brand-shorter-name = Firefox
 -brand-short-name = Firefox Developer Edition
--vendor-short-name = Mozilla
 -brand-full-name = Firefox Developer Edition
--brand-shorter-name = Firefox
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
+-vendor-short-name = Mozilla
 trademarkInfo = { " " }
--- a/browser/branding/aurora/locales/en-US/brand.properties
+++ b/browser/branding/aurora/locales/en-US/brand.properties
@@ -1,10 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 brandShorterName=Firefox
 brandShortName=Firefox Developer Edition
 brandFullName=Firefox Developer Edition
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
 vendorShortName=Mozilla
 
 syncBrandShortName=Sync
--- a/browser/branding/nightly/locales/en-US/brand.dtd
+++ b/browser/branding/nightly/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShorterName      "Nightly">
 <!ENTITY  brandShortName        "Nightly">
 <!ENTITY  brandFullName         "Firefox Nightly">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName      "Firefox">
 <!ENTITY  vendorShortName       "Mozilla">
 <!ENTITY  trademarkInfo.part1   " ">
--- a/browser/branding/nightly/locales/en-US/brand.ftl
+++ b/browser/branding/nightly/locales/en-US/brand.ftl
@@ -7,13 +7,16 @@
 ## Firefox must be treated as a brand, and kept in English.
 ## It cannot be:
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
+-brand-shorter-name = Nightly
 -brand-short-name = Nightly
--vendor-short-name = Mozilla
 -brand-full-name = Firefox Nightly
--brand-shorter-name = Nightly
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
+-vendor-short-name = Mozilla
 trademarkInfo = { " " }
--- a/browser/branding/nightly/locales/en-US/brand.properties
+++ b/browser/branding/nightly/locales/en-US/brand.properties
@@ -1,10 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 brandShorterName=Nightly
 brandShortName=Nightly
 brandFullName=Firefox Nightly
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
 vendorShortName=Mozilla
 
 syncBrandShortName=Sync
--- a/browser/branding/official/locales/en-US/brand.dtd
+++ b/browser/branding/official/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShorterName      "Firefox">
 <!ENTITY  brandShortName        "Firefox">
 <!ENTITY  brandFullName         "Mozilla Firefox">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName      "Firefox">
 <!ENTITY  vendorShortName       "Mozilla">
 <!ENTITY  trademarkInfo.part1   "Firefox and the Firefox logos are trademarks of the Mozilla Foundation.">
--- a/browser/branding/official/locales/en-US/brand.ftl
+++ b/browser/branding/official/locales/en-US/brand.ftl
@@ -7,13 +7,16 @@
 ## Firefox must be treated as a brand, and kept in English.
 ## It cannot be:
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
+-brand-shorter-name = Firefox
 -brand-short-name = Firefox
--vendor-short-name = Mozilla
 -brand-full-name = Mozilla Firefox
--brand-shorter-name = Firefox
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
+-vendor-short-name = Mozilla
 trademarkInfo = Firefox and the Firefox logos are trademarks of the Mozilla Foundation.
--- a/browser/branding/official/locales/en-US/brand.properties
+++ b/browser/branding/official/locales/en-US/brand.properties
@@ -1,10 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 brandShorterName=Firefox
 brandShortName=Firefox
 brandFullName=Mozilla Firefox
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
 vendorShortName=Mozilla
 
 syncBrandShortName=Sync
--- a/browser/branding/unofficial/locales/en-US/brand.dtd
+++ b/browser/branding/unofficial/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShorterName      "Nightly">
 <!ENTITY  brandShortName        "Nightly">
 <!ENTITY  brandFullName         "Nightly">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName      "Firefox">
 <!ENTITY  vendorShortName       "Mozilla">
 <!ENTITY  trademarkInfo.part1   " ">
--- a/browser/branding/unofficial/locales/en-US/brand.ftl
+++ b/browser/branding/unofficial/locales/en-US/brand.ftl
@@ -7,13 +7,16 @@
 ## Firefox must be treated as a brand, and kept in English.
 ## It cannot be:
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
+-brand-shorter-name = Nightly
 -brand-short-name = Nightly
--vendor-short-name = Mozilla
 -brand-full-name = Nightly
--brand-shorter-name = Nightly
-trademarkInfo = { " " } 
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
+-vendor-short-name = Mozilla
+trademarkInfo = { " " }
--- a/browser/branding/unofficial/locales/en-US/brand.properties
+++ b/browser/branding/unofficial/locales/en-US/brand.properties
@@ -1,10 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 brandShorterName=Nightly
 brandShortName=Nightly
 brandFullName=Nightly
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
 vendorShortName=Mozilla
 
 syncBrandShortName=Sync
deleted file mode 100644
--- a/browser/components/about/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/aboutconfig/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ],
-};
deleted file mode 100644
--- a/browser/components/attribution/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": "plugin:mozilla/xpcshell-test",
-};
deleted file mode 100644
--- a/browser/components/contextualidentity/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/dirprovider/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/downloads/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/enterprisepolicies/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
--- a/browser/components/extensions/test/browser/.eslintrc.js
+++ b/browser/components/extensions/test/browser/.eslintrc.js
@@ -1,13 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/browser-test",
-
   "env": {
     "webextensions": true,
   },
 
   "rules": {
     "no-shadow": 0,
   },
 };
--- a/browser/components/extensions/test/mochitest/.eslintrc.js
+++ b/browser/components/extensions/test/mochitest/.eslintrc.js
@@ -1,10 +1,8 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/mochitest-test",
-
   "env": {
     "browser": true,
     "webextensions": true,
   },
 };
--- a/browser/components/extensions/test/xpcshell/.eslintrc.js
+++ b/browser/components/extensions/test/xpcshell/.eslintrc.js
@@ -1,11 +1,9 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/xpcshell-test",
-
   "env": {
     // The tests in this folder are testing based on WebExtensions, so lets
     // just define the webextensions environment here.
     "webextensions": true
   }
 };
--- a/browser/components/migration/.eslintrc.js
+++ b/browser/components/migration/.eslintrc.js
@@ -12,10 +12,20 @@ module.exports = {
     "no-multi-str": "error",
     "no-return-assign": "error",
     "no-shadow": "error",
     "no-unused-vars": ["error", { "args": "after-used", "vars": "all" }],
     "semi-spacing": ["error", {"before": false, "after": true}],
     "space-in-parens": ["error", "never"],
     "strict": ["error", "global"],
     "yoda": "error"
-  }
+  },
+
+  "overrides": [{
+    "files": "tests/unit/head*.js",
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }],
 };
deleted file mode 100644
--- a/browser/components/migration/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/newtab/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/newtab/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/originattributes/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/originattributes/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
--- a/browser/components/payments/.eslintrc.js
+++ b/browser/components/payments/.eslintrc.js
@@ -10,16 +10,25 @@ module.exports = {
         "res/paymentRequest.js",
         "res/PaymentsStore.js",
         "test/mochitest/test_*.html",
       ],
       parserOptions: {
         sourceType: "module",
       },
     },
+    {
+      "files": "test/unit/head.js",
+      "rules": {
+        "no-unused-vars": ["error", {
+          "args": "none",
+          "vars": "local",
+        }],
+      },
+    },
   ],
   rules: {
     "mozilla/var-only-at-top-level": "error",
 
     "array-bracket-spacing": ["error", "never"],
     "block-scoped-var": "error",
     complexity: ["error", {
       max: 20,
deleted file mode 100644
--- a/browser/components/payments/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ],
-};
-
deleted file mode 100644
--- a/browser/components/payments/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ],
-};
deleted file mode 100644
--- a/browser/components/payments/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/places/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/places/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/places/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/privatebrowsing/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/protocolhandler/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/resistfingerprinting/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
-
-};
deleted file mode 100644
--- a/browser/components/resistfingerprinting/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
--- a/browser/components/resistfingerprinting/test/mochitest/.eslintrc.js
+++ b/browser/components/resistfingerprinting/test/mochitest/.eslintrc.js
@@ -1,11 +1,7 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ],
-
   "rules": {
     "no-eval": "off"
   },
 };
deleted file mode 100644
--- a/browser/components/search/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/search/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/sessionstore/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/shell/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/syncedtabs/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/syncedtabs/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/translation/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/urlbar/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/components/urlbar/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/browser/extensions/formautofill/.eslintrc.js
+++ b/browser/extensions/formautofill/.eslintrc.js
@@ -98,9 +98,19 @@ module.exports = {
     "strict": ["error", "global"],
 
     // Disallow Yoda conditions (where literal value comes first).
     "yoda": "error",
 
     // Disallow function or variable declarations in nested blocks
     "no-inner-declarations": "error",
   },
+
+  "overrides": [{
+    "files": "test/unit/head.js",
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }],
 };
deleted file mode 100644
--- a/browser/extensions/formautofill/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ],
-};
deleted file mode 100644
--- a/browser/extensions/formautofill/test/browser/creditCard/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ],
-};
deleted file mode 100644
--- a/browser/extensions/formautofill/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ],
-};
deleted file mode 100644
--- a/browser/extensions/formautofill/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-};
deleted file mode 100644
--- a/browser/extensions/webcompat-reporter/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/modules/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/modules/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/browser/tools/mozscreenshots/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/caps/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/docshell/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/docshell/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/docshell/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/docshell/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/docshell/test/unit_ipc/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/abort/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-};
deleted file mode 100644
--- a/dom/animation/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ],
-};
deleted file mode 100644
--- a/dom/base/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-};
deleted file mode 100644
--- a/dom/base/test/unit_ipc/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-};
deleted file mode 100644
--- a/dom/cache/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/dom/cache/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/dom/cache/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/canvas/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
deleted file mode 100644
--- a/dom/console/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/dom/credentialmanagement/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/dom/encoding/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/dom/indexedDB/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,13 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-  "plugins": [
-    "mozilla"
-  ],
-  "rules": {
-    "no-shadow": "off",
-  }
-};
deleted file mode 100644
--- a/dom/localstorage/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
--- a/dom/media/gmp/GMPDiskStorage.cpp
+++ b/dom/media/gmp/GMPDiskStorage.cpp
@@ -51,31 +51,21 @@ static nsresult GetGMPStorageDir(nsIFile
     return rv;
   }
 
   rv = tmpFile->Append(aGMPName);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   rv = tmpFile->AppendNative(NS_LITERAL_CSTRING("storage"));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   rv = tmpFile->AppendNative(aNodeId);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
   if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -209,43 +209,27 @@ nsresult GeckoMediaPluginServiceParent::
     return rv;
   }
 
   rv = mStorageBaseDir->AppendNative(NS_LITERAL_CSTRING("gmp"));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
-    return rv;
-  }
-
-  nsCOMPtr<nsIFile> gmpDirWithoutPlatform;
-  rv = mStorageBaseDir->Clone(getter_AddRefs(gmpDirWithoutPlatform));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   nsAutoString platform;
   rv = GMPPlatformString(platform);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mStorageBaseDir->Append(platform);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
-    return rv;
-  }
-
   return GeckoMediaPluginService::Init();
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject,
                                        const char* aTopic,
                                        const char16_t* aSomeData) {
   LOGD(("%s::%s topic='%s' data='%s'", __CLASS__, __FUNCTION__, aTopic,
@@ -1134,38 +1118,28 @@ nsresult GeckoMediaPluginServiceParent::
   // Otherwise, try to see if we've previously generated and stored salt
   // for this origin pair.
   nsCOMPtr<nsIFile> path;  // $profileDir/gmp/$platform/
   rv = GetStorageDir(getter_AddRefs(path));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  // $profileDir/gmp/$platform/$gmpName/
   rv = path->Append(aGMPName);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  // $profileDir/gmp/$platform/$gmpName/
-  rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
+  // $profileDir/gmp/$platform/$gmpName/id/
   rv = path->AppendNative(NS_LITERAL_CSTRING("id"));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  // $profileDir/gmp/$platform/$gmpName/id/
-  rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   nsAutoCString hashStr;
   hashStr.AppendInt((int64_t)hash);
 
   // $profileDir/gmp/$platform/$gmpName/id/$hash
   rv = path->AppendNative(hashStr);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -1320,28 +1294,16 @@ static void KillPlugins(const nsTArray<R
     }
   }
 
   for (size_t i = 0; i < pluginsToKill.Length(); i++) {
     pluginsToKill[i]->CloseActive(false);
   }
 }
 
-static nsresult DeleteDir(nsIFile* aPath) {
-  bool exists = false;
-  nsresult rv = aPath->Exists(&exists);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (exists) {
-    return aPath->Remove(true);
-  }
-  return NS_OK;
-}
-
 struct NodeFilter {
   explicit NodeFilter(const nsTArray<nsCString>& nodeIDs) : mNodeIDs(nodeIDs) {}
   bool operator()(GMPParent* aParent) {
     return mNodeIDs.Contains(aParent->GetNodeId());
   }
 
  private:
   const nsTArray<nsCString>& mNodeIDs;
@@ -1411,17 +1373,17 @@ void GeckoMediaPluginServiceParent::Clea
       continue;
     }
 
     rv = dirEntry->AppendNative(nodeId);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       continue;
     }
 
-    if (NS_FAILED(DeleteDir(dirEntry))) {
+    if (NS_FAILED(dirEntry->Remove(true))) {
       NS_WARNING("Failed to delete GMP storage directory for the node");
     }
   }
 }
 
 void GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread(
     const nsACString& aSite, const mozilla::OriginAttributesPattern& aPattern) {
   MOZ_ASSERT(mGMPThread->EventTarget()->IsOnCurrentThread());
@@ -1598,17 +1560,17 @@ void GeckoMediaPluginServiceParent::Clea
   KillPlugins(mPlugins, mMutex, &IsNodeIdValid);
 
   nsCOMPtr<nsIFile> path;  // $profileDir/gmp/$platform/
   nsresult rv = GetStorageDir(getter_AddRefs(path));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  if (NS_FAILED(DeleteDir(path))) {
+  if (NS_FAILED(path->Remove(true))) {
     NS_WARNING("Failed to delete GMP storage directory");
   }
 
   // Clear private-browsing storage.
   mTempGMPStorage.Clear();
 
   nsCOMPtr<nsIRunnable> task =
       new NotifyObserversTask("gmp-clear-storage-complete");
--- a/dom/media/ipc/RemoteVideoDecoder.cpp
+++ b/dom/media/ipc/RemoteVideoDecoder.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "RemoteVideoDecoder.h"
 
 #include "mozilla/layers/ImageDataSerializer.h"
 
 #ifdef MOZ_AV1
 #  include "AOMDecoder.h"
+#  include "DAV1DDecoder.h"
 #endif
 #include "ImageContainer.h"  // for PlanarYCbCrData and BufferRecycleBin
 #include "RemoteDecoderManagerChild.h"
 
 namespace mozilla {
 
 using namespace layers;  // for PlanarYCbCrData and BufferRecycleBin
 
@@ -146,17 +147,21 @@ RemoteVideoDecoderParent::RemoteVideoDec
   params.mImageContainer = new layers::ImageContainer();
   params.mRate = CreateDecoderParams::VideoFrameRate(aFramerate);
   params.mOptions = aOptions;
   MediaResult error(NS_OK);
   params.mError = &error;
 
 #ifdef MOZ_AV1
   if (AOMDecoder::IsAV1(params.mConfig.mMimeType)) {
-    mDecoder = new AOMDecoder(params);
+    if (StaticPrefs::MediaAv1UseDav1d()) {
+      mDecoder = new DAV1DDecoder(params);
+    } else {
+      mDecoder = new AOMDecoder(params);
+    }
   }
 #endif
 
   if (NS_FAILED(error)) {
     MOZ_ASSERT(aErrorDescription);
     *aErrorDescription = error.Description();
   }
 
deleted file mode 100644
--- a/dom/media/tests/mochitest/identity/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/dom/notification/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/dom/notification/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
deleted file mode 100644
--- a/dom/notification/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/dom/notification/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/plugins/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/presentation/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/dom/presentation/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/promise/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ],
-};
deleted file mode 100644
--- a/dom/quota/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/dom/security/featurepolicy/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/dom/security/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/dom/svg/SVGIntegerPair.cpp
+++ b/dom/svg/SVGIntegerPair.cpp
@@ -24,34 +24,29 @@ static SVGAttrTearoffTable<SVGIntegerPai
     sSVGSecondAnimatedIntegerTearoffTable;
 
 /* Implementation */
 
 static nsresult ParseIntegerOptionalInteger(const nsAString& aValue,
                                             int32_t aValues[2]) {
   nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tokenizer(
       aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
-  if (tokenizer.whitespaceBeforeFirstToken()) {
-    return NS_ERROR_DOM_SYNTAX_ERR;
-  }
-
   uint32_t i;
   for (i = 0; i < 2 && tokenizer.hasMoreTokens(); ++i) {
     if (!SVGContentUtils::ParseInteger(tokenizer.nextToken(), aValues[i])) {
       return NS_ERROR_DOM_SYNTAX_ERR;
     }
   }
   if (i == 1) {
     aValues[1] = aValues[0];
   }
 
-  if (i == 0 ||                                   // Too few values.
-      tokenizer.hasMoreTokens() ||                // Too many values.
-      tokenizer.whitespaceAfterCurrentToken() ||  // Trailing whitespace.
-      tokenizer.separatorAfterCurrentToken()) {   // Trailing comma.
+  if (i == 0 ||                                  // Too few values.
+      tokenizer.hasMoreTokens() ||               // Too many values.
+      tokenizer.separatorAfterCurrentToken()) {  // Trailing comma.
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   return NS_OK;
 }
 
 nsresult SVGIntegerPair::SetBaseValueString(const nsAString& aValueAsString,
                                             SVGElement* aSVGElement) {
--- a/dom/svg/SVGNumberPair.cpp
+++ b/dom/svg/SVGNumberPair.cpp
@@ -20,34 +20,29 @@ static SVGAttrTearoffTable<SVGNumberPair
     sSVGFirstAnimatedNumberTearoffTable;
 static SVGAttrTearoffTable<SVGNumberPair, SVGNumberPair::DOMAnimatedNumber>
     sSVGSecondAnimatedNumberTearoffTable;
 
 static nsresult ParseNumberOptionalNumber(const nsAString& aValue,
                                           float aValues[2]) {
   nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tokenizer(
       aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
-  if (tokenizer.whitespaceBeforeFirstToken()) {
-    return NS_ERROR_DOM_SYNTAX_ERR;
-  }
-
   uint32_t i;
   for (i = 0; i < 2 && tokenizer.hasMoreTokens(); ++i) {
     if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), aValues[i])) {
       return NS_ERROR_DOM_SYNTAX_ERR;
     }
   }
   if (i == 1) {
     aValues[1] = aValues[0];
   }
 
-  if (i == 0 ||                                   // Too few values.
-      tokenizer.hasMoreTokens() ||                // Too many values.
-      tokenizer.whitespaceAfterCurrentToken() ||  // Trailing whitespace.
-      tokenizer.separatorAfterCurrentToken()) {   // Trailing comma.
+  if (i == 0 ||                                  // Too few values.
+      tokenizer.hasMoreTokens() ||               // Too many values.
+      tokenizer.separatorAfterCurrentToken()) {  // Trailing comma.
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   return NS_OK;
 }
 
 nsresult SVGNumberPair::SetBaseValueString(const nsAString& aValueAsString,
                                            SVGElement* aSVGElement) {
--- a/dom/svg/test/mochitest.ini
+++ b/dom/svg/test/mochitest.ini
@@ -51,16 +51,17 @@ support-files =
 skip-if = true # disabled-for-intermittent-failures--bug-701060
 [test_length.xhtml]
 [test_lengthParsing.html]
 [test_markerOrient.xhtml]
 [test_nonAnimStrings.xhtml]
 [test_non-scaling-stroke.html]
 [test_object-delayed-intrinsic-size.html]
 [test_onerror.xhtml]
+[test_pairParsing.html]
 [test_pathAnimInterpolation.xhtml]
 skip-if = true # We need to polyfill the SVG DOM for path data
 [test_pointAtLength.xhtml]
 [test_pointer-events-1a.xhtml]
 [test_pointer-events-1b.xhtml]
 [test_pointer-events-2.xhtml]
 [test_pointer-events-3.xhtml]
 skip-if = android_version == '18' # bug 1147994
new file mode 100644
--- /dev/null
+++ b/dom/svg/test/test_pairParsing.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1512745
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test pair parsing</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1512745">Mozilla Bug 1512745</a>
+
+<svg width="230" height="120"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <filter><feGaussianBlur id="x1" stdDeviation=" 5 " /></filter>
+  <filter><feGaussianBlur id="x2" stdDeviation=" 5 10 " /></filter>
+  <filter><feGaussianBlur id="x3" stdDeviation="5 10 " /></filter>
+  <filter><feGaussianBlur id="x4" stdDeviation=" 5,10 " /></filter>
+</svg>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+  function checkValue(id, x, y) {
+    if (y === undefined) {
+      y = x;
+    }
+    let e = document.getElementById(id);
+    is(e.stdDeviationX.baseVal, x, "Wrong stdDeviationX");
+    is(e.stdDeviationY.baseVal, y, "Wrong stdDeviationY");
+  }
+
+  checkValue("x1", 5);
+  checkValue("x2", 5, 10);
+  checkValue("x3", 5, 10);
+  checkValue("x4", 5, 10);
+</script>
+</pre>
+</body>
+</html>
deleted file mode 100644
--- a/dom/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/dom/tests/mochitest/ajax/offline/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-module.exports = {
-  "globals": {
-    "SimpleTest": true,
-    "OfflineTest": true,
-    "SpecialPowers": true,
-  }
-};
deleted file mode 100644
--- a/dom/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/dom/webauthn/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/dom/webgpu/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/dom/workers/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/extensions/cookie/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/extensions/pref/autoconfig/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
\ No newline at end of file
deleted file mode 100644
--- a/extensions/spellcheck/hunspell/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/gfx/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/gfx/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
deleted file mode 100644
--- a/gfx/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2142,33 +2142,16 @@ static void ShutdownCMS() {
     gCMSsRGBProfile = nullptr;
   }
 
   // Reset the state variables
   gCMSMode = eCMSMode_Off;
   gCMSInitialized = false;
 }
 
-// default SetupClusterBoundaries, based on Unicode properties;
-// platform subclasses may override if they wish
-void gfxPlatform::SetupClusterBoundaries(gfxTextRun* aTextRun,
-                                         const char16_t* aString) {
-  if (aTextRun->GetFlags() & gfx::ShapedTextFlags::TEXT_IS_8BIT) {
-    // 8-bit text doesn't have clusters.
-    // XXX is this true in all languages???
-    // behdad: don't think so.  Czech for example IIRC has a
-    // 'ch' grapheme.
-    // jfkthame: but that's not expected to behave as a grapheme cluster
-    // for selection/editing/etc.
-    return;
-  }
-
-  aTextRun->SetupClusterBoundaries(0, aString, aTextRun->GetLength());
-}
-
 int32_t gfxPlatform::GetBidiNumeralOption() {
   if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
     mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
   }
   return mBidiNumeralOption;
 }
 
 /* static */
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -298,23 +298,21 @@ class gfxPlatform : public mozilla::laye
   }
 
   virtual mozilla::gfx::BackendType GetPreferredCanvasBackend() {
     return mPreferredCanvasBackend;
   }
   mozilla::gfx::BackendType GetFallbackCanvasBackend() {
     return mFallbackCanvasBackend;
   }
+
   /*
    * Font bits
    */
 
-  virtual void SetupClusterBoundaries(gfxTextRun* aTextRun,
-                                      const char16_t* aString);
-
   /**
    * Fill aListOfFonts with the results of querying the list of font names
    * that correspond to the given language group or generic font family
    * (or both, or neither).
    */
   virtual nsresult GetFontList(nsAtom* aLangGroup,
                                const nsACString& aGenericFamily,
                                nsTArray<nsString>& aListOfFonts);
deleted file mode 100644
--- a/image/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/image/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/intl/uconv/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
--- a/intl/unicharutil/util/nsUnicodeProperties.cpp
+++ b/intl/unicharutil/util/nsUnicodeProperties.cpp
@@ -220,35 +220,57 @@ void ClusterIterator::Next() {
           break;
         default:
           break;
       }
       break;
     }
   }
 
+  const uint32_t kVS16 = 0xfe0f;
+  const uint32_t kZWJ = 0x200d;
+  // UTF-16 surrogate values for Fitzpatrick type modifiers
+  const uint32_t kFitzpatrickHigh = 0xD83C;
+  const uint32_t kFitzpatrickLowFirst = 0xDFFB;
+  const uint32_t kFitzpatrickLowLast = 0xDFFF;
+
+  bool baseIsEmoji = (GetEmojiPresentation(ch) == EmojiDefault) ||
+                     (GetEmojiPresentation(ch) == TextDefault &&
+                      ((mPos < mLimit && *mPos == kVS16) ||
+                       (mPos + 1 < mLimit &&
+                        *mPos == kFitzpatrickHigh &&
+                        *(mPos + 1) >= kFitzpatrickLowFirst &&
+                        *(mPos + 1) <= kFitzpatrickLowLast)));
+  bool prevWasZwj = false;
+
   while (mPos < mLimit) {
     ch = *mPos;
+    size_t chLen = 1;
 
     // Check for surrogate pairs; note that isolated surrogates will just
     // be treated as generic (non-cluster-extending) characters here,
     // which is fine for cluster-iterating purposes
     if (NS_IS_HIGH_SURROGATE(ch) && mPos < mLimit - 1 &&
         NS_IS_LOW_SURROGATE(*(mPos + 1))) {
       ch = SURROGATE_TO_UCS4(ch, *(mPos + 1));
+      chLen = 2;
     }
 
-    if (!IsClusterExtender(ch)) {
+    bool extendCluster = IsClusterExtender(ch) ||
+        (baseIsEmoji && prevWasZwj &&
+            ((GetEmojiPresentation(ch) == EmojiDefault) ||
+             (GetEmojiPresentation(ch) == TextDefault &&
+              mPos + chLen < mLimit &&
+              *(mPos + chLen) == kVS16)));
+    if (!extendCluster) {
       break;
     }
 
-    mPos++;
-    if (!IS_IN_BMP(ch)) {
-      mPos++;
-    }
+    prevWasZwj = (ch == kZWJ);
+    mPos += chLen;
   }
 
   NS_ASSERTION(mText < mPos && mPos <= mLimit,
                "ClusterIterator::Next has overshot the string!");
 }
 
 void ClusterReverseIterator::Next() {
   if (AtEnd()) {
--- a/js/src/jit-test/lib/jitopts.js
+++ b/js/src/jit-test/lib/jitopts.js
@@ -28,38 +28,41 @@ function withJitOptions(opts, fn) {
 // N.B. Ion opts *must come before* baseline opts because there's some kind of
 // "undo eager compilation" logic. If we don't set the baseline warmup-counter
 // *after* the Ion warmup-counter we end up setting the baseline warmup-counter
 // to be the default if we hit the "undo eager compilation" logic.
 var Opts_BaselineEager =
     {
       'ion.enable': 1,
       'ion.warmup.trigger': 100,
+      'ion.full.warmup.trigger': 100,
       'baseline.enable': 1,
       'baseline.warmup.trigger': 0,
       'offthread-compilation.enable': 1
     };
 
 // Checking for offthread compilation being off is often helpful if the test
 // requires a function be Ion compiled. Each individual test will usually
 // finish before the Ion compilation thread has a chance to attach the
 // compiled code.
 var Opts_IonEagerNoOffthreadCompilation =
     {
       'ion.enable': 1,
       'ion.warmup.trigger': 0,
+      'ion.full.warmup.trigger': 0,
       'baseline.enable': 1,
       'baseline.warmup.trigger': 0,
       'offthread-compilation.enable': 0,
     };
 
 var Opts_Ion2NoOffthreadCompilation =
     {
       'ion.enable': 1,
       'ion.warmup.trigger': 2,
+      'ion.full.warmup.trigger': 2,
       'baseline.enable': 1,
       'baseline.warmup.trigger': 1,
       'offthread-compilation.enable': 0
     };
 
 var Opts_NoJits =
     {
       'ion.enable': 0,
--- a/js/src/jit-test/tests/asm.js/testBug1125561.js
+++ b/js/src/jit-test/tests/asm.js/testBug1125561.js
@@ -1,11 +1,11 @@
 load(libdir + "asm.js");
 
-setJitCompilerOption("ion.warmup.trigger", 0);
+setJitCompilerOption("ion.full.warmup.trigger", 0);
 setJitCompilerOption("baseline.warmup.trigger", 0);
 setJitCompilerOption("offthread-compilation.enable", 0);
 
 function ffi1() { assertJitStackInvariants() }
 function ffi2() { return { valueOf() { assertJitStackInvariants() } } }
 
 // FFI with no coercion
 var m = asmCompile('stdlib', 'foreign', `
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -1,10 +1,11 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
+setJitCompilerOption("ion.full.warmup.trigger", 20);
 var i;
 
 var config = getBuildConfiguration();
 var max = 200;
 
 // Check that we are able to remove the operation inside recover test functions (denoted by "rop..."),
 // when we inline the first version of uceFault, and ensure that the bailout is correct
 // when uceFault is replaced (which cause an invalidation bailout)
--- a/js/src/jit-test/tests/ion/recover-lambdas.js
+++ b/js/src/jit-test/tests/ion/recover-lambdas.js
@@ -1,12 +1,13 @@
 // |jit-test| --ion-osr=off
 
 var max = 40;
 setJitCompilerOption("ion.warmup.trigger", max - 10);
+setJitCompilerOption("ion.full.warmup.trigger", max - 10);
 
 // This function is used to escape "g" which is a non-escaped inner function.
 // As it is not escaped within "f", the lambda for "g" would be computed on the
 // bailout path. Resolving the first ".caller" implies that we have to recover
 // the lambda. Resolving the second ".caller" is needed such as we can build the
 // test case without explicitly escaping "g", which would prevent this
 // optimization.
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -13375,47 +13375,56 @@ void CodeGenerator::visitWasmLoadTls(LWa
     default:
       MOZ_CRASH("MIRType not supported in WasmLoadTls");
   }
 }
 
 void CodeGenerator::visitRecompileCheck(LRecompileCheck* ins) {
   Label done;
   Register tmp = ToRegister(ins->scratch());
-  OutOfLineCode* ool;
-
-  using Fn = bool (*)(JSContext*);
-  if (ins->mir()->forceRecompilation()) {
-    ool = oolCallVM<Fn, IonForcedRecompile>(ins, ArgList(), StoreNothing());
-  } else {
-    ool = oolCallVM<Fn, IonRecompile>(ins, ArgList(), StoreNothing());
+
+  OutOfLineCode* ool = nullptr;
+  if (ins->mir()->checkCounter()) {
+    using Fn = bool (*)(JSContext*);
+    if (ins->mir()->forceInvalidation()) {
+      ool =
+          oolCallVM<Fn, IonForcedInvalidation>(ins, ArgList(), StoreNothing());
+    } else if (ins->mir()->forceRecompilation()) {
+      ool = oolCallVM<Fn, IonForcedRecompile>(ins, ArgList(), StoreNothing());
+    } else {
+      ool = oolCallVM<Fn, IonRecompile>(ins, ArgList(), StoreNothing());
+    }
   }
 
   // Check if warm-up counter is high enough.
   AbsoluteAddress warmUpCount =
       AbsoluteAddress(ins->mir()->script()->addressOfWarmUpCounter());
   if (ins->mir()->increaseWarmUpCounter()) {
     masm.load32(warmUpCount, tmp);
     masm.add32(Imm32(1), tmp);
     masm.store32(tmp, warmUpCount);
-    masm.branch32(Assembler::BelowOrEqual, tmp,
-                  Imm32(ins->mir()->recompileThreshold()), &done);
+    if (ins->mir()->checkCounter()) {
+      masm.branch32(Assembler::BelowOrEqual, tmp,
+                    Imm32(ins->mir()->recompileThreshold()), &done);
+    }
   } else {
     masm.branch32(Assembler::BelowOrEqual, warmUpCount,
                   Imm32(ins->mir()->recompileThreshold()), &done);
   }
 
   // Check if not yet recompiling.
-  CodeOffset label = masm.movWithPatch(ImmWord(uintptr_t(-1)), tmp);
-  masm.propagateOOM(ionScriptLabels_.append(label));
-  masm.branch32(Assembler::Equal,
-                Address(tmp, IonScript::offsetOfRecompiling()), Imm32(0),
-                ool->entry());
-  masm.bind(ool->rejoin());
-  masm.bind(&done);
+  if (ins->mir()->checkCounter()) {
+    CodeOffset label = masm.movWithPatch(ImmWord(uintptr_t(-1)), tmp);
+    masm.propagateOOM(ionScriptLabels_.append(label));
+    masm.branch32(Assembler::Equal,
+                  Address(tmp, IonScript::offsetOfRecompiling()), Imm32(0),
+                  ool->entry());
+    masm.bind(ool->rejoin());
+    masm.bind(&done);
+  }
 }
 
 void CodeGenerator::visitLexicalCheck(LLexicalCheck* ins) {
   ValueOperand inputValue = ToValue(ins, LLexicalCheck::Input);
   Label bail;
   masm.branchTestMagicValue(Assembler::Equal, inputValue,
                             JS_UNINITIALIZED_LEXICAL, &bail);
   bailoutFrom(&bail, ins->snapshot());
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2235,16 +2235,20 @@ static MethodStatus Compile(JSContext* c
     return Method_Skipped;
   }
 
   if (!CanLikelyAllocateMoreExecutableMemory()) {
     script->resetWarmUpCounter();
     return Method_Skipped;
   }
 
+  if (script->baselineScript()->hasPendingIonBuilder()) {
+    LinkIonScript(cx, script);
+  }
+
   if (script->hasIonScript()) {
     IonScript* scriptIon = script->ionScript();
     if (!scriptIon->method()) {
       return Method_CantCompile;
     }
 
     // Don't recompile/overwrite higher optimized code,
     // with a lower optimization level.
@@ -2260,26 +2264,16 @@ static MethodStatus Compile(JSContext* c
 
     if (osrPc) {
       scriptIon->resetOsrPcMismatchCounter();
     }
 
     recompile = true;
   }
 
-  if (script->baselineScript()->hasPendingIonBuilder()) {
-    IonBuilder* buildIon = script->baselineScript()->pendingIonBuilder();
-    if (optimizationLevel <= buildIon->optimizationInfo().level() &&
-        !forceRecompile) {
-      return Method_Compiled;
-    }
-
-    recompile = true;
-  }
-
   AbortReason reason =
       IonCompile(cx, script, osrFrame, osrPc, recompile, optimizationLevel);
   if (reason == AbortReason::Error) {
     MOZ_ASSERT(cx->isExceptionPending());
     return Method_Error;
   }
 
   if (reason == AbortReason::Disable) {
@@ -2576,16 +2570,18 @@ bool jit::IonCompileScriptForBaseline(JS
 MethodStatus jit::Recompile(JSContext* cx, HandleScript script,
                             BaselineFrame* osrFrame, jsbytecode* osrPc,
                             bool force) {
   MOZ_ASSERT(script->hasIonScript());
   if (script->ionScript()->isRecompiling()) {
     return Method_Compiled;
   }
 
+  MOZ_ASSERT(!script->baselineScript()->hasPendingIonBuilder());
+
   MethodStatus status = Compile(cx, script, osrFrame, osrPc, force);
   if (status != Method_Compiled) {
     if (status == Method_CantCompile) {
       ForbidCompilation(cx, script);
     }
     return status;
   }
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4563,17 +4563,17 @@ bool jit::AnalyzeNewScriptDefiniteProper
     return false;
   }
 
   CompileInfo info(CompileRuntime::get(cx->runtime()), script, fun,
                    /* osrPc = */ nullptr, Analysis_DefiniteProperties,
                    script->needsArgsObj(), inlineScriptTree);
 
   const OptimizationInfo* optimizationInfo =
-      IonOptimizations.get(OptimizationLevel::Normal);
+      IonOptimizations.get(OptimizationLevel::Full);
 
   CompilerConstraintList* constraints = NewCompilerConstraintList(temp);
   if (!constraints) {
     ReportOutOfMemory(cx);
     return false;
   }
 
   BaselineInspector inspector(script);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -479,16 +479,29 @@ IonBuilder::InliningDecision IonBuilder:
   }
 
   // Don't inline functions which don't have baseline scripts.
   if (!inlineScript->hasBaselineScript()) {
     trackOptimizationOutcome(TrackedOutcome::CantInlineNoBaseline);
     return DontInline(inlineScript, "No baseline jitcode");
   }
 
+  // Don't inline functions with a higher optimization level.
+  if (!isHighestOptimizationLevel()) {
+    OptimizationLevel level = optimizationLevel();
+    if (inlineScript->hasIonScript() &&
+        (inlineScript->ionScript()->isRecompiling() ||
+         inlineScript->ionScript()->optimizationLevel() > level)) {
+      return DontInline(inlineScript, "More optimized");
+    }
+    if (IonOptimizations.levelForScript(inlineScript, nullptr) > level) {
+      return DontInline(inlineScript, "Should be more optimized");
+    }
+  }
+
   if (TooManyFormalArguments(target->nargs())) {
     trackOptimizationOutcome(TrackedOutcome::CantInlineTooManyArgs);
     return DontInline(inlineScript, "Too many args");
   }
 
   // We check the number of actual arguments against the maximum number of
   // formal arguments as we do not want to encode all actual arguments in the
   // callerResumePoint.
@@ -771,17 +784,20 @@ AbortReasonOr<Ok> IonBuilder::build() {
 #ifdef JS_STRUCTURED_SPEW
   if (!info().isAnalysis()) {
     JitSpewBaselineICStats(script(), "To-Be-Compiled");
   }
 #endif
 
   MOZ_TRY(init());
 
-  if (script()->hasBaselineScript()) {
+  // The BaselineScript-based inlining heuristics only affect the highest
+  // optimization level. Other levels do almost no inlining and we don't want to
+  // overwrite data from the highest optimization tier.
+  if (script()->hasBaselineScript() && isHighestOptimizationLevel()) {
     script()->baselineScript()->resetMaxInliningDepth();
   }
 
   MBasicBlock* entry;
   MOZ_TRY_VAR(entry, newBlock(info().firstStackSlot(), pc));
   MOZ_TRY(setCurrentAndSpecializePhis(entry));
 
 #ifdef JS_JITSPEW
@@ -791,17 +807,17 @@ AbortReasonOr<Ok> IonBuilder::build() {
             (void*)script(), AnalysisModeString(info().analysisMode()));
   } else {
     JitSpew(JitSpew_IonScripts,
             "%sompiling script %s:%u:%u (%p) (warmup-counter=%" PRIu32
             ", level=%s)",
             (script()->hasIonScript() ? "Rec" : "C"), script()->filename(),
             script()->lineno(), script()->column(), (void*)script(),
             script()->getWarmUpCount(),
-            OptimizationLevelString(optimizationInfo().level()));
+            OptimizationLevelString(optimizationLevel()));
   }
 #endif
 
   MOZ_TRY(initParameters());
   initLocals();
 
   // Initialize something for the env chain. We can bail out before the
   // start instruction, but the snapshot is encoded *at* the start
@@ -904,17 +920,17 @@ AbortReasonOr<Ok> IonBuilder::build() {
 
   auto clearLastPriorResumePoint = mozilla::MakeScopeExit([&] {
     // Discard unreferenced & pre-allocated resume points.
     replaceMaybeFallbackFunctionGetter(nullptr);
   });
 
   MOZ_TRY(traverseBytecode());
 
-  if (script_->hasBaselineScript() &&
+  if (isHighestOptimizationLevel() && script_->hasBaselineScript() &&
       inlinedBytecodeLength_ >
           script_->baselineScript()->inlinedBytecodeLength()) {
     script_->baselineScript()->setInlinedBytecodeLength(inlinedBytecodeLength_);
   }
 
   MOZ_TRY(maybeAddOsrTypeBarriers());
   MOZ_TRY(processIterators());
 
@@ -4358,17 +4374,20 @@ IonBuilder::InliningDecision IonBuilder:
 
   BaselineScript* outerBaseline =
       outermostBuilder()->script()->baselineScript();
   if (inliningDepth_ >= maxInlineDepth) {
     // We hit the depth limit and won't inline this function. Give the
     // outermost script a max inlining depth of 0, so that it won't be
     // inlined in other scripts. This heuristic is currently only used
     // when we're inlining scripts with loops, see the comment below.
-    outerBaseline->setMaxInliningDepth(0);
+    // These heuristics only apply to the highest optimization level.
+    if (isHighestOptimizationLevel()) {
+      outerBaseline->setMaxInliningDepth(0);
+    }
 
     trackOptimizationOutcome(TrackedOutcome::CantInlineExceededDepth);
     return DontInline(targetScript, "Vetoed: exceeding allowed inline depth");
   }
 
   // Inlining functions with loops can be complicated. For instance, if we're
   // close to the inlining depth limit and we inline the function f below, we
   // can no longer inline the call to g:
@@ -4381,27 +4400,31 @@ IonBuilder::InliningDecision IonBuilder:
   //
   // If the loop has many iterations, it's more efficient to call f and inline
   // g in f.
   //
   // To avoid this problem, we record a separate max inlining depth for each
   // script, indicating at which depth we won't be able to inline all functions
   // we inlined this time. This solves the issue above, because we will only
   // inline f if it means we can also inline g.
-  if (targetScript->hasLoops() &&
+  //
+  // These heuristics only apply to the highest optimization level: other tiers
+  // do very little inlining and performance is not as much of a concern there.
+  if (isHighestOptimizationLevel() && targetScript->hasLoops() &&
       inliningDepth_ >= targetScript->baselineScript()->maxInliningDepth()) {
     trackOptimizationOutcome(TrackedOutcome::CantInlineExceededDepth);
     return DontInline(targetScript,
                       "Vetoed: exceeding allowed script inline depth");
   }
 
   // Update the max depth at which we can inline the outer script.
   MOZ_ASSERT(maxInlineDepth > inliningDepth_);
   uint32_t scriptInlineDepth = maxInlineDepth - inliningDepth_ - 1;
-  if (scriptInlineDepth < outerBaseline->maxInliningDepth()) {
+  if (scriptInlineDepth < outerBaseline->maxInliningDepth() &&
+      isHighestOptimizationLevel()) {
     outerBaseline->setMaxInliningDepth(scriptInlineDepth);
   }
 
   // End of heuristics, we will inline this function.
 
   outerBuilder->inlinedBytecodeLength_ += targetScript->length();
 
   return InliningDecision_Inline;
@@ -5942,22 +5965,22 @@ AbortReasonOr<Ok> IonBuilder::jsop_call(
       }
       if (!callTargets->append(&target.target->as<JSFunction>())) {
         return abort(AbortReason::Alloc);
       }
     }
   }
 
   if (status == InliningStatus_WarmUpCountTooLow && callTargets &&
-      callTargets->length() == 1) {
+      callTargets->length() == 1 && isHighestOptimizationLevel()) {
     JSFunction* target = callTargets.ref()[0];
     MRecompileCheck* check =
         MRecompileCheck::New(alloc(), target->nonLazyScript(),
                              optimizationInfo().inliningRecompileThreshold(),
-                             MRecompileCheck::RecompileCheck_Inlining);
+                             MRecompileCheck::RecompileCheckType::Inlining);
     current->add(check);
   }
 
   return makeCall(callTargets, callInfo);
 }
 
 AbortReasonOr<bool> IonBuilder::testShouldDOMCall(TypeSet* inTypes,
                                                   JSFunction* func,
@@ -7614,37 +7637,43 @@ static bool ObjectHasExtraOwnProperty(Co
   }
 
   // Resolve hooks can install new properties on objects on demand.
   JSObject* singleton = object->isSingleton() ? object->singleton() : nullptr;
   return ClassMayResolveId(realm->runtime()->names(), clasp, id, singleton);
 }
 
 void IonBuilder::insertRecompileCheck() {
+  MOZ_ASSERT(pc == script()->code() || *pc == JSOP_LOOPENTRY);
+
   // No need for recompile checks if this is the highest optimization level.
-  OptimizationLevel curLevel = optimizationInfo().level();
+  OptimizationLevel curLevel = optimizationLevel();
   if (IonOptimizations.isLastLevel(curLevel)) {
     return;
   }
 
-  // Add recompile check.
-
-  // Get the topmost builder. The topmost script will get recompiled when
-  // warm-up counter is high enough to justify a higher optimization level.
-  IonBuilder* topBuilder = outermostBuilder();
+  // Add recompile check. See MRecompileCheck::RecompileCheckType for how this
+  // works.
+
+  MRecompileCheck::RecompileCheckType type;
+  if (*pc == JSOP_LOOPENTRY) {
+    type = MRecompileCheck::RecompileCheckType::OptimizationLevelOSR;
+  } else if (this != outermostBuilder()) {
+    type = MRecompileCheck::RecompileCheckType::OptimizationLevelInlined;
+  } else {
+    type = MRecompileCheck::RecompileCheckType::OptimizationLevel;
+  }
 
   // Add recompile check to recompile when the warm-up count reaches the
   // threshold of the next optimization level.
   OptimizationLevel nextLevel = IonOptimizations.nextLevel(curLevel);
   const OptimizationInfo* info = IonOptimizations.get(nextLevel);
-  uint32_t warmUpThreshold =
-      info->compilerWarmUpThreshold(topBuilder->script());
+  uint32_t warmUpThreshold = info->recompileWarmUpThreshold(script(), pc);
   MRecompileCheck* check =
-      MRecompileCheck::New(alloc(), topBuilder->script(), warmUpThreshold,
-                           MRecompileCheck::RecompileCheck_OptimizationLevel);
+      MRecompileCheck::New(alloc(), script(), warmUpThreshold, type);
   current->add(check);
 }
 
 JSObject* IonBuilder::testSingletonProperty(JSObject* obj, jsid id) {
   // We would like to completely no-op property/global accesses which can
   // produce only a particular JSObject. When indicating the access result is
   // definitely an object, type inference does not account for the
   // possibility that the property is entirely missing from the input object
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -691,16 +691,23 @@ class IonBuilder : public MIRGenerator,
   // Oracles.
   InliningDecision canInlineTarget(JSFunction* target, CallInfo& callInfo);
   InliningDecision makeInliningDecision(JSObject* target, CallInfo& callInfo);
   AbortReasonOr<Ok> selectInliningTargets(const InliningTargets& targets,
                                           CallInfo& callInfo,
                                           BoolVector& choiceSet,
                                           uint32_t* numInlineable);
 
+  OptimizationLevel optimizationLevel() const {
+    return optimizationInfo().level();
+  }
+  bool isHighestOptimizationLevel() const {
+    return IonOptimizations.isLastLevel(optimizationLevel());
+  }
+
   // Native inlining helpers.
   // The typeset for the return value of our function.  These are
   // the types it's been observed returning in the past.
   TemporaryTypeSet* getInlineReturnTypeSet();
   // The known MIR type of getInlineReturnTypeSet.
   MIRType getInlineReturnType();
 
   // Array natives.
--- a/js/src/jit/IonOptimizationLevels.cpp
+++ b/js/src/jit/IonOptimizationLevels.cpp
@@ -25,31 +25,43 @@ void OptimizationInfo::initNormalOptimiz
   edgeCaseAnalysis_ = true;
   eliminateRedundantChecks_ = true;
   inlineInterpreted_ = true;
   inlineNative_ = true;
   licm_ = true;
   gvn_ = true;
   rangeAnalysis_ = true;
   reordering_ = true;
+  scalarReplacement_ = true;
   sincos_ = true;
   sink_ = true;
 
   registerAllocator_ = RegisterAllocator_Backtracking;
 
-  inlineMaxBytecodePerCallSiteMainThread_ = 550;
-  inlineMaxBytecodePerCallSiteHelperThread_ = 1100;
+  inlineMaxBytecodePerCallSiteMainThread_ = 200;
+  inlineMaxBytecodePerCallSiteHelperThread_ = 400;
   inlineMaxCalleeInlinedBytecodeLength_ = 3550;
   inlineMaxTotalBytecodeLength_ = 85000;
   inliningMaxCallerBytecodeLength_ = 1600;
+  maxInlineDepth_ = 0;
+  smallFunctionMaxInlineDepth_ = 1;
+  inliningWarmUpThresholdFactor_ = 0.5;
+  inliningRecompileThresholdFactor_ = 4;
+}
+
+void OptimizationInfo::initFullOptimizationInfo() {
+  initNormalOptimizationInfo();
+
+  level_ = OptimizationLevel::Full;
+
+  inlineMaxBytecodePerCallSiteMainThread_ = 550;
+  inlineMaxBytecodePerCallSiteHelperThread_ = 1100;
   maxInlineDepth_ = 3;
-  scalarReplacement_ = true;
   smallFunctionMaxInlineDepth_ = 10;
   inliningWarmUpThresholdFactor_ = 0.125;
-  inliningRecompileThresholdFactor_ = 4;
 }
 
 void OptimizationInfo::initWasmOptimizationInfo() {
   // The Wasm optimization level
   // Disables some passes that don't work well with wasm.
 
   // Take normal option values for not specified values.
   initNormalOptimizationInfo();
@@ -98,18 +110,39 @@ uint32_t OptimizationInfo::compilerWarmU
   // It's more efficient to enter outer loops, rather than inner loops, via OSR.
   // To accomplish this, we use a slightly higher threshold for inner loops.
   // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
   uint32_t loopDepth = LoopEntryDepthHint(pc);
   MOZ_ASSERT(loopDepth > 0);
   return warmUpThreshold + loopDepth * (baseCompilerWarmUpThreshold() / 10);
 }
 
+uint32_t OptimizationInfo::recompileWarmUpThreshold(JSScript* script,
+                                                    jsbytecode* pc) const {
+  MOZ_ASSERT(pc == script->code() || *pc == JSOP_LOOPENTRY);
+
+  uint32_t threshold = compilerWarmUpThreshold(script, pc);
+  if (*pc != JSOP_LOOPENTRY || JitOptions.eagerIonCompilation()) {
+    return threshold;
+  }
+
+  // If we're stuck in a long-running loop at a low optimization level, we have
+  // to invalidate to be able to tier up. This is worse than recompiling at
+  // function entry (because in that case we can use the lazy link mechanism and
+  // avoid invalidation completely). Use a very high recompilation threshold for
+  // loop edges so that this only affects very long-running loops.
+
+  uint32_t loopDepth = LoopEntryDepthHint(pc);
+  MOZ_ASSERT(loopDepth > 0);
+  return threshold + loopDepth * (baseCompilerWarmUpThreshold() / 10);
+}
+
 OptimizationLevelInfo::OptimizationLevelInfo() {
   infos_[OptimizationLevel::Normal].initNormalOptimizationInfo();
+  infos_[OptimizationLevel::Full].initFullOptimizationInfo();
   infos_[OptimizationLevel::Wasm].initWasmOptimizationInfo();
 
 #ifdef DEBUG
   OptimizationLevel level = firstLevel();
   while (!isLastLevel(level)) {
     OptimizationLevel next = nextLevel(level);
     MOZ_ASSERT_IF(level != OptimizationLevel::DontCompile, level < next);
     level = next;
@@ -119,28 +152,31 @@ OptimizationLevelInfo::OptimizationLevel
 
 OptimizationLevel OptimizationLevelInfo::nextLevel(
     OptimizationLevel level) const {
   MOZ_ASSERT(!isLastLevel(level));
   switch (level) {
     case OptimizationLevel::DontCompile:
       return OptimizationLevel::Normal;
     case OptimizationLevel::Normal:
+      return OptimizationLevel::Full;
+    case OptimizationLevel::Full:
     case OptimizationLevel::Wasm:
-    case OptimizationLevel::Count:;
+    case OptimizationLevel::Count:
+      break;
   }
   MOZ_CRASH("Unknown optimization level.");
 }
 
 OptimizationLevel OptimizationLevelInfo::firstLevel() const {
   return nextLevel(OptimizationLevel::DontCompile);
 }
 
 bool OptimizationLevelInfo::isLastLevel(OptimizationLevel level) const {
-  return level == OptimizationLevel::Normal;
+  return level == OptimizationLevel::Full;
 }
 
 OptimizationLevel OptimizationLevelInfo::levelForScript(JSScript* script,
                                                         jsbytecode* pc) const {
   OptimizationLevel prev = OptimizationLevel::DontCompile;
 
   while (!isLastLevel(prev)) {
     OptimizationLevel level = nextLevel(prev);
--- a/js/src/jit/IonOptimizationLevels.h
+++ b/js/src/jit/IonOptimizationLevels.h
@@ -12,25 +12,51 @@
 #include "jstypes.h"
 
 #include "jit/JitOptions.h"
 #include "js/TypeDecls.h"
 
 namespace js {
 namespace jit {
 
-enum class OptimizationLevel : uint8_t { Normal, Wasm, Count, DontCompile };
+// [SMDOC] Ion Optimization Levels
+//
+// Ion can do aggressive inlining, but inlining a lot of code will have a
+// negative effect on compilation time and memory usage. It also means we spend
+// more time in the slower Baseline code while compiling the Ion code
+// off-thread or after an invalidation.
+//
+// To address this, Ion consists of two tiers:
+//
+// * Normal: the first tier (warm-up threshold of 1,000) only inlines small
+//           functions one level deep. This tier also has recompile checks to
+//           recompile the script when it becomes very hot.
+//
+// * Full: the second tier (warm-up threshold of 100,000) is only used for very
+//         hot code so we can afford inlining a lot more code.
+//
+// See MRecompileCheck::RecompileCheckType for more info.
+
+enum class OptimizationLevel : uint8_t {
+  Normal,
+  Full,
+  Wasm,
+  Count,
+  DontCompile
+};
 
 #ifdef JS_JITSPEW
 inline const char* OptimizationLevelString(OptimizationLevel level) {
   switch (level) {
     case OptimizationLevel::DontCompile:
       return "Optimization_DontCompile";
     case OptimizationLevel::Normal:
       return "Optimization_Normal";
+    case OptimizationLevel::Full:
+      return "Optimization_Full";
     case OptimizationLevel::Wasm:
       return "Optimization_Wasm";
     case OptimizationLevel::Count:;
   }
   MOZ_CRASH("Invalid OptimizationLevel");
 }
 #endif
 
@@ -119,16 +145,18 @@ class OptimizationInfo {
   // is hot enough to recompile the outerScript to inline that function,
   // as a multiplication of inliningWarmUpThreshold.
   uint32_t inliningRecompileThresholdFactor_;
 
   uint32_t baseCompilerWarmUpThreshold() const {
     switch (level_) {
       case OptimizationLevel::Normal:
         return JitOptions.normalIonWarmUpThreshold;
+      case OptimizationLevel::Full:
+        return JitOptions.fullIonWarmUpThreshold;
       case OptimizationLevel::DontCompile:
       case OptimizationLevel::Wasm:
       case OptimizationLevel::Count:
         break;
     }
     MOZ_CRASH("Unexpected optimization level");
   }
 
@@ -156,31 +184,34 @@ class OptimizationInfo {
         inliningMaxCallerBytecodeLength_(0),
         maxInlineDepth_(0),
         scalarReplacement_(false),
         smallFunctionMaxInlineDepth_(0),
         inliningWarmUpThresholdFactor_(0.0),
         inliningRecompileThresholdFactor_(0) {}
 
   void initNormalOptimizationInfo();
+  void initFullOptimizationInfo();
   void initWasmOptimizationInfo();
 
   OptimizationLevel level() const { return level_; }
 
   bool inlineInterpreted() const {
     return inlineInterpreted_ && !JitOptions.disableInlining;
   }
 
   bool inlineNative() const {
     return inlineNative_ && !JitOptions.disableInlining;
   }
 
   uint32_t compilerWarmUpThreshold(JSScript* script,
                                    jsbytecode* pc = nullptr) const;
 
+  uint32_t recompileWarmUpThreshold(JSScript* script, jsbytecode* pc) const;
+
   bool gvnEnabled() const { return gvn_ && !JitOptions.disableGvn; }
 
   bool licmEnabled() const { return licm_ && !JitOptions.disableLicm; }
 
   bool rangeAnalysisEnabled() const {
     return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
   }
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10835,59 +10835,80 @@ class MCheckReturn : public MBinaryInstr
   NAMED_OPERANDS((0, returnValue), (1, thisValue))
 };
 
 // Increase the warm-up counter of the provided script upon execution and test
 // if the warm-up counter surpasses the threshold. Upon hit it will recompile
 // the outermost script (i.e. not the inlined script).
 class MRecompileCheck : public MNullaryInstruction {
  public:
-  enum RecompileCheckType {
-    RecompileCheck_OptimizationLevel,
-    RecompileCheck_Inlining
+  enum class RecompileCheckType : uint8_t {
+    // If we're not at the highest optimization level, keep incrementing the
+    // warm-up counter for the outermost script on entry. The warmup check will
+    // trigger recompilation to tier up. The lazy link mechanism will be used to
+    // tier up once recompilation is done.
+    OptimizationLevel,
+
+    // If we're not at the highest optimization level, keep incrementing the
+    // warm-up counter at loop edges. This check will trigger invalidation for
+    // very long-running loops to ensure we still tier up even if we don't
+    // invoke the lazy link stub.
+    OptimizationLevelOSR,
+
+    // If we're not at the highest optimization level, keep incrementing the
+    // warm-up counter for inlined scripts. This check does not trigger any
+    // recompilation or invalidation, it exists to ensure inlined scripts have
+    // an accurate warm-up count.
+    OptimizationLevelInlined,
+
+    // Used at the last optimization level for callees that weren't hot enough
+    // to be inlined. If a callee becomes hot enough we force recompilation of
+    // the caller's Ion script.
+    Inlining
   };
 
  private:
   JSScript* script_;
   uint32_t recompileThreshold_;
-  bool forceRecompilation_;
-  bool increaseWarmUpCounter_;
+  RecompileCheckType type_;
 
   MRecompileCheck(JSScript* script, uint32_t recompileThreshold,
                   RecompileCheckType type)
       : MNullaryInstruction(classOpcode),
         script_(script),
-        recompileThreshold_(recompileThreshold) {
-    switch (type) {
-      case RecompileCheck_OptimizationLevel:
-        forceRecompilation_ = false;
-        increaseWarmUpCounter_ = true;
-        break;
-      case RecompileCheck_Inlining:
-        forceRecompilation_ = true;
-        increaseWarmUpCounter_ = false;
-        break;
-      default:
-        MOZ_CRASH("Unexpected recompile check type");
-    }
-
+        recompileThreshold_(recompileThreshold),
+        type_(type) {
     setGuard();
   }
 
  public:
   INSTRUCTION_HEADER(RecompileCheck)
   TRIVIAL_NEW_WRAPPERS
 
   JSScript* script() const { return script_; }
 
   uint32_t recompileThreshold() const { return recompileThreshold_; }
 
-  bool forceRecompilation() const { return forceRecompilation_; }
-
-  bool increaseWarmUpCounter() const { return increaseWarmUpCounter_; }
+  bool forceInvalidation() const {
+    return type_ == RecompileCheckType::OptimizationLevelOSR;
+  }
+
+  bool forceRecompilation() const {
+    return type_ == RecompileCheckType::Inlining;
+  }
+
+  bool checkCounter() const {
+    return type_ != RecompileCheckType::OptimizationLevelInlined;
+  }
+
+  bool increaseWarmUpCounter() const {
+    return (type_ == RecompileCheckType::OptimizationLevel ||
+            type_ == RecompileCheckType::OptimizationLevelInlined ||
+            type_ == RecompileCheckType::OptimizationLevelOSR);
+  }
 
   AliasSet getAliasSet() const override { return AliasSet::None(); }
 };
 
 class MAtomicIsLockFree : public MUnaryInstruction,
                           public ConvertToInt32Policy<0>::Data {
   explicit MAtomicIsLockFree(MDefinition* value)
       : MUnaryInstruction(classOpcode, value) {
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -133,16 +133,17 @@ namespace jit {
   _(InterpretResume, js::jit::InterpretResume)                                 \
   _(InterruptCheck, js::jit::InterruptCheck)                                   \
   _(InvokeFunction, js::jit::InvokeFunction)                                   \
   _(InvokeFunctionShuffleNewTarget, js::jit::InvokeFunctionShuffleNewTarget)   \
   _(IonBinaryArithICUpdate, js::jit::IonBinaryArithIC::update)                 \
   _(IonBindNameICUpdate, js::jit::IonBindNameIC::update)                       \
   _(IonCompareICUpdate, js::jit::IonCompareIC::update)                         \
   _(IonCompileScriptForBaseline, js::jit::IonCompileScriptForBaseline)         \
+  _(IonForcedInvalidation, js::jit::IonForcedInvalidation)                     \
   _(IonForcedRecompile, js::jit::IonForcedRecompile)                           \
   _(IonGetIteratorICUpdate, js::jit::IonGetIteratorIC::update)                 \
   _(IonGetNameICUpdate, js::jit::IonGetNameIC::update)                         \
   _(IonGetPropSuperICUpdate, js::jit::IonGetPropSuperIC::update)               \
   _(IonGetPropertyICUpdate, js::jit::IonGetPropertyIC::update)                 \
   _(IonHasOwnICUpdate, js::jit::IonHasOwnIC::update)                           \
   _(IonInICUpdate, js::jit::IonInIC::update)                                   \
   _(IonInstanceOfICUpdate, js::jit::IonInstanceOfIC::update)                   \
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1319,16 +1319,37 @@ bool RecompileImpl(JSContext* cx, bool f
 bool IonForcedRecompile(JSContext* cx) {
   return RecompileImpl(cx, /* force = */ true);
 }
 
 bool IonRecompile(JSContext* cx) {
   return RecompileImpl(cx, /* force = */ false);
 }
 
+bool IonForcedInvalidation(JSContext* cx) {
+  MOZ_ASSERT(cx->currentlyRunningInJit());
+  JitActivationIterator activations(cx);
+  JSJitFrameIter frame(activations->asJit());
+
+  MOZ_ASSERT(frame.type() == FrameType::Exit);
+  ++frame;
+
+  RootedScript script(cx, frame.script());
+  MOZ_ASSERT(script->hasIonScript());
+
+  if (script->baselineScript()->hasPendingIonBuilder()) {
+    LinkIonScript(cx, script);
+    return true;
+  }
+
+  Invalidate(cx, script, /* resetUses = */ false,
+             /* cancelOffThread = */ false);
+  return true;
+}
+
 bool SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index,
                      HandleValue value, bool strict) {
   // This function is called from Ion code for StoreElementHole's OOL path.
   // In this case we know the object is native and that no type changes are
   // needed.
 
   DenseElementResult result = obj->setOrExtendDenseElements(
       cx, index, value.address(), 1, ShouldUpdateTypes::DontUpdate);
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -995,16 +995,18 @@ MOZ_MUST_USE bool InitBaselineFrameForOs
                                           InterpreterFrame* interpFrame,
                                           uint32_t numStackValues);
 
 JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
                                 HandleObject owner, int32_t offset);
 
 MOZ_MUST_USE bool IonRecompile(JSContext* cx);
 MOZ_MUST_USE bool IonForcedRecompile(JSContext* cx);
+MOZ_MUST_USE bool IonForcedInvalidation(JSContext* cx);
+
 JSString* StringReplace(JSContext* cx, HandleString string,
                         HandleString pattern, HandleString repl);
 
 MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj,
                                   int32_t index, HandleValue value,
                                   bool strict);
 
 void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
--- a/js/src/vm/CharacterEncoding.cpp
+++ b/js/src/vm/CharacterEncoding.cpp
@@ -17,16 +17,17 @@
 #include "util/StringBuffer.h"
 #include "util/Unicode.h"  // unicode::REPLACEMENT_CHARACTER
 #include "vm/JSContext.h"
 
 using mozilla::IsAscii;
 using mozilla::Utf8Unit;
 
 using namespace js;
+using namespace js::unicode;
 
 Latin1CharsZ JS::LossyTwoByteCharsToNewLatin1CharsZ(
     JSContext* cx, const mozilla::Range<const char16_t> tbchars) {
   MOZ_ASSERT(cx);
   size_t len = tbchars.length();
   unsigned char* latin1 = cx->pod_malloc<unsigned char>(len + 1);
   if (!latin1) {
     return Latin1CharsZ();
@@ -42,28 +43,28 @@ template <typename CharT>
 static size_t GetDeflatedUTF8StringLength(const CharT* chars, size_t nchars) {
   size_t nbytes = nchars;
   for (const CharT* end = chars + nchars; chars < end; chars++) {
     char16_t c = *chars;
     if (c < 0x80) {
       continue;
     }
     uint32_t v;
-    if (0xD800 <= c && c <= 0xDFFF) {
+    if (LeadSurrogateMin <= c && c <= TrailSurrogateMax) {
       /* nbytes sets 1 length since this is surrogate pair. */
-      if (c >= 0xDC00 || (chars + 1) == end) {
+      if (c >= TrailSurrogateMin || (chars + 1) == end) {
         nbytes += 2; /* Bad Surrogate */
         continue;
       }
       char16_t c2 = chars[1];
-      if (c2 < 0xDC00 || c2 > 0xDFFF) {
+      if (c2 < TrailSurrogateMin || c2 > TrailSurrogateMax) {
         nbytes += 2; /* Bad Surrogate */
         continue;
       }
-      v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+      v = ((c - LeadSurrogateMin) << 10) + (c2 - TrailSurrogateMin) + NonBMPMin;
       nbytes--;
       chars++;
     } else {
       v = c;
     }
     v >>= 11;
     nbytes++;
     while (v) {
@@ -95,31 +96,32 @@ static void DeflateStringToUTF8Buffer(co
   if (numcharsp) {
     *numcharsp = 0;
   }
 
   while (srclen) {
     uint32_t v;
     char16_t c = *src++;
     srclen--;
-    if (c >= 0xDC00 && c <= 0xDFFF) {
-      v = unicode::REPLACEMENT_CHARACTER;
-    } else if (c < 0xD800 || c > 0xDBFF) {
+    if (c >= TrailSurrogateMin && c <= TrailSurrogateMax) {
+      v = REPLACEMENT_CHARACTER;
+    } else if (c < LeadSurrogateMin || c > LeadSurrogateMax) {
       v = c;
     } else {
       if (srclen < 1) {
-        v = unicode::REPLACEMENT_CHARACTER;
+        v = REPLACEMENT_CHARACTER;
       } else {
         char16_t c2 = *src;
-        if (c2 < 0xDC00 || c2 > 0xDFFF) {
-          v = unicode::REPLACEMENT_CHARACTER;
+        if (c2 < TrailSurrogateMin || c2 > TrailSurrogateMax) {
+          v = REPLACEMENT_CHARACTER;
         } else {
           src++;
           srclen--;
-          v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+          v = ((c - LeadSurrogateMin) << 10) + (c2 - TrailSurrogateMin) +
+              NonBMPMin;
         }
       }
     }
 
     size_t utf8Len;
     if (v < 0x0080) {
       /* no encoding necessary - performance hack */
       if (dstlenp && *dstlenp + 1 > capacity) {
@@ -216,34 +218,35 @@ static uint32_t Utf8ToOneUcs4CharImpl(co
   MOZ_ASSERT(1 <= utf8Length && utf8Length <= 4);
 
   if (utf8Length == 1) {
     MOZ_ASSERT(!(*utf8Buffer & 0x80));
     return *utf8Buffer;
   }
 
   /* from Unicode 3.1, non-shortest form is illegal */
-  static const uint32_t minucs4Table[] = {0x80, 0x800, 0x10000};
+  static const uint32_t minucs4Table[] = {0x80, 0x800, NonBMPMin};
 
   MOZ_ASSERT((*utf8Buffer & (0x100 - (1 << (7 - utf8Length)))) ==
              (0x100 - (1 << (8 - utf8Length))));
   uint32_t ucs4Char = *utf8Buffer++ & ((1 << (7 - utf8Length)) - 1);
   uint32_t minucs4Char = minucs4Table[utf8Length - 2];
   while (--utf8Length) {
     MOZ_ASSERT((*utf8Buffer & 0xC0) == 0x80);
     ucs4Char = (ucs4Char << 6) | (*utf8Buffer++ & 0x3F);
   }
 
   if (MOZ_UNLIKELY(ucs4Char < minucs4Char)) {
     return INVALID_UTF8;
   }
 
   // WTF-8 allows lone surrogate.
   if (std::is_same<InputCharsT, UTF8Chars>::value &&
-      MOZ_UNLIKELY(ucs4Char >= 0xD800 && ucs4Char <= 0xDFFF)) {
+      MOZ_UNLIKELY(ucs4Char >= LeadSurrogateMin &&
+                   ucs4Char <= TrailSurrogateMax)) {
     return INVALID_UTF8;
   }
 
   return ucs4Char;
 }
 
 uint32_t JS::Utf8ToOneUcs4Char(const uint8_t* utf8Buffer, int utf8Length) {
   return Utf8ToOneUcs4CharImpl<UTF8Chars>(utf8Buffer, utf8Length);
@@ -258,17 +261,17 @@ static void ReportInvalidCharacter(JSCon
 
 static void ReportBufferTooSmall(JSContext* cx, uint32_t dummy) {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             JSMSG_BUFFER_TOO_SMALL);
 }
 
 static void ReportTooBigCharacter(JSContext* cx, uint32_t v) {
   char buffer[10];
-  SprintfLiteral(buffer, "0x%x", v + 0x10000);
+  SprintfLiteral(buffer, "0x%x", v + NonBMPMin);
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             JSMSG_UTF8_CHAR_TOO_LARGE, buffer);
 }
 
 enum class LoopDisposition {
   Break,
   Continue,
 };
@@ -307,17 +310,17 @@ static bool InflateUTF8ToUTF16(JSContext
     if (ErrorAction == OnUTF8Error::Throw) {                        \
       report(cx, arg);                                              \
       return false;                                                 \
     } else if (ErrorAction == OnUTF8Error::Crash) {                 \
       MOZ_CRASH("invalid UTF-8 string: " #report);                  \
     } else {                                                        \
       char16_t replacement;                                         \
       if (ErrorAction == OnUTF8Error::InsertReplacementCharacter) { \
-        replacement = unicode::REPLACEMENT_CHARACTER;               \
+        replacement = REPLACEMENT_CHARACTER;                        \
       } else {                                                      \
         MOZ_ASSERT(ErrorAction == OnUTF8Error::InsertQuestionMark); \
         replacement = '?';                                          \
       }                                                             \
       if (dst(replacement) == LoopDisposition::Break) {             \
         break;                                                      \
       }                                                             \
       n = n2;                                                       \
@@ -357,29 +360,31 @@ static bool InflateUTF8ToUTF16(JSContext
       for (uint32_t m = 1; m < n; m++) {
         if ((src[i + m] & 0xC0) != 0x80) {
           INVALID(ReportInvalidCharacter, i, m);
         }
       }
 
       // Determine the code unit's length in CharT and act accordingly.
       v = Utf8ToOneUcs4CharImpl<InputCharsT>((uint8_t*)&src[i], n);
-      if (v < 0x10000) {
+      if (v < NonBMPMin) {
         // The n-byte UTF8 code unit will fit in a single CharT.
         if (dst(char16_t(v)) == LoopDisposition::Break) {
           break;
         }
       } else {
-        v -= 0x10000;
+        v -= NonBMPMin;
         if (v <= 0xFFFFF) {
           // The n-byte UTF8 code unit will fit in two CharT units.
-          if (dst(char16_t((v >> 10) + 0xD800)) == LoopDisposition::Break) {
+          if (dst(char16_t((v >> 10) + LeadSurrogateMin)) ==
+              LoopDisposition::Break) {
             break;
           }
-          if (dst(char16_t((v & 0x3FF) + 0xDC00)) == LoopDisposition::Break) {
+          if (dst(char16_t((v & 0x3FF) + TrailSurrogateMin)) ==
+              LoopDisposition::Break) {
             break;
           }
         } else {
           // The n-byte UTF8 code unit won't fit in two CharT units.
           INVALID(ReportTooBigCharacter, v, 1);
         }
       }
 
deleted file mode 100644
--- a/layout/inspector/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
deleted file mode 100644
--- a/layout/style/test/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-  ]
-};
deleted file mode 100644
--- a/layout/tools/layout-debug/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/layout/tools/layout-debug/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
--- a/mobile/android/branding/beta/locales/en-US/brand.dtd
+++ b/mobile/android/branding/beta/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShortName  "Firefox Beta">
 <!ENTITY  brandFullName   "Mozilla Firefox Beta">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName "Firefox">
 <!ENTITY  vendorShortName "Mozilla">
 
 <!ENTITY  brandPocket     "Pocket">
--- a/mobile/android/branding/beta/locales/en-US/brand.ftl
+++ b/mobile/android/branding/beta/locales/en-US/brand.ftl
@@ -9,9 +9,12 @@
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
 -brand-short-name = Firefox Beta
 -brand-full-name = Mozilla Firefox Beta
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
 -vendor-short-name = Mozilla
--- a/mobile/android/branding/beta/locales/en-US/brand.properties
+++ b/mobile/android/branding/beta/locales/en-US/brand.properties
@@ -1,6 +1,10 @@
 # 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/.
 
 brandShortName=Firefox Beta
 brandFullName=Mozilla Firefox Beta
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
--- a/mobile/android/branding/nightly/locales/en-US/brand.dtd
+++ b/mobile/android/branding/nightly/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShortName  "Nightly">
 <!ENTITY  brandFullName   "Mozilla Nightly">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName "Firefox">
 <!ENTITY  vendorShortName "Mozilla">
 
 <!ENTITY  brandPocket     "Pocket">
--- a/mobile/android/branding/nightly/locales/en-US/brand.ftl
+++ b/mobile/android/branding/nightly/locales/en-US/brand.ftl
@@ -9,9 +9,12 @@
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
 -brand-short-name = Nightly
 -brand-full-name = Mozilla Nightly
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
 -vendor-short-name = Mozilla
--- a/mobile/android/branding/nightly/locales/en-US/brand.properties
+++ b/mobile/android/branding/nightly/locales/en-US/brand.properties
@@ -1,6 +1,10 @@
 # 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/.
 
 brandShortName=Nightly
 brandFullName=Mozilla Nightly
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
--- a/mobile/android/branding/official/locales/en-US/brand.dtd
+++ b/mobile/android/branding/official/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShortName  "Firefox">
 <!ENTITY  brandFullName   "Mozilla Firefox">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName "Firefox">
 <!ENTITY  vendorShortName "Mozilla">
 
 <!ENTITY  brandPocket     "Pocket">
--- a/mobile/android/branding/official/locales/en-US/brand.ftl
+++ b/mobile/android/branding/official/locales/en-US/brand.ftl
@@ -9,9 +9,12 @@
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
 -brand-short-name = Firefox
 -brand-full-name = Mozilla Firefox
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
 -vendor-short-name = Mozilla
--- a/mobile/android/branding/official/locales/en-US/brand.properties
+++ b/mobile/android/branding/official/locales/en-US/brand.properties
@@ -1,6 +1,10 @@
 # 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/.
 
 brandShortName=Firefox
 brandFullName=Mozilla Firefox
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
--- a/mobile/android/branding/unofficial/locales/en-US/brand.dtd
+++ b/mobile/android/branding/unofficial/locales/en-US/brand.dtd
@@ -1,9 +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/. -->
 
 <!ENTITY  brandShortName  "Fennec">
 <!ENTITY  brandFullName   "Mozilla Fennec">
+<!-- LOCALIZATION NOTE (brandProductName):
+   This brand name can be used in messages where the product name needs to
+   remain unchanged across different versions (Nightly, Beta, etc.). -->
+<!ENTITY  brandProductName "Firefox">
 <!ENTITY  vendorShortName "Mozilla">
 
 <!ENTITY  brandPocket     "Pocket">
--- a/mobile/android/branding/unofficial/locales/en-US/brand.ftl
+++ b/mobile/android/branding/unofficial/locales/en-US/brand.ftl
@@ -9,9 +9,12 @@
 ## - Declined to adapt to grammatical case.
 ## - Transliterated.
 ## - Translated.
 ##
 ## Reference: https://www.mozilla.org/styleguide/communications/translation/
 
 -brand-short-name = Fennec
 -brand-full-name = Mozilla Fennec
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+-brand-product-name = Firefox
 -vendor-short-name = Mozilla
--- a/mobile/android/branding/unofficial/locales/en-US/brand.properties
+++ b/mobile/android/branding/unofficial/locales/en-US/brand.properties
@@ -1,6 +1,10 @@
 # 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/.
 
 brandShortName=Fennec
 brandFullName=Mozilla Fennec
+# LOCALIZATION NOTE(brandProductName):
+# This brand name can be used in messages where the product name needs to
+# remain unchanged across different versions (Nightly, Beta, etc.).
+brandProductName=Firefox
deleted file mode 100644
--- a/mobile/android/tests/browser/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/modules/libjar/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/modules/libjar/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/modules/libjar/zipwriter/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/modules/libmar/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -1658,31 +1658,40 @@ VARCACHE_PREF(
   RelaxedAtomicBool, true
 )
 
 // AV1
 #if defined(XP_WIN) && !defined(_ARM64_)
 # define PREF_VALUE true
 #elif defined(XP_MACOSX)
 # define PREF_VALUE true
-#elif defined(XP_UNIX)
+#elif defined(XP_UNIX) && !defined(Android)
 # define PREF_VALUE true
 #else
 # define PREF_VALUE false
 #endif
 VARCACHE_PREF(
   "media.av1.enabled",
    MediaAv1Enabled,
   RelaxedAtomicBool, PREF_VALUE
 )
 #undef PREF_VALUE
+
 VARCACHE_PREF(
   "media.av1.use-dav1d",
    MediaAv1UseDav1d,
+#if defined(XP_WIN) && !defined(_ARM64_)
+  RelaxedAtomicBool, true
+#elif defined(XP_MACOSX)
+  RelaxedAtomicBool, true
+#elif defined(XP_UNIX) && !defined(Android)
+  RelaxedAtomicBool, true
+#else
   RelaxedAtomicBool, false
+#endif
 )
 
 VARCACHE_PREF(
   "media.flac.enabled",
    MediaFlacEnabled,
   bool, true
 )
 
deleted file mode 100644
--- a/modules/libpref/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/modules/libpref/test/unit_ipc/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/netwerk/cookie/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/netwerk/cookie/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/netwerk/cookie/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/netwerk/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-  ]
-};
deleted file mode 100644
--- a/netwerk/test/mochitests/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test",
-  ]
-};
deleted file mode 100644
--- a/netwerk/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/netwerk/test/unit_ipc/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/parser/xml/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/remote/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.exports = {
-  "extends": ["plugin:mozilla/browser-test"],
-};
deleted file mode 100644
--- a/remote/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-module.exports = {
-  "extends": ["plugin:mozilla/xpcshell-test"],
-};
deleted file mode 100644
--- a/security/manager/ssl/tests/mochitest/browser/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": "plugin:mozilla/browser-test"
-};
--- a/security/manager/ssl/tests/mochitest/mixedcontent/.eslintrc.js
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/.eslintrc.js
@@ -1,9 +1,8 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/mochitest-test",
   "rules": {
 	// Boilerplate runTest and afterNavigationtest calls use opening braces on newline.
     "brace-style": "off"
   }
 };
deleted file mode 100644
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-module.exports = {
-  // mochitest-chrome tests also exist in this directory, but don't appear to
-  // use anything not also available to plain mochitests. Since plain mochitests
-  // are the majority, we take the safer option and only extend the
-  // mochitest-plain eslintrc file.
-  "extends": "plugin:mozilla/mochitest-test"
-};
deleted file mode 100644
--- a/security/manager/ssl/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": "plugin:mozilla/xpcshell-test"
-};
deleted file mode 100644
--- a/services/common/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/services/crypto/component/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/services/crypto/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/services/fxaccounts/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/services/fxaccounts/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/services/fxaccounts/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/services/settings/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/services/sync/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/storage/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/testing/marionette/test/unit/.eslintrc.js
+++ b/testing/marionette/test/unit/.eslintrc.js
@@ -1,12 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": ["plugin:mozilla/xpcshell-test"],
   "rules": {
     "camelcase": "off",
     "max-len": ["error", 100, {
       "ignoreStrings": true,
       "ignoreTemplateLiterals": true,
       "ignoreUrls": true,
     }],
   },
deleted file mode 100644
--- a/testing/mochitest/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/testing/mochitest/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/testing/modules/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
--- a/testing/mozbase/mozproxy/mozproxy/backends/mitm.py
+++ b/testing/mozbase/mozproxy/mozproxy/backends/mitm.py
@@ -157,17 +157,17 @@ class Mitmproxy(Playback):
         """Startup mitmproxy and replay the specified flow file"""
         if self.mitmproxy_proc is not None:
             raise Exception("Proxy already started.")
         LOG.info("mitmdump path: %s" % mitmdump_path)
         LOG.info("browser path: %s" % browser_path)
 
         # mitmproxy needs some DLL's that are a part of Firefox itself, so add to path
         env = os.environ.copy()
-        env["PATH"] = os.path.dirname(browser_path) + ";" + env["PATH"]
+        env["PATH"] = os.path.dirname(browser_path) + os.pathsep + env["PATH"]
         command = [mitmdump_path, "-k"]
 
         if "playback_tool_args" in self.config:
             command.extend(self.config["playback_tool_args"])
 
         LOG.info("Starting mitmproxy playback using env path: %s" % env["PATH"])
         LOG.info("Starting mitmproxy playback using command: %s" % " ".join(command))
         # to turn off mitmproxy log output, use these params for Popen:
--- a/testing/raptor/raptor/tests/raptor-tp6-1.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-1.ini
@@ -8,71 +8,63 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 60000
 gecko_profile_interval = 1
 gecko_profile_entries = 14000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-amazon-firefox]
 apps = firefox
 test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
 playback_recordings = amazon.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-facebook-firefox]
 apps = firefox
 test_url = https://www.facebook.com
 playback_recordings = facebook.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-google-firefox]
 apps = firefox
 # note: use the full url as the first part (without '&cad=h') redirects
 # to the url + '&cad=h'; that redirection causes measure.js content
 # to be loaded into that page also; resulting in 2 fnbpaint values etc.
 test_url = https://www.google.com/search?hl=en&q=barack+obama&cad=h
 playback_recordings = google-search.mp
-measure = fnbpaint, fcp, hero, dcf, ttfi, loadtime
-hero = hero1
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-youtube-firefox]
 apps = firefox
 test_url = https://www.youtube.com
 playback_recordings = youtube.mp
-measure = fnbpaint, fcp, hero, dcf, loadtime
-hero = hero1
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-amazon-chrome]
 apps = chrome
 test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
 playback_recordings = amazon.mp
-measure = fcp, hero, loadtime
-hero = hero1
+measure = fcp, loadtime
 
 [raptor-tp6-facebook-chrome]
 apps = chrome
 test_url = https://www.facebook.com
 playback_recordings = facebook.mp
-measure = fcp, hero, loadtime
-hero = hero1
+measure = fcp, loadtime
 
 [raptor-tp6-google-chrome]
 apps = chrome
 test_url = https://www.google.com/#hl=en&q=barack+obama
 playback_recordings = google-search.mp
-measure = fcp, hero, loadtime
-hero = hero1
+measure = fcp, loadtime
 
 [raptor-tp6-youtube-chrome]
 apps = chrome
 test_url = https://www.youtube.com
 playback_recordings = youtube.mp
-measure = fcp, hero, loadtime
-hero = hero1
+measure = fcp, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6-10.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-10.ini
@@ -7,36 +7,34 @@
 [DEFAULT]
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 60000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-paypal-firefox]
 apps = firefox
 test_url = https://www.paypal.com/myaccount/summary/
 playback_pageset_manifest = mitmproxy-recordings-raptor-paypal.manifest
 playback_recordings = paypal.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-tumblr-firefox]
 apps = firefox
 test_url = https://www.tumblr.com/dashboard
 playback_pageset_manifest = mitmproxy-recordings-raptor-tumblr.manifest
 playback_recordings = tumblr.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-paypal-chrome]
 apps = chrome
 test_url = https://www.paypal.com/myaccount/summary/
 playback_pageset_manifest = mitmproxy-recordings-raptor-paypal.manifest
 playback_recordings = paypal.mp
 measure = fcp, loadtime
 
--- a/testing/raptor/raptor/tests/raptor-tp6-2.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-2.ini
@@ -17,45 +17,39 @@ page_timeout = 60000
 gecko_profile_interval = 1
 gecko_profile_entries = 14000000
 alert_on = fcp
 
 [raptor-tp6-docs-firefox]
 apps = firefox
 test_url = https://docs.google.com/document/d/1US-07msg12slQtI_xchzYxcKlTs6Fp7WqIc6W5GK5M8/edit?usp=sharing
 playback_recordings = google-docs.mp
-measure = fnbpaint, fcp, hero, dcf
-hero = hero1
+measure = fnbpaint, fcp, dcf
 
 [raptor-tp6-sheets-firefox]
 apps = firefox
 test_url = https://docs.google.com/spreadsheets/d/1jT9qfZFAeqNoOK97gruc34Zb7y_Q-O_drZ8kSXT-4D4/edit?usp=sharing
 playback_recordings = google-sheets.mp
-measure = fnbpaint, fcp, hero, dcf
-hero = hero1
+measure = fnbpaint, fcp, dcf
 
 [raptor-tp6-slides-firefox]
 apps = firefox
 test_url = https://docs.google.com/presentation/d/1Ici0ceWwpFvmIb3EmKeWSq_vAQdmmdFcWqaiLqUkJng/edit?usp=sharing
 playback_recordings = google-slides.mp
-measure = fnbpaint, fcp, hero, dcf
-hero = hero1
+measure = fnbpaint, fcp, dcf
 
 [raptor-tp6-docs-chrome]
 apps = chrome
 test_url = https://docs.google.com/document/d/1US-07msg12slQtI_xchzYxcKlTs6Fp7WqIc6W5GK5M8/edit?usp=sharing
 playback_recordings = google-docs.mp
-measure = fcp, hero
-hero = hero1
+measure = fcp
 
 [raptor-tp6-sheets-chrome]
 apps = chrome
 test_url = https://docs.google.com/spreadsheets/d/1jT9qfZFAeqNoOK97gruc34Zb7y_Q-O_drZ8kSXT-4D4/edit?usp=sharing
 playback_recordings = google-sheets.mp
-measure = fcp, hero
-hero = hero1
+measure = fcp
 
 [raptor-tp6-slides-chrome]
 apps = chrome
 test_url = https://docs.google.com/presentation/d/1Ici0ceWwpFvmIb3EmKeWSq_vAQdmmdFcWqaiLqUkJng/edit?usp=sharing
 playback_recordings = google-slides.mp
-measure = fcp, hero
-hero = hero1
+measure = fcp
--- a/testing/raptor/raptor/tests/raptor-tp6-3.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-3.ini
@@ -8,41 +8,39 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-3.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-imdb-firefox]
 apps = firefox
 test_url = https://www.imdb.com/title/tt0084967/?ref_=nv_sr_2
 playback_recordings = imdb.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-imgur-firefox]
 apps = firefox
 test_url = https://imgur.com/gallery/m5tYJL6
 playback_recordings = imgur.mp
-measure = fnbpaint, fcp, dcf, ttfi
+measure = fnbpaint, fcp, dcf
 alert_on = fcp
 
 [raptor-tp6-wikia-firefox]
 apps = firefox
 test_url = http://fandom.wikia.com/articles/fallout-76-will-live-and-die-on-the-creativity-of-its-playerbase
 playback_recordings = wikia.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-imdb-chrome]
 apps = chrome
 test_url = https://www.imdb.com/title/tt0084967/?ref_=nv_sr_2
 playback_recordings = imdb.mp
 measure = fcp, loadtime
 
 [raptor-tp6-imgur-chrome]
--- a/testing/raptor/raptor/tests/raptor-tp6-4.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-4.ini
@@ -8,34 +8,32 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-4.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-bing-firefox]
 apps = firefox
 test_url = https://www.bing.com/search?q=barack+obama
 playback_recordings = bing.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-yandex-firefox]
 apps = firefox
 test_url = https://yandex.ru/search/?text=barack%20obama&lr=10115
 playback_recordings = yandex.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-bing-chrome]
 apps = chrome
 test_url = https://www.bing.com/search?q=barack+obama
 playback_recordings = bing.mp
 measure = fcp, loadtime
 
 [raptor-tp6-yandex-chrome]
--- a/testing/raptor/raptor/tests/raptor-tp6-5.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-5.ini
@@ -8,35 +8,33 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-5.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-apple-firefox]
 apps = firefox
 test_url = https://www.apple.com/macbook-pro/
 playback_recordings = apple.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-microsoft-firefox]
 apps = firefox
 test_url = https://www.microsoft.com/en-us/windows/get-windows-10
 page_timeout = 60000
 playback_recordings = microsoft.mp
-measure = fnbpaint, fcp, dcf, ttfi
+measure = fnbpaint, fcp, dcf
 alert_on = fcp
 
 [raptor-tp6-apple-chrome]
 apps = chrome
 test_url = https://www.apple.com/macbook-pro/
 playback_recordings = apple.mp
 measure = fcp, loadtime
 
--- a/testing/raptor/raptor/tests/raptor-tp6-6.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-6.ini
@@ -8,35 +8,33 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-6.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-reddit-firefox]
 apps = firefox
 test_url = https://www.reddit.com/r/technology/comments/9sqwyh/we_posed_as_100_senators_to_run_ads_on_facebook/
 playback_recordings = reddit.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-yahoo-news-firefox]
 apps = firefox
 test_url = https://www.yahoo.com/lifestyle/police-respond-noise-complaint-end-playing-video-games-respectful-tenants-002329963.html
 playback_pageset_manifest =  mitmproxy-recordings-raptor-yahoo-news.manifest
 playback_recordings = yahoo-news.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-reddit-chrome]
 apps = chrome
 test_url = https://www.reddit.com/r/technology/comments/9sqwyh/we_posed_as_100_senators_to_run_ads_on_facebook/
 playback_recordings = reddit.mp
 measure = fcp, loadtime
 
 [raptor-tp6-yahoo-news-chrome]
--- a/testing/raptor/raptor/tests/raptor-tp6-7.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-7.ini
@@ -8,42 +8,40 @@
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-7.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 60000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-instagram-firefox]
 apps = firefox
 test_url = https://www.instagram.com/
 playback_recordings = instagram.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-twitter-firefox]
 apps = firefox
 test_url = https://twitter.com/BarackObama
 playback_pageset_manifest = mitmproxy-recordings-raptor-twitter.manifest
 playback_recordings = twitter.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-yahoo-mail-firefox]
 apps = firefox
 test_url = https://mail.yahoo.com/
 playback_pageset_manifest = mitmproxy-tp6-yahoo-mail.manifest
 playback_recordings = yahoo-mail.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-instagram-chrome]
 apps = chrome
 test_url = https://www.instagram.com/
 playback_recordings = instagram.mp
 measure = fcp, loadtime
 
 [raptor-tp6-twitter-chrome]
--- a/testing/raptor/raptor/tests/raptor-tp6-8.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-8.ini
@@ -7,36 +7,34 @@
 [DEFAULT]
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-ebay-firefox]
 apps = firefox
 test_url = https://www.ebay.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-ebay.manifest
 playback_recordings = ebay.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-wikipedia-firefox]
 apps = firefox
 test_url = https://en.wikipedia.org/wiki/Barack_Obama
 playback_pageset_manifest = mitmproxy-recordings-raptor-wikipedia.manifest
 playback_recordings = wikipedia.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-ebay-chrome]
 apps = chrome
 test_url = https://www.ebay.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-ebay.manifest
 playback_recordings = ebay.mp
 measure = fcp, loadtime
 
--- a/testing/raptor/raptor/tests/raptor-tp6-9.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-9.ini
@@ -7,36 +7,34 @@
 [DEFAULT]
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-google-mail-firefox]
 apps = firefox
 test_url = https://mail.google.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-google-mail.manifest
 playback_recordings = google-mail.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-pinterest-firefox]
 apps = firefox
 test_url = https://pinterest.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-pinterest.manifest
 playback_recordings = pinterest.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6-google-mail-chrome]
 apps = chrome
 test_url = https://mail.google.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-google-mail.manifest
 playback_recordings = google-mail.mp
 measure = fcp, loadtime
 
--- a/testing/raptor/raptor/tests/raptor-tp6-binast-1.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6-binast-1.ini
@@ -7,23 +7,21 @@
 [DEFAULT]
 type =  pageload
 playback = mitmproxy
 playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
 page_cycles = 25
 unit = ms
 lower_is_better = true
 alert_threshold = 2.0
-# TTI/TTFI can take a while on some pages, and requires at least 5 seconds
-# beyond typical pageload time
 page_timeout = 30000
 gecko_profile_interval = 1
 gecko_profile_entries = 2000000
 alert_on = fcp, loadtime
 
 [raptor-tp6-binast-instagram-firefox]
 apps = firefox
 test_url = https://www.instagram.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-binast-instagram.manifest
 playback_recordings = instagram-binast.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 preferences = {"dom.script_loader.binast_encoding.enabled": true,
               "dom.script_loader.binast_encoding.domain.restrict.list": "*.instagram.com"}
--- a/testing/raptor/raptor/tests/raptor-tp6m-1.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-1.ini
@@ -15,58 +15,58 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-amazon-geckoview]
 apps = geckoview
 test_url = https://www.amazon.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-amazon.manifest
 playback_recordings = android-amazon.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-facebook-geckoview]
 apps = geckoview
 test_url = https://m.facebook.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-facebook.manifest
 playback_recordings = android-facebook.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-google-geckoview]
 apps = geckoview
 test_url = https://www.google.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-google.manifest
 playback_recordings = android-google.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-youtube-geckoview]
 apps = geckoview
 test_url = https://www.youtube.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
 playback_recordings = android-youtube.mp
 measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-amazon-refbrow]
 apps = refbrow
 test_url = https://www.amazon.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-amazon.manifest
 playback_recordings = android-amazon.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-facebook-refbrow]
 apps = refbrow
 test_url = https://m.facebook.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-facebook.manifest
 playback_recordings = android-facebook.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-google-refbrow]
 apps = refbrow
 test_url = https://www.google.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-google.manifest
 playback_recordings = android-google.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-youtube-refbrow]
 apps = refbrow
 test_url = https://www.youtube.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
 playback_recordings = android-youtube.mp
 measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-2.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-2.ini
@@ -15,37 +15,37 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-instagram-geckoview]
 apps = geckoview
 test_url = https://www.instagram.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-instagram-mobile.manifest
 playback_recordings = instagram-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-bing-geckoview]
 apps = geckoview
 test_url = https://www.bing.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-bing-mobile.manifest
 playback_recordings = bing-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-bing-restaurants-geckoview]
 apps = geckoview
 test_url = https://www.bing.com/search?q=restaurants
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-bing-restaurants-mobile.manifest
 playback_recordings = bing-restaurants-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-ebay-kleinanzeigen-geckoview]
 apps = geckoview
 test_url = https://m.ebay-kleinanzeigen.de
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-ebay-kleinanzeigen-mobile.manifest
 playback_recordings = ebay-kleinanzeigen-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-ebay-kleinanzeigen-search-geckoview]
 apps = geckoview
 test_url = https://m.ebay-kleinanzeigen.de/s-anzeigen/auf-zeit-wg-berlin/zimmer/c199-l3331
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-ebay-kleinanzeigen-search-mobile.manifest
 playback_recordings = ebay-kleinanzeigen-search-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-3.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-3.ini
@@ -15,17 +15,17 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-google-maps-geckoview]
 apps = geckoview
 test_url = https://www.google.com/maps?force=pwa
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-google-maps.manifest
 playback_recordings = google_maps_mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-google-restaurants-geckoview]
 apps = geckoview
 test_url = https://www.google.com/search?q=restaurants+near+me
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-google-restaurants.manifest
 playback_recordings = google-search-restaurants-mobile.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 disabled = Bug 1533283 Intermittent timeouts running raptor-tp6m-google-restaurants-geckoview
--- a/testing/raptor/raptor/tests/raptor-tp6m-4.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-4.ini
@@ -15,25 +15,25 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-booking-geckoview]
 apps = geckoview
 test_url = https://www.booking.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-booking.manifest
 playback_recordings = android-booking.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-cnn-geckoview]
 apps = geckoview
 test_url = https://edition.cnn.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-cnn.manifest
 playback_recordings = android-cnn.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 disabled = Bug 1533287 Intermittent timeouts running raptor-tp6m-cnn-geckoview
 
 [raptor-tp6m-cnn-ampstories-geckoview]
 apps = geckoview
 test_url = https://edition.cnn.com/ampstories/us/why-hurricane-michael-is-a-monster-unlike-any-other
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-cnn-ampstories.manifest
 playback_recordings = android-cnn-ampstories.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 disabled = Bug 1533666 Intermittent timeouts running raptor-tp6m-cnn-ampstories-geckoview
--- a/testing/raptor/raptor/tests/raptor-tp6m-5.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-5.ini
@@ -15,23 +15,23 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-amazon-search-geckoview]
 apps = geckoview
 test_url = https://www.amazon.com/s/ref=nb_sb_noss_2/139-6317191-5622045?url=search-alias%3Daps&field-keywords=mobile+phone
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-amazon-search.manifest
 playback_recordings = android-amazon-search.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-wikipedia-geckoview]
 apps = geckoview
 test_url = https://en.m.wikipedia.org/wiki/Main_Page
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-wikipedia.manifest
 playback_recordings = android-wikipedia.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-youtube-watch-geckoview]
 apps = geckoview
 test_url = https://www.youtube.com/watch?v=COU5T-Wafa4
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube-watch.manifest
 playback_recordings = android-youtube-watch.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-6.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-6.ini
@@ -15,24 +15,24 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-reddit-geckoview]
 apps = geckoview
 test_url = https://www.reddit.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-reddit.manifest
 playback_recordings = mitmproxy-recordings-raptor-tp6m-reddit.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-bbc-geckoview]
 apps = geckoview
 test_url = https://www.bbc.com/news/business-47245877
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-bbc.manifest
 playback_recordings = mitmproxy-recordings-raptor-tp6m-bbc.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 disabled = Bug 1533304 Investigating tp6m-6 raptor test for raptor-tp6m-bbc-geckoview
 
 [raptor-tp6m-stackoverflow-geckoview]
 apps = geckoview
 test_url = https://stackoverflow.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-stackoverflow.manifest
 playback_recordings = mitmproxy-recordings-raptor-tp6m-stackoverflow.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-7.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-7.ini
@@ -15,24 +15,24 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-microsoft-support-geckoview]
 apps = geckoview
 test_url = https://support.microsoft.com/en-us
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-microsoft-support.manifest
 playback_recordings = android-microsoft-support.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 disabled = Bug 1533306 Investigating tp6m-7 raptor test raptor-tp6m-microsoft-support-geckoview
 
 [raptor-tp6m-jianshu-geckoview]
 apps = geckoview
 test_url = https://www.jianshu.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-jianshu.manifest
 playback_recordings = android-jianshu.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-imdb-geckoview]
 apps = geckoview
 test_url = https://m.imdb.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-imdb.manifest
 playback_recordings = android-imdb.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-8.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-8.ini
@@ -15,23 +15,23 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-allrecipes-geckoview]
 apps = geckoview
 test_url = https://www.allrecipes.com/
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-allrecipes.manifest
 playback_recordings = android-allrecipes.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-espn-geckoview]
 apps = geckoview
 test_url = http://www.espn.com/nba/story/_/page/allstarweekend25788027/the-comparison-lebron-james-michael-jordan-their-own-words
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-espn.manifest
 playback_recordings = android-espn.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
 
 [raptor-tp6m-web-de-geckoview]
 apps = geckoview
 test_url = https://web.de/magazine/politik/politologe-glaubt-grossen-koalition-herbst-knallen-33563566
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-web-de.manifest
 playback_recordings = android-web-de.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-9.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-9.ini
@@ -15,9 +15,9 @@ alert_threshold = 2.0
 page_timeout = 60000
 alert_on = fcp, loadtime
 
 [raptor-tp6m-facebook-cristiano-geckoview]
 apps = geckoview
 test_url = https://m.facebook.com/Cristiano
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-facebook-cristiano.manifest
 playback_recordings = android-facebook-cristiano.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
--- a/testing/raptor/raptor/tests/raptor-tp6m-cold-1.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6m-cold-1.ini
@@ -16,9 +16,9 @@ page_timeout = 60000
 alert_on = fcp, loadtime
 cold = true
 
 [raptor-tp6m-amazon-geckoview-cold]
 apps = geckoview
 test_url = https://www.amazon.com
 playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-amazon.manifest
 playback_recordings = android-amazon.mp
-measure = fnbpaint, fcp, dcf, ttfi, loadtime
+measure = fnbpaint, fcp, dcf, loadtime
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text/line-breaking/line-breaking-013.html.ini
@@ -0,0 +1,3 @@
+[line-breaking-013.html]
+  expected:
+    if os == "mac": FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text/line-breaking/line-breaking-014.html.ini
@@ -0,0 +1,3 @@
+[line-breaking-014.html]
+  expected:
+    if os == "mac": FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/line-breaking/line-breaking-013.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>CSS Text — line breaking of emoji sequences that should form single clusters</title>
+<meta name=assert content="A UA must use the extended grapheme cluster (not legacy grapheme cluster), as defined in [UAX29], as the basis for its typographic character unit.">
+<link rel=help href="https://www.w3.org/TR/css-text-3/#characters">
+<link rel=match href="reference/line-breaking-013-ref.html">
+<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<style>
+div {
+    line-height: 1em;
+    font-size: 30px;
+}
+.container {
+    position: relative;
+    margin: .5em;
+}
+.ref {
+    background-color: white;
+    padding: .25em;
+}
+.test {
+    color: transparent;
+    background-color: red;
+    position: absolute;
+    width: .5em;
+    left: 0;
+    top: 0;
+    padding: .25em;
+    z-index: -1;
+}
+</style>
+<body>
+    <p>Each emoji should appear on a single line with no red background.</p>
+    <div class=container>
+        <div class=ref>&#x1F468;&#x200D;&#x1F4BB;</div><!-- man technologist -->
+        <div class=test>&#x1F468;&#x200D;&#x1F4BB;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;</div><!-- family with mother, son and daughter -->
+        <div class=test>&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F939;&#x200D;&#x2640;&#xFE0F;</div><!-- woman juggling -->
+        <div class=test>&#x1F939;&#x200D;&#x2640;&#xFE0F;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x26F9;&#x1F3FF;&#x200D;&#x2640;&#xFE0F;</div><!-- woman basketball player (fitzpatrick type 6) -->
+        <div class=test>&#x26F9;&#x1F3FF;&#x200D;&#x2640;&#xFE0F;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F3;&#xFE0F;&#x200D;&#x1F308;</div><!-- rainbow flag -->
+        <div class=test>&#x1F3F3;&#xFE0F;&#x200D;&#x1F308;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F4;&#xE0067;&#xE0062;&#xE0077;&#xE006C;&#xE0073;&#xE007F;</div><!-- flag of Wales -->
+        <div class=test>&#x1F3F4;&#xE0067;&#xE0062;&#xE0077;&#xE006C;&#xE0073;&#xE007F;</div>
+    </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/line-breaking/line-breaking-014.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>CSS Text — line breaking (with word-break:break-all) of emoji sequences that should form single clusters</title>
+<meta name=assert content="A UA must use the extended grapheme cluster (not legacy grapheme cluster), as defined in [UAX29], as the basis for its typographic character unit.">
+<link rel=help href="https://www.w3.org/TR/css-text-3/#characters">
+<link rel=match href="reference/line-breaking-013-ref.html">
+<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<style>
+div {
+    line-height: 1em;
+    font-size: 30px;
+}
+.container {
+    position: relative;
+    margin: .5em;
+}
+.ref {
+    background-color: white;
+    padding: .25em;
+}
+.test {
+    word-break: break-all;
+    color: transparent;
+    background-color: red;
+    position: absolute;
+    width: .5em;
+    left: 0;
+    top: 0;
+    padding: .25em;
+    z-index: -1;
+}
+</style>
+<body>
+    <p>Each emoji should appear on a single line with no red background.</p>
+    <div class=container>
+        <div class=ref>&#x1F468;&#x200D;&#x1F4BB;</div><!-- man technologist -->
+        <div class=test>&#x1F468;&#x200D;&#x1F4BB;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;</div><!-- family with mother, son and daughter -->
+        <div class=test>&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F939;&#x200D;&#x2640;&#xFE0F;</div><!-- woman juggling -->
+        <div class=test>&#x1F939;&#x200D;&#x2640;&#xFE0F;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x26F9;&#x1F3FF;&#x200D;&#x2640;&#xFE0F;</div><!-- woman basketball player (fitzpatrick type 6) -->
+        <div class=test>&#x26F9;&#x1F3FF;&#x200D;&#x2640;&#xFE0F;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F3;&#xFE0F;&#x200D;&#x1F308;</div><!-- rainbow flag -->
+        <div class=test>&#x1F3F3;&#xFE0F;&#x200D;&#x1F308;</div>
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F4;&#xE0067;&#xE0062;&#xE0077;&#xE006C;&#xE0073;&#xE007F;</div><!-- flag of Wales -->
+        <div class=test>&#x1F3F4;&#xE0067;&#xE0062;&#xE0077;&#xE006C;&#xE0073;&#xE007F;</div>
+    </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/line-breaking/reference/line-breaking-013-ref.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>CSS Text — reference file for emoji sequence line-breaking test</title>
+<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<style>
+div {
+    line-height: 1em;
+    font-size: 30px;
+}
+.container {
+    position: relative;
+    margin: .5em;
+}
+.ref {
+    background-color: white;
+    padding: .25em;
+}
+</style>
+<body>
+    <p>Each emoji should appear on a single line with no red background.</p>
+    <div class=container>
+        <div class=ref>&#x1F468;&#x200D;&#x1F4BB;</div><!-- man technologist -->
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F469;&#x200D;&#x1F467;&#x200D;&#x1F466;</div><!-- family with mother, son and daughter -->
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F939;&#x200D;&#x2640;&#xFE0F;</div><!-- woman juggling -->
+    </div>
+    <div class=container>
+        <div class=ref>&#x26F9;&#x1F3FF;&#x200D;&#x2640;&#xFE0F;</div><!-- woman basketball player (fitzpatrick type 6) -->
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F3;&#xFE0F;&#x200D;&#x1F308;</div><!-- rainbow flag -->
+    </div>
+    <div class=container>
+        <div class=ref>&#x1F3F4;&#xE0067;&#xE0062;&#xE0077;&#xE006C;&#xE0073;&#xE007F;</div><!-- flag of Wales -->
+    </div>
+</body>
+</html>
deleted file mode 100644
--- a/testing/xpcshell/example/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -16,16 +16,19 @@
     _PREFS_FILE */
 
 /* defined by XPCShellImpl.cpp */
 /* globals load, sendCommand */
 
 /* must be defined by tests using do_await_remote_message/do_send_remote_message */
 /* globals Cc, Ci */
 
+/* defined by this file but is defined as read-only for tests */
+/* globals runningInParent: true */
+
 /* may be defined in test files */
 /* globals run_test */
 
 var _quit = false;
 var _passed = true;
 var _tests_pending = 0;
 var _cleanupFunctions = [];
 var _pendingTimers = [];
@@ -1436,17 +1439,17 @@ function run_next_test() {
           if (_isGenerator(result)) {
             Assert.ok(false, "Task returned a generator");
           }
           run_next_test();
         }, ex => {
           _gTaskRunning = false;
           try {
             do_report_unexpected_exception(ex);
-          } catch (ex) {
+          } catch (error) {
             // The above throws NS_ERROR_ABORT and we don't want this to show up
             // as an unhandled rejection later.
           }
         });
       } else {
         // Exceptions do not kill asynchronous tests, so they'll time out.
         try {
           _gRunningTest();
@@ -1489,19 +1492,19 @@ try {
 function _load_mozinfo() {
   let mozinfoFile = Cc["@mozilla.org/file/local;1"]
     .createInstance(Ci.nsIFile);
   mozinfoFile.initWithPath(_MOZINFO_JS_PATH);
   let stream = Cc["@mozilla.org/network/file-input-stream;1"]
     .createInstance(Ci.nsIFileInputStream);
   stream.init(mozinfoFile, -1, 0, 0);
   let bytes = _NetUtil.readInputStream(stream, stream.available());
-  let mozinfo = JSON.parse((new TextDecoder()).decode(bytes));
+  let decoded = JSON.parse((new TextDecoder()).decode(bytes));
   stream.close();
-  return mozinfo;
+  return decoded;
 }
 
 Object.defineProperty(this, "mozinfo", {
   configurable: true,
   get() {
     let _mozinfo = _load_mozinfo();
     Object.defineProperty(this, "mozinfo", {
       configurable: false,
deleted file mode 100644
--- a/toolkit/components/aboutmemory/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/aboutperformance/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
--- a/toolkit/components/antitracking/test/browser/.eslintrc.js
+++ b/toolkit/components/antitracking/test/browser/.eslintrc.js
@@ -1,11 +1,7 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
-
   "env": {
     "webextensions": true,
   },
 };
deleted file mode 100644
--- a/toolkit/components/asyncshutdown/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/autocomplete/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/captivedetect/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/cleardata/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/cloudstorage/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/commandlines/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/commandlines/test/unit_unix/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/commandlines/test/unit_win/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/contentprefs/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/contentprefs/tests/unit_cps2/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/contextualidentity/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/crashes/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/crashmonitor/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/ctypes/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/ctypes/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/downloads/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/downloads/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/toolkit/components/extensions/.eslintrc.js
+++ b/toolkit/components/extensions/.eslintrc.js
@@ -283,9 +283,19 @@ module.exports = {
     "yoda": "error",
 
     // Disallow function or variable declarations in nested blocks
     "no-inner-declarations": "error",
 
     // Disallow labels that share a name with a variable
     "no-label-var": "error",
   },
+
+  "overrides": [{
+    "files": "test/xpcshell/head*.js",
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }],
 };
--- a/toolkit/components/extensions/test/browser/.eslintrc.js
+++ b/toolkit/components/extensions/test/browser/.eslintrc.js
@@ -1,13 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/browser-test",
-
   "env": {
     "webextensions": true,
   },
 
   "rules": {
     "no-shadow": "off",
   },
 };
--- a/toolkit/components/extensions/test/mochitest/.eslintrc.js
+++ b/toolkit/components/extensions/test/mochitest/.eslintrc.js
@@ -1,13 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/mochitest-test",
-
   "env": {
     "browser": true,
     "webextensions": true,
   },
 
   "rules": {
     "no-shadow": 0,
   },
--- a/toolkit/components/extensions/test/xpcshell/.eslintrc.js
+++ b/toolkit/components/extensions/test/xpcshell/.eslintrc.js
@@ -1,11 +1,9 @@
 "use strict";
 
 module.exports = {
-  "extends": "plugin:mozilla/xpcshell-test",
-
   "env": {
     // The tests in this folder are testing based on WebExtensions, so lets
     // just define the webextensions environment here.
     "webextensions": true
   }
 };
deleted file mode 100644
--- a/toolkit/components/featuregates/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-module.exports = {
-  extends: [
-    "plugin:mozilla/xpcshell-test"
-  ],
-
-  plugins: [
-    "mozilla"
-  ],
-};
deleted file mode 100644
--- a/toolkit/components/filewatcher/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/kvstore/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/lz4/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/mediasniffer/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/normandy/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-module.exports = {
-  extends: [
-    "plugin:mozilla/browser-test"
-  ],
-
-  plugins: [
-    "mozilla"
-  ],
-};
deleted file mode 100644
--- a/toolkit/components/normandy/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-module.exports = {
-  extends: [
-    "plugin:mozilla/xpcshell-test"
-  ],
-
-  plugins: [
-    "mozilla"
-  ],
-};
--- a/toolkit/components/osfile/tests/xpcshell/.eslintrc.js
+++ b/toolkit/components/osfile/tests/xpcshell/.eslintrc.js
@@ -1,11 +1,7 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ],
-
   "rules": {
     "no-shadow": "off",
   }
 };
--- a/toolkit/components/passwordmgr/test/browser/.eslintrc.js
+++ b/toolkit/components/passwordmgr/test/browser/.eslintrc.js
@@ -1,11 +1,7 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
-
   rules:  {
     "brace-style": ["error", "1tbs", {"allowSingleLine": false}],
   },
 };
deleted file mode 100644
--- a/toolkit/components/passwordmgr/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/places/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/places/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test",
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/places/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/promiseworker/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/remotebrowserutils/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/remotepagemanager/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/reputationservice/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/satchel/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/satchel/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/search/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/startup/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/startup/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/telemetry/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/telemetry/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/terminator/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/timermanager/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/url-classifier/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/url-classifier/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/urlformatter/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/utils/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,11 +0,0 @@
-"use strict";
-
-module.exports = {
-  extends: [
-    "plugin:mozilla/browser-test"
-  ],
-
-  plugins: [
-    "mozilla"
-  ],
-};
deleted file mode 100644
--- a/toolkit/components/utils/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/viewsource/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/windowcreator/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/xulstore/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/components/xulstore/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/content/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/content/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/content/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/content/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/crashreporter/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/crashreporter/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/crashreporter/test/unit_ipc/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/forgetaboutsite/test/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/forgetaboutsite/test/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/modules/subprocess/test/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": "plugin:mozilla/xpcshell-test",
-};
deleted file mode 100644
--- a/toolkit/modules/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/modules/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/mozapps/downloads/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test",
-    "plugin:mozilla/mochitest-test",
-  ]
-};
-
deleted file mode 100644
--- a/toolkit/mozapps/downloads/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
--- a/toolkit/mozapps/extensions/.eslintrc.js
+++ b/toolkit/mozapps/extensions/.eslintrc.js
@@ -6,10 +6,19 @@ module.exports = {
     // XXX Bug 1326071 - This should be reduced down - probably to 20 or to
     // be removed & synced with the mozilla/recommended value.
     "complexity": ["error", {"max": 68}],
 
     "no-unused-vars": ["error", {
       "args": "none",
       "vars": "all",
     }],
-  }
+  },
+  "overrides": [{
+    "files": "test/xpcshell/head*.js",
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }],
 };
--- a/toolkit/mozapps/extensions/test/browser/.eslintrc.js
+++ b/toolkit/mozapps/extensions/test/browser/.eslintrc.js
@@ -1,15 +1,11 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
-
   "env": {
     "webextensions": true,
   },
 
   "rules": {
     "no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^end_test$"}],
   }
 };
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
--- a/toolkit/mozapps/extensions/test/xpcshell/.eslintrc.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/.eslintrc.js
@@ -1,10 +1,16 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ],
   "rules": {
     "no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^end_test$"}],
-  }
+  },
+  "overrides": [{
+    "files": "head*.js",
+    "rules": {
+      "no-unused-vars": ["error", {
+        "args": "none",
+        "vars": "local",
+      }],
+    },
+  }],
 };
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/chrome-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/unit_base_updater/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/unit_service_updater/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/tools/code-coverage/tests/mochitest/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/mochitest-test"
-  ]
-};
deleted file mode 100644
--- a/tools/code-coverage/tests/xpcshell/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/tools/profiler/tests/chrome/.eslintrc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-"use strict";
-
-module.exports = {
-  // Extend from the shared list of defined globals for mochitests.
-  "extends": "plugin:mozilla/chrome-test"
-};
deleted file mode 100644
--- a/uriloader/exthandler/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};
deleted file mode 100644
--- a/widget/tests/browser/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ],
-};
deleted file mode 100644
--- a/widget/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test",
-  ]
-};
deleted file mode 100644
--- a/xpcom/tests/unit/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/xpcshell-test"
-  ]
-};