summaryrefslogtreecommitdiffstats
path: root/docs/code-quality/lint/linters/eslint-plugin-mozilla
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla.rst114
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst30
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst76
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst8
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst14
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst18
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst5
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst28
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst25
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst8
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst22
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst27
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst21
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst38
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst26
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst6
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst24
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst23
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst6
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst22
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst35
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst29
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst19
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst36
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst45
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst36
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst22
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst27
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst22
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst13
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst6
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst26
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst26
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst33
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst24
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst19
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst21
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst42
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst20
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst21
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst21
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst42
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst55
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst30
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst24
-rw-r--r--docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst21
58 files changed, 1514 insertions, 0 deletions
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst
new file mode 100644
index 0000000000..d1d60c963c
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla.rst
@@ -0,0 +1,114 @@
+=====================
+Mozilla ESLint Plugin
+=====================
+
+This is the documentation of Mozilla ESLint PLugin.
+
+Environments
+============
+
+The plugin implements the following environments:
+
+
+.. toctree::
+ :maxdepth: 2
+
+ eslint-plugin-mozilla/environment
+
+Rules
+=====
+
+The plugin implements the following rules:
+
+.. toctree::
+ :maxdepth: 1
+
+ eslint-plugin-mozilla/avoid-Date-timing
+ eslint-plugin-mozilla/avoid-removeChild
+ eslint-plugin-mozilla/balanced-listeners
+ eslint-plugin-mozilla/balanced-observers
+ eslint-plugin-mozilla/consistent-if-bracing
+ eslint-plugin-mozilla/import-browser-window-globals
+ eslint-plugin-mozilla/import-content-task-globals
+ eslint-plugin-mozilla/import-globals
+ eslint-plugin-mozilla/import-globals-from
+ eslint-plugin-mozilla/import-headjs-globals
+ eslint-plugin-mozilla/lazy-getter-object-name
+ eslint-plugin-mozilla/mark-exported-symbols-as-used
+ eslint-plugin-mozilla/mark-test-function-used
+ eslint-plugin-mozilla/no-aArgs
+ eslint-plugin-mozilla/no-addtask-setup
+ eslint-plugin-mozilla/no-arbitrary-setTimeout
+ eslint-plugin-mozilla/no-compare-against-boolean-literals
+ eslint-plugin-mozilla/no-cu-reportError
+ eslint-plugin-mozilla/no-define-cc-etc
+ eslint-plugin-mozilla/no-redeclare-with-import-autofix
+ eslint-plugin-mozilla/no-throw-cr-literal
+ eslint-plugin-mozilla/no-useless-parameters
+ eslint-plugin-mozilla/no-useless-removeEventListener
+ eslint-plugin-mozilla/no-useless-run-test
+ eslint-plugin-mozilla/prefer-boolean-length-check
+ eslint-plugin-mozilla/prefer-formatValues
+ eslint-plugin-mozilla/reject-addtask-only
+ eslint-plugin-mozilla/reject-chromeutils-import-params
+ eslint-plugin-mozilla/reject-eager-module-in-lazy-getter
+ eslint-plugin-mozilla/reject-global-this
+ eslint-plugin-mozilla/reject-globalThis-modification
+ eslint-plugin-mozilla/reject-importGlobalProperties
+ eslint-plugin-mozilla/reject-lazy-imports-into-globals
+ eslint-plugin-mozilla/reject-mixing-eager-and-lazy
+ eslint-plugin-mozilla/reject-multiple-getters-calls
+ eslint-plugin-mozilla/reject-relative-requires
+ eslint-plugin-mozilla/reject-requires-await
+ eslint-plugin-mozilla/reject-scriptableunicodeconverter
+ eslint-plugin-mozilla/reject-some-requires
+ eslint-plugin-mozilla/reject-top-level-await
+ eslint-plugin-mozilla/reject-import-system-module-from-non-system
+ eslint-plugin-mozilla/use-cc-etc
+ eslint-plugin-mozilla/use-chromeutils-generateqi
+ eslint-plugin-mozilla/use-chromeutils-import
+ eslint-plugin-mozilla/use-default-preference-values
+ eslint-plugin-mozilla/use-includes-instead-of-indexOf
+ eslint-plugin-mozilla/use-isInstance
+ eslint-plugin-mozilla/use-ownerGlobal
+ eslint-plugin-mozilla/use-returnValue
+ eslint-plugin-mozilla/use-services
+ eslint-plugin-mozilla/use-static-import
+ eslint-plugin-mozilla/valid-ci-uses
+ eslint-plugin-mozilla/valid-lazy
+ eslint-plugin-mozilla/valid-services
+ eslint-plugin-mozilla/valid-services-property
+ eslint-plugin-mozilla/var-only-at-top-level
+
+Tests
+=====
+
+The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most
+of the tests use the `ESLint Rule Unit Test framework`_.
+
+.. _mochajs: https://mochajs.org/
+.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests
+
+Running Tests
+-------------
+
+The tests for eslint-plugin-mozilla are run via `mochajs`_ on top of node. Most
+of the tests use the `ESLint Rule Unit Test framework`_.
+
+The rules have some self tests, these can be run via:
+
+.. code-block:: shell
+
+ $ cd tools/lint/eslint/eslint-plugin-mozilla
+ $ npm install
+ $ npm run test
+
+Disabling tests
+---------------
+
+In the unlikely event of needing to disable a test, currently the only way is
+by commenting-out. Please file a bug if you have to do this. Bugs should be filed
+in the *Testing* product under *Lint*.
+
+.. _mochajs: https://mochajs.org/
+.. _ESLint Rule Unit Test Framework: http://eslint.org/docs/developer-guide/working-with-rules#rule-unit-tests
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst
new file mode 100644
index 0000000000..b01b568a28
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-Date-timing.rst
@@ -0,0 +1,30 @@
+avoid-Date-timing
+=================
+
+Rejects grabbing the current time via Date.now() or new Date() for timing
+purposes when the less problematic performance.now() can be used instead.
+
+The performance.now() function returns milliseconds since page load. To
+convert that to milliseconds since the epoch, use:
+
+.. code-block:: js
+
+ performance.timing.navigationStart + performance.now()
+
+Often timing relative to the page load is adequate and that conversion may not
+be necessary.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Date.now()
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ new Date('2017-07-11');
+ performance.now()
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst
new file mode 100644
index 0000000000..15ece94d0d
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/avoid-removeChild.rst
@@ -0,0 +1,20 @@
+avoid-removeChild
+=================
+
+Rejects using ``element.parentNode.removeChild(element)`` when ``element.remove()``
+can be used instead.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ elt.parentNode.removeChild(elt);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ elt.remove();
+ elt.parentNode.removeChild(elt2);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst
new file mode 100644
index 0000000000..f53c11e7aa
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-listeners.rst
@@ -0,0 +1,20 @@
+balanced-listeners
+==================
+
+Checks that for every occurrence of 'addEventListener' or 'on' there is an
+occurrence of 'removeEventListener' or 'off' with the same event name.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler, false);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('event', handler);
+ elt.removeEventListener('event', handler);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst
new file mode 100644
index 0000000000..b169a520a3
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/balanced-observers.rst
@@ -0,0 +1,20 @@
+balanced-observers
+==================
+
+Checks that for every occurrence of ``addObserver`` there is an
+occurrence of ``removeObserver`` with the same topic.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Services.obs.addObserver(observer, 'observable');
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ Services.obs.addObserver(observer, 'observable');
+ Services.obs.removeObserver(observer, 'observable');
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst
new file mode 100644
index 0000000000..7bf6b796ef
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/consistent-if-bracing.rst
@@ -0,0 +1,23 @@
+consistent-if-bracing
+=====================
+
+Checks that if/elseif/else bodies are braced consistently, so either all bodies
+are braced or unbraced. Doesn't enforce either of those styles though.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ if (true) {1} else 0
+ if (true) 1; else {0}
+ if (true) {1} else if (true) 2; else {0}
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ if (true) {1} else {0}
+ if (false) 1; else 0
+ if (true) {1} else if (true) {2} else {0}
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst
new file mode 100644
index 0000000000..2c779410d6
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/environment.rst
@@ -0,0 +1,76 @@
+Environment
+===========
+
+These environments are available by specifying a comment at the top of the file,
+e.g.
+
+.. code-block:: js
+
+ /* eslint-env mozilla/chrome-worker */
+
+There are also built-in ESLint environments available as well. Find them here: http://eslint.org/docs/user-guide/configuring#specifying-environments
+
+browser-window
+--------------
+
+Defines the environment for scripts that are in the main browser.xhtml scope.
+
+chrome-script
+-------------
+
+Defines the environment for scripts loaded by
+``SpecialPowers.loadChromeScript``.
+
+chrome-worker
+-------------
+
+Defines the environment for chrome workers. This differs from normal workers by
+the fact that `ctypes` can be accessed as well.
+
+frame-script
+------------
+
+Defines the environment for scripts loaded by ``Services.mm.loadFrameScript``.
+
+jsm
+---
+
+Defines the environment for jsm files (javascript modules).
+
+privileged
+----------
+
+Defines the environment for privileged JS files.
+
+process-script
+--------------
+
+Defines the environment for scripts loaded by
+``Services.ppmm.loadProcessScript``.
+
+remote-page
+-----------
+
+Defines the environment for scripts loaded with ``<script src="...">`` in
+``about:`` pages.
+
+simpletest
+----------
+
+Defines the environment for scripts that use the SimpleTest mochitest harness.
+
+sjs
+---
+
+Defines the environment for sjs files.
+
+special-powers-sandbox
+----------------------
+
+Defines the environment for scripts evaluated inside ``SpecialPowers`` sandbox
+with the default options.
+
+xpcshell
+--------
+
+Defines the environment for xpcshell test files.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst
new file mode 100644
index 0000000000..35c09cc8fd
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-browser-window-globals.rst
@@ -0,0 +1,8 @@
+import-browser-window-globals
+=============================
+
+For scripts included in browser-window, this will automatically inject the
+browser-window global scopes into the file.
+
+This is a rule rather than an environment, as it allowed us to automatically
+select the files to include.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst
new file mode 100644
index 0000000000..f2550a1412
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-content-task-globals.rst
@@ -0,0 +1,14 @@
+import-content-task-globals
+===========================
+
+For files containing ContentTask.spawn calls, this will automatically declare
+the frame script variables in the global scope. ContentTask is only available
+to test files, so by default the configs only specify it for the mochitest based
+configurations.
+
+This saves setting the file as a mozilla/frame-script environment.
+
+Note: due to the way ESLint works, it appears it is only easy to declare these
+variables on a file global scope, rather than function global. This may mean that
+they are incorrectly allowed, but given they are test files, this should be
+detected during testing.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst
new file mode 100644
index 0000000000..c2956ba05a
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals-from.rst
@@ -0,0 +1,18 @@
+import-globals-from
+===================
+
+Parses a file for globals defined in various unique Mozilla ways.
+
+When a ``/* import-globals-from <path> */`` comment is found in a file, then all
+globals from the file at <path> will be imported in the current scope. This will
+also operate recursively.
+
+This is useful for scripts that are loaded as <script> tag in a window and rely
+on each other's globals.
+
+If <path> is a relative path, then it must be relative to the file being
+checked by the rule.
+
+Note: ``import-globals-from`` does not support loading globals from ES modules.
+These should be imported as variable definitions directly, or the file where
+they are imported should be referenced.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst
new file mode 100644
index 0000000000..2c47a5210f
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-globals.rst
@@ -0,0 +1,5 @@
+import-globals
+==============
+
+Checks ``XPCOMUtils.defineLazyGetter`` etc and adds the name to the global
+scope.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst
new file mode 100644
index 0000000000..a754bd7985
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/import-headjs-globals.rst
@@ -0,0 +1,28 @@
+import-headjs-globals
+=====================
+
+Import globals from head.js and from any files that were imported by
+head.js (as far as we can correctly resolve the path).
+
+This rule is included in the test configurations.
+
+The following file import patterns are supported:
+
+- ``Services.scriptloader.loadSubScript(path)``
+- ``loader.loadSubScript(path)``
+- ``loadSubScript(path)``
+- ``loadHelperScript(path)``
+- ``import-globals-from path``
+
+If path does not exist because it is generated e.g.
+``testdir + "/somefile.js"`` we do our best to resolve it.
+
+The following patterns are supported:
+
+- ``Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");``
+- ``loader.lazyRequireGetter(this, "name2"``
+- ``loader.lazyServiceGetter(this, "name3"``
+- ``XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)``
+- ``loader.lazyGetter(this, "toolboxStrings"``
+- ``XPCOMUtils.defineLazyGetter(this, "clipboardHelper"``
+- ``ChromeUtils.defineLazyGetter(this, "clipboardHelper"``
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst
new file mode 100644
index 0000000000..090f445b69
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/lazy-getter-object-name.rst
@@ -0,0 +1,25 @@
+lazy-getter-object-name
+=============================
+
+Enforce the standard object variable name ``lazy`` for
+``ChromeUtils.defineESModuleGetters``
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ const obj = {};
+ ChromeUtils.defineESModuleGetters(obj, {
+ AppConstants: “resource://gre/modules/AppConstants.sys.mjs”,
+ });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const lazy = {};
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: “resource://gre/modules/AppConstants.sys.mjs”,
+ });
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst
new file mode 100644
index 0000000000..92e315a249
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-exported-symbols-as-used.rst
@@ -0,0 +1,23 @@
+mark-exported-symbols-as-used
+=============================
+
+Marks variables listed in ``EXPORTED_SYMBOLS`` as used so that ``no-unused-vars``
+does not complain about them.
+
+This rule also checks that ``EXPORTED_SYMBOLS`` is not defined using ``let`` as
+``let`` isn't allowed as the lexical scope may die after the script executes.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ let EXPORTED_SYMBOLS = ["foo"];
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ var EXPORTED_SYMBOLS = ["foo"];
+ const EXPORTED_SYMBOLS = ["foo"];
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst
new file mode 100644
index 0000000000..a518d7415b
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/mark-test-function-used.rst
@@ -0,0 +1,8 @@
+mark-test-function-used
+=======================
+
+Simply marks ``test`` (the test method) or ``run_test`` as used when in mochitests
+or xpcshell tests respectively. This avoids ESLint telling us that the function
+is never called.
+
+This rule is included in the test configurations.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst
new file mode 100644
index 0000000000..7e398bcbbe
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-aArgs.rst
@@ -0,0 +1,22 @@
+no-aArgs
+========
+
+Checks that function argument names don't start with lowercase 'a' followed by
+a capital letter. This is to prevent the use of Hungarian notation whereby the
+first letter is a prefix that indicates the type or intended use of a variable.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ function(aFoo, aBar) {}
+ (aFoo, aBar) => {}
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ function(foo, bar) {}
+ (foo, bar) => {})
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst
new file mode 100644
index 0000000000..f26a869371
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-addtask-setup.rst
@@ -0,0 +1,27 @@
+no-addtask-setup
+================
+
+Reject using ``add_task(async function setup() { ... })`` in favour of
+``add_setup(async function() { ... })``.
+
+Using semantically separate setup functions makes ``.only`` work correctly
+and will allow for future improvements to setup/cleanup abstractions.
+
+This option can be autofixed (``--fix``).
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ add_task(async function setup() { ... });
+ add_task(function setup() { ... });
+ add_task(function init() { ... });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ add_setup(async function() { ... });
+ add_setup(function() { ... });
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst
new file mode 100644
index 0000000000..a7d62e74ba
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-arbitrary-setTimeout.rst
@@ -0,0 +1,23 @@
+no-arbitrary-setTimeout
+=======================
+
+Disallows setTimeout with non-zero values in tests. Using arbitrary times for
+setTimeout may cause intermittent failures in tests. A value of zero is allowed
+as this is letting the event stack unwind, however also consider the use
+of ``TestUtils.waitForTick``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ function(aFoo, aBar) {}
+ (aFoo, aBar) => {}
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ function(foo, bar) {}
+ (foo, bar) => {})
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst
new file mode 100644
index 0000000000..b7785f2fc2
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-compare-against-boolean-literals.rst
@@ -0,0 +1,23 @@
+no-compare-against-boolean-literals
+===================================
+
+Checks that boolean expressions do not compare against literal values
+of ``true`` or ``false``. This is to prevent overly verbose code such as
+``if (isEnabled == true)`` when ``if (isEnabled)`` would suffice.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ if (foo == true) {}
+ if (foo != false) {}
+ if (false == foo) {}
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ if (!foo) {}
+ if (!!foo) {}
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst
new file mode 100644
index 0000000000..9f5a0def27
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-cu-reportError.rst
@@ -0,0 +1,23 @@
+no-cu-reportError
+=================
+
+Disallows Cu.reportError. This has been deprecated and should be replaced by
+console.error.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Cu.reportError("message");
+ Cu.reportError("message", stack);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ console.error("message");
+ let error = new Error("message");
+ error.stack = stack;
+ console.error(error);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst
new file mode 100644
index 0000000000..4421f4dd54
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-define-cc-etc.rst
@@ -0,0 +1,23 @@
+no-define-cc-etc
+================
+
+Disallows old-style definitions for ``Cc``/``Ci``/``Cu``/``Cr``. These are now
+defined globally for all chrome contexts.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ var Cc = Components.classes;
+ var Ci = Components.interfaces;
+ var {Ci: interfaces, Cc: classes, Cu: utils} = Components;
+ var Cr = Components.results;
+
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const CC = Components.Constructor;
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst
new file mode 100644
index 0000000000..d7d4edab50
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-redeclare-with-import-autofix.rst
@@ -0,0 +1,21 @@
+no-redeclare-with-import-autofix
+================================
+
+This is the
+`builtin eslint rule no-redeclare <https://eslint.org/docs/latest/rules/no-redeclare>`_,
+but with an additional fixer that can automatically remove superfluous
+(duplicate) imports.
+
+For redeclarations that are not imports, there is no automatic fix, as
+the author will likely have to rename variables so that they do not
+redeclare existing variables or conflict with the name of a builtin
+property or global variable.
+
+Typical duplicate imports happen when a `head.js` file, imports
+a module and a test then subsequently also attempts to import the same
+module.
+
+In browser mochitests, an additional typical scenario is importing
+modules that are already imported in the main browser window. Because
+these tests run in a scope that inherits from the main browser window
+one, there is no need to re-import such modules.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst
new file mode 100644
index 0000000000..0f9222de30
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.rst
@@ -0,0 +1,38 @@
+no-throw-cr-literal
+===================
+
+This is similar to the ESLint built-in rule no-throw-literal. It disallows
+throwing Components.results code directly.
+
+Throwing bare literals is inferior to throwing Exception objects, which provide
+stack information. Cr.ERRORs should be be passed as the second argument to
+``Components.Exception()`` to create an Exception object with stack info, and
+the correct result property corresponding to the NS_ERROR that other code
+expects.
+Using a regular ``new Error()`` to wrap just turns it into a string and doesn't
+set the result property, so the errors can't be recognised.
+
+This option can be autofixed (``--fix``).
+
+.. code-block:: js
+
+ performance.timing.navigationStart + performance.now()
+
+Often timing relative to the page load is adequate and that conversion may not
+be necessary.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ throw Cr.NS_ERROR_UNEXPECTED;
+ throw Components.results.NS_ERROR_ABORT;
+ throw new Error(Cr.NS_ERROR_NO_INTERFACE);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ throw Components.Exception("Not implemented", Cr.NS_ERROR_NOT_IMPLEMENTED);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst
new file mode 100644
index 0000000000..485caf6522
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-parameters.rst
@@ -0,0 +1,26 @@
+no-useless-parameters
+=====================
+
+Reject common XPCOM methods called with useless optional parameters (eg.
+``Services.io.newURI(url, null, null)``, or non-existent parameters (eg.
+``Services.obs.removeObserver(name, observer, false)``).
+
+This option can be autofixed (``--fix``).
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler, false);
+ Services.io.newURI('http://example.com', null, null);
+ Services.obs.notifyObservers(obj, 'topic', null);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler);
+ Services.io.newURI('http://example.com');
+ Services.obs.notifyObservers(obj, 'topic');
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst
new file mode 100644
index 0000000000..ce314ab58d
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-removeEventListener.rst
@@ -0,0 +1,20 @@
+no-useless-removeEventListener
+==============================
+
+Reject calls to removeEventListener where ``{once: true}`` could be used instead.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', function listener() {
+ elt.removeEventListener('click', listener);
+ });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ elt.addEventListener('click', handler, {once: true});
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst
new file mode 100644
index 0000000000..a079405696
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/no-useless-run-test.rst
@@ -0,0 +1,6 @@
+no-useless-run-test
+===================
+
+Designed for xpcshell-tests. Rejects definitions of ``run_test()`` where the
+function only contains a single call to ``run_next_test()``. xpcshell's head.js
+already defines a utility function so there is no need for duplication.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst
new file mode 100644
index 0000000000..cd6ee4e544
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-boolean-length-check.rst
@@ -0,0 +1,24 @@
+prefer-boolean-length-check
+===========================
+
+Prefers using a boolean length check rather than comparing against zero.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ if (foo.length == 0) {}
+ if (foo.length > 0) {}
+ if (foo && foo.length == 0) {}
+ function bar() { return foo.length > 0 }
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ if (foo.length && foo.length) {}
+ if (!foo.length) {}
+ var a = foo.length > 0
+ function bar() { return !!foo.length }
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst
new file mode 100644
index 0000000000..88eedee792
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/prefer-formatValues.rst
@@ -0,0 +1,23 @@
+prefer-formatValues
+===================
+
+Rejects multiple calls to document.l10n.formatValue in the same code block, to
+reduce localization overheads.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ {
+ document.l10n.formatValue('foobar');
+ document.l10n.formatValue('foobaz');
+ }
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ document.l10n.formatValue('foobar');
+ document.l10n.formatValues(['foobar', 'foobaz']);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst
new file mode 100644
index 0000000000..e540b24416
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-addtask-only.rst
@@ -0,0 +1,6 @@
+reject-addtask-only
+===================
+
+Designed for JavaScript tests using the add_task pattern. Rejects chaining
+.only() to an add_task() call, which is useful for local testing to run a
+single task in isolation but is easy to land into the tree by accident.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst
new file mode 100644
index 0000000000..4710878f8d
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-chromeutils-import-params.rst
@@ -0,0 +1,22 @@
+reject-chromeutils-import-params
+================================
+
+``ChromeUtils.import`` used to be able to be called with two arguments, however
+the second argument is no longer supported. Exports from modules should now be
+explicit, and the imported symbols being accessed from the returned object.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm", null);
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst
new file mode 100644
index 0000000000..fd81793690
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-eager-module-in-lazy-getter.rst
@@ -0,0 +1,35 @@
+reject-eager-module-in-lazy-getter
+==================================
+
+Rejects defining a lazy getter for module that's known to be loaded early in the
+startup process and it is not necessary to lazy load it.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ XPCOMUtils: "resource://gre/modules/XPCOMUtils.jsm",
+ });
+ XPCOMUtils.defineLazyModuleGetter(
+ lazy,
+ "AppConstants",
+ "resource://gre/modules/AppConstants.jsm",
+ });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+ const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+ );
+ const { AppConstants } = ChromeUtils.import(
+ "resource://gre/modules/AppConstants.jsm"
+ );
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst
new file mode 100644
index 0000000000..b3d94321f5
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-global-this.rst
@@ -0,0 +1,29 @@
+reject-global-this
+======================
+
+Rejects global ``this`` usage in JSM files. The global ``this`` is not
+available in ESM, and this is a preparation for the migration.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ this.EXPORTED_SYMBOLS = ["foo"];
+
+ XPCOMUtils.defineLazyModuleGetters(this, {
+ AddonManager: "resource://gre/modules/AddonManager.jsm",
+ });
+
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const EXPORTED_SYMBOLS = ["foo"];
+
+ const lazy = {};
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ AddonManager: "resource://gre/modules/AddonManager.jsm",
+ });
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst
new file mode 100644
index 0000000000..dd4fc4b2af
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-globalThis-modification.rst
@@ -0,0 +1,19 @@
+reject-globalThis-modification
+==============================
+
+Reject any modification to ``globalThis`` inside the system modules.
+
+``globalThis`` is the shared global inside the system modules, and modification
+on it is visible from all modules, and it shouldn't be done unless it's really
+necessary.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ globalThis.foo = 10;
+ Object.defineProperty(globalThis, "bar", { value: 20});
+ ChromeUtils.defineESModuleGetters(globalThis, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst
new file mode 100644
index 0000000000..d168676745
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-import-system-module-from-non-system.rst
@@ -0,0 +1,36 @@
+reject-import-system-module-from-non-system
+===========================================
+
+Rejects static import declaration for system modules (``.sys.mjs``) from non-system
+modules.
+
+Using static import for a system module into a non-system module would create a separate instance of the imported object(s) that is not shared with the other system modules and would break the per-process singleton expectation.
+
+The reason for this is that inside system modules, a static import will load the module into the shared global. Inside non-system modules, the static import will load into a different global (e.g. window). This will cause the module to be loaded into different scopes, and hence create separate instances. The fix is to use ``ChromeUtils.importESModule`` which will import the object via the system module shared global scope.
+
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+Inside a non-system module:
+
+.. code-block:: js
+
+ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+Examples of correct code for this rule:
+---------------------------------------
+
+Inside a non-system module:
+
+.. code-block:: js
+
+ const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+ );
+
+Inside a system module:
+
+.. code-block:: js
+
+ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst
new file mode 100644
index 0000000000..68b2e46928
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-importGlobalProperties.rst
@@ -0,0 +1,45 @@
+reject-importGlobalProperties
+=============================
+
+Rejects calls to ``Cu.importGlobalProperties`` or
+``XPCOMUtils.defineLazyGlobalGetters``.
+
+In system modules all the required properties should already be available. In
+non-module code or non-system modules, webidl defined interfaces should already
+be available and hence do not need importing.
+
+Options
+-------
+
+* "everything": Disallows using the import/getters completely.
+* "allownonwebidl": Disallows using the import functions for webidl symbols. Allows
+ other symbols.
+
+everything
+----------
+
+Incorrect code for this option:
+
+.. code-block:: js
+
+ Cu.importGlobalProperties(['TextEncoder']);
+ XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder']);
+
+allownonwebidl
+--------------
+
+Incorrect code for this option:
+
+.. code-block:: js
+
+ // AnimationEffect is a webidl property.
+ Cu.importGlobalProperties(['AnimationEffect']);
+ XPCOMUtils.defineLazyGlobalGetters(this, ['AnimationEffect']);
+
+Correct code for this option:
+
+.. code-block:: js
+
+ // TextEncoder is not defined by webidl.
+ Cu.importGlobalProperties(['TextEncoder']);
+ XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder']);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst
new file mode 100644
index 0000000000..64230ab6f1
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-lazy-imports-into-globals.rst
@@ -0,0 +1,36 @@
+reject-lazy-imports-into-globals
+================================
+
+Rejects importing lazy items into ``window`` or ``globalThis`` when in a
+non-system module scope.
+
+Importing into the ``window`` scope (or ``globalThis``) will share the imported
+global with everything else in the same window. In modules, this is generally
+unnecessary and undesirable because each module imports what it requires.
+Additionally, sharing items via the global scope makes it more difficult for
+linters to determine the available globals.
+
+Instead, the globals should either be imported directly, or into a lazy object.
+If there is a good reason for sharing the globals via the ``window`` scope, then
+this rule may be disabled as long as a comment is added explaining the reasons.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ XPCOMUtils.defineLazyModuleGetter(globalThis, "foo", "foo.jsm");
+ XPCOMUtils.defineLazyModuleGetter(window, "foo", "foo.jsm");
+ XPCOMUtils.defineLazyGetter(globalThis, "foo", () => {});
+ XPCOMUtils.defineLazyGetter(window, "foo", () => {});
+ ChromeUtils.defineLazyGetter(globalThis, "foo", () => {});
+ ChromeUtils.defineLazyGetter(window, "foo", () => {});
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const lazy = {};
+ XPCOMUtils.defineLazyGetter(lazy, "foo", () => {});
+ ChromeUtils.defineLazyGetter(lazy, "bar", () => {});
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst
new file mode 100644
index 0000000000..1bf5100901
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-mixing-eager-and-lazy.rst
@@ -0,0 +1,22 @@
+reject-mixing-eager-and-lazy
+==================================
+
+Rejects defining a lazy getter for a module that's eagerly imported at
+top-level script unconditionally.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ const { SomeProp } = ChromeUtils.import("resource://gre/modules/Foo.jsm");
+ XPCOMUtils.defineLazyModuleGetter(lazy, {
+ OtherProp: "resource://gre/modules/Foo.jsm",
+ });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const { SomeProp, OtherProp } = ChromeUtils.import("resource://gre/modules/Foo.jsm");
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst
new file mode 100644
index 0000000000..7ea048402b
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.rst
@@ -0,0 +1,27 @@
+reject-multiple-getters-calls
+=============================
+
+Rejects multiple calls on ``ChromeUtils.defineESModuleGetters`` for the same
+target in the same context.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+ ChromeUtils.defineESModuleGetters(lazy, {
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst
new file mode 100644
index 0000000000..4387041b26
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-relative-requires.rst
@@ -0,0 +1,22 @@
+reject-relative-requires
+========================
+
+Rejects calls to require which use relative directories.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ require("./relative/path")
+ require("../parent/folder/path")
+ loader.lazyRequireGetter(this, "path", "../parent/folder/path", true)
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ require("devtools/absolute/path")
+ require("resource://gre/modules/SomeModule.jsm")
+ loader.lazyRequireGetter(this, "path", "devtools/absolute/path", true)
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst
new file mode 100644
index 0000000000..2a8618939f
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-requires-await.rst
@@ -0,0 +1,20 @@
+reject-requires-await
+=====================
+
+`Assert.rejects` must be preceded by an `await`, otherwise the assertion
+may not be completed before the test finishes, might not be caught
+and might cause intermittent issues in other tests.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Assert.rejects(myfunc(), /startup failed/, "Should reject");
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ await Assert.rejects(myfunc(), /startup failed/, "Should reject");
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst
new file mode 100644
index 0000000000..8f6ae39060
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-scriptableunicodeconverter.rst
@@ -0,0 +1,13 @@
+reject-scriptableunicodeconverter
+================================================
+
+Rejects calls into ``Ci.nsIScriptableUnicodeConverter``. This is configured as a warning.
+You should use |TextEncoder|_ or |TextDecoder|_ for new code.
+If modifying old code, please consider swapping it in if possible; if this is tricky please ensure
+a bug is on file.
+
+.. |TextEncoder| replace:: ``TextEncoder``
+.. _TextEncoder: https://searchfox.org/mozilla-central/source/dom/webidl/TextEncoder.webidl
+
+.. |TextDecoder| replace:: ``TextDecoder``
+.. _TextDecoder: https://searchfox.org/mozilla-central/source/dom/webidl/TextDecoder.webidl
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst
new file mode 100644
index 0000000000..476dcbcb94
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-some-requires.rst
@@ -0,0 +1,6 @@
+reject-some-requires
+====================
+
+This takes an option, a regular expression. Invocations of
+``require`` with a string literal argument are matched against this
+regexp; and if it matches, the ``require`` use is flagged.
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst
new file mode 100644
index 0000000000..38be0b2d22
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/reject-top-level-await.rst
@@ -0,0 +1,26 @@
+reject-top-level-await
+======================
+
+Rejects ``await`` at the top-level of code in modules. Top-level ``await`` is
+not currently support in Gecko's component modules, so this is rejected.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ await foo;
+
+ if (expr) {
+ await foo;
+ }
+
+ for await (let x of [1, 2, 3]) { }
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ async function() { await foo; }
+ async function() { for await (let x of [1, 2, 3]) { } }
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst
new file mode 100644
index 0000000000..902b4a630c
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-cc-etc.rst
@@ -0,0 +1,26 @@
+use-cc-etc
+======================
+
+This requires using ``Cc`` rather than ``Components.classes``, and the same for
+``Components.interfaces``, ``Components.results`` and ``Components.utils``.
+This has a slight performance advantage by avoiding the use of the dot.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ let foo = Components.classes['bar'];
+ let bar = Components.interfaces.bar;
+ Components.results.NS_ERROR_ILLEGAL_INPUT;
+ Components.utils.reportError('fake');
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ let foo = Cc['bar'];
+ let bar = Ci.bar;
+ Cr.NS_ERROR_ILLEGAL_INPUT;
+ Cu.reportError('fake');
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst
new file mode 100644
index 0000000000..3da22e139a
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-generateqi.rst
@@ -0,0 +1,33 @@
+use-chromeutils-generateqi
+==========================
+
+Reject use of ``XPCOMUtils.generateQI`` and JS-implemented QueryInterface
+methods in favor of ``ChromeUtils``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ X.prototype.QueryInterface = XPCOMUtils.generateQI(["nsIMeh"]);
+ X.prototype = { QueryInterface: XPCOMUtils.generateQI(["nsIMeh"]) };
+ X.prototype = { QueryInterface: function QueryInterface(iid) {
+ if (
+ iid.equals(Ci.nsISupports) ||
+ iid.equals(Ci.nsIMeh) ||
+ iid.equals(nsIFlug) ||
+ iid.equals(Ci.amIFoo)
+ ) {
+ return this;
+ }
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ } };
+
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ X.prototype.QueryInterface = ChromeUtils.generateQI(["nsIMeh"]);
+ X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh"]) }
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst
new file mode 100644
index 0000000000..c38304193a
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-chromeutils-import.rst
@@ -0,0 +1,24 @@
+use-chromeutils-import
+======================
+
+Require use of ``ChromeUtils.import`` and ``ChromeUtils.defineModuleGetter``
+rather than ``Components.utils.import`` and
+``XPCOMUtils.defineLazyModuleGetter``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Components.utils.import("resource://gre/modules/AppConstants.jsm", this);
+ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm");
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);
+ ChromeUtils.defineModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm");
+ // 4 argument version of defineLazyModuleGetter is allowed.
+ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants","resource://gre/modules/AppConstants.jsm","Foo");
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst
new file mode 100644
index 0000000000..2392709e89
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-default-preference-values.rst
@@ -0,0 +1,19 @@
+use-default-preference-values
+=============================
+
+Require providing a second parameter to ``get*Pref`` methods instead of
+using a try/catch block.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ try { blah = branch.getCharPref('blah'); } catch(e) {}
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ blah = branch.getCharPref('blah', true);
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst
new file mode 100644
index 0000000000..bb65ebea2c
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-includes-instead-of-indexOf.rst
@@ -0,0 +1,21 @@
+use-includes-instead-of-indexOf
+===============================
+
+Use ``.includes`` instead of ``.indexOf`` to check if something is in an array
+or string.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ let a = foo.indexOf(bar) >= 0;
+ let a = foo.indexOf(bar) == -1;
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ let a = foo.includes(bar);
+ let a = foo.indexOf(bar) > 0;
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst
new file mode 100644
index 0000000000..dca1e51c82
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-isInstance.rst
@@ -0,0 +1,42 @@
+use-isInstance
+==============
+
+Prefer ``.isInstance()`` in chrome scripts over the standard ``instanceof``
+operator for DOM interfaces, since the latter will return false when the object
+is created from a different context.
+
+These files are covered:
+
+- ``*.sys.mjs``
+- ``*.jsm``
+- ``*.jsm.js``
+- ``*.xhtml`` with ``there.is.only.xul``
+- ``*.js`` with a heuristic
+
+Since there is no straightforward way to detect chrome scripts, currently the
+linter assumes that any script including the following words are chrome
+privileged. This of course may not be sufficient and is open for change:
+
+- ``ChromeUtils``, but not ``SpecialPowers.ChromeUtils``
+- ``BrowserTestUtils``, ``PlacesUtils``
+- ``document.createXULElement``
+- ``loader.lazyRequireGetter``
+- ``Services.foo``, but not ``SpecialPowers.Services.foo``
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ node instanceof Node
+ text instanceof win.Text
+ target instanceof this.contentWindow.HTMLAudioElement
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ Node.isInstance(node)
+ win.Text.isInstance(text)
+ this.contentWindow.HTMLAudioElement.isInstance(target)
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst
new file mode 100644
index 0000000000..5d9905fc9f
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-ownerGlobal.rst
@@ -0,0 +1,20 @@
+use-ownerGlobal
+===============
+
+Require ``.ownerGlobal`` instead of ``.ownerDocument.defaultView``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ aEvent.target.ownerDocument.defaultView;
+ this.DOMPointNode.ownerDocument.defaultView.getSelection();
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ aEvent.target.ownerGlobal;
+ this.DOMPointNode.ownerGlobal.getSelection();
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst
new file mode 100644
index 0000000000..1280703747
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-returnValue.rst
@@ -0,0 +1,20 @@
+use-returnValue
+===============
+
+Warn when idempotent methods are called and their return value is unused.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ foo.concat(bar)
+ baz.concat()
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ a = foo.concat(bar)
+ b = baz.concat()
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst
new file mode 100644
index 0000000000..1a57e3da10
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-services.rst
@@ -0,0 +1,21 @@
+use-services
+============
+
+Requires the use of ``Services`` rather than ``Cc[].getService()`` where a
+service is already defined in ``Services``.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+ Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ Services.wm.addListener()
+ Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator)
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst
new file mode 100644
index 0000000000..9090dd80b7
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.rst
@@ -0,0 +1,21 @@
+use-static-import
+=================
+
+Requires the use of static imports in system ES module files (``.sys.mjs``)
+where possible.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs");
+ const { XPCOMUtils: foo } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs");
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+ import { XPCOMUtils as foo } from "resource://gre/modules/XPCOMUtils.sys.mjs";
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst
new file mode 100644
index 0000000000..440d730e05
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-ci-uses.rst
@@ -0,0 +1,42 @@
+valid-ci-uses
+=============
+
+Ensures that interface accesses on ``Ci`` are valid, and property accesses on
+``Ci.<interface>`` are also valid.
+
+This rule requires a full build to run, and is not turned on by default. To run
+this rule manually, use:
+
+.. code-block:: console
+
+ MOZ_OBJDIR=objdir-ff-opt ./mach eslint --rule="mozilla/valid-ci-uses: error" *
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+``nsIFoo`` does not exist.
+
+.. code-block:: js
+
+ Ci.nsIFoo
+
+``UNKNOWN_CONSTANT`` does not exist on nsIURIFixup.
+
+.. code-block:: js
+
+ Ci.nsIURIFixup.UNKNOWN_CONSTANT
+
+Examples of correct code for this rule:
+---------------------------------------
+
+``nsIFile`` does exist.
+
+.. code-block:: js
+
+ Ci.nsIFile
+
+``FIXUP_FLAG_NONE`` does exist on nsIURIFixup.
+
+.. code-block:: js
+
+ Ci.nsIURIFixup.FIXUP_FLAG_NONE
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst
new file mode 100644
index 0000000000..fcbe5d064e
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-lazy.rst
@@ -0,0 +1,55 @@
+valid-lazy
+==========
+
+Ensures that definitions and uses of properties on the ``lazy`` object are valid.
+This rule checks for using unknown properties, duplicated symbols, unused
+symbols, and also lazy getter used at top-level unconditionally.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ const lazy = {};
+ if (x) {
+ // Unknown lazy member property {{name}}
+ lazy.bar.foo();
+ }
+
+.. code-block:: js
+
+ const lazy = {};
+ XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm");
+
+ // Duplicate symbol foo being added to lazy.
+ XPCOMUtils.defineLazyGetter(lazy, "foo", "foo1.jsm");
+ if (x) {
+ lazy.foo3.bar();
+ }
+
+.. code-block:: js
+
+ const lazy = {};
+ // Unused lazy property foo
+ XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm");
+
+.. code-block:: js
+
+ const lazy = {};
+ XPCOMUtils.defineLazyGetter(lazy, "foo", "foo.jsm");
+ // Used at top-level unconditionally.
+ lazy.foo.bar();
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ const lazy = {};
+ XPCOMUtils.defineLazyGetter(lazy, "foo1", () => {});
+ XPCOMUtils.defineLazyModuleGetters(lazy, { foo2: "foo2.jsm" });
+
+ if (x) {
+ lazy.foo1.bar();
+ lazy.foo2.bar();
+ }
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst
new file mode 100644
index 0000000000..c6c61abac2
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services-property.rst
@@ -0,0 +1,30 @@
+valid-services-property
+=======================
+
+Ensures that accesses of properties of items accessed via the ``Services``
+object are valid.
+
+This rule requires a full build to run, and is not turned on by default. To run
+this rule manually, use:
+
+.. code-block:: console
+
+ MOZ_OBJDIR=objdir-ff-opt ./mach eslint --rule="mozilla/valid-services-property: error" *
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+Assuming ``foo`` is not defined within ``Ci.nsISearchService``.
+
+.. code-block:: js
+
+ Services.search.foo();
+
+Examples of correct code for this rule:
+---------------------------------------
+
+Assuming ``bar`` is defined within ``Ci.nsISearchService``.
+
+.. code-block:: js
+
+ Services.search.bar();
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst
new file mode 100644
index 0000000000..bd76cb52ac
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/valid-services.rst
@@ -0,0 +1,24 @@
+valid-services
+==============
+
+Ensures that accesses of the ``Services`` object are valid.
+``Services`` are defined in ``tools/lint/eslint/eslint-plugin-mozilla/lib/services.json`` and can be added by copying from
+``<objdir>/xpcom/components/services.json`` after a build.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+Assuming ``foo`` is not defined within Services.
+
+.. code-block:: js
+
+ Services.foo.fn();
+
+Examples of correct code for this rule:
+---------------------------------------
+
+Assuming ``bar`` is defined within Services.
+
+.. code-block:: js
+
+ Services.bar.fn();
diff --git a/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst b/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst
new file mode 100644
index 0000000000..d21fc1b299
--- /dev/null
+++ b/docs/code-quality/lint/linters/eslint-plugin-mozilla/var-only-at-top-level.rst
@@ -0,0 +1,21 @@
+var-only-at-top-level
+=====================
+
+Marks all var declarations that are not at the top level invalid.
+
+Examples of incorrect code for this rule:
+-----------------------------------------
+
+.. code-block:: js
+
+ { var foo; }
+ function() { var bar; }
+
+Examples of correct code for this rule:
+---------------------------------------
+
+.. code-block:: js
+
+ var foo;
+ { let foo; }
+ function () { let bar; }